亚信安全科创板IPO真的安全吗?
06-17
1.使用定时器来实现灯光的闪烁。
当我们学习微控制器时,我们的第一个例子是灯光的闪烁。
这是通过延迟程序完成的。
现在回想起来,这并不是很实用。
合适,为什么?我们的主程序就闪灯了,不能再做其他事情了。
这是微控制器工作的唯一方式吗?当然不是,我们可以使用定时器来实现灯的闪烁功能。
? / 计数器 0 工作模式为 1 MOV TH0, #15H MOV TL0, #0A0H;计数 SETB TR0;定时器/计数器0开始运行 LOOP:JBC TF0,NEXT;如果 TF0 等于 1,则清除 TF0 并转到 NEXT AJMP LOOP;否则跳到LOOP并运行 NEXT:CPL P1.0 MOV TH0,#15H MOV TL0,#9FH;重复设置定时器/计数器的初始值 AJMP LOOP END AJMP LOOP END 输入程序,你看到什么?灯在闪烁。
这是通过定时器完成的,不再是主程序的循环。
简单分析一下程序,为什么要用JBC? TF0 是定时器/计数器 0 的溢出标志位。
当定时器溢出时,该位由 0 变为 1,因此通过查询该位可以知道时间是否已到。
该位设置为 1 后,必须用软件将该标志位清零,以便在下一个定时器到期时该位由 0 变为 1。
因此,使用JBC指令。
当判断该位转为1时,该位??也会转为1。
清除为0。
上面的程序可以实现灯的闪烁,但是主程序除了闪烁之外仍然不能做其他事情。
光!不,这是不对的,我们可以在LOOP:...和AJMP LOOP指令之间插入一些指令来做其他事情,只要这些指令的执行时间小于预定的时间即可。
那么我们在使用软件延时程序的时候,是不是也可以使用一些指令来代替DJNZ呢?是的,但是这需要你精确计算所使用的指令的时间,然后减去相应的DJNZ周期数,这是非常不方便的。
现在只要求所用指令的时间小于计时时间,显然偏低了。
当然这种方法还是不好,所以我们经常使用下面的方法来实现。
程序2:使用中断实现 ORG H AJMP START ORG BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到实时程序 ORG 30H START: MOV P1,#0FFH ;关灯 MOV TMOD,#B ;定时器/计数器0工作在模式1 MOV TH0,#15H MOV TL0,#0A0H ;即 SETB EA ;打开总中断使能 SETB ET0 ;打开定时器/计数器0使能 SETB TR0 ;定时/计数器0开始运行 LOOP: AJMP LOOP ;真正工作时,可以在这里编写任何程序 TIME0: ;定时器0的中断处理程序 PUSH ACC PUSH PSW ;推送PSW和ACC堆栈保护 CPL P1.0 MOV TH0,#15H MOV TL0,#0A0H ;复位定时常数 POP PSW POP ACC RETI END 在上面的例子,一旦定时时间到了,TF0由0变为1,就会触发中断。
CPU会自动去B地址寻找程序并执行。
由于留给定时器中断的空间只剩下8个字节,显然是不够写所有的中断处理程序的,所以在B处安排了一条跳转指令,去到真正处理中断的程序中。
这样,中断程序就可以写在任何地方、任意长度。
进入定时中断后,首先要保存当前的一些状态。
该程序仅演示保存 ACC 和 PSW。
实际工作中,应该根据需要将可能发生变化的单位的值压入堆栈进行保护(实际上本程序中不需要保存任何值,这只是为了演示)。
运行以上两个程序后,我们发现灯闪烁的速度非常快,根本无法区分。
我们只是在视觉上感觉到光线有点晃动。
为什么?我们可以计算出定时器中预设的数字是,所以每计数到0个脉冲,计时时间就到了。
这些 0 脉冲的时间是多少?我们的晶振是12M的,所以是0微秒,也就是60毫秒,所以速度很快。
如果我想实现1S定时该怎么办?在此晶振失效率下,最长计时为65毫秒!上面给出了一个例子。
ORG H AJMP START ORG BH ;定时器0的中断向量地址 AJMP TIME0 ;跳转到实时定时器程序 ORG 30H START: MOV P1, #0FFH;关闭所有灯 MOV 30H,#00H;预清除软件计数器至0 MOV TMOD,#B ;定时器/计数器 0 工作在模式 1 MOV TH0,#3CH MOV TL0,#0B0H ;即计数 6 SETB EA ;使能总中断使能 SETB ET0;打开定时器/计数器 0 并允许 SETB TR0 ;定时器/计数器 0 开始运行 LOOP: AJMP LOOP ;实际工作时,可以在这里编写任何程序 TIME0: ;定时器 0 中断处理程序 PUSH ACC PUSH PSW ;将 PSW 和 ACC 推入堆栈保护 INC 30H MOV A,30H CJNE A,#20,T_RET ;30H 单元的值是否已达到 20? ?设置时序常数 POP PSW POP ACC RETI END 先自己分析一下,看看它是如何实现的?这里用到了软件计数器的概念。
想法如下。
首先使用定时器/计数器0制作一个50毫秒的定时器。
定时器超时后,P10 并不立即反转,而是将软件计数器中的值加 1。
如果软件计数器达到 20,则将 P10 反转并清除软件计数器中的值。

否则直接返回。
这样,在将P10反转一次之前就变成了20个定时中断,因此计时时间延长到20 *50毫秒。
这个想法在工程中非常有用。
有时我们需要多个定时器,但51个定时器中只有2个,怎么办?其实只要这些计时时间有一定的公分母,我们就可以使用软件定时器来实现。
比如我想实现P10口连接的灯每次按下1S,P11口连接的灯按下2S每次闪烁。
,如何实现呢?顺便说一句,我们使用两个计数器。
当数到 20 时,它会将 P10 反转并将其清零,如上所示。
当另一个数到40时,它反转P11,然后将其清除为0。
这还不够吗?该部分程序如下: ORG H AJMP START ORG BH;定时器0的中断向量地址 AJMP TIME0;跳转到实时计时器程序 ORG 30H ? MOV TH0,#3CH MOV TL0,#0B0H ;即6 SETB EA ;开启总中断使能 SETB ET0 ;开启定时器/计数器0使能 SETB TR0 ;启动定时器/计数器0运行 LOOP: AJMP LOOP ;实际工作时,可以在这里编写任何程序 TIME0:;定时器0的中断处理程序 PUSH ACC PUSH PSW;将PSW和ACC推入堆栈保护 INC 30H INC 31H;两个计数器都加1 MOV A,30H CJNE A,#20,T_NEXT ;30H 单元的值是否达到 20? T_L1: CPL P1.0 ;到达,反转 P10 MOV 30H,#0 ;清除软件计数器 T_NEXT: MOV A,31H CJNE A,#40,T_RET ;31h 单元中的值是否已达到 40? T_L2: CPL P1.1 MOV 31H,#0;到达后,将 P11 取反,清零计数器,返回 T_RET: MOV TH0,#15H MOV TL0,#9FH ;重置定时常数 POP PSW POP ACC RETI END 可以用定时器的方法来实现前面提到的流水灯吗?试一试。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-17
06-18
06-08
06-17
06-18
最新文章
使用电子管有哪些注意事项?如何检查电子管之间是否短路?
博通支付1200万美元和解SEC财务欺诈指控
八名运营商高管确认加入虚拟运营商
内蒙古农牧区雷电灾害成因分析及防雷对策
北京联通将5G应用于世园会远程医疗急救
TD-SCDMA最后一轮冲刺测试启动,产业前景更加光明
专访阿里云总裁王健:云计算服务平台梦想成真
USB2.0控制器CY7C68013的接口设计与实现