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


2)驱动层程序编写
如果将 KeyDat想象成 P1 口 , 那么这个跟学习板那标准的扫描程序不就是一样了吗?对的 , 这个就是底层映射的目的了 。
3)应用层程序编写
根据消息 , 硬件层是必须分离出来 , 然而驱动层和应用层的要求就不那么严格了 , 事实上一些简单的项目没有必要将这两层分离开来 , 根据实际应用灵活应对就可以了 。
其实这样写程序是很方便移植的 , 根据板子的不同而适当的修改一下硬件层那个 ReadPort 函数就完成了 , 驱动层和应用层很多代码可以不经过修改直接用 , 很能提高开发效率的 。 当然这个按键程序会存在一定的问题 , 特别是遇到常闭按键和点触按键的混合使用的场合 。 这个留给大家自己去想了 , 反正问题总是能找到解决办法的 , 尽管方法有好有坏 。
时间片轮设计思想
先用一个小例子引出今天的主题 , 想象一下 , 一个基本的家电控制板 , 肯定或多或少的会包含 :LED 或者 数码管显示 , 按键 ,继电器或者可控硅的输出 这3部分 。 数码管需要 10ms到20ms的动态扫描 , 按键也需要20ms左右的延时消抖 , 有没有意识到 , 其实这些时间是同时在进行的 。
回想一下咱们的教科书怎么教 按键 的延时消抖的?没错 , 死循环 , 绝对是原地踏步死循环 , 用指令来计时 。 这样很自然的引发一个问题 , 单片机在原地踏步死循环的话 , 那么其它的工作怎么办?如数码管的动态扫描怎么办?
唯有等按键扫描之后再进行了 , 这样出来的效果 , 数码管肯定会闪烁的 , 扫描时间过长了 , 缩短按键消抖时间也不是解决办法 , 想象如果咱们还有其它很多工作也是同时做的呢?解决办法之一 , 就是今天的主题 , 分时扫描的思想 。 当然不会是唯一的办法 , 只不过俺一直在用 , 觉得这个是非常不错的思想 , 可以解决很多实际问题 。 大胆妄言一下 , 分时扫描的思想也是单片机编程最核心的思想了 , 信不信就由你自己判断了 。
核心思想的实现过程
第一、用RTC中断来计时 , RTC的中断时间短一点 , 我习惯是125us, 为了解红外遥控的码 , 这个时间是需要的 。 RTC计时是相当准的 , 尽量利用 。
第二、在RTC的中断服务程序里面放3个(数量自定)记时器(说白了就是计数器) , 我的习惯是 2ms 5ms 500ms 这3个是作为基准时间 , 提供给整个系统来调用的 , 所以必须准确一点 , 实际用示波器调一下就OK了 , 不难 。
第三、在主程序的循环里面放一个专门处理时间的子程序 。 (注:单片机是不会停的 , 永远在不断循环的跑 , 这个跟学校学的貌似有点不同 , 俺面试的时候被问过这个问题 ….)  将所有的时间处理都放在时间处理子程序里面做 , 这样是非常方便的 , 一个单片机系统最起码需要处理 10~20个不同的时间 , 也需要10~20个计时器了 , 而且相当多要求同时不同步工作的 , 如果每个都单独的话是相当的麻烦 。
第四、“程序是跑着来等 , 而不是站着来等” , 这话看来有点玄 , 一个跟俺一起进去公司的工程师讨论的时候提到的这个问题 , 俺觉得这个也是分时系统的一个比较重要的思想 , 所以也这样叫 , 下面有细说 。
第五、下面用程序来说话 , 注释尽量详细 , 可以不用看代码 , 直接看注释就可以了 。
先中断服务程序部分
每 125us 中断一次 , 产生几个基准时间 。


(1) ref_2ms寄存器不断的减1 , 每次中断减1 , 一共减 16次 , 所以这里经过的时间是 125us × 16 = 2ms , 这个就是所谓的计时/计数器 了 。 这样就可以靠一个系统的RTC中断 , 来实现我们需要的很多个定时时间 。