DotC 2016 今天与大家共同探讨一下如何对MCU进行喂狗。一孔之言,不一定正确。希望大家踊跃拍砖,共同探讨,相互提高。O(∩_∩)O~
想必刚接触电子行业的一些人,都会对MCU需不要需要看门狗;为什么要喂狗;看门狗有没有用;用内部看门狗好还是外部看门狗好,如何对MUC进行喂狗……等诸多问题有疑惑。即便工作好多年的工程师对其一些问题的处理方式也不尽相同。今天在这里我们先不 讨论前面的问题了,主要对其如何喂狗进行探讨。
在探讨之前我还是先说下自己的观点吧——为了保证产品的稳定性(尤其工业级以上的产品),尽量在系统中增加看门狗功能,最好还是独立看门狗(个人感觉一般外置独立看门的抗干扰能力要大于一般MCU,当然你非要选个国产的外置看门狗做对比,我也没有办法),喂狗尽量在主循环函数中进行喂狗,如果为了写代码方便最好的是在中断中增加二次喂狗,不过要处理好中断喂狗与主循环喂狗的关系。
我们总是期望程序能够按照自己的意愿去执行。但是往往程序中会有BUG存在。比如内存溢出,数组越界,死循环没有出来、外部干扰、芯片内部碎坏……诸多因素往往导致程序没有按照自己想的顺序执行,当出现偏差的情况下就有可能导致产品不工作,尤其是产品死机。产品死机问题在工业产品以上显得更为棘手。与功能、性能、体验效果来讲,产品的稳定性排在第一位绝对是没有异议的。不同于消费类产品,有时候我们还可以通过断电,重新上电进行产品复位,你会发现产品又可以工作了,这些有时候我们都可以勉强接受。我就记得我以前的一部手机死机后扣电池就可以解决问题,O(∩_∩)O~。当然我也碰到过不能扣电池的手机死机的情况。可是对于大部分工业产品这点肯定行不通,谁一天24小时整天看着它啊。所以稳定是绝对在最前面的。哪怕你设备真死机了,你能够自动重启有时候也是可行的。当然了做到设备永远不死机是最好的了,不过这个还真有点难度,呵呵,反正我是做不到啦。
那么好了,为了保证我们的产品不死机,为此我们就需要对产品的代码仔细斟酌,产品各种因素的去做测试。这个时候为了保证更好的效果我们增加看门狗功能。因为不光你代码的BUG问题,MCU也有可能因为内部的因素、比如高温、内部门电路碎坏;外部的因素比如干扰因素而死机、或者跑非程序。虽然现在很多MCU都有内部的看门狗了,什么看门狗的时钟都是内部的RC震荡时钟,最有效的避免因为外部晶振的问题导致整个系统都有问题。但是作为工程师希望你根据产品的功能、使用环境、用户体验性、产品的成本等因素好好斟酌你是需要外部的看门狗还是内置的看门狗。这个的确不好说。不差钱的,还是工业级别以上的产品你最好还是加上一个外置的看门狗。
一般看门狗都是连接着MCU的复位管脚,同时又一个喂狗管脚。当然有些看门狗可能还是IIC总线或者SPI总线的,总之有办法喂狗就可以了。当我们在系统中增加看门的时候,期望是在产品不可控的情况下MCU能够复位,在正常的情况下,在看门狗没有溢出之前我们还必须对其喂狗,否则看门狗芯片也会对MCU进行复位,这也是我们不期望的。
不管我们的程序是用的操作系统一个一个的任务也好,还是自己写的一个主MAIN()函数。在这里我们都把把它看成程序的主体执行部分。一般我们都是在初始化板子后进入主循环函数或者把任务交给操作系统。一般这些程序的执行都是按部就班的执行的,所有把喂狗操作放进主循环里面基本上一般就很有效了。
当然这个时候领我们比较头疼的是有可能整个程序有太多的任务需要处理,甚至还是自己写的延时函数,工程师一般把控不全到底哪个增添个喂狗处理比较好。有些索性就是写一段代码就加上,有一段代码就加上。你会看到整个程序中你搜索一下喂狗处理,搜出来一大片。呵呵。不过有些工程师感觉放到中断里面多好啊。没200ms、1S的中断我就喂狗一次。甚是简单啊!可是如果你真是要这么处理的话,一般产品在外部干扰的情况下一般是不会复位的。因为对于所有的MCU来讲。中断都是硬件级别的处理,它会强制把程序指针指引到发声中断的地方,是不受你程序控制的。所以说哪怕你程序死在了一个while(1)循环里面,中断该执行还是执行。那么这个时候我们要是再中断函数里面加了喂狗处理,也需要在主循环里面也增加喂狗处理。但是这个中断函数里面的喂狗的目的并不是简单的去喂狗,它还有第二个目的——件事主循环里面的喂狗到底执行没有执行。否则你和一个中断函数喂狗根本没有区别嘛。
那么好了,既然为了更好地写代码,我们增加了两处喂狗的地方,也知道了其各自的目的。主循环喂狗,保证程序按照自己的主循环意愿一直走下去;中断喂狗,一是保证对看门狗喂狗,二是监视主循环喂狗情况。所以在中断函数里面我们就需要对主循环里面的喂狗进行判断。一般我是这么处理的。在主循环里面喂狗后进行喂狗次数( 整形)Watchdog_number ++,中断函数里面根据主循环一次执行的大体时间做一个时间判断 比如500ms1S 2S等。可以根据自己的情况去设定。如果时间到——判断当前的喂狗次数与上一次的喂狗次数Old_Watchdog_number是不是不相等,不相等则说明主循环执行喂狗处理了。如果没有则有可能发生了死机情况。另外需要注意的是不能设置中断的判断时间太短也不能太长。原因是防止Watchdog_number刷新的太快导致溢出后又回到了原来的位置。比如现在Watchdog_number是100。主循环跑的太快太快2S后又变成100了,所以这里Watchdog_number设置为整形。代码实在word里面写的有点乱大家将就看吧O(∩_∩)O~。没看懂的帖子里面交流吧。该做饭了。O(∩_∩)O哈哈~
void main()
{
……
……
Watchdog _task();
……
……
}
Watchdog _task()
{
……看门狗喂狗语句;
Watchdog_number++;
}
interrupt handler _task(
{
static uint Old_Watchdog_number=0;
Old_Watchdog_number= Watchdog_number;
…………
if(2S==OK)
{
if(Watchdog_number!= uint Old_Watchdog_number)
_NOP_();
else……主循环在设定的2S 时间之内没有执行 执行看门狗复位处理——想办法软件MCU复位。
} Watchdog _task();
…………
}
本帖最后由 点创@布丁 于 2016-12-20 18:08 编辑
谢谢浏览帖子的坛友们 O(∩_∩)O~
坛友们实在抱歉:
当时用word写的代码 时间紧没考虑周到 有点错误 这里用C++更正一下(直接上图片了 方便看)