单片机最重要的功能是按照指定的时间定时完成给定的任务。用C51语言编写51单片机定时程序,必须采用硬件定时器来实现。 本文用每秒钟1次进行LED闪3下光的例子来介绍如何形成一套规范的单片机硬件定时方法和各种方法的利弊。该例子的视频如下:
本文将分4个部分分别介绍用软件延时来进行定时控制存在的问题、定时器中断服务程序ISR信号、在中断中执行任务A产生的中断阻塞问题和前后台任务间信号量通讯同步方法。 一、用软件延时来进行定时控制存在的问题 (1)上一篇文章:《C51语言中的微秒、毫秒软件延迟函数探讨》 https://www.stcaimcu.com/forum.php?mod=viewthread&tid=11218 (出处: 国芯技术交流网站) 介绍了用软件实现准确延时的方法,理论上说也可以用这种方法来进行定时控制。 下图是LED闪3下光的任务函数A的程序: 其中Test_LED5、Test_LED6和Test_LED7对应左面的3个LED灯,低电平发光。整个过程需要750毫秒。
(2)在主函数中用软件延时的方法进行定时控制的程序如下: 其中第59行程序是一个补充延时,希望用它来保证每个主循环的周期是1000毫秒。 (3)软件延时函数只有在没有中断的情况下才会准确(下一篇文章将专门讨论这个问题),因此如果没有中断,上面的第59行程序延时250毫秒就可以每个主循环的周期是1000毫秒。 本文要探讨的问题是如果我们不知道中断对任务A中的软件延时函数的影响是如何的情况下(也就是在不知道任务A的精确执行时间的情况下),如何保证整个主循环的周期为1000毫秒。 二、定时器中断服务程序ISR信号 (4)首先先引入2个定时器中断,定时器11作为系统节拍定时器,经过100倍分频后每秒钟产生一次中断,定时器0作为参考中断信号,每1毫秒产生一次中断。 下面是主函数和这2个定时器中断的ISR: 其中定时器0的每次中断翻转LED0电平,定时器11的每次中断翻转LED1电平。 下图是这两个中断的逻辑分析仪信号图: 其中通道1的定时器11信号很明显,而通道0的定时器0信号由于时间标度关系,高频率的信号连成了一片。
三、在中断中执行任务A产生的中断阻塞问题 (5)硬件定时器是靠单片机时钟驱动的,其产生的周期性中断的准确性是亚微秒级的,因此如果把主循环里面的执行任务A的程序放到1秒周期的定时器11中断服务程序ISR中,执行任务A的周期精度也就可以准确到微秒量级了。 下图是在中断中执行任务A方法的程序: 对比前面程序,同步信号和执行任务A的程序都移到中断ISR的第77到第86行了。逻辑分析仪的第1通道正脉冲代表这一过程。 (6)下图是该程序运行时的逻辑分析仪信号截屏: 图中第1通道的周期为997.778毫秒,其中正脉冲为751.98毫秒是定时器11的中断时间。 图中通道2是同步信号,通道3的正脉冲是任务A的执行时间,通道5、6、7是LED灯信号,低电平发光。 (7)从上面图中通道0定时器0的中断信号可以看到在通道1定时器11的中断期间,是停止的。这种在一个中断期间(从中断开始到“RETI”指令为止的期间)阻止了其他中断的现象称为“中断阻塞”。 一个中断发生期间时会阻塞其他优先级小于或等于它的优先级的中断发生。 (8)结论1:由于单片机定时器产生的周期中断具有很高的时间精确性,因此对于时间要求性较高的需求,不能采用软件延时的方法,必须使用硬件定时器。 (9)结论2:由于存在中断阻塞现象,为了不影响其他中断的正常运行,花费时间长的任务不应该放在中断中执行。比如本节例子,定时器11就在75%的时间里阻塞了定时器0的中断。
四、前后台任务间信号量通讯同步方法 (9)本文要探讨的问题是如何保证整个主循环的周期为1000毫秒。 因此不必要将整个主循环的任务都放在每1000毫秒1次的定时器11中断ISR里,只需要像体育比赛开始放信号枪一样,定时器11每1000毫秒发一个信号给“main()”函数里的程序,程序收到信号后再开始执行一次主循环任务A程序,然后原地踏步,等待下一次信号的到来,这种方法就称为“前后台任务信号量通讯方法”。
(10)下面是信号量方法程序的前半部分: 1)第31行定义一个全局变量“Task_A_Ready”作为信号量,定义在DATA存储空间是为了变量存取速度更快。 2)第57行程序将信号量置0。本信号量只有两个状态,等于0表示主循环开始的时机不到,等于1表示主循环开始的时机已经到了。 3)主函数第63行到第68行是让程序在主循环开始的地方等待信号量变绿,一旦收到信号(信号量不等于0),程序就从第71行往下执行。 4)本范例通道1用来显示信号量的状态,第71行和第72行程序在主循环开始时清0,为下一轮执行做好准备。
(11)下面是信号量方法程序的后半部分: 1)其中第74行到第83行是执行任务A的程序。对比前面软件延时程序,第86行程序直接转到主循环开始,等待下一轮开始,采用信号量方法就不再需要用软件延时来控制时间了。 2)定时器11的ISR总共只有第102和103两行程序,在每1000毫秒的开始设置信号量为主循环开始信号,等退出中断后,主循环程序检测到后就可以开始新一轮执行了。
(12)下面是信号量方法的时序图: 从图中可以看到通道1(定时器11)的执行很短,再也不会对通道0定时器0中断产生阻塞了。
(13)下面是将时序图放大来观测通道1的信号图: 其中通道1的正脉冲宽度代表了在中断(前台任务)中从信号量被置1到主函数(后台任务)响应时间为0.25us。 值得一提的这个0.25us时间就是操作系统理论中前后台多任务的“实时响应时间”,它远小于本论坛里所有的RTOS的实时响应时间,见《单片机RTOS实时响应时间排行榜重大宣布:STC32G12K128单片机 全面碾压 STM32F103C》 https://www.stcaimcu.com/forum.php?mod=viewthread&tid=7724
(出处: 国芯技术交流网站)
附件:0200_硬件定时方法.rar
(315 KB, 下载次数: 31)
|