51单片机学习笔记(四)

      隔了两天没有写笔记了,也不算是偷懒吧,因为这两天写的程序也不少的,只是有些问题没有弄清楚,所以没有写笔记,今天基本上弄懂了,但还是有一些地方处理不好,还是把它留到日后处理吧,感觉这些问题不是我一时半会能够搞定的。

    这两天主要是学习了51单片机的计时器的使用。分别尝试了查询法计时和中断法计时。

其中查询法计时我自己编写程序时检测完 TF0 口数据为1时(数据溢出),时间到。于是开始执行相应的指令,但忘记用clr tf0来使tf0口清零,以置后续计时出错。参考书本后发现有jbc这样的指令,可以在检测到tf0为1时跳转且把tf0位清零。免去clr指令。

 

   下面说一说重点。数字电子时钟。

这个程序一共有200多行,第一次写那么长的程序,但其实很多地方是重复的,只要稍稍修改一下引脚就可以了。编写这个程序让我学会了编写程序的时候应先做一个类似的程序,然后其它稍加改进,就可以完成,一个模块一个模块地去处理。写多长也不觉得可怕了。

 

   以下是一些心得:

使用keil软件编译时,保护现场所用的堆栈指令push 和pop指令不能直接用push a 或pop a ,而要写成push acc

和pop acc,这里就涉及了acc与a的区别。虽然acc与a都是代表累加器a,但实际又有区别

*********************************************

如下:

INC A 是寄存器寻址
  INC A 是单字节指令,转换成机器码是:04H,机器码中没有明确指出操作数,隐含操作
  数是累加器A,所以把这种方式寻址叫寄存器寻址。
INC ACC是直接寻址
  INC ACC 是双字节指令,转换成机器码是:05H,E0H。机器码中包含了累加器A的地址E0H
  这个 E0H 可以换成其他直接地址,所以这种方式寻址叫直接寻址。
PUSH 和 POP 指令只支持直接寻址,所以不能用 A
  PUSH ACC 机器码:C0H E0H
  POP  ACC 机器码:D0H E0H
 
*******************************
所以push和pop指令都要用acc。还有在中断中调用push和pop要成对出现,而且在有不同出口的中断子程序中,应在出口前都要加上pop指令,否则在实际中整个程序反而因为“保护现场”而出错。
 
   我这个数字电子时钟还需要按键处理来调节时间,所以我分别对“时,分,秒”都设置了两个按键来处理,一个是 1分钟(秒,时)1分钟(秒,时)地加,另一个按键是 10分钟(秒,时)10分钟(秒,时)地加。因为我显示子程序中设置了CJNE SECOND,#60,FANHUI 用于到60或24时就清零。但这个指令只能针对1+1+1+1这样的方式,如果从54分时,再按一下加10分钟,这时就会显示64分,明显错误,但CJNE 只能用于检测是否等于60,不能判定大小 。这时我才发现汇编的指令中没有比较大小的指令。在网上发贴咨询后终于找到了方法。
*******************************
     51单片机中有一个cy寄存器,当使用cjne指令时,如:cjne a,#60,leb 如果累加器中a小于或等于60时,cy寄存器中的值就会变为 cy=1 ,如果是等于60就执行下一个指令,如果是小于就跳到leb中执行。
当a中的数值大于60时,cy就会变为cy=0。并跳到标号leb中执行。所以就可以通过检测cy中的数值来判定a中的数据是大于60还是小于60了。从而实现数的大小比较。
 
 
***************************
       数的大小比较告一段落,于是我开始修改程序,添加限制数不能超过60的指令,每个按键者添加上比较指令后,出现跳转超出范围的编译错误如sjmp跳转超出范围,jnb跳转超出范围。就是这个问题,目前的我还没
方法处理,搞不懂jnb之类的指令跳转范围。但我换了一个方式,把比较指令从检测按键中整合到了输出前检测中,完善了这个时钟程序。(花了我几个小时去完善)。
     还有一个收获:
汇编节约空间方法:
 
        在完善程序的过程中我发现了一个节约空间的方法,就是把数据相同的数先用mov ri,#xx
然后什么时候需要就把用 mov xx,ri ,即用寄存器中的数代替实际的数字,这样每条就能省下一个字节的空间哦。
 
 
 附件:(数字电子时钟程序)
 
  SECOND EQU 20H ;***************内存地址命名 **************** MINUTE EQU 21H ;***************内存地址命名 **************** HOUR EQU 22H ;***************内存地址命名 **************** ORG 0000H SJMP START ORG 000BH SJMP COUNT ;***************中断子程序存放地址 **************** ORG 0030H ;***************数据初始化**************** START: MOV SP,#060H ;***************指针初始化 **************** MOV P0,#0FFH ;***************高电平,熄灭 **************** MOV P2,#0FFH ;***************高电平,熄灭 **************** MOV P1,#0FFH ;***************高电平,熄灭 **************** MOV R0,#00H ;*************** r0置零 **************** MOV R3,#00H ;*************** r3置零,用于其它变量清零 **************** MOV R5,#10 ;*************** r5置10,用于按键累加及b的赋值 **************** MOV DPTR,#TAB ;*************** 查表指针初始化 **************** MOV TH0,#03CH ;*************** 计时高8位 **************** MOV TL0,#0B0H ;******计时低8位 ,与高8位联合,赋计时器初始值**************** MOV TMOD,#00000001B ;*************** 计时器模式1 **************** MOV IE,#10000010B ;*************** 中断允许 **************** SETB TR0 ;*************** 计时器开始计时 **************** ;***************无限循环的主程序**************** MAIN: CALL DISPLAY CALL KEY SJMP MAIN ;***************中断触发的计时处理程序**************** COUNT: PUSH ACC ;***************入栈,保护累加器**************** INC R0 ;***************一个50ms结束,计数器r0加1 **************** MOV TH0,#03CH ;***************计时器重置**************** MOV TL0,#0B0H ;***************计时器重置**************** CJNE R0,#20,FANHUI ;*************** r0不等于20(不足1秒),跳转继续计时**************** MOV R0,#0H ;*************** 1秒时间到,r0重置**************** INC SECOND ;*************** 1秒时间到,秒位加1 **************** MOV A,SECOND ;***************秒位数据转移至累加器**************** CJNE A,#60,FANHUI ;***************判定秒位是否等于60,不等不处理,返回**************** MOV SECOND,R3 ;***************等于60,秒位清零**************** INC MINUTE ;***************等于60秒,分位加1 **************** MOV A,MINUTE ;***************分位数据转移**************** CJNE A,#60,FANHUI ;***************判定分位是否等于60,不等不处理,返回***** INC HOUR ;***************等于60,分位清零**************** MOV MINUTE,R3 ;***************等于60分,时位加1 **************** MOV A,HOUR ;***************时位数据转移**************** CJNE A,#24,FANHUI ;***************判定是否等于24,不是不处理,返回 **************** MOV HOUR,R3 ;***************等于24时,时位清零 **************** FANHUI: POP ACC ;***************出栈,还原累加器数据**************** RETI ;***************中断子程序返回出口**************** ;***************显示子程序**************** DISPLAY: ;***************秒位输出**************** SECONDDIS: MOV A,SECOND ;***************数据转移,为了比较**************** MOV B,R5 ;*******************小于60,继续执行*********** DIV AB ;***************数字分隔(除法)处理**************** MOVC A,@A+DPTR ;***************十位查表**************** MOV P0,A ;***************十位数据输出**************** CLR P1.6 ;***************控制总线控制p1.6数码管亮**************** CALL DELAY ;***************点亮延时**************** SETB P1.6 ;***************熄灭**************** MOV A,B ;***************个位数据转移**************** MOVC A,@A+DPTR ;***************查表**************** MOV P0,A ;***************个位数据输出**************** CLR P1.7 ;***************控制总线控制p1.7数码管亮**************** CALL DELAY ;***************点亮延时**************** SETB P1.7 ;***************熄灭**************** ;***************分位输出**************** MINUTEDIS: MOV A,MINUTE MOV B,R5 DIV AB MOVC A,@A+DPTR MOV P0,A CLR P1.3 CALL DELAY SETB P1.3 MOV A,B MOVC A,@A+DPTR MOV P0,A CLR P1.4 CALL DELAY SETB P1.4 ;***************时位输出**************** HOURDIS: MOV A,HOUR MOV B,R5 DIV AB MOVC A,@A+DPTR MOV P0,A CLR P1.0 CALL DELAY SETB P1.0 MOV A,B MOVC A,@A+DPTR MOV P0,A CLR P1.1 CALL DELAY SETB P1.1 ;*************** 输出分隔符 **************** MOV P0,#040H CLR P1.2 CALL DELAY SETB P1.2 MOV P0,#040H CLR P1.5 CALL DELAY SETB P1.5 ;******************************************************************************** RET ;***************输出子程序返回出口**************** ;***************************************************************************************** ;***************按键检测子程序**************** KEY: JNB P2.0,SECONDGW ;***************若p2.0按键被按下则跳至k1(去抖动处理)**************** JNB P2.1,SECONDSW ;***************p2.1键,处理同上**************** JNB P2.2,MINUTEGW ;***************处理同上**************** JNB P2.3,MINUTESW ;***************处理同上**************** JNB P2.4,HOURGW ;***************处理同上**************** JNB P2.5,HOURSW ;***************处理同上**************** HUI: MOV A,SECOND ;**按键处理后,返回前检测溢出,秒位数据转移**************** CJNE A,#60,SECONDBD ;***************秒数据与60相比,不等跳转**************** SECONDWB: MOV A,MINUTE CJNE A,#60,MINUTEBD MINUTEWB: MOV A,HOUR CJNE A,#24,HOURBD HOURWB: RET ;*若都没按下,则返回主程序(同时为去抖动处理,溢出检测处理出口)**************** ;********************溢出处理程序********************** SECONDBD: JC SECONDWB ;判断cy是0还是1,以判断秒是大于60还是小于60,小于跳回检测分**************** MOV SECOND,R3 ;***************大于60,秒位置零 **************** SJMP SECONDWB ;***************秒位处理结束,检测分位 **************** MINUTEBD: JC MINUTEWB MOV MINUTE,R3 SJMP MINUTEWB HOURBD: JC HOURWB MOV HOUR,R3 SJMP HOURWB ;************************************************* ;***************去抖动按键1**************** SECONDGW: CALL DELAY2 ;***************延时**************** JB P2.0,HUI ;***************延时后p2.0没按下,则为干扰,返回主程序**************** WAIT: CALL DISPLAY ;***************接下等待按键释放,同时输出原数字,防止数码管熄灭**************** JNB P2.0,WAIT ;***************等待按键释放**************** INC SECOND ;***************按键已释放,秒加1 **************** SJMP HUI ;***************处理完毕,返回主程序**************** ;***************去抖动按键2**************** SECONDSW: CALL DELAY2 ;***************延时**************** JB P2.1,HUI ;***************延时后p2.1没按下,则为干扰,返回主程序************* WAIT2: CALL DISPLAY ;***************接下等待按键释放,同时输出原数字,防止数码管熄灭*** JNB P2.1,WAIT2 ;***************等待按键释放**************** MOV A,SECOND ;***************把秒的数据转移至累加器**************** ADD A,R5 ;***************累加器加10 **************** MOV SECOND,A ;*************** 累加器结果返回秒 **************** SJMP HUI ;***************处理完毕,返回主程序**************** ;***************去抖动按键3,同k1 **************** MINUTEGW: CALL DELAY2 JB P2.2,HUI WAIT3: CALL DISPLAY JNB P2.2,WAIT3 INC MINUTE SJMP HUI ;***************去抖动按4,同k2**************** MINUTESW: CALL DELAY2 JB P2.3,HUI WAIT4: CALL DISPLAY JNB P2.3,WAIT4 MOV A,MINUTE ADD A,R5 MOV MINUTE,A SJMP HUI ;***************去抖动按键5,同k1**************** HOURGW: CALL DELAY2 JB P2.4,HUI WAIT5: CALL DISPLAY JNB P2.4,WAIT5 INC HOUR AJMP HUI ;***************去抖动按键6,同k2**************** HOURSW: CALL DELAY2 JB P2.5,HUI WAIT6: CALL DISPLAY JNB P2.5,WAIT6 MOV A,HOUR ADD A,R5 MOV HOUR,A AJMP HUI ;***********用于数码管显示和熄灭的延时***************** DELAY: MOV R1,#5 D1: MOV R2,#250 D2: DJNZ R2,D2 DJNZ R1,D1 RET ;********用于去抖动的延时**************** DELAY2: MOV R1,#50 D11: MOV R2,#100 D22: DJNZ R2,D22 DJNZ R1,D11 RET ;*****************共阴极数码表**************** TAB: DB 03FH,006H,05BH,04FH,066H ;0,1,2,3,4 DB 06DH,07DH,007H,07FH,06FH ;5,6,7,8,9 END    

你可能感兴趣的:(单片机)