完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
|
|
相关推荐
1个回答
|
|
一,介绍
STM32看门狗分为独立看门狗和窗口看门狗两种,其两者使用调条件如下所示: IWDG和WWDG两者特点如下图所示: 独立看门狗的手册资料: 窗口看门狗的手册资料: 应当注意:在窗口看门狗中,当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位 【注】 图中的WDGTB为3表示2^3=8,表示8分频,最小时间910us也等于每次计数器减一所需要经过的时间:T(LSB),每隔910us减1。 最大值也等于,设置重载(喂狗)值127时(最大),一个复位周期的时间就是最大值58.25ms,也就是所能维持进入复位的最大时间。 由于窗口看门狗使用的APB1的PCLK1,时钟最高36MHZ,和RCC_APB2Periph_GPIOx不同,APB1最大就是36MHZ,APB2最大就是72MHZ。 所以串口看门狗需要配置APB1时钟使能,如下语句。 可以从图1-3 窗口看门狗编程说明看到T(WWDG)=T(PCLK1) x 4096 x 2^WDGTB x (T[5:0]+1) ; (ms) WDGTB[1:0]: 时基 (Timer base),也就是设置WDGTB 的值是1/2/4还是8,这在配置寄存器(WWDG_CFR)寄存器的位8:7 中设置, 其预分频器的时基可以设置如下: 00: CK计时器时钟(PCLK1除以4096)除以1 01: CK计时器时钟(PCLK1除以4096)除以2 10: CK计时器时钟(PCLK1除以4096)除以4 11: CK计时器时钟(PCLK1除以4096)除以8 也可以直接用这个函数 WWDG_SetPrescaler(WWDG_Prescaler_8); //8预分频,则WWDG时钟频率=(PCK1(36M)/4096)/8=1099Hz(910us) 也可以直接用这个函数 其次是设置窗口值,用来与递减计数器进行比较用的窗口值。通过如下函数即可 WWDG_SetWindowValue(80);//设置窗口值为80则WWDG的计数值必须在64~80之间才能喂狗(64是0x40,当再次减1就会T6清零,从而导致复位了,即刷新窗口设置成了80-64,127-80也是不能更新值得否则也会复位) 应当注意:在窗口看门狗中,当递减计数器在窗口外被重新装载,(若看门狗被启动)则产生复位,也即是说在90-64外面使用这个重载函数,会有问题发生 最后我们设置 (T[5:0]+1)的值,这里我们设置最大127,代码如下,以后每次喂狗也可以用这个函数进行重载计数值(喂狗)。 WWDG_Enable(127) 因为这是会导致产生复位,所以重载的窗口一定要设置好。 总结就是我们使用串口看门狗应该先配置寄存器(WWDG_CFR),即配置窗口值是多少到最小的0x40*T(LSB)(假定T(LSB)为每减一计数所需要的时间),这个配置会告诉单片机什么时候来与递减计数器进行值比较,如果计数值值小于0x40就产生复位。 当然,本例中如果你在减减计数值还在0x7E0x50(12780)之间就重载计数值(喂狗)同样会导致芯片复位。所以窗口的概念一定要理解好,在窗内才可以重载计数值(喂狗),这样才不会莫名被复位。 二、代码实现 最终的初始化窗口看门狗的配置函数(WWDG)如下: /************************************************************* Function : WWDGReste_Init Description: 窗口看门狗定时器 Input : none return : none *************************************************************/ void WWDGReste_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE);//WWDG连接在PCLK1(36M)的时钟线上 WWDG_SetPrescaler(WWDG_Prescaler_8); //8预分频,则WWDG时钟频率=(PCK1(36M)/4096)/8=1099Hz(910us) WWDG_SetWindowValue(80);//设置窗口值为80则WWDG的计数值必须在64~80之间才能喂狗(64是0x40,当再次减1就会T6清零,从而导致复位了) //设置WWDG计数值为127,超时时间=910us*64=58.25ms,所以 WWDG_Enable(127);//(0x7F为设置的最小值,0x40为最大的复位值,取值应该在0x40~0x7F之间)刷新窗口为:910us*(127-80)=42.77ms < 刷新窗口 < 910us*64=58.25ms } 主函数如下: void mian(void) { //初始化 while(1) { delay_ms(400) WWDG_Enable(127); //无需判断直接等待窗口看门狗中断触发 } } 或者这样的留参带使能中断形式: #include "wdg.h" #include "stm32f10x_wwdg.h" static u8 WWDG_CNT=0x7f; /*保存WWDG计数器的设置值,默认为最大127. */ //======================================================================================== /** * 初始化窗口看门狗 * tr :T[6:0],计数器值 * wr :W[6:0],窗口值 * fprer:分频系数(WDGTB),仅最低2位有效 * Fwwdg=PCLK1/(4096*2^fprer). // 计数器值为7f,窗口寄存器为5f,分频数为8 WWDG_Init(0X7F,0X5F,WWDG_Prescaler_8); */ void WWDG_Init(u8 tr,u8 wr,u32 fprer) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG, ENABLE); /*WWDG时钟使能*/ WWDG_SetPrescaler(fprer); /*设置IWDG预分频值*/ WWDG_SetWindowValue(wr); /*设置窗口值*/ WWDG_CNT=tr&WWDG_CNT; /* 初始化WWDG_CNT. */ WWDG_Enable(WWDG_CNT); /*使能看门狗 , 设置 counter . */ WWDG_ClearFlag(); /*清除提前唤醒中断标志位*/ WWDG_NVIC_Init();/* 初始化窗口看门狗 NVIC */ WWDG_EnableIT(); /* 开启窗口看门狗中断 */ } /** * 窗口看门狗中断服务程序 */ void WWDG_NVIC_Init(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_InitStructure.NVIC_IRQChannel = WWDG_IRQn; /*WWDG中断*/ /* 抢占2,子优先级3 */ NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //中断使能, NVIC_Init(&NVIC_InitStructure);/* NVIC初始化*/ } /** * 重设置WWDG计数器的值,喂狗 */ void WWDG_Set_Counter(u8 cnt) { WWDG_Enable(cnt); /*使能看门狗 , 设置 counter . */ } /** * 看门狗中断服务程序 */ void WWDG_IRQHandler(void) { WWDG_Set_Counter(WWDG_CNT); WWDG_ClearFlag(); /*清除提前唤醒中断标志位*/ LED1 = ~LED1; /*LED状态翻转 */ } void mian(void) { //初始化 while(1) { } } 三、中断说明: 关于void WWDG_IRQHandler(void)里的中断进入是在减计数到0x40时,处罚中断进入这个中断函数,如果在中断函数中进行减计数的操作,可以避免复位的厄运,但是如果你不做喂狗操作,那减计数值将接着减,数值将为0x3F,此时bit7被置零,此时将会直接导致复位。总之,进入中断函数并非就复位了,只是此时的减计数值到了0x40,而下一次减计数器减一后值为0x3F将导致芯片复位了。 附录: 独立看门狗(IWDG)的代码: /** * 初始化独立看门狗 * prer:分频数:0~7(只有低 3 位有效!) * 分频因子=4*2^prer.但最大值只能是 256! * rlr:重装载寄存器值:低 11 位有效. * 时间计算(大概):Tout=((4*2^prer)*rlr)/40 (ms). *IWDG_Init(4,625);//初始化独立看门狗,分频数为64,重装载值为625,溢出时间计算为:64*625/40=1000ms=1s */ void IWDG_Init(u8 prer,u16 rlr) { IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); /* 使能对寄存器IWDG_PR和IWDG_RLR的写操作*/ IWDG_SetPrescaler(prer); /*设置IWDG预分频值:设置IWDG预分频值*/ IWDG_SetReload(rlr); /*设置IWDG重装载值*/ IWDG_ReloadCounter(); /*按照IWDG重装载寄存器的值重装载IWDG计数器*/ IWDG_Enable(); /*使能IWDG*/ } /** * 喂独立看门狗 */ void IWDG_Feed(void) { IWDG_ReloadCounter(); /*reload*/ } /** *main函数 */ void main(void) { NVIC_Configuration();//优先级配置 IWDG_Init(4,625);//初始化独立看门狗,分频数为64,重装载值为625,溢出时间计算为:64*625/40=1000ms=1s while(1) { delay_ms(500);//0.5秒喂一次狗 IWDG_Feed();//喂狗 } } 此文章转载仅用于学习 |
|
|
|
只有小组成员才能发言,加入小组>>
调试STM32H750的FMC总线读写PSRAM遇到的问题求解?
1617 浏览 1 评论
X-NUCLEO-IHM08M1板文档中输出电流为15Arms,15Arms是怎么得出来的呢?
1543 浏览 1 评论
977 浏览 2 评论
STM32F030F4 HSI时钟温度测试过不去是怎么回事?
683 浏览 2 评论
ST25R3916能否对ISO15693的标签芯片进行分区域写密码?
1595 浏览 2 评论
1863浏览 9评论
STM32仿真器是选择ST-LINK还是选择J-LINK?各有什么优势啊?
644浏览 4评论
STM32F0_TIM2输出pwm2后OLED变暗或者系统重启是怎么回事?
515浏览 3评论
531浏览 3评论
stm32cubemx生成mdk-arm v4项目文件无法打开是什么原因导致的?
504浏览 3评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 08:32 , Processed in 0.833775 second(s), Total 77, Slave 60 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号