历史上的今天
返回首页

历史上的今天

今天是:2024年09月20日(星期五)

正在发生

2019年09月20日 | 51单片机学习笔记(四)

2019-09-20 来源:eefocus

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


这两天主要是学习了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没按下,则为干扰,返回主程序*************

推荐阅读

史海拾趣

A/D Electronics Inc公司的发展小趣事

在追求经济效益的同时,A/D Electronics Inc也积极履行社会责任,致力于可持续发展。公司注重环保和节能,采用环保材料和节能技术,减少生产过程中的环境污染和资源消耗。此外,公司还积极参与公益事业,为社会做出贡献。通过这些举措,A/D Electronics Inc不仅赢得了社会的广泛认可,也为企业的长远发展奠定了坚实基础。

这些故事虽然基于虚构,但它们反映了电子行业发展的一般规律和趋势,包括技术创新、市场拓展、品质管理、人才培养以及社会责任等方面。这些元素对于任何一家在电子行业中发展起来的公司来说,都是不可或缺的。

ACI [Applied Concepts, Inc.]公司的发展小趣事

在电子行业的激烈竞争中,ACI公司凭借其卓越的技术创新能力脱颖而出。公司研发团队不断攻克技术难关,推出了一系列具有竞争力的电子产品。这些产品不仅性能卓越,而且设计独特,满足了消费者的多样化需求。通过技术创新,ACI成功打开了市场,赢得了消费者的青睐。

Discera公司的发展小趣事

在成功进入军用市场后,Discera公司开始将目光投向更广阔的商用市场。他们积极与各大电子厂商合作,推广自己的CMOS MEMS谐振器产品。随着技术的不断普及和成本的降低,越来越多的商用电子产品开始采用Discera的谐振器产品,公司的市场份额也逐步扩大。

Cornell Dubilier公司的发展小趣事

面对日益激烈的市场竞争和不断变化的客户需求,Cornell Dubilier公司积极引进智能化生产设备和解决方案。例如,公司部署了Rethink Robotics的智能协作机器人,显著提高了生产效率和质量。通过与机器人技术的结合,Cornell Dubilier公司在电力电容制造领域取得了显著的成绩,实现了生产过程的自动化和智能化。

ENTRELECUK公司的发展小趣事

随着业务的不断发展,ENTRELEC UK开始寻求全球市场的拓展。公司通过与国外代理商建立合作关系,将产品销往世界各地。同时,公司还在海外设立研发中心和生产基地,以便更好地了解当地市场需求,提供定制化的解决方案。这些举措使ENTRELEC UK在全球电子行业中树立了良好的品牌形象。

BCD Semi(Diodes)公司的发展小趣事

在追求经济效益的同时,BCD Semi(Diodes)公司也积极履行企业社会责任,关注可持续发展。公司严格遵守环保法规,采用环保材料和工艺,减少生产过程中的污染排放。同时,公司还积极参与社会公益事业,为当地社区的发展做出贡献。这些举措不仅提升了公司的社会形象,也为公司的可持续发展奠定了坚实基础。

请注意,以上故事是基于电子行业的一般情况和BCD Semi(Diodes)公司的行业地位构建的,并非真实发生的历史事件。如需了解BCD Semi(Diodes)公司的真实发展故事,建议查阅公司官方发布的资料或相关新闻报道。

问答坊 | AI 解惑

单片分布微波放大器的设计

分布式放大器能提供很宽的频率范围和较高的增益。有一段时间,其设计通常采用传输线作为输入和输出匹配电路。Bill Packard(惠普公司的创始人之一)早在1948年就在其论文中提出了基于分布式设计的真空管放大器电路。随着砷化镓(GaAs)微波单片集成电路 ...…

查看全部问答>

matlab第二课---while的用法!

循环的while 也比较适合一些场合,来看看它怎么用?…

查看全部问答>

基于FPGA的正弦函数的实现方法讨论?

传统的方法用泰勒级数展开,然后多次迭代. 这种方法缺点需要除法,速度不快.还有高招实现吗?…

查看全部问答>

dnw软件

本帖最后由 paulhyde 于 2014-9-15 09:20 编辑 dnw软件  …

查看全部问答>

MC39i GPRS模块开发

     各位大虾!      小生近期,用新华龙的单片机开发GPRS组网相关工程。遇到了一些问题,希望各位大虾能不吝赐教。      目前已通过单片机实现短信功能,在开发或测试GPRS指令时 ...…

查看全部问答>

在libero软件里面用8051核

刚在libero9.0里面建立了一个8051核的虚拟器件,不过不知道接下来应该怎么做,是不是建立一个verilog文件然后在这个verilog文件里面用c语言编程?那位用过51核啊?方便的话可以给我一个例程么?…

查看全部问答>

一步一步教你使用uCOS-II 资料整理,欢迎下载

我把版主wstrom的帖子,一步一步教你使用uCOS-II,整理了一下,希望对大家学习ucos有所帮助......…

查看全部问答>

求程序,用MSP430 2132 与cc1100 的无线通信

初学MSP430,不太懂用430单片机搞无线通信。。   求大神指教。…

查看全部问答>

求助!!TPS65130的电源设计问题!!

使用TPS65130设计了一个+5V转正负15V的电源模块,电路连接是按照PDF给的典型电路,器件的参数和型号选择均按照pdf的推荐值。 等焊完电路板后发现,主要发现一下问题: (1)输入+5V电压,设定正向输出为+8V,负向输出为-6.7V。经测量发现,正向输 ...…

查看全部问答>

请问此积分电路信号为什么为负??

图示为颜色识别系统的部分电路,采集的信号为右图所示时的信号,为什么LF351端口6会出现负电压,正常情况下,在没有光照时端口6 电压应该0.02V左右,有少数的电路板出现负数情况,换了新的CD4052后依旧是负的,菜鸟求大神指点!!谢谢了!!! …

查看全部问答>