SATM32單片機(jī)的看門狗有獨(dú)立看門狗和窗口看門狗之分,這兩者的工作原理卻完全不同,今天來(lái)看一下他們的具體區(qū)別和配置方法。
由專門的低速時(shí)鐘(LSI)驅(qū)動(dòng),即便是主時(shí)鐘發(fā)生故障它仍能夠有效,所以此狗狗可以工作在與主時(shí)鐘無(wú)關(guān)的要求下,或者待機(jī)模塊下等,所以它叫獨(dú)立看門狗,注意一旦開(kāi)啟此看門狗則只能由MCU復(fù)位后才清除,讓它不再工作。
它的時(shí)鐘是一個(gè)內(nèi)部RC時(shí)鐘,它會(huì)在30KHZ到60KHZ之間變化,并非是精確的40KHZ,而只是一般計(jì)算時(shí)取40KHZ。
獨(dú)立看門狗需設(shè)置四個(gè)寄存器如下:
其中,預(yù)分頻寄存器(IWDG_PR),最低三位PR[2:0](Prescaler divider)有效,可設(shè)置有8種不同的計(jì)數(shù)器時(shí)鐘預(yù)分頻因子。
重裝載寄存器(IWDG_RLR)低12位RL[11:0]: 看門狗計(jì)數(shù)器重裝載值 (Watchdog counter reload value) 有效,用來(lái)設(shè)置計(jì)數(shù)器的重裝載值。
注意要設(shè)置以上兩個(gè)寄存器的值需滿足兩個(gè)條件,詳見(jiàn)如下:
鍵寄存器(IWDG_KR),用來(lái)控制去除IWDG_PR和IWDG_RLR寫保護(hù)功能以便正常寫值,向此寄存器寫入0x5555則暫時(shí)去除IWDG_PR和IWDG_RLR的寫保護(hù)功能才可向兩個(gè)寄存器中寫值。
當(dāng)向此寄存器寫入0xAAAA則IWDG_RLR的值會(huì)重裝載,防止MCU復(fù)位,向入0xCCCC是開(kāi)啟狗立看門狗動(dòng)作。
狀態(tài)寄存器(IWDG_SR)最低兩位有效RVU: 看門狗計(jì)數(shù)器重裝載值更新 (Watchdog counter reload value update) 標(biāo)識(shí)位和PVU: 看門狗預(yù)分頻值更新?(Watchdog prescaler value update) 標(biāo)識(shí)位,分別用來(lái)指示此時(shí)是否可向IWDG_RLR ?和 IWDG_PR寫值,此寄存器由硬件置1與清0,只有當(dāng)為0時(shí)才可向上面兩個(gè)寄存器寫值。
//時(shí)間計(jì)算(大概):Tout=((4*2^prer)*rlr)/40?(ms)
void?IWDG_Init(u8?prer,u16?rlr)
{???????
????????IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);?
?????????IWDG_SetPrescaler(prer);???
?????????IWDG_SetReload(rlr);?
?????????IWDG_ReloadCounter();??????
?????????IWDG_Enable();?
}
喂狗可通過(guò)調(diào)用如下函數(shù)進(jìn)行:
IWDG_ReloadCounter();//reload
另外要注意不要使用硬件時(shí)鐘中斷喂狗,因?yàn)橛布r(shí)鐘中斷一般都有較高優(yōu)先級(jí)且獨(dú)立于主控程序,這樣有時(shí)會(huì)出現(xiàn)主控程序雖然跑飛了,但仍能夠正常喂狗的現(xiàn)象。
獨(dú)立看門狗能夠在一定程度上監(jiān)控著程序正常運(yùn)行,然而我認(rèn)為更加強(qiáng)大,應(yīng)用更靈活及更能保證程序穩(wěn)定運(yùn)行的還屬窗口看門狗,雖然它開(kāi)始時(shí)不太好理解。
看似簡(jiǎn)單,但設(shè)置及應(yīng)用起來(lái)有不少玄機(jī)。
控制寄存器(WWDG_CR)中的值必須在0xFF與0xC0之間, 因?yàn)樗牡?至第6位為遞減計(jì)數(shù)器CNT,在它的第6位變?yōu)?時(shí)將產(chǎn)生復(fù)位,所以在初始化時(shí)需要為1,第7位WDGA是用來(lái)設(shè)置啟動(dòng)或禁止窗口看門狗的,當(dāng)為1進(jìn)才會(huì)啟動(dòng)窗口看門狗,所以第6和第7位都需為1,即WWDG_CR 的值需要大于等于0xC0 。
配置寄存器(WWDG_CFR) 第0至第6位 是設(shè)置窗口邊界值用的,只有當(dāng)遞減計(jì)數(shù)器CNT的值小于邊界值時(shí)才可以喂狗,過(guò)早不行,狗還不餓,撐死了。
并且7位遞減計(jì)數(shù)器CNT減少到0x3F時(shí)即T6位變?yōu)?,此時(shí)MCU也會(huì)復(fù)位,過(guò)晚了,狗餓死了。
所以必須在指定的時(shí)間范圍喂狗,過(guò)早或過(guò)晚都將產(chǎn)生復(fù)位,而這樣設(shè)計(jì)可以減少軟件跑飛了卻仍能夠歪打正著地喂狗的發(fā)生概率。
狀態(tài)寄存器(WWDG_CFR) 只用到了第0位,EWIF(Early wakeup interrupt flag )是提前喚醒中斷標(biāo)識(shí),當(dāng)遞減計(jì)數(shù)器CNT的值到達(dá)0X40(若再減少一次則T6位變?yōu)?,產(chǎn)生復(fù)位)時(shí)此位由硬件置1,且需用軟件清0,注意無(wú)論中斷是否使能此位都會(huì)被硬件置1。
而提前喚醒中斷使能設(shè)置是在配置寄存器(WWDG_CFR)第9位EWI(Early wakeup interrupt),此位需由軟件置1,則會(huì)在當(dāng)遞減計(jì)數(shù)器CNT的值到達(dá)0X40時(shí)產(chǎn)生中斷,并且與EWIF不同,此位是由硬件清0。
另外控制寄存器(WWDG_CR)中第7位WDGA(Activation bit)激活位,需用軟件來(lái)置1,以啟動(dòng)窗口看門狗,并且一旦啟動(dòng)后,只能在復(fù)位或重啟后由硬件來(lái)清0。
配置寄存器(WWDG_CFR)的第8位和第7位WDGTB[1:0]用來(lái)設(shè)置時(shí)基(Timer base)預(yù)分頻數(shù)。
窗口看門狗應(yīng)用時(shí)還要注意算準(zhǔn)最小與最大喂狗時(shí)間,以便正確地喂狗,如下:
上窗口時(shí)間:T_min = 4096 * (2^WDGTB)*(WWDG_CR[6:0] - WWDG_CFR[6:0])/36 (us)
下窗口時(shí)間:T_max = 4096 * (2^WDGTB)*(WWDG_CR[6:0] - 0x40)/36 (us) 。
喂狗動(dòng)作需在這段時(shí)間之間進(jìn)行,而喂狗動(dòng)作為向控制寄存器(WWDG_CR)中寫值。
窗口看門狗中斷函數(shù)void WWDG_IRQHandler(void);是用來(lái)做什么的呢。
窗口看門狗中斷函數(shù)是在遞減計(jì)數(shù)器減少到0x40是被調(diào)用,因?yàn)樗旧碛?jì)數(shù)就比較慢,所以離數(shù)到0x3F復(fù)位還有一段時(shí)間,我認(rèn)為這樣設(shè)計(jì)是為MCU復(fù)位之前留下一點(diǎn)時(shí)間,能夠使工程設(shè)計(jì)人員根據(jù)需要在中斷函數(shù)保存一些重要的數(shù)據(jù),這樣在復(fù)位后MCU可知道系統(tǒng)因異常復(fù)位的某此狀態(tài),以使系統(tǒng)有更高穩(wěn)定性。
并且我覺(jué)得在窗口看門狗中斷函數(shù)中喂狗沒(méi)有什么意義,程序本來(lái)已經(jīng)不按正常運(yùn)行了,還在中斷函數(shù)中喂狗防止復(fù)位只會(huì)錯(cuò)上加錯(cuò),不好好利用它干點(diǎn)正事, 更是浪費(fèi)資源。
這點(diǎn)上我個(gè)人認(rèn)為不要被點(diǎn)原子示例代碼誤導(dǎo)哦,但其還是有部分借鑒意義的,以下為初始化相關(guān)代碼:
??//窗口看門狗中斷服務(wù)設(shè)置程序
????void?WWDG_NVIC_Init()
????{
??????NVIC_InitTypeDef?NVIC_InitStructure;
??????NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);??????
??????NVIC_InitStructure.NVIC_IRQChannel?=?WWDG_IRQn;???????//WWDG?中斷
??????NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority?=?2;?//搶占2?子優(yōu)先級(jí)3?組2
??????NVIC_InitStructure.NVIC_IRQChannelSubPriority?=?3;????//搶占2,子優(yōu)先級(jí)3,組2
??????NVIC_Init(&NVIC_InitStructure);???????????????????????//NVIC?初始化
????}
//保存WWDG?計(jì)數(shù)器的設(shè)置值,默認(rèn)為最大.
u8?WWDG_CNT=0x7f;
?//初始化窗口看門狗
????//tr??:T[6:0],計(jì)數(shù)器值
????//wr???:W[6:0],窗口值
????//fprer:分頻系數(shù)(WDGTB?),僅最低2?位有效
????//Fwwdg=PCLK1/(4096*2^fprer).
????void?WWDG_Init(u8?tr,u8?wr,u32?fprer)
????{
??????RCC_APB1PeriphClockCmd(RCC_APB1Periph_WWDG,?ENABLE);?//?WWDG?時(shí)鐘使能
??????WWDG_CNT=tr&WWDG_CNT;??????//初始化WWDG_CNT.
??????WWDG_SetPrescaler(fprer);????????//設(shè)置IWDG?預(yù)分頻值
??????WWDG_SetWindowValue(wr);???????//設(shè)置窗口值
??????WWDG_Enable(WWDG_CNT);???????//使能看門狗,設(shè)置counter
??????WWDG_ClearFlag();???????????????//清除提前喚醒中斷標(biāo)志位?(注:若沒(méi)有此句則會(huì)在初始化后先進(jìn)入中斷一次)
??????WWDG_NVIC_Init();???????????????//初始化窗口看門狗NVIC
??????WWDG_EnableIT();????????????????//開(kāi)啟窗口看門狗中斷
}
以上代碼朋友們也可以跳到庫(kù)函數(shù)代碼中自己研究下,另外要說(shuō)明下的是WWDG_EnableIT(); 函數(shù)相關(guān)代碼
#define?CFR_EWI_BB????????(PERIPH_BB_BASE?+?(CFR_OFFSET?*?32)?+?(EWI_BitNumber?*?4))
用到位帶操作,具體理解可參照《Cortex-M3權(quán)威指南》第五章的位帶操作相關(guān)介紹(具體89頁(yè))。
來(lái)源 | 玩轉(zhuǎn)嵌入式
|?整理文章為傳播相關(guān)技術(shù),版權(quán)歸原作者所有?|
|?如有侵權(quán),請(qǐng)聯(lián)系刪除?|
【1】單片機(jī)為何既有Flash又有EEPROM?
【2】“史上”最爛代碼!
【3】goto語(yǔ)句對(duì)與錯(cuò)
【4】C語(yǔ)言內(nèi)存操作的陷阱!你踩過(guò)坑嗎?
【5】RTOS 是如何進(jìn)行任務(wù)劃分的?