新聞中心

        STM32的獨(dú)立看門狗

        作者: 時(shí)間:2016-11-19 來(lái)源:網(wǎng)絡(luò) 收藏
        STM32 內(nèi)

        部自帶了 2 個(gè)看門狗:獨(dú)立看門狗(IWDG)和窗口看門狗(WWDG)

        本文引用地址:http://www.104case.com/article/201611/318191.htm

        STM32 的獨(dú)立看門狗由內(nèi)部專門的 40Khz 低速時(shí)鐘驅(qū)動(dòng),即使主時(shí)鐘發(fā)生故障,它也仍然
        有效。這里需要注意獨(dú)立看門狗的時(shí)鐘是一個(gè)內(nèi)部 RC 時(shí)鐘,所以并不是準(zhǔn)確的 40Khz,而是
        在 30~60Khz 之間的一個(gè)可變化的時(shí)鐘,只是我們?cè)诠浪愕臅r(shí)候,以 40Khz 的頻率來(lái)計(jì)算,看
        門狗對(duì)時(shí)間的要求不是很精確,所以,時(shí)鐘有些偏差,都是可以接受的。
        首先我們得講解一下看門狗的原理。這個(gè)百度百科里面有很詳細(xì)的解釋。我們總結(jié)一下:
        單片機(jī)系統(tǒng)在外界的干擾下會(huì)出現(xiàn)程序跑飛的現(xiàn)象導(dǎo)致出現(xiàn)死循環(huán),看門狗電路就是為了避免
        這種情況的發(fā)生。看門狗的作用就是在一定時(shí)間內(nèi)(通過(guò)定時(shí)計(jì)數(shù)器實(shí)現(xiàn))沒(méi)有接收喂狗信號(hào)
        (表示 MCU 已經(jīng)掛了),便實(shí)現(xiàn)處理器的自動(dòng)復(fù)位重啟(發(fā)送復(fù)位信號(hào))。 IWDG_PR 和 IWDG_RLR 寄存器具有寫(xiě)保護(hù)功能。要修改這兩個(gè)寄存器的值,必須先向
        IWDG_KR 寄存器中寫(xiě)入 0x5555。將其他值寫(xiě)入這個(gè)寄存器將會(huì)打亂操作順序,寄存器將重新
        被保護(hù)。重裝載操作(即寫(xiě)入 0xAAAA)也會(huì)啟動(dòng)寫(xiě)保護(hù)功能。
        還有兩個(gè)寄存器,一個(gè)預(yù)分頻寄存器(IWDG_PR),該寄存器用來(lái)設(shè)置看門狗時(shí)鐘的分頻
        系數(shù)。另一個(gè)重裝載寄存器。該寄存器用來(lái)保存重裝載到計(jì)數(shù)器中的值。該寄存器也是一個(gè) 32
        位寄存器,但是只有低 12 位是有效的。
        只要對(duì)以上三個(gè)寄存器進(jìn)行相應(yīng)的設(shè)置,我們就可以啟動(dòng) STM32 的獨(dú)立看門狗,啟動(dòng)過(guò)
        程可以按如下步驟實(shí)現(xiàn)(獨(dú)立看門狗相關(guān)的庫(kù)函數(shù)和定義分布在文件 stm32f10x_iwdg.h 和
        stm32f10x_iwdg.c 中):
        1)取消寄存器寫(xiě)保護(hù)(向 IWDG_KR 寫(xiě)入 0X5555)
        通過(guò)這步,我們?nèi)∠?IWDG_PR 和 IWDG_RLR 的寫(xiě)保護(hù),使后面可以操作這兩個(gè)寄存器,
        設(shè)置 IWDG_PR 和 IWDG_RLR 的值。這在庫(kù)函數(shù)中的實(shí)現(xiàn)函數(shù)是:
        IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable);
        這個(gè)函數(shù)非常簡(jiǎn)單,顧名思義就是開(kāi)啟/取消寫(xiě)保護(hù),也就是使能/失能寫(xiě)權(quán)限。
        2)設(shè)置獨(dú)立看門狗的預(yù)分頻系數(shù)和重裝載值

        設(shè)置看門狗的分頻系數(shù)的函數(shù)是:
        void IWDG_SetPrescaler(uint8_t IWDG_Prescaler); //設(shè)置 IWDG 預(yù)分頻值
        設(shè)置看門狗的重裝載值的函數(shù)是:
        void IWDG_SetReload(uint16_t Reload); //設(shè)置 IWDG 重裝載值
        設(shè)置好看門狗的分頻系數(shù) prer 和重裝載值就可以知道看門狗的喂狗時(shí)間(也就是看門狗溢
        出時(shí)間),該時(shí)間的計(jì)算方式為:
        Tout=((4×2^prer) ×rlr) /40
        其中 Tout 為看門狗溢出時(shí)間(單位為 ms);prer 為看門狗時(shí)鐘預(yù)分頻值(IWDG_PR 值),
        范圍為 0~7;rlr 為看門狗的重裝載值(IWDG_RLR 的值);
        比如我們?cè)O(shè)定 prer 值為 4,rlr 值為 625,那么就可以得到 Tout=64×625/40=1000ms,這樣,
        看門狗的溢出時(shí)間就是 1s,只要你在一秒鐘之內(nèi),有一次寫(xiě)入 0XAAAA 到 IWDG_KR,就不
        會(huì)導(dǎo)致看門狗復(fù)位(當(dāng)然寫(xiě)入多次也是可以的)。這里需要提醒大家的是,看門狗的時(shí)鐘不是準(zhǔn)
        確的 40Khz,所以在喂狗的時(shí)候,最好不要太晚了,否則,有可能發(fā)生看門狗復(fù)位。
        3)重載計(jì)數(shù)值喂狗(向 IWDG_KR 寫(xiě)入 0XAAAA)
        庫(kù)函數(shù)里面重載計(jì)數(shù)值的函數(shù)是:
        IWDG_ReloadCounter(); //按照 IWDG 重裝載寄存器的值重裝載 IWDG 計(jì)數(shù)器
        通過(guò)這句,將使 STM32 重新加載 IWDG_RLR 的值到看門狗計(jì)數(shù)器里面。即實(shí)現(xiàn)獨(dú)立看門
        狗的喂狗操作。
        4) 啟動(dòng)看門狗(向 IWDG_KR 寫(xiě)入 0XCCCC)
        庫(kù)函數(shù)里面啟動(dòng)獨(dú)立看門狗的函數(shù)是:
        IWDG_Enable(); //使能 IWDG
        通過(guò)這句,來(lái)啟動(dòng) STM32 的看門狗。注意 IWDG 在一旦啟用,就不能再被關(guān)閉!想要關(guān)
        閉,只能重啟,并且重啟之后不能打開(kāi) IWDG,否則問(wèn)題依舊,所以在這里提醒大家,如果不
        用 IWDG 的話,就不要去打開(kāi)它,免得麻煩。
        通過(guò)上面 4 個(gè)步驟,我們就可以啟動(dòng) STM32 的看門狗了,使能了看門狗,在程序里面就
        必須間隔一定時(shí)間喂狗,否則將導(dǎo)致程序復(fù)位。利用這一點(diǎn),我們本章將通過(guò)一個(gè) LED 燈來(lái)指
        示程序是否重啟,來(lái)驗(yàn)證 STM32 的獨(dú)立看門狗。
        在配置看門狗后,DS0 將常亮,如果 WK_UP 按鍵按下,就喂狗,只要 WK_UP 不停的按,
        看門狗就一直不會(huì)產(chǎn)生復(fù)位,保持 DS0 的常亮,一旦超過(guò)看門狗定溢出時(shí)間(Tout)還沒(méi)按,
        那么將會(huì)導(dǎo)致程序重啟,這將導(dǎo)致 DS0 熄滅一次

        wdg.c 里面的代碼如下:

        #include "wdg.h"
        //初始化獨(dú)立看門狗
        //prer:分頻數(shù):0~7(只有低 3 位有效!)
        //分頻因子=4*2^prer.但最大值只能是 256!
        //rlr:重裝載寄存器值:低 11 位有效.
        //時(shí)間計(jì)算(大概):Tout=((4*2^prer)*rlr)/40 (ms).
        void IWDG_Init(u8 prer,u16 rlr)
        {
        IWDG_WriteAccessCmd(IWDG_WriteAccess_Enable); //①使能對(duì)寄存器 I 寫(xiě)操作
        IWDG_SetPrescaler(prer); //②設(shè)置 IWDG 預(yù)分頻值:設(shè)置 IWDG 預(yù)分頻值
        IWDG_SetReload(rlr); //②設(shè)置 IWDG 重裝載值
        IWDG_ReloadCounter(); //③按照 IWDG 重裝載寄存器的值重裝載 IWDG 計(jì)數(shù)器
        IWDG_Enable(); //④使能 IWDG
        }
        //喂獨(dú)立看門狗
        void IWDG_Feed(void)
        {
        IWDG_ReloadCounter();//reload
        }

        該代碼就 2 個(gè)函數(shù),void IWDG_Init(u8 prer,u16 rlr)是獨(dú)立看門狗初始化函數(shù),就是按照
        上面介紹的步驟 1~4 來(lái)初始化獨(dú)立看門狗的。該函數(shù)有 2 個(gè)參數(shù),分別用來(lái)設(shè)置與預(yù)分頻數(shù)與
        重裝寄存器的值的。通過(guò)這兩個(gè)參數(shù),就可以大概知道看門狗復(fù)位的時(shí)間周期為多少了。其計(jì)
        算方式上面有詳細(xì)的介紹,這里不再多說(shuō)了。
        void IWDG_Feed(void)函數(shù),該函數(shù)用來(lái)喂狗,因?yàn)?STM32 的喂狗只需要向鍵值寄存器寫(xiě)
        入 0XAAAA 即可,也就是調(diào)用 IWDG_ReloadCounter()函數(shù),所以,我們這個(gè)函數(shù)也是簡(jiǎn)單的很。
        頭文件 wdg.h 的源碼如下大家可以看下,這里我們就不列出來(lái)了。
        接下來(lái)我們看看主函數(shù) main 的代碼。在主程序里面我們先初始化一下系統(tǒng)代碼,然后啟動(dòng)
        按鍵輸入和看門狗,在看門狗開(kāi)啟后馬山點(diǎn)亮 LED0(DS0),并進(jìn)入死循環(huán)等待按鍵的輸入,
        一旦 WK_UP 有按鍵,則喂狗,否則等待 IWDG 復(fù)位的到來(lái)。這段代碼很容易理解,該部分代
        碼如下:
        int main(void)
        {
        delay_init();
        //延時(shí)函數(shù)初始化
        NVIC_Configuration(); //設(shè)置 NVIC 中斷分組 2:2 位搶占優(yōu)先級(jí),2 位響應(yīng)優(yōu)先級(jí)
        uart_init(9600);
        //串口初始化波特率為 9600
        LED_Init();
        //初始化與 LED 連接的硬件接口
        KEY_Init(); //按鍵初始化
        185
        delay_ms(500); //讓人看得到滅
        IWDG_Init(4,625); //與分頻數(shù)為 64,重載值為 625,溢出時(shí)間為 1s
        LED0=0;
        //點(diǎn)亮 LED0
        while(1)
        {
        if(KEY_Scan(0)==KEY_UP)
        {
        IWDG_Feed(); //如果 WK_UP 按下,則喂狗
        }
        delay_ms(10);
        };
        }



        關(guān)鍵詞: STM32獨(dú)立看門

        評(píng)論


        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 娄烦县| 林州市| 响水县| 木兰县| 苏尼特左旗| 通州市| 温州市| 军事| 建宁县| 彰化县| 常州市| 安平县| 阿拉善右旗| 嘉黎县| 建湖县| 克什克腾旗| 商丘市| 始兴县| 县级市| 嘉祥县| 曲水县| 丹寨县| 霍城县| 乡城县| 汶上县| 天门市| 博罗县| 太和县| 邯郸市| 台南市| 潼南县| 友谊县| 平武县| 萝北县| 天全县| 五台县| 荔波县| 积石山| 获嘉县| 郴州市| 天全县|