凌阳单片机使用中的一些问题.docx
《凌阳单片机使用中的一些问题.docx》由会员分享,可在线阅读,更多相关《凌阳单片机使用中的一些问题.docx(26页珍藏版)》请在冰豆网上搜索。
凌阳单片机使用中的一些问题
凌阳单片机使用中的一些问题
一、基础实验
1、熟悉μ’nSP™IDE环境下的汇编程序的编写
2、熟悉μ’nSP™IDE环境下的C语言的编写
1、2两个实验通过观察寄存器窗口、变量窗口和内存窗口并单步运行来了解程序的执行情况。
3、使用汇编语言实现A口的输出实验
4、使用C语言实现A口的输出实验
5、使用汇编语言实现A口为输入B口为输出实验
6、使用C语言实现A口为输入B口为输出实验
3、4、5、6四个实验
方法一:
采用软件仿真的方法,观察了解程序的执行情况,注意:
DownLoad后要按下F5键才能看到仿真的结果。
方法二:
采用硬件运行的方法来验证结果,下载到实验系统中以后就使它自动运行。
方法三:
采用软硬件调试的方法来验证结果,下载到实验系统中以后通过IDE的各种调试方法(比如:
单步运行)来运行程序。
试验:
自己新建工程和源文件,把实验4中的main.c的内容复制、粘贴到新源文件中,并且要hardware.asm文件复制到新工程文件夹中,然后将hardware.asm文件加入工程的源文件中,之后编译、下载、运行,结果正确。
注意:
实验5和6时,按键的输入必须在拨码开关S28处于上面时才可以。
5、6两个实验中的key.asm修改为:
//Progarm:
Theheadfileforkey.asminassemblyview
//Arrangedby:
AndyHsu
//Lastmodifieddate:
//Functions:
//F_Key_Scan_Initial;
//F_Key_Scan_ServiceLoop;
//F_Key_DebounceCnt_Down;
//
//callF_SP_GetCh;
.INCLUDEhardware.inc;
.PUBLICF_Key_Scan_Initial;
.PUBLICF_Key_Scan_ServiceLoop;
.PUBLICF_Key_DebounceCnt_Down;
.PUBLIC_SP_GetCh;
.PUBLICF_SP_GetCh;
.PUBLICR_KeyStrobe;
//////////////////////////////////////////////////////////////////
//RAMDefineArea
//////////////////////////////////////////////////////////////////
.RAM
.VARR_DebounceReg;//forkeyboardscan每次的即时键值
.VARR_KeyStrobe;//forkeyboardscan去抖动后的最终键值
.VARR_DebounceCnt;//forkeyboardscan
.DEFINEC_DebounceCnt0x0002;
.CODE
//////////////////////////////////////////////////////////////////
//Function:
InitializationforF_Key_Scan_ServiceLoop
//////////////////////////////////////////////////////////////////
F_Key_Scan_Initial:
r1=0x0000;//
[R_DebounceReg]=r1;//
r1=C_DebounceCnt;//
[R_DebounceCnt]=r1;//resetdebouncecounter
retf;
//////////////////////////////////////////////////////////////////
//Function:
F_Key_Scan_ServiceLoop
//////////////////////////////////////////////////////////////////
F_Key_Scan_ServiceLoop:
r1=[P_IOA_Data];//getkeydatafromIOA
r1=r1and0xff;//
r2=[R_DebounceReg];//
[R_DebounceReg]=r1;//
cmpr2,[R_DebounceReg];//
jeL_KS_StableTwoSample;//
r1=C_DebounceCnt;//debouncetimesetting
[R_DebounceCnt]=r1;//
retf;//
L_KS_StableTwoSample:
r1=[R_DebounceCnt];//
jzL_KS_StableOverDebounce;//
retf;
L_KS_StableOverDebounce:
r1=[R_DebounceReg];//
[R_KeyStrobe]=r1;//savestablekeycodetoR_KeyStrobe
retf;
//////////////////////////////////////////////////////////////////
//Function:
debouncecounterdowncount
//////////////////////////////////////////////////////////////////
F_Key_DebounceCnt_Down:
r1=[R_DebounceCnt];//DebouncesubroutineforF_IO_Key_Scan:
jzL_DebounceCntZero;//stopcountifzero
r1-=0x0001;//
[R_DebounceCnt]=r1;//
L_DebounceCntZero:
//
retf;//
//****************************************************************
//Function:
GetKeycodeforI/OPort
//Destoryregister:
r1,r2
//****************************************************************
_SP_GetCh:
F_SP_GetCh:
r1=[R_KeyStrobe];//GetKeycode
r2=0x0000;//ClearKeyStrobefornextkey
[R_KeyStrobe]=r2;//
retf;
//Endofkey.asm
7、定时器TimerA/B实验
本实验的几个关键问题:
(1)溢出频率的计算
Fosc默认为24.576MHZ
time_clk=Fosc/2=12.288MHZ
情况一:
若r1=0x0000;//设定TA_TIMEOUT/16=(time_clk/65535)/16=11.7Hz
[P_TimerA_Data]=r1;
并且占空比为50%,波形和二极管的闪烁现象比较明显。
情况二:
若r1=0xff9f;//设定TA_TIMEOUT/16=(time_clk/96)/16=8kHz
[P_TimerA_Data]=r1;
并且占空比为50%,波形很好,但二极管的闪烁现象没有。
情况三:
若r1=0xc000;//设定TA_TIMEOUT/16=(time_clk/16383)/16=46.9Hz
[P_TimerA_Data]=r1;
并且占空比为50%,波形很好,但二极管的闪烁现象也没有。
(2)改变系统频率和PWM波占空比的方法
方法一:
直接改变r1的值太麻烦,因为每次必须查找书上对应的表格
r1=time_pwm或time_clk;
[P_TimerA_Ctrl]=r1;
方法二:
//选择不同的时钟源,占空比都为8/16,观察示波器中频率的变化
.definetimefosc_20x0230;//clkA选择fosc/2Hz
.definetimefosc_2560x0231;//clkA选择fosc/256Hz
.definetimeclk_327680x0232;//clkA选择32768Hz
.definetimeclk_81920x0233;//clkA选择8192Hz
.definetimeclk_40960x0234;//clkA选择4096Hz
.definetimeclk_20480x0205;//clkB选择2048Hz
.definetimeclk_10240x020d;//clkB选择1024Hz
.definetimeclk_2560x0215;//clkB选择256Hz
.definetimeclk_40x0225;//clkB选择4Hz
.definetimeclk_20x022d;//clkB选择2Hz
//频率选择fosc/2Hz,设置不同的占空比
.definetimepwm_10x0070;//脉宽选择1/16
.definetimepwm_20x00b0;//脉宽选择2/16
.definetimepwm_30x00f0;//脉宽选择3/16
.definetimepwm_40x0130;//脉宽选择4/16
.definetimepwm_50x0170;//脉宽选择5/16
.definetimepwm_60x01b0;//脉宽选择6/16
.definetimepwm_70x01f0;//脉宽选择7/16
.definetimepwm_80x0230;//脉宽选择8/16
.definetimepwm_90x0270;//脉宽选择9/16
.definetimepwm_100x02b0;//脉宽选择10/16
.definetimepwm_110x02f0;//脉宽选择11/16
.definetimepwm_120x0330;//脉宽选择12/16
.definetimepwm_130x0370;//脉宽选择13/16
.definetimepwm_140x03b0;//脉宽选择14/16
.definetime_clktimefosc_256;//占空比为50%时频率的选择
.definetime_pwmtimepwm_8;//频率为fosc/2Hz时脉宽的选择
以上方法也不好,因为频率和脉宽要求同时改变时,就非常麻烦。
方法三:
//实现功能:
1)选择不同的时钟源,同一占空比一定,观察示波器中频率的变化
//2)选择同一时钟源,改变占空比,观察示波器,比较脉冲宽度
//3)时钟源频率和占空比同时改变
//日期:
2003/6/9
//============================================================
//频率的选择
.definetimefosc_20x0030;//clkA选择fosc/2Hz
.definetimefosc_2560x0031;//clkA选择fosc/256Hz
.definetimeclk_327680x0032;//clkA选择32768Hz
.definetimeclk_81920x0033;//clkA选择8192Hz
.definetimeclk_40960x0034;//clkA选择4096Hz
.definetimeclk_20480x0005;//clkB选择2048Hz
.definetimeclk_10240x000d;//clkB选择1024Hz
.definetimeclk_2560x0015;//clkB选择256Hz
.definetimeclk_40x0025;//clkB选择4Hz
.definetimeclk_20x002d;//clkB选择2Hz
//占空比的选择
.definetimepwm_10x0040;//脉宽选择1/16
.definetimepwm_20x0080;//脉宽选择2/16
.definetimepwm_30x00c0;//脉宽选择3/16
.definetimepwm_40x0100;//脉宽选择4/16
.definetimepwm_50x0140;//脉宽选择5/16
.definetimepwm_60x0180;//脉宽选择6/16
.definetimepwm_70x01c0;//脉宽选择7/16
.definetimepwm_80x0200;//脉宽选择8/16
.definetimepwm_90x0240;//脉宽选择9/16
.definetimepwm_100x0280;//脉宽选择10/16
.definetimepwm_110x02c0;//脉宽选择11/16
.definetimepwm_120x0300;//脉宽选择12/16
.definetimepwm_130x0340;//脉宽选择13/16
.definetimepwm_140x0380;//脉宽选择14/16
.definetime_clktimefosc_2;//频率选择
.definetime_pwmtimepwm_2;//脉宽选择
.defineP_TimerA_Data0x700A;
.defineP_TimerA_Ctrl0x700B;
.defineP_IOB_DATA0x7005;
.defineP_IOB_DIR0x7007;
.defineP_IOB_ATTRI0x7008;
.defineP_Feedback0x7009;
.definep_watchdog_clear0x7012;
r1=time_clk|time_pwm;
[P_TimerA_Ctrl]=r1;
8、系统时钟实验
没有问题,能否改成跑马灯的形式。
9、FIQ中断实验
FIQ三个中断的入口地址均为FFF6H,因此产生这种中断时必须要进行判断。
FIQ_fosc/1024和IRQ0_fosc/1024类似于时基中断,也就是给定一个系统时钟频率比如24.576MHZ,中断频率就为24.576MHZ/1024,凌阳技术人员说设计者原来想用来作为midi载波的,但很少使用,在下一代产品中已经将其去掉了。
中断的入口地址与中断服务程序之间的关系?
比如说:
FIQ中断的入口地址为FFF6H,IDE编译器把带关键字”_FIQ”的中断服务程序的代码首地址直接写到FIQ中断的入口地址FFF6H处。
只要一产生FIQ中断,程序就跳转到FFF6H处,并由FFF6H处的地址开始执行中断服务程序。
实验箱下载以后将ICE拨码开关扳下来程序不能自动运行,必须再将ICE拨码开关扳一次,程序才能运行。
按复位按键也不能使程序自动运行,之后必须再将ICE拨码开关扳一次,程序才能运行。
不知何故?
自制板子的情况一样。
但是实验七、八都不存在上述问题,说明复位按键、上电复位对定时器没有影响,没有启动定时器。
程序一:
没有上述问题较好
.INCLUDEhardware.inc;
.DEFINEC_TimeA_Clk0x000d;//1024Hz时钟源
.DEFINEC_TimeB_Clk0x0004;//4096Hz时钟源
.RAM
.CODE
.PUBLIC_main
_main:
intoff
r1=0x000f//IOA口设为同相高电平输出口;
[P_IOA_Attrib]=r1
[P_IOA_Dir]=r1
[P_IOA_Data]=r1
r1=0x000f//B口的低8位设置为同相高电平输出
[P_IOB_Dir]=r1
[P_IOB_Attrib]=r1
[P_IOB_Data]=r1
r1=0xF7FF;
[P_TimerA_Data]=r1;//定时设置2秒
r1=0xEFFF;
[P_TimerB_Data]=r1;//定时设置1秒
r1=C_TimeA_Clk;
[P_TimerA_Ctrl]=r1;
r1=C_TimeB_Clk;
[P_TimerB_Ctrl]=r1;
r1=0xa800//开中断FIQ_PWM、FIQ_TMA、FIQ_TMB
[P_INT_Ctrl]=r1
intfiq
L:
r1=0x0001;
[P_Watchdog_Clear]=r1;//清看门狗
jmpL;
.Text
.PUBLIC_FIQ
_FIQ:
pushr1,r5to[sp]
r1=[P_INT_Ctrl]//读取中断标志
testr1,0x2000//是否为TimerA的FIQ中断?
jnz?
L_FIQ_TMA//是则跳转
testr1,0x0800//是否为TimerB的FIQ中断?
jnz?
L_FIQ_TMB//是则跳转
?
L_FIQ_PWM:
//Fosc/1024的FIQ中断
r1=0x8000
[P_INT_Clear]=r1
popr1,r5from[sp]
reti
?
L_FIQ_TMA:
//TimerA的FIQ中断
r1=[P_IOA_Buffer]//读取上次输出值
r1^=0x000f//与0x000f异或,即将低四位数据取反
[P_IOA_Data]=r1
r1=0x2000
[P_INT_Clear]=r1//清中断标志位
popr1,r5from[sp]
reti
?
L_FIQ_TMB:
//TimerB的FIQ中断
r1=[P_IOB_Buffer]//读取上次IOB口的输出值
r1^=0x000f
[P_IOB_Buffer]=r1
r1=0x0800
[P_INT_Clear]=r1
popr1,r5from[sp]
reti
程序二:
也不会出现上述问题这种程序不好
.TEXT
.PUBLIC_FIQ
_FIQ:
pushr1,r5to[sp]
r1=[P_INT_Ctrl]
testr1,0x0800
jnzL_FIQ_TMB
testr1,0x2000
jnzL_FIQ_TMA
L_FIQ_PWM:
r1=0x8000
[P_INT_Clear]=r1
popr1,r5from[sp]
reti
L_FIQ_TMA:
r1=0x000f//点亮接在A口低四位的四个LED灯
[P_IOA_Data]=r1
r2=0xffff;//延时
L_Delay1:
r1=0x0001;
[P_Watchdog_Clear]=r1;//清看门狗
r2-=1;
jnzL_Delay1;
r1=0x0000;//熄灭LED
[P_IOA_Data]=r1;
r1=0x2000;
[P_INT_Clear]=r1;
popr1,r5from[sp];//原因是因为此处的r1原来误写为r2会出现上述问题
reti;
L_FIQ_TMB:
r1=0x000f;//点亮接在B口低四位的四个LED灯
[P_IOB_Data]=r1;
r2=0xffff;//延时
L_Delay2:
r1=0x0001;
[P_Watchdog_Clear]=r1;//清看门狗
r2-=1;
JNZL_Delay2;
r1=0x0000;//熄灭接在B口低四位的四个LED灯
[P_IOB_Data]=r1;
r1=0x0800;
[P_INT_Clear]=r1;
popr1,r5from[sp];//原因是因为此处的r1原来误写为r2会出现上述问题
reti;
10、IRQ0/IRQ1/IRQ2中断实验
因为IRQ0、IRQ1、IRQ2中断入口地址分别为:
FFF8H、FFF9H、FFFAH,因此产生这三个中断,无须再判断。
.TEXT
.PUBLIC_IRQ0;
.PUBLIC_IRQ1;
.PUBLIC_IRQ2;
_IRQ0:
pushr1,r5to[sp];//压栈保护
r1=0x4000;
[P_INT_CLEAR]=r1;
popr1,r5from[sp];
reti
_IRQ1:
pushr1,r5to[sp];//压栈保护
r1=0xfff0;//熄灭与A口低四位相连的LED灯
[P_IOA_DATA]=r1;
r1=0x1000;
[P_INT_CLEAR]=r1;
popr1,r5from[sp];