历史上的今天
今天是:2024年11月07日(星期四)
2019年11月07日 | STM8S——watchdog(IWDG)
2019-11-07 来源:eefocus
IWDG工作原理:
1、当键值寄存器(IWDG_KR)中写入数值0xCC后,独立看门狗就会被启动,计数器开始从它的复位值0xFF开始递减计数,当计数减到0x00时就会产生一个复位信号。
2、使用IWDG_PR和IWDG_RLR寄存器配独立看门狗。
(1)IWDG_PR寄存器是用于选择驱动计数器时钟的预分频系数。
(2)当KEY_REFRESH的数值(0xAA)写入到IWDG_KR寄存器时,独立看门狗将用IWDG_RLR的数值刷新计数器的内容,从而避免了产生看门狗的复位。
3、IWDG_PR和IWDG_RLR寄存器具有写保护功能,要修改它们前,需首先在IWDG_KR寄存器写入KEY_ACCESS代码(0x55);在IWDG_KR写入0xAA将恢复写保护状态。
IWDG工作细节:
1、为了避免程序忙跑跑死了没反应,加上一个看门狗watchdog实时监控着程序,一旦程序没有在规定的时间喂狗,则狗叫使得单片机复位。
2、Independent watchdog(IWDG)内部有时钟源(128kHz),所以即使主时钟挂了watchdog还是能继续工作的。
另外还有个Window watchdog (WWDG),比IWDG复杂得多,我们没有采用。

3、由于内部是128kHz,所以watchdog能允许的最大延迟时间为510ms(当RL[7:0]= 0xFF时),最小延迟时间为2ms(当RL[7:0]= 0x00时);我们选取510ms。

也就是说一旦打开看门狗,最迟每隔510ms就要进行喂狗操作,否则看门狗将会打开复位。
4、看门狗的实现不难,难点在于怎样验证自己设置的看门狗是否正确,难点在与想办法测试watchdog。
方法是在while(1)的循环里延时510ms以上(如延时600ms),通过对相关寄存器特征值的显示查看,来判断单片机是否被复位,若被复位则验证成功。
5、值得注意的是,开门狗一旦打开就无法关闭,只有通过不断的喂狗来防止复位。
6、下面给出代码思路并且附带详细注释:
由于延时函数如果延时太久会无法实现喂狗操作,所以应该在原来的Delay1ms()函数的基础上,再另外定义一个newDelay()函数,目的是每次延时250ms时(即调用Delay1ms(250))喂狗;
1 /*-- private variable --*/
2 __IO uint32_t space_reloadTM = 250;//define every after 250 ms reload IWDG
3
4 /*-- private function --*/
5 void NewDelay(__IO uint32_t nTime);//include reload IWDG
6
7 static void IWDG_Config_Enable(void);//config and enable IWDG
8
9
10 /*-- main function --*/
11 int main()
12 {
13 IWDG_Config_Enable(); //config and enable IWDG
14
15 //for test
16 while (1)
17 {
18 Delay1ms(600); //timeout and reset happend
19
20 /*-- never runs here --*/
21
22 //Reload IWDG counter
23 IWDG_ReloadCounter();
24 }
25 }
26
27
28
29 void NewDelay(__IO uint32_t nTime)
30 {
31 uint32_t time_divisor = nTime/space_reloadTM;
32 uint32_t time_remainder = nTime%space_reloadTM;
33 uint8_t i;
34
35 /* every after 250ms reload IWDG */
36 for(i=0;i 38 Delay1ms(space_reloadTM); 39 //Reload IWDG counter 40 IWDG_ReloadCounter(); 41 } 42 43 /* delay the remain time */ 44 Delay1ms(time_remainder); 45 //Reload IWDG counter 46 IWDG_ReloadCounter(); 47 } 48 /* 49 void Delay1ms(__IO uint32_t nTime) 50 { 51 TimingDelay = nTime; 52 53 while (TimingDelay != 0); 54 } 55 */ 56 57 58 59 /** 60 * @brief Configures the IWDG to generate a Reset if it is not refreshed at the 61 * correct time. 62 * @param None 63 * @retval None 64 */ 65 static void IWDG_Config_Enable(void) 66 { 67 /* Check if the system has resumed from IWDG reset */ 68 if (RST_GetFlagStatus(RST_FLAG_IWDGF) != RESET) 69 { 70 printf("nr"); 71 uart2str(uartbuff,RST->SR,8,2,'0'); //output RST register 72 printf("Timeout, RST_SR=%snr",uartbuff); 73 74 printf("timeout!!!"); 75 76 /* IWDGF flag set */ 77 /* Clear IWDGF Flag */ 78 RST_ClearFlag(RST_FLAG_IWDGF); 79 } 80 else 81 { 82 //IWDGF flag is not set 83 } 84 85 86 /* --- IWDG Configuration --- */ 87 88 /* Enable IWDG (the LSI oscillator will be enabled by hardware) */ 89 IWDG_Enable(); //0xCC 90 91 /* IWDG timeout equal to 250 ms (the timeout may varies due to LSI frequency 92 dispersion) */ 93 /* Enable write access to IWDG_PR and IWDG_RLR registers */ 94 IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //0x55 95 96 /* IWDG counter clock: LSI/128 */ 97 IWDG_SetPrescaler(IWDG_Prescaler_128); 98 99 /* Set counter reload value to obtain 250ms IWDG Timeout. 100 Counter Reload Value = 250ms/IWDG counter clock period 101 = 250ms / (LSI/128) 102 = 0.25s / (LsiFreq/128) 103 = LsiFreq/(128 * 4) 104 = LsiFreq/512 105 */ 106 IWDG_SetReload((uint8_t)(0xFF));//510ms 107 108 /* Reload IWDG counter */ 109 IWDG_ReloadCounter(); //0xAA 110 } watchdog 为了验证代码的可实现性,故意在主函数中调用Delay1ms(600),所以正确的执行结果应该是:执行Delay1ms(600),watchdog启动复位,输出timeout之类的提示; 其中证明是否是watchdog启动的复位:查看RST->SR(Reset status register)中Bit1的值,为1表示An IWDG reset occurred,为0表示No IWDG reset occurred。
史海拾趣
|
PIC烧写调试器ICD2,18F4550+16F877A+USB取电,配进口USB线, 淘宝地址http://auction1.taobao.com/auction/item_detail-0db2-f856961a8480fb64ad9297cf42c260f3.jhtml… 查看全部问答> |
|
您正在尝试访问一个早期版本的 SQL Server Compact Edition 数据库。如果是 SQL Server CE 1.0 或 2.0 数据库…… 我用vs2005,c#编写了一个简单的数据库操作程序,代码如下: string strconn = @\"Data Source=\\Northwindoledb.sdf\"; SqlCeConnec ...… 查看全部问答> |
|
本人做了个上电自检的程序,是基于vxworks6.5的, 我把自检函数直接添加在usrconfig.c文件中,usrRoot()函数里,bootrom启动过程中完成了上电自检, 且检测所有硬件(主要是内存和flash)都正常,可是生成操作系统以后(用workbench生成的操作系 ...… 查看全部问答> |
|
楼主: 你好! 买了一个STR912的开发板,发现912的性能还不错,听说又有一个加强版的要出来了,很想把UCOS移上去,请发一个移植模板.谢谢!… 查看全部问答> |
|
u8 buf1[100]; //都初始化0 u8 buf2[100]; //都初始化0 u16 rev; //中断接收计数 串口发送方式: DMA 串口接收方式: 中断 DMA_InitStructure.DMA_PeripheralBaseAddr = USART1_DR_Base; DMA_InitStructure.DMA_MemoryBaseAdd ...… 查看全部问答> |
|
我想给P3.1定义为data,然后编程时写data=1;P3.1就输出1,我该如何定义? 我写了 #define P3.1 data 不好使啊???… 查看全部问答> |




