单片机|分享两种单片机编程思想( 四 )


(2)置2ms 计时结束标志 , 这个是提供给时间处理程序用的 , 这是一个计时器的框架 , 下面的5ms计时完全相同 。
这程序还用了一个块的框架 , 比较方便的 , 不过跟今天的主题无关 , 以后郁闷的时候再上来写写这个 。 上面的程序就是中断服务程序里面的计时器 , 分别定时 2ms 5ms 500ms , 计时完毕溢出是flag_time 标志来记录的 , 程序通过读这个标志就可以知道定时的时间是否已经到了 。

下面看那个统一的时间服务子程序

上面用了按键20ms消抖的计时器作为例子 , 如果理解之后就可以发现 , 我们可以完全模仿那个计时器而在下面放很多很多的计时器 , 则每5ms 进来一下 , 每个计时器都同时在计数了 , 谁先计算完毕就先关掉自己 , 置相应的标志给其它程序调用 , 而对其它计时器完全没有影响!这样 , 我们可以在这里放很多个计时器了 , 一般来说 , 十来二十个是没有问题的 , 完全满足一个单片机系统对多个时间的需求了 。
单个计时器的结构很简单 , 先判断允许计时标志是否进入计时 , 然后一个专用的寄存器在加1或者减1 , 加/减相应的数值之后也就是相应的时间到了 , 关掉计时器 , 置相应需要用到的标志 。
到这里差不多了 , 俺们需要的时间都可以出来了 , 这样做是不是非常方便?咱们再来看看在这段时间里单片机在做了什么东西?只有中断计时够 5ms 或者 500ms, 那个溢出标志才有效 , 才能进入上面的计时程序 , 其它时间都是在做其它事情 。 而且进入上面的计时器的时候 , 可以看出 , 并不是在那里死循环 , 只是单纯的加减一下寄存器就退出了 , 整个过程耗时极其短 , 看代码不同吧 , 5us到 20us左右吧 , 对主程序的执行没有什么影响 。
下面看看具体怎么调用
最开始谈过的按键的消抖时间处理问题 , 现在就用上面介绍的办法来看具体怎么解决问题 。

大概是这样的:判断什么时候有健 , 没有的话跳出 , 有的话开始延时消抖的计时 , 第二次进来的时候直接由标志位控制过去判断时间时候够 。
同样是等待 , 这里就是最后一点所说的 , 咱这是跑着来等 , 不是站着来等 。 跟死循环定时比较 , 在没有定时到20ms 的这段时间里面单片机在做什么?死循环的话 , 肯定就是在原地等 , 什么都不做 , 而看看上面的程序 , 他只是判断是否定时够 , 具体的定时在统一的时间子程序里面做 , 判断没有到时间的话就跳出了 , 继续跑其它的程序 , 直到当时间到了 , 单片机判断出flag_delaykey_flow 符合条件 , 开始进入按键处理程序了 , 在这个期间 , 单片机都在做其它事情 , 只是一个主循环跑回来判断一次 , 所以单片机完全有空跑其它的程序 , 而没有将时间都耗在消抖上面 。
主程序循环体

这个就是用到的循环体了 , 所有功能都做成子程序形式了 , 需要就挂上去就可以了 , 比较方便 , 这样一个总的循环体 , 单片机就是在不断的执行这个循环体 , 如果整个程序都采用上面说的分时扫的思想的话 , 一周循环回来的时间是相当短的 , 其实是不是跟电脑的思想有点像呢?
电脑再快也并不是同时处理多个任务 , 而且每次处理一个 , 然后非常快的速度来循环处理 , 让我们感觉上他是在同时处理多个程序那样 , 我想 , 我最终想表达的思想也就是这个而已 。 这也是操作系统的一个功能 , 有这个思想支撑下 , 单片机的程序变得比较容易上手了 , 剩下的只是集中精力去用程序来实现我们的思想而已 , 当然 , 这里只是说一种可行的办法而已 , 不是说只有这种办法 。