课程设计П实验报告
模块名称_ _____凌阳单片机______ _
班级学号_______B080210
姓 名__ ____ _ _______
指导老师_赵建立__叶玲__董恒 梅霆_
开课时间 2011/2012 学年, 第 一 学期
实验1 熟悉’nSP™ IDE环境下的汇编程序和C程序的编写
一、实验目的
熟悉汇编程序和C程序的编写。编译程序,软件调试,观察并跟踪其结果,查看各个寄存器状态,等等。
二、实验设备
装有WINDOWS操作系统以及μ’nSP™ IDE仿真开发环境的PC机一台;十六位单片机实验板及扩展板。
三、实验原理
参照SPCE061A单片机教材和实验指导书熟悉凌阳单片机的开发环境。
四、流程图
汇编程序主程序流程图:
五、关键代码
汇编程序代码:
//===============================================================//
// Program: 计算1 to 100累加值
// Output: [sum] = 5050(十进制) 或 13BA(十六进制)
//===============================================================//
.RAM // 定义预定义 RAM 段
.var R_Sum; // 定义变量
.CODE //定义代码段
.public _main; // 对main程序段声明
_main:
r1 = 0x0001; // r1=[1..100]
r2 = 0x0000; // 寄存器清零
L_SumLoop:
r2 += r1; // 累计值存到寄存器r2
r1 += 1; // 下一个数值
cmp r1,100; // 加到100否
jna L_SumLoop; // 如果 r1 <= 100 跳到 L_SumLoop
[R_Sum] = r2; // 在R_Sum中保存最终结果
L_ProgramEndLoop: // 程序死循环
jmp L_ProgramEndLoop;
C程序代码:
//===============================================================//
// Program: 计算1 to 100累加值
// Output: [sum] = 5050(十进制) 或 13BA(十六进制)
//===============================================================//
int main()
{
int i, Sum=0;
for (i=0;i<=100;i++)
Sum = Sum + i; // Sum 是累加的结果
while(1){ }; // 程序死循环
// 用变量 Watch 窗口看 Sum 的值
}
六、实验结果
用RegisterWindow工具观察各个寄存器状态变化符合实际情况。
实验2 键盘与二极管实验
一、实验目的
通过本实验熟悉μ’nSP™ IDE单片机的I/O、定时器的使用方法、中断系统的使用。熟悉IDE开发环境的使用。
二、实验设备
装有WINDOWS操作系统以及SunPlus IDE仿真开发环境的PC机一台;十六位单片机实验板及扩展板。
三、实验原理
通过键盘扫描获得键值后分别控制二极管的亮灭;使用定时器产生不同的显示。
四、实验步骤
1.连接PC机与SunPlus061A仿真板;
2.连接实验板与仿真板;
3.运行IDE开发环境程序;
4.建立新工程;
5.往新工程里添加C文件,编写主程序框架;
6.往工程里添加ASM文件,编写汇编子程序;
7.往新工程中添加中断处理程序;
8.添加头文件(hardware.inc等);
9.程序编译调试,观察运行结果,寄存器状态等;
10.脱机运行。
要求:对于每个不同的按键,分别有下列响应:1.全亮;2.轮流点亮;3.交替闪亮;4.快慢闪烁。
五、流程图
主函数流程图:
六、关键代码
//主程序main函数用C语言编写
int main(void)
{
int Key;
while(1)
{
Key=getkey();
switch(Key)
{
case 0xfffe: one();break;
case 0xfffd: two();break;
case 0xfffb: three();break;
case 0xfff7: four();break;
break;
default:
break;
}
}
return 0;
}
//获取键值函数 IOA低8位输入 设置A口为带上拉电阻的输入 汇编语言编写
.include hardware.inc;
.public _getkey;
.code
_getkey:
r1=0x0000;
[P_IOA_Dir]=r1;
[P_IOA_Attrib]=r1;
r1=0xffff;
[P_IOA_Data]=r1;
r1=[P_IOA_Data];
retf;
//交替亮 (以交替亮为例,全亮、轮流亮、快慢闪烁等与此类似,略去)
.INCLUDE Hardware.inc;
.CODE
.PUBLIC _three
_three:
r1 = 0x00FF;
[P_IOB_Dir] = r1; // IOB: [7..0] output
[P_IOB_Attrib] = r1;
[P_IOB_Data] = r1;
r2 =0;
L_MainLoop:
r2=r2+1;
r1 = 0x00AA; //LED10101010亮
[P_IOB_Data] = r1;
call L_Delay;
r1 = 0x0055; //LED01010101亮
[P_IOB_Data] = r1;
call L_Delay;
cmp r2,0x000A;
jnz L_MainLoop;
retf;
L_Delay: //延时
r3 = 0x0004;
L_DelayLoop2:
r4 = 0xFFFF;
L_DelayLoop1:
r4 - = 1;
jnz L_DelayLoop1;
r3 - = 1;
jnz L_DelayLoop2;
retf;
七、实验结果及分析
当按下IOA0时,IOB口的低8位全亮;
当按下IOA1时,IOB口的低8位轮流亮;
当按下IOA2时,IOB口的低8位交替亮;
当按下IOA3时,IOB口的低8位快慢闪烁。
但是在一种状态下按下键不能立即转到下一状态,即不能及时读取键值。
实验3 实时时钟实验
一、实验目的
1)了解SPCE061 PLL 振荡器的功能及其应用。
2)掌握系统时钟单元P_SystemClock的设置方法。
3)熟悉系统时钟和CPU时钟频率的编程方法。
二、实验设备
1)装有µ’nSP™ IDE仿真环境的PC机一台。
2)µ’nSP™十六位单片机实验箱一个。
3)示波器一台。
三、实验原理
在SPCE061A内,P_SystemClock(写)($7013H)单元控制着系统时钟和CPU时钟。通过设置该单元的B5-B7位可以改变系统时钟的频率(Fosc=20/24/32/40/49MHz);将第0-2位置为“111”可以使CPU时钟停止工作,系统切换至低功耗的备用状态。在备用状态下,通过设置该单元的B4位可以接通或关闭32KHz实时时钟。而且通过设置该单元的B3位可以使32768Hz时钟处自动弱振或强振状态。本实验通过选择不同Fosc信号频率或改变CPUClk频率来观察发光二极管亮灭的快慢。
四、实验步骤
1)根据实验内容连接硬件电路并检查。
2)画流程图并编写程序代码。
3)编译程序,软件调试。
4)观察LED亮灭的快慢,并通过示波器观察波形。
要求: LED亮灭的快慢及通过示波器观察波形反映的定时信号与设计一致.
五、流程图
六、关键代码
//***********************************************************
// Note: 1)选择不同Fosc信号频率,观察发光二极管亮灭快慢
// 2) 改变CPUClk频率,观察发光二极管亮灭快慢
//*************************************************************
.INCLUDE Hardware.inc;
.DEFINE C_FoscCLK_20 0x00; //Fosc=20.480MHz
.DEFINE C_FoscCLK_24 0x20; //Fosc=24.576MHz
.DEFINE C_FoscCLK_32 0x40; //Fosc=32.768MHz
.DEFINE C_FoscCLK_40 0x60; //Fosc=40.960MHz
.DEFINE C_FoscCLK_49 0x80; //Fosc=49.152MHz
.DEFINE CPUCLK_Fosc 0x00; //CPUClk选Fosc
.DEFINE CPUCLK_Fosc2 0x01; //CPUClk选Fosc/2
.DEFINE CPUCLK_Fosc4 0x02; //CPUClk选Fosc/4
.DEFINE CPUCLK_Fosc8 0x03; //CPUClk选Fosc/8
.DEFINE CPUCLK_Fosc16 0x04; //CPUClk选Fosc/16
.DEFINE CPUCLK_Fosc32 0x05; //CPUClk选Fosc/32
.DEFINE CPUCLK_Fosc 0x06; //CPUClk选Fosc/
//=============================================================
// 函数名称: main()
// 功能描述: 1)选择不同Fosc信号频率,观察发光二极管亮灭快慢
// 2)改变CPUClk频率,观察发光二极管亮灭快慢
// 语法格式: main()
//入口参数: 无
// 出口参数: 无
// 注意事项: 仅为用户模型
//=============================================================
.CODE
.PUBLIC _main
_main:
r1 = 0xffff;
[P_IOB_Dir] = r1; // IOB: [7..0] output
[P_IOB_Attrib] = r1;
r1 = 0x0000;
[P_IOB_Data] = r1;
begin: r2=0;
C_FoscCLK_20_CPUCLK_Fosc2: (选择其他频率时与此段类似)
r2=r2+1;
r1 = C_FoscCLK_20; //Fosc
r1|= CPUCLK_Fosc2; //CPUClk
[P_SystemClock] = r1;
r1 = 0x0000; //LED亮
[P_IOB_Data] = r1;
call L_Delay;
r1 = 0xFFFF; //LED灭
[P_IOB_Data] = r1;
call L_Delay;
cmp r2,0x0005;
JZ C_FoscCLK_24_CPUCLK_Fosc4;
jmp C_FoscCLK_20_CPUCLK_Fosc2;
L_Delay: //延时
r3 = 0x0004;
L_DelayLoop2:
r4 = 0xFFFF;
L_DelayLoop1:
r4 - = 1;
jnz L_DelayLoop1;
r3 - = 1;
jnz L_DelayLoop2;
retf;
七、实验结果及分析
当选择不同的系统频率与CPU频率时,灯闪烁的快慢不同,与之一致,达到实验要求。
实验5 UART实验
一、实验目的
1)了解SPCE061A串行口(UART)的结构、与PC机串行通讯的原理。
2)了解UART的各配置单元P_UART_BaudScalarLow (7024H)、P_UART_BaudScalarHigh (7025H)、 P_UART_Command1(7021H)和P_UART_Command2 (7022H)的功能及控制方法。
3)掌握PC机与单片机通讯的编程方法。
二、实验设备
装有µ’nSP™ IDE仿真环境的PC机一台、 µ’nSP™十六位单片机实验箱一个、串口线一个。
三、实验原理
UART模块提供了一个全双工标准接口,用于完成SPCE061A与外设之间的串行通讯。借助于IOB口的特殊功能和UART IRQ中断,可以同时完成UART接口的接收发送数据的过程。 硬件电路原理为:因为SPCE061在线调试器有232接口,PC机端也有232接口,所以使用一个串口线连接起来就可以,或者使用9针头串口座焊接一个串口线。
四、实验步骤
1)根据内容自行设计硬件连接图,连接硬件并检查;2)画流程图并编写程序代码;3)编译程序,软件调试;4)观察LED、各个寄存器状态。
要求:1) 从内存中能观测到从PC发来的数据;2) 按不同的键时向 PC发送不同内容的字符串。
五、流程图
六、关键代码
//****************************************************************************
//程序名称:UART_PC.asm
//描述:与PC机通讯,使用串口总线与PC机通讯。
//终端软件:超级终端,
//收到超级终端发送的数据并发送回去,在超级终端界面可以看到接收到的数据。
//****************************************************************************
.include hardware.inc
.ram
.var recFlag; //接收数据标识,0 未接收数据 1 接收数据
.code
.public _main;
_main:
_UART_INIT:
F_UART_INIT:
INT OFF;
r1 = 0x0000;
[recFlag] = r1;
R1 = 0x0000; //未使能任何中断
[P_INT_Ctrl] = R1;
R1 = 0x0480; //设置IOB7为输入IOB10为输出
[P_IOB_Attrib] = R1;
R1 = 0x0400;
[P_IOB_Dir] = R1;
R1 = 0x0000;
[P_IOB_Data] = R1;
R1 = 0x006b; //设置波特率为115.2Kbps
[P_UART_BaudScalarLow] = R1;
R1 = 0x0000;
[P_UART_BaudScalarHigh] = R1;
R1 = 0x0000;
R4 = 0x00C0; //输入和输出使能设置
[P_UART_Command1] = R1;
[P_UART_Command2] = R4;
L_ResendData:
L_Check_TxRDY:
R2 = [P_UART_Command2];
R2 &= 0x0040; //检测输出是否READY
JZ L_Check_RxRDY;//发送8位十六进制数cc
r1 = [recFlag];
cmp r1,0x0000; //是否接收过数据
jz L_Check_RxRDY;
[P_UART_Data] = R4; //发送数据
r1 = 0x0000;
[recFlag] = r1;
L_Check_RxRDY:
R2 = [P_UART_Command2]; //检测是否有数据接收
R2 &= 0x0080;
JZ L_Check_RxRDY;
R4 = [P_UART_Data]; //接收数据
r1 = 0x0001;
[recFlag] = r1; //设置接收标识符
goto L_ResendData;
七、实验结果与分析
PC机发送数据,单片机收到相同的数据,然后再送回给PC机。不同按键输入,终端显示相应的输出
实验6 A/D转换
一、实验目的
1)了解ADC输入接口的结构与转换原理
2)熟悉模拟量输入口LINE_IN1—LINE_IN7的使用
3)掌握 P_ADC、 P_ADC_CTRL单元的设置方法
二、实验设备
装有µ’nSP™ IDE仿真环境的PC机一台 、µ’nSP™十六位单片机实验箱一个
三、实验原理
ADC工作方式分手动和自动两种当ADC工作在自动方式下:
1)外部信号由LIN_IN[1~7]即IOA[0~6]输入并直接被送入缓冲器P_ADC_MUX_Data($702BH);,在ADC自动方式被启用后,会产生出一个启动信号,即RDY=0。此时,DAC0的电压模拟量输出值与外部的电压模拟量输入值进行比较,以尽快找出外部电压模拟量的数字量输出值,A/D转换的结果保存在SAR内。
2)当10位A/D转换完成时,RDY会被置‘1’。此时,用户通过读取P_ADC_MUX_Data($702BH)单元可以获得10位A/D转换的数据。而从该单元读取数据后,又会使RDY自动清‘0’来重新开始进行A/D转换。 本实验通过改变LINE_IN端口的模拟电压来改变IOB口输出的数据,采用自动方式即定时器A溢出执行ADC转换,可以通过发光二极管的点亮了解转换的数据值。
四、实验步骤
1)根据实验内容连接硬件电路并检查。
2)画流程图并编写程序代码。
3)编译程序,软件调试。
4) 通过改变输入电压,来观察LED灯的亮灭。
要求:LED灯的亮灭与输入电压值相符合。
五、流程图
六、关键代码
//**********************************************************************
//Note:通过模拟量输入口LINE_IN输入电压值,通过读取P_ADC_MUX_Data单元可以获得10
//位A/D转换的数据。而从该单元读取数据后,又会使RDY自动清'0'来重新开始进行A/D转换。//若未读取P_ADC_MUX_Data单元中的数据RDY仍保持为'1',则不会启动下一次的A/D转换。
//**********************************************************************
.include hardware.inc
.CODE
.public _main
_main:
r1=0xffff
[P_IOB_Attrib]=r1 //IOB口设置为同向输出口
[P_IOB_Dir]=r1
//r1=0x0000
[P_IOB_Data]=r1;
R1=0x0001 //选择通道LINE_IN为IOA0
[P_ADC_MUX_Ctrl]=R1
R1 = 0x0001 //允许A/D转换
[P_ADC_Ctrl] = R1
nop
nop
nop
nop
_AD:
r1=[P_ADC_MUX_Ctrl] //读寄存器[P_ADC_MUX_Ctrl]的B15位
//判断是否转换完毕
test r1,0x8000
jz _AD //否,继续转换
r1=[P_ADC_MUX_DATA] //是,则读出[P_ADC_MUX_DATA]转换结果
//同时触发A/D重新转换
[P_IOB_Data]=r1;
jmp _AD;
七、实验结果与分析
IOA[0..6]为模拟量输入口,应设为悬浮输入形式;B口高10位为A/D转换量输出。当改动滑动变阻器的阻值时,会给IOA0口输入不同的电压值,经过模数转换后,会生成相应的数值,IOB7-10的对应位的灯会随之亮灭。
实验8 IRQ4 中断实验
一、实验目的
1)了解IRQ4的中断向量和中断源。
2)掌握中断控制单元P_INT_Ctrl, P_INT_Clear的设置方法。
3)熟悉中断的编程方法。
二、实验设备
1)装有µ’nSP™ IDE仿真环境的PC机一台。 2)µ’nSP™十六位单片机实验箱一个。
三、实验原理
IRQ4 中断对应4096Hz、2048Hz、1024Hz 中断源,通过写P_INT_Ctrl来设置中断允许,CPU响应后进入中断, 我们编写一个用中断方式控制发光二极管亮灭程序, 中断程序里读取P_INT_Ctrl单元,判断是哪个中断源,转到相应中断程序控制对应发光二极管亮或灭.从而了解IRQ4 中断的组成及编程。
四、实验步骤
1)根据实验内容自行设计,连接硬件电路并检查。
2)画流程图并编写程序代码。
3)编译程序,软件调试。
4) 观察LED、各个寄存器状态等。
要求: 能用LED的状态验证中断正确工作。
五、流程图
主程序:
中断服务子程序流程图:
六、关键代码
// Note: IRQ5中断有三个中断源:1KHz、2Kz和4KHz,每一个中断分别控制与IOA0-IOA1、
//IOA2-IOA3和IOA4-IOA7相连的LED灯。
.include hardware.inc
.RAM
.VAR TIME1
.VAR TIME2
.VAR TIME4
.code
.public _main
_main:
int off;
r1=0xffff; //IOA口为同相高电平输出口;
[P_IOA_ATTRI]=r1;
[P_IOA_DIR]=r1;
[P_IOA_DATA]=r1;
r1=0x0070; //开中断IRQ4_4KHz、IRQ4_2KHz和IRQ4_1KHz;
[P_INT_CTRL]=r1;
R1=0;
[TIME1]=r1;
[TIME2]=r1;
[TIME4]=r1;
int irq;
loop:
nop;
nop;
nop;
jmp loop;
.text
.public _IRQ4
_IRQ4:
push r1,r5 to [sp] //压栈保护;
r1=0x0010;
test r1,[P_INT_CTRL]; //比较是否为1KHz的中断源;
jnz l_irq4_1k; //是,则转至对应程序段;
r1=0x0020;
test r1,[P_INT_CTRL] //否,则比较是否为2KHz的中断源;
jnz l_irq4_2k; //是,则转至对应程序段;
l_irq4_4k: //否,则进入4KHz程序段; (l_irq4_2k程序段和l_irq4_1k程序段与此类似)
r2=[TIME4];
r2+=0x0001;
[TIME4]=R2;
cmp r2,0x03ff //比较是否为0.25秒;
jbe LED4kHZ_OFF //小于等于则LED灭;
r1=0x00f0; //大于则LED亮;
[P_IOA_DATA]=r1;
cmp r2,0x07ff //比较是否为0.5秒;
jbe LED4kHz_RET //小于等于则LED继续亮;
r2=0x0000; //否则,TIME4单元清零,返回中断;
[TIME4]=R2;
jmp LED4kHz_RET
LED4kHZ_OFF:
r1=0x0000;
[P_IOA_DATA]=r1;
LED4kHz_RET:
r1=0x0040;
[P_INT_CLEAR]=r1;
pop r1,r5 from [sp]
RETI;
七、实验结果与分析
各个灯闪烁的快慢与触发它们的中断源的频率对应一致。
实验小结
接近三周的凌阳单片机课程设计,贯通了很多汇编语言和单片机硬件的知识。课程设计是对所学知识的灵活运用,对硬件和软件有了更深刻的理解。其实凌阳单片机并不像这个字看起来这么简单。实际操作起来还是比较复杂的。如果对相关知识不是十分了解,对硬件部分了解不够的话,编程的时候就会遇到很多的问题。
课程设计刚开始的时候,我自己也不是十分清楚要怎么做,然后慢慢阅读老师给的课件,才有了大致的思路。知道了μ’nSP(TM)的内核由总线、算术逻辑运算单元、寄存器组、中断系统及堆栈等部分组成。了解SPCE061 PLL 振荡器的功能, 系统时钟单元P_SystemClock的设置方法。 对系统时钟和CPU时钟频率的编程方法也有了初步的理解。
在多次研究课件的基础上,开始着手于编程工作,经过多次调试,反复纠正,终于符合了实验的要求。下载本文