新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > STC89C5X單片機“看門狗”原理、詳解和演示程序

        STC89C5X單片機“看門狗”原理、詳解和演示程序

        作者: 時間:2011-01-27 來源:網絡 收藏
        “看門狗定時器”是這樣一種東西,從功能上說它可以讓微控制器在意外狀況下(比如軟件陷入死循環)重新回復到系統上電狀態,以保證系統出問題的時候重啟一次就跟我們現在用電腦一樣,死機了你就按一下reset鍵重啟一次電腦,看門狗就是負責干這個事兒的。它是52增加的一個功能,以前Intel 8031、……、AT 89C51時代片內都沒有“看門狗”功能,需要我們外擴看門狗芯片,比如X5045。

          很多人初次接觸不太理解怎么用,書上也講的含含糊糊,故意說的很復雜很玄妙(可能是現在寫書人的通病,生怕寫的簡單的別人覺得他沒水平)。其實要是說明白點:“看門狗”就是一個計數器,由于位數有限計數器能夠裝的數值是有限的(比如8位的最多裝256個數、16位的最多裝65536個數),從開啟“看門狗”那刻起,它就開始不停的數機器周期,數一個機器周期就計數器加1,加到計數器盛不下了(術語叫溢出)就就產生一個復位信號,重啟系統

          注解:這里順便說一下,一般教材上叫“看門狗定時器”,其實定時器原理還是計數器,只是計的是時鐘周期,所以我為了初學者好理解叫統一叫“計數器”,這里闡明一下。

          明白了上面的原理,我們在設計程序時,先根據看門狗計數器的位數系統的時鐘周期算一下計滿數需要的時間,就是說在這個時間內“看門狗”計數器是不會裝滿的,然后在這個時間內告訴它重新開始計數,就是把計數器清零,這個過程叫“喂狗”,這樣隔一段時間喂一次狗,只要程序正常運行他就永遠計不滿,一旦出現死循環之類的故障,沒有及時來清零計數器,就會導致裝滿了溢出,他就重啟系統,這就是看門狗的看門原理,其實想想傻傻的、笨笨的。

          舉個例子說:8051 選用12MHz晶振,一個時鐘周期為1us,如果“看門狗計數器”是16位的,最大計數65536個,那么從0開始計到65535需要約65ms,所以我們可以在程序的50ms左右清零一次計數器(“喂狗”),讓他重新從0開始計,再過50ms,再清,……,這樣下去只要程序正常運行,計數器永遠不會計滿,也就永遠不會被“看門狗”復位。當然這個喂狗的時間是大家自己選的,只要不超過65ms,你選多少都可以,一般不要喂得太勤,這樣單片機運行時間浪費了,比如你1ms喂一次就太勤了,也不要說那我65ms喂一次,這樣太邊緣,這樣抗干擾能力就下降了,最好是留一定的余量,這個就是設計者自己掌握了,我一般是讓計到90%左右就清一次。

          每種單片機的“看門狗”實現方法不盡相同,但是原理都一樣,而且“看門狗”都是啟動了之后就不能被關閉,只能系統復位(重新斷電在上電)才能關閉。設置“看門狗”的一般步驟如下:
          1. 設置“看門狗”相關寄存器,啟動“看門狗”;
          2. 隔一段時間清零一次,“喂狗”;
          3. 如果程序正常,一直運行;如果程序出錯,沒有按時“喂狗”,“看門狗”就在溢出的時候復位系統。

        值得提一下:

          由于現在AT89S52應用比較廣泛,所以我先說說ATMEL的看門狗;再說說本次試驗用的STC89C52RC的看門狗;注意兩個不一樣!!!

          AT89S52單片機看門狗定時器是14位的,最大計數214=16384個數,每計16384個時鐘周期就溢出一次。也就是說如果使用12M晶振的話,至少應該在16.384ms內喂一次狗。

          STC89C5X系列單片機由于采用了“預分頻技術”,它的溢出時間是=(N*Prescale*32768)/晶振頻率(不要問我為什么,他們就是這么設計的,我們就這么用就行)。

        • 其中N是單片機的時鐘周期,STC89C5X系列單片機提供6時鐘周期和12時鐘周期兩種時鐘周期,可以在燒寫程序時修改;
        • Prescale是預分頻數,通過設置【看門狗控制寄存器】可以設置為2、4、8、16、32、64、128、256;怎么設置演示程序中有介紹;
        • 晶振頻率就是系統選用的晶振。

          所以如果同樣選擇12MHz晶振,使用傳統的12時鐘周期,它最小的溢出時間是(12*2*32768)/(12*106)=65.536ms,最大溢出時間是(12*256*32768)/(12*106)≈8.38s。如果選擇256分頻,也就是說只要在8.38秒之內喂一次狗就可以了。戲謔的說:這只狗比較抗餓,J~~

          對于我們用戶來說,看門狗的時間是越長越好,這樣可以節省更多的單片機資源,尤其是對時間要求精準的系統,如果執行過程中我們不停地“喂狗”,那么是比較浪費時間的。所以STC89C5X系列單片機的看門狗更有優勢一些。當然這個也是個人的選擇,如果對時間要求的不苛刻的話,勤喂幾次狗也沒關系。

          下面我就以STC89C52RC單片機為例說說典型的的看門狗程序如何寫,關于STC89C52RC單片機的“看門狗”定義請看STC89C51RC-RD單片機使用說明。以下程序在Keil 2和Keil 3下調時通過,下載在本校的實驗板上達到預期效果。STC89C52RC/54RD+/58RD+/516RD+單片機上測試正常運行。

          如果沒有我們的實驗板,請按照下面的硬件原理圖自己在最小系統上搭建一個實驗環境也很容易。

        STC89C5X單片機“看門狗”原理、詳解和演示程序

        圖1. STC89C52最小單片機系統+兩個指示燈

        STC89C5X單片機“看門狗”原理、詳解和演示程序

        圖2. 串行口接口(用于下載程序和測試本次試驗)

        view source
        print?
        001/***************************************************************************
        002程序功能:本程序演示STC看門狗程序
        003程序設計:燕山大學 魯信瓊
        004晶振選擇:11.0592MHz, 如果晶振不匹配,請修改延時函數參數
        005承接程序、VB/VC++上位機程序、電子產品軟硬件設計開發工作
        006EMail: xqlu(at)ysu.net.cn QQ: 9790335
        007
        008由于現在AT89S52很流行,所以我先說說ATMEL的看門狗;再說說本次試驗用的STC89C52RC的看門狗;注意兩個不一樣!!!
        009
        010★下面是關于ATMEL-51單片機看門狗的描述
        011【看門狗計數器】(watchdog timer)是一個14位的計數器,它以機器周期(晶振頻率/12)增加,當計數值計滿(16383/0x3FFF)了就使單片機軟復位;
        012當啟動了【看門狗計數器】之后,我們需要在它計數沒有滿之前復位計數器強制它不能夠溢出,這個過程稱作喂狗。
        013
        014"看門狗"原理:
        0151. 系統上電并不啟動看門狗計數器,通過設置【看門狗重置寄存器(WDTRST SFR)】啟動【看門狗計數器】,一般設置是給WDTRST寫入0x1E和0xE1啟動;
        0162. 【看門狗計數器】一旦啟動不可停止,除非是硬件RST或者看門狗的軟復位才能使其停止;
        0173. 設計程序在適當的時間喂狗一次,使其不能計滿,程序就能不間斷執行;
        0184. 如果程序中出現死循環或者執行某一步超時,看門狗計數器就會計滿溢出,(這個時候我們認為程序沒有按照預定計劃執行--程序跑飛),則復位系統。
        019
        020★下面是關于STC89C5XX-51單片機看門狗的描述
        021WDT_CONTR位置0xE1; [-] [-] [EN_WDT] [CLR_WDT] [IDLE_WDT] [PS2] [PS1] [PS0]
        022EN_WDT: 看門狗允許位,置1啟動看門狗,看門狗不能自動啟動,需要設置該位后啟動,一旦啟動不能關閉(只能系統重新上電和看門狗復位可以關閉)
        023CLR_WDT: 看門狗計數器清零位,置1清零看門狗計數器,當計數器開始重新計數,硬件清零該位。
        024IDLE_WDT: 單片機IDLE模式看門狗允許位,當IDLE_WDT=1時,單片機在IDLE模式(空閑模式)依然啟用看門狗
        025PS2~PS0: 看門狗定時器預分頻器,下表中Prescale表示預分頻數
        026PS2 PS1 PS0 Prescale
        0270 0 0 2
        0280 0 1 4
        0290 1 0 8
        0300 1 1 16
        0311 0 0 32
        0321 0 1 64
        0331 1 0 128
        0341 1 1 256
        035
        036看門狗溢出時間:(N*Prescale*32768)/晶振頻率,其中N表示指令周期數N=12表示12時鐘周期模式;N=6表示6時鐘周期模式
        037
        038關于實驗的注意事項:
        0391. 本次試驗使用的是11.0592MHz晶振,設置WDT_CONTR=(0011 0100)B,32預分頻,單片機使用12指令周期模式。
        040計算看門狗溢出時間:[12*32*32768/(11059200)]≈1s。
        0412. 本次試驗的硬件電路很簡單,就是最小系統上增加兩個LED燈,原理圖見正文,用戶可以很容易實現。
        042***************************************************************************/
        043#include REG52.H>
        044sfr WDT_CONTR=0xE1; //定義特殊功能寄存器:STC單片機看門狗控制寄存器
        045#define uchar unsigned char
        046#define true 1
        047#define false 0
        048#define WEIGOU WDT_CONTR=0x34 //看門狗啟動設置和“喂狗”操作
        049sbit LED=P1^6; //信號燈,系統正常工作就一閃一閃的
        050sbit LED_busy=P1^7; //工作燈,上電滅一會兒(約800ms),然后正常工作的時候一直亮著;用于指示系統是否重啟
        051uchar timer0_ctr,i;
        052const uchar str[]="I love !"; //定義一句話,讓他從串口輸出,只有系統重啟的時候才輸出一次,所以也是用于驗證看門狗有沒有重啟系統
        053
        054/*************************************************************************/
        055//延時函數,11.0592MHz晶振下延時約xms毫秒
        056void delay_ms(unsigned xms)
        057{
        058unsigned x,y;
        059for(x=xms; x>0; x--)
        060for(y=110; y>0; y--);
        061}
        062/*************************************************************************/
        063
        064/*************************************************************************/
        065//主程序初始化函數
        066void InitMain()
        067{
        068//初始化時兩盞燈都熄滅
        069LED=1;
        070LED_busy=1;
        071
        072TMOD=0x21; //定時器0工作在方式1,作為16位定時器;定時器1工作在方式2,作為串行口波特率發生器
        073TH0=0x4C; //定時器0裝初值:每隔50ms溢出一次
        074TL0=0x00;
        075IE=0x82; //IE=(1000 0010)B, 使能定時器0中斷
        076TR0=1; //啟動定時器0
        077}
        078/*************************************************************************/
        079
        080/*************************************************************************/
        081//串行口初始化程序
        082void InitCOM()
        083{
        084SCON=0x50; //SCON=(0101 0000)B,波特率不加倍,允許接收
        085TH1=0xFD; //設置波特率=9600bps
        086TL1=TH1;
        087TR1=1; //啟動定時器1
        088}
        089/*************************************************************************/
        090
        091/*************************************************************************/
        092//定時器0中斷服務程序程序,控制信號燈閃爍。如果系統正常運行,信號燈1.5秒閃一次
        093void Timer0_isr() interrupt 1
        094{
        095TH0=0x4C;
        096TL0=0x00;
        097timer0_ctr++;
        098
        099if(timer0_ctr>=30)
        100{
        101TR0=0; //定時器0暫停,否則再次來中斷會沖斷程序
        102timer0_ctr=0;
        103LED=0;
        104delay_ms(100);
        105LED=1;
        106TR0=1; //定時器0重新啟動
        107}
        108}
        109/*************************************************************************/
        110
        111void main()
        112{
        113WEIGOU; //上來第一步設置看門狗定時器,并且啟動
        114InitMain();
        115InitCOM();
        116
        117//開機通過串口發送一次“I love !”,使用串口調試助手可以查看
        118//由于在while大循環外邊,所以只要系統不重新啟動,則上電后只會發送一次,用于判斷系統是否重啟
        119i=0;
        120while(str[i]!=' 主站蜘蛛池模板: 福州市| 建瓯市| 锦屏县| 田林县| 满城县| 炎陵县| 精河县| 迁安市| 固原市| 丹巴县| 高唐县| 建阳市| 赤城县| 神木县| 白银市| 德保县| 松原市| 南江县| 长春市| 荥经县| 靖州| 洛宁县| 巴楚县| 浙江省| 台江县| 东乡族自治县| 康乐县| 珲春市| 蕉岭县| 乐昌市| 青海省| 当雄县| 阿拉尔市| 社旗县| 桓台县| 永定县| 佛教| 伊吾县| 湘潭县| 高邮市| 江华|