问题
单片机内存有限,若功能过多,会导致C程序过大超过内存容量。
某些子程序需要快速执行,可用汇编程序替代。
以STC89C52RC单片机为例,功能为独立数码管变换显示数字,用C语言写时:
#include //数码管0~9的段码code unsigned char ledCode[] = {0xC0, 0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98 };void Delay1S(void);//声明函数/* 主函数 */int main(){ unsigned char count = 0; P0 = 0x00;//熄灭数码管 while(1) { P0 = ledCode[count++];//修改P0口电平 Delay1S(); //汇编程序延时1秒 if(count == 10) { count = 0; } } }/* 延时子函数 */void Delay1S(void){ unsigned char a, b, c; for(a=0 ; a<150; a++) { for(b=0 ; b<150; b++) { for(c=0; c<5; c++); } }}
编译后所占内存大小:
这里的data:单片机内部RAM,低128字节,速度快,可直接或间接寻址
xdata:内部扩展RAM,高128字节,速度慢,只能间接寻址
code:程序存储区,该型号单片机为8KB
改用C语言调用汇编延时程序时:
/* C语言程序 main.c文件中 */#include //数码管0~9的段码const unsigned char ledCode[] = {0xC0, 0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x98 };void Delay1S(void);//声明函数/* 主函数 */int main(){ unsigned char count = 0; P0 = 0x00;//熄灭数码管 while(1) { P0 = ledCode[count++];//修改P0口电平 Delay1S(); //汇编程序延时1秒 if(count == 10) { count = 0; } } }/* 汇编程序 delay.asm文件中 */PUBLIC Delay1S ;定义子程序名DelayCode SEGMENT CODE ;命名子文件的程序段RSEG DelayCode ;用于标明该段代码是可重定位的,可以避免代码段地址冲突;-------------------------- 延时函数Delay1S: ;1S = 2us*500 000 = 50*100*100 MOV R7, #100 ; R7寄存器赋初值L_loop2: ;第二层循环 MOV R6, #50 ; R6寄存器赋初值 L_loop1: ;第三层循环 MOV R5, #100 ;递减100次 DJNZ R5,$ ;两个机器周期, 12MHz晶振是2us,这条语句运行次数最多 DJNZ R6,L_loop1 ;不为0就跳转到L_loop1 DJNZ R7,L_loop2 ;不为0就跳转到L_loop2 RETEND
其中,汇编程序的主要延时操作是:
DJNZ R5,$
由数据手册知:DJNZ 指令在12时钟模式下需要24个机器周期,我们使用的晶振为12MHz,该单片机为12T模式,即12个时钟周期为1个机器周期,机器周期为1us,因周期DJNZ需要24个时钟周期,即2个机器周期=2us。
编译后所占内存大小:
code区从100减少到67。
现在看一下效果:
最后总结一下C语言调用汇编的格式:
/* C语言程序 */void 子函数名字(void);int main(){ while(1); 使用子函数;}/* 汇编程序 */PUBLIC 子函数名字 ;定义子函数名子文件程序段名字 SEGMENT CODE ;命名子文件的程序段RSEG 子文件程序段名字 ;用于标明该段代码是可重定位的,可以避免代码段地址冲突 ;子程序内容 END
每天进步一点点,学习路上不间断!!!
END
更多内容请关注公众号:嵌入式的路上