畅聊单片机中C语言与汇编语言的转换
发布时间:2021-11-18 11:29:43 所属栏目:PHP教程 来源:互联网
导读:做了一单片机设计,要用C语言与汇编语言同时实现,现将这次设计的感受和收获,还有遇到的问题写下,欢迎感兴趣的朋友交流想法,提出建议。 单片机设计:基于51单片机的99码表设计 软件环境:Proteus8.0 + Keil4 要求:1,开关按一下,数码管开始计时。2,按
做了一单片机设计,要用C语言与汇编语言同时实现,现将这次设计的感受和收获,还有遇到的问题写下,欢迎感兴趣的朋友交流想法,提出建议。 单片机设计:基于51单片机的99码表设计 软件环境:Proteus8.0 + Keil4 要求:1,开关按一下,数码管开始计时。2,按两下,数码管显示静止。3,按三下,数码管数值清零。 C语言程序如下: #include<reg51.h> #define uint unsigned int #define uchar unsigned char uchar shi,ge,aa,keycount=0,temp; sbit anjian=P1^7; uchar code table[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f}; void display(shi,ge); void key (); void init(); void delay(uint z); /*-----主程序-----*/ void main() { init(); //初始化 while(1) { key (); if(keycount==1) TR0=1; //开中断 if(keycount==2) TR0=0; if(keycount==3) { temp=0; keycount=0; } if(aa==10){aa=0; if(temp<=99) { temp++;display(shi,ge); } else temp=0;} } } /*------初始化程序-------*/ void init() { keycount=0; temp=0; TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; //TR0=0; } /*-----定时器中断-----*/ void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; aa++; } /*-----显示子程序-----*/ void display(shi,ge) { shi=temp/10; ge=temp%10; P0=table[shi];;delay(70); P2=table[ge]; ;delay(70); } /*-----按键检测子程序-----*/ void key () { if(anjian==0) { delay(5); //消抖 if(anjian==0) keycount++; } //while(anjian==0); //display(shi,ge); //等待按键弹起 } /*-----延时子程序-----*/ void delay(uint z) //延时约1ms { uint x,y; for(x=z;x>0;x--) for(y=100;y>0;y--); } 电路仿真结果如下: 好了,那么接下来我们就开始C语言——>汇编语言之旅^_^ (1)C语言1-10行改为 ORG 0000H //汇编起始伪指令,功能是规定程序存储器中源程序或数据块存放的起始地址 ajmp STAR //ajmp无条件跳转指令 ORG 000bh ajmp timer0 anjian equ P1.7 //位定义 keycount equ 40h shi equ 41h gewei equ 42h aa equ 43h temp equ 44h tab: db 3fh,6h,5bh,4fh,66h //建表 db 6dh,7dh,7h,7fh,6fh (2)C语言中的初始化函数 12-14行和39-49行改为 1 STAR: 2 acall init //子程序近程调用指令,功能是主程序调用子程序,调用子程序的范围为2kb init: mov keycount,#0 //keycount=0 mov temp,#0 //temp=1 mov tmod,#01h //TMOD=0x01 mov TH0,#60 mov TL0,#176 setb EA //位置位指令,对操作数所指出的位进行置1操作 setb ET0 setb TR0 ret acall为子程序近程调用指令,返回用ret。 (3)C语言中15-35行是个while循环,逻辑比较繁琐,注意了! START: acall display inc temp //加1指令,将操作数所指定的单元或寄存器中的内容加1 acall delay70 //近程调用delay70 x8: mov r0,keycount cjne r0,#2,F1 //cjne比较跳转指令,若r0=2则跳转到x8,否则跳转到F1。 ajmp x8 F1: mov r0,temp cjne r0,#99,START //若r0<99时,重复循环,否则temp=0 mov temp,#0 ajmp START F9: acall key mov r0,keycount cjne r0,#0,F2 //keycount=0顺序执行,否则跳转到F1 CLR P1.3 //清0 SETB TR0 F2: mov r0,keycount //第二次按键 cjne r0,#2,F2 clr TR0 reti mov r0,keycount //第三次按键 cjne r0,#3,F3 mov temp,#0 mov keycount,#0 inc 增量指令,功能是将操作数所指定的单元或寄存器中的内容加1,其结果返还回原操作数单元中。 clr 位复位,功能是对操作数所指出的位进行清“0”操作。 或者在中断函数中 timer0: w1: acall key mov TH0,#60 mov TL0,#176 cpl p1.0 JB keycount,x2 ajmp x3 x2: ajmp START clr p1.0 ajmp w1 ajmp w1 x3: mov r0,keycount cjne r0,#3,w1 //若r0=3则顺序执行,否则跳转到w1 mov temp,#0 mov keycount,#0 ret (4)C语言58-64行display函数改为 display: mov a,temp mov b,#10 div ab //除法指令,实现两个八位无符号数的除法操作。 mov r2,A mov r3,B mov dptr,#tab //16位数据传送使用方式 mov a,r2 movc a,@a+dptr //查表,先将累加器A的内容与数据指针寄存器DPTR的内容相加,再以其结果为地址,将该地址的结果送入A中 mov P0,a acall delay70 nop //空指令 mov a,r3 movc a,@a+dptr mov P2,a nop acall delay70 ret div为除法指令,功能是实现两个8位无符号数的除法操作,一般被除数放在累加器A中,除数放在寄存器B中。指令执行后,商放在A中,余数放在B中。 movc为查表指令,先将累加器A的内容与数据指针寄存器DPTR的内容相加,再以其结果为地址,将该地址的内容送入A中。 nop为空操作指令,它不作任何操作,但要占用一个机器周期(即12个振荡周期)的时间,常用于延时或等待。(有些程序执行的效果由于延时时间太短,在人眼视觉暂时作用下无法辨认清楚) 此段程序的作用在于将一个两位数分别分在一个十位上的数码管和一个个位上的数码管显示。 (5)C语言66-76行key函数改为 1 key: 2 jb anjian,F6 //若anjian=0则顺序执行,否则跳转到F6 3 ACALL delay5 4 inc keycount //keycount++ 5 F6: 6 ret jb为位条件转移指令,功能是若直接寻址的位bit=1,则程序转移到指定的目标地址去执行,若bit=0,则程序顺序执行。 (6)C语言78-83行delay函数改为 delay70: mov r6,#70 D2: mov R7,#248 d1: djnz R7,d1 //248*70次 djnz R6,D2 ret delay5: mov r6,#5 //消抖。 F7: mov R7,#248 F8: djnz r7,F8 //248*5次 djnz r6,F7 ret 注意:248=28 ,约等于1ms。delay为延时程序。 温馨提示:在汇编中���序代码的大小写不受影响,但在C语言中就有影响了。 思考1:ret 和 reti都是程序返回指令,有什么区别? 我的回答:ret是子程序返回指令,reti是中断子程序返回指令。区别在于如果是acall 、lcall指令调用的子程序,返回指令就用ret;如果地址是0003,0013,000B,001B,0023调用的子程序,返回指令就用reti。 思考2:mov 20h,#0h 和 setb 20h 都是加1,用什么区别? 我的回答:mov指令中的20h指字节,setb中的20h是位。 旅途结束! 还记得前段时间我一直纠结于汇编语言中的各种指令的语法和功能,直到一个阳光明媚的中午,我一手拿着已经写好的两页半的C语言代码,一手拿着一本单片机的汇编指令查询手册,开始一行一行的翻译,可能汇编代码会在调试中有所错误,但基本逻辑是对的。而且这次C——>汇编,使我更加深入地理解了数据在计算机中的存储与调用。在此期间班主任和同学也给我答疑解惑,相信在以后的道路上,我会更加更深入地理解计算机。越努力,越幸运! ![]() (编辑:应用网_丽江站长网) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |