/***********************************************
**** AVR 復(fù)位檢測(cè)和控制看門(mén)狗的范例 ***
**** ***
**** 作者: HJJourAVR ***
**** 編譯器:WINAVR20050214 ***
**** ***
**** www.OurAVR.com 2005.9.28 ***
***********************************************/
/*
本程序簡(jiǎn)單的示范了AVRATMEGA16的復(fù)位檢測(cè)和控制看門(mén)狗
系統(tǒng)控制和復(fù)位
復(fù)位來(lái)源的檢測(cè)
JTAG復(fù)位指示
看門(mén)狗復(fù)位指示
BOD復(fù)位指示
RESET引腳復(fù)位指示
上電復(fù)位指示
看門(mén)狗的控制
出于簡(jiǎn)化程序考慮,各種數(shù)據(jù)沒(méi)有對(duì)外輸出,學(xué)習(xí)時(shí)建議使用JTAG ICE硬件仿真器。
熔絲位設(shè)置
1 使能BOD功能 BODEN=0
2 選擇BOD電平 BODLEVEL=1 2.7V(VCC=3V) (可選)
BODLEVEL=0 4.0V(VCC=5V) (可選)
*/
[code="CSHARP"]
#include <avr/io.h>
#include <avr/delay.h>
//時(shí)鐘定為內(nèi)部RC 1MHz,F_CPU=1000000 也可以采用其他時(shí)鐘
#include <avr/wdt.h>
/*
wdt.h里面
看門(mén)狗溢出時(shí)間常量定義
#define WDTO_15MS 0
#define WDTO_30MS 1
#define WDTO_60MS 2
#define WDTO_120MS 3
#define WDTO_250MS 4
#define WDTO_500MS 5
#define WDTO_1S 6
#define WDTO_2S 7
下面的4S/8S定義只能用于 ATtiny2313, ATmega48, ATmega88 and the ATmega168.
#define WDTO_4S 8
#define WDTO_8S 9
看門(mén)狗操作函數(shù)
wdt_disable()
關(guān)閉看門(mén)狗
wdt_enable(timeout)
使能看門(mén)狗及溢出時(shí)間設(shè)定
wdt_reset()
復(fù)位看門(mén)狗(喂狗)
*/
//管腳定義
#define WDT_EN 7 //PA7 看門(mén)狗的喂狗控制引腳
// 高電平,不喂狗
// 低電平,喂狗
#define LED_JT 4 //PA4 JTAG復(fù)位指示
#define LED_WD 3 //PA3 看門(mén)狗復(fù)位指示
#define LED_BO 2 //PA2 BOD復(fù)位指示
#define LED_EXT 1 //PA1 RESET引腳復(fù)位指示
#define LED_PO 0 //PA0 上電復(fù)位指示
//以上信號(hào)皆為低電平有效
int main(void)
{
unsigned char CPU_STATUS;
unsigned char i;
//上電默認(rèn)DDRx=0x00,PORTx=0x00 輸入,無(wú)上拉電阻
PORTB =0xFF; //不用的管腳使能內(nèi)部上拉電阻。
PORTC =0xFF;
PORTD =0xFF;
PORTA =0xFF;
DDRA =(1<<LED_JT)|(1<<LED_WD)|(1<<LED_BO)|(1<<LED_EXT)|(1<<LED_PO); //輸出驅(qū)動(dòng)LED
CPU_STATUS =MCUCSR; //讀取MCU控制和狀態(tài)寄存器
//可以在JTAG調(diào)試時(shí)直接觀(guān)察 MCUCSR的狀態(tài)。
CPU_STATUS&=0x1F;
switch (CPU_STATUS)
{
case (1<<JTRF): //JTAG引起的復(fù)位?
PORTA&=~(1<<LED_JT);
break;
case (1<<WDRF): //看門(mén)狗引起的復(fù)位?
PORTA&=~(1<<LED_WD);
break;
case (1<<BORF): //BOD引起的復(fù)位?
PORTA&=~(1<<LED_BO);
break;
case (1<<EXTRF): //RESET引腳引起的復(fù)位?
PORTA&=~(1<<LED_EXT);
break;
case (1<<PORF): //上電引起的復(fù)位?
PORTA&=~(1<<LED_PO);
break;
default: //多種復(fù)位同時(shí)發(fā)生?
PORTA=~CPU_STATUS;
break;
}
MCUCSR=0x00; //清除標(biāo)志位
for(i=0;i<200;i++)
_delay_ms(10); //延時(shí)2秒
wdt_enable(WDTO_2S); //使能看門(mén)狗,溢出時(shí)間為2秒左右
while(1)
{
if (!(PINA&(1<<WDT_EN)))
wdt_reset(); //如果PA7為低電平時(shí),復(fù)位看門(mén)狗(喂狗)
}
}
[/code]
/*
程序運(yùn)行效果
如果PA7是高電平,不喂狗,則每2秒鐘看門(mén)狗復(fù)位一次,LED_WD亮
如果PA7是低電平,喂狗,則方便作如下實(shí)驗(yàn)
第一次上電時(shí),發(fā)生上電復(fù)位事件,LED_PO亮
按下復(fù)位按鍵,發(fā)上外部復(fù)位事件,LED_EXT亮
調(diào)節(jié)電源電壓調(diào)到4.0V(或2.7V)以下,然后調(diào)回5.0V(3.0V),發(fā)生BOD復(fù)位事件,LED_BO亮
在JTAG調(diào)試時(shí),使用[reset]功能,發(fā)生JTAG復(fù)位事件,LED_JT亮
注意:有時(shí)候會(huì)出現(xiàn)多種復(fù)位事件同時(shí)發(fā)生,例如:
上電的同時(shí)按住復(fù)位按鍵,將會(huì)同時(shí)發(fā)生 上電復(fù)位事件和外部復(fù)位事件
*/
/*
系統(tǒng)控制和復(fù)位
復(fù)位AVR 復(fù)位時(shí)所有的I/O 寄存器都被設(shè)置為初始值,程序從復(fù)位向量處開(kāi)始執(zhí)行。
復(fù)位向量處的指令必須是絕對(duì)跳轉(zhuǎn)JMP 指令,以使程序跳轉(zhuǎn)到復(fù)位處理例程。
如果程序永遠(yuǎn)不利用中斷功能,中斷向量可以由一般的程序代碼所覆蓋。
這個(gè)處理方法同樣適用于當(dāng)復(fù)位向量位于應(yīng)用程序區(qū),中斷向量位于Boot 區(qū) — 或者反過(guò)來(lái) — 的時(shí)候。
復(fù)位源有效時(shí)I/O 端口立即復(fù)位為初始值。此時(shí)不要求任何時(shí)鐘處于正常運(yùn)行狀態(tài)。
所有的復(fù)位信號(hào)消失之后,芯片內(nèi)部的一個(gè)延遲計(jì)數(shù)器被激活,將內(nèi)部復(fù)位的時(shí)間延長(zhǎng)。
這種處理方式使得在MCU 正常工作之前有一定的時(shí)間讓電源達(dá)到穩(wěn)定的電平。
延遲計(jì)數(shù)器的溢出時(shí)間通過(guò)熔絲位SUT 與CKSEL 設(shè)定。延遲時(shí)間的選擇請(qǐng)參見(jiàn) P23“ 時(shí)鐘源” 。
復(fù)位源ATmega16 有5 個(gè)復(fù)位源:
上電復(fù)位。電源電壓低于上電復(fù)位門(mén)限 VPOT 時(shí), MCU 復(fù)位。
外部復(fù)位。引腳 RESET 上的低電平持續(xù)時(shí)間大于最小脈沖寬度時(shí)MCU 復(fù)位。
看門(mén)狗復(fù)位??撮T(mén)狗使能并且看門(mén)狗定時(shí)器溢出時(shí)復(fù)位發(fā)生。
掉電檢測(cè)復(fù)位。掉電檢測(cè)復(fù)位功能使能,且電源電壓低于掉電檢測(cè)復(fù)位門(mén)限 VBOT 時(shí)MCU 即復(fù)位。
JTAG AVR復(fù)位。復(fù)位寄存器為1時(shí)MCU復(fù)位。詳見(jiàn) P215“IEEE 1149.1 (JTAG) 邊界掃描” 。
上電復(fù)位
上電復(fù)位(POR) 脈沖由片內(nèi)檢測(cè)電路產(chǎn)生。
無(wú)論何時(shí)VCC 低于檢測(cè)電平POR 即發(fā)生。
POR 電路可以用來(lái)觸發(fā)啟動(dòng)復(fù)位,或者用來(lái)檢測(cè)電源故障。
POR電路保證器件在上電時(shí)復(fù)位。
VCC 達(dá)到上電門(mén)限電壓后觸發(fā)延遲計(jì)數(shù)器。在計(jì)數(shù)器溢出之前器件一直保持為復(fù)位狀態(tài)。
當(dāng)VCC 下降時(shí),只要低于檢測(cè)門(mén)限,RESET 信號(hào)立即生效。
外部復(fù)位
外部復(fù)位由外加于RESET 引腳的低電平產(chǎn)生。
當(dāng)復(fù)位低電平持續(xù)時(shí)間大于最小脈沖寬度時(shí)即觸發(fā)復(fù)位過(guò)程,即使此時(shí)并沒(méi)有時(shí)鐘信號(hào)在運(yùn)行。
當(dāng)外加信號(hào)達(dá)到復(fù)位門(mén)限電壓VRST( 上升沿) 時(shí), tTOUT 延時(shí)周期開(kāi)始。
延時(shí)結(jié)束后MCU 即啟動(dòng)。
掉電檢測(cè)
ATmega16 具有片內(nèi)BOD(Brown-out Detection) 電路,通過(guò)與固定的觸發(fā)電平的對(duì)比來(lái)檢測(cè)工作過(guò)程中VCC 的變化。
此觸發(fā)電平通過(guò)熔絲位BODLEVEL 來(lái)設(shè)定, 2.7V(BODLEVEL 未編程),4.0V (BODLEVEL 已編程)。
BOD 的觸發(fā)電平具有遲滯功能以消除電源尖峰的影響。
這個(gè)遲滯功能可以解釋為VBOT+ = VBOT + VHYST/2 以及VBOT- = VBOT- VHYST/2。
BOD 電路的開(kāi)關(guān)由熔絲位BODEN控制。
當(dāng)BOD使能后(BODEN被編程),一旦VCC下降到觸發(fā)電平以下(VBOT-), BOD 復(fù)位立即被激發(fā)。
當(dāng)VCC 上升到觸發(fā)電平以上時(shí)(VBOT+),延時(shí)計(jì)數(shù)器開(kāi)始計(jì)數(shù),一旦超過(guò)溢出時(shí)間tTOUT,MCU即恢復(fù)工作。
如果VCC一直低于觸發(fā)電平并保持tBOD時(shí)間, BOD電路將只檢測(cè)電壓跌落。
看門(mén)狗復(fù)位
看門(mén)狗定時(shí)器溢出時(shí)將產(chǎn)生持續(xù)時(shí)間為1 個(gè)CK 周期的復(fù)位脈沖。
在脈沖的下降沿,延時(shí)定時(shí)器開(kāi)始對(duì)tTOUT 記數(shù)
MCU控制和狀態(tài)寄存器-MCUCSR
MCU 控制和狀態(tài)寄存器提供了有關(guān)引起MCU 復(fù)位的復(fù)位源的信息
Bit 4 – JTRF: JTAG 復(fù)位標(biāo)志
通過(guò)JTAG 指令A(yù)VR_RESET 可以使JTAG 復(fù)位寄存器置位,并引發(fā)MCU 復(fù)位,并使JTRF 置位。
上電復(fù)位將使其清零,也可以通過(guò)寫(xiě)”0” 來(lái)清除。
Bit 3 – WDRF: 看門(mén)狗復(fù)位標(biāo)志
看門(mén)狗復(fù)位發(fā)生時(shí)置位。
上電復(fù)位將使其清零,也可以通過(guò)寫(xiě)”0” 來(lái)清除。
Bit 2 – BORF: 掉電檢測(cè)復(fù)位標(biāo)志
掉電檢測(cè)復(fù)位發(fā)生時(shí)置位。
上電復(fù)位將使其清零,也可以通過(guò)寫(xiě)”0” 來(lái)清除。
Bit 1 – EXTRF: 外部復(fù)位標(biāo)志
外部復(fù)位發(fā)生時(shí)置位。
上電復(fù)位將使其清零,也可以通過(guò)寫(xiě)”0” 來(lái)清除。
Bit 0 – PORF: 上電復(fù)位標(biāo)志
上電復(fù)位發(fā)生時(shí)置位。
只能通過(guò)寫(xiě)”0” 來(lái)清除。
為了使用這些復(fù)位標(biāo)志來(lái)識(shí)別復(fù)位條件,用戶(hù)應(yīng)該盡早讀取此寄存器的數(shù)據(jù),然后將其復(fù)位。
如果在其他復(fù)位發(fā)生之前將此寄存器復(fù)位,則后續(xù)復(fù)位源可以通過(guò)檢查復(fù)位標(biāo)志來(lái)了解
看門(mén)狗定時(shí)器
看門(mén)狗定時(shí)器由獨(dú)立的1Mhz 片內(nèi)振蕩器驅(qū)動(dòng)。這是VCC = 5V 時(shí)的典型值。
通過(guò)設(shè)置看門(mén)狗定時(shí)器的預(yù)分頻器可以調(diào)節(jié)看門(mén)狗復(fù)位的時(shí)間間隔。
看門(mén)狗復(fù)位指令WDR 用來(lái)復(fù)位看門(mén)狗定時(shí)器。
此外,禁止看門(mén)狗定時(shí)器或發(fā)生復(fù)位時(shí)定時(shí)器也被復(fù)位。
復(fù)位時(shí)間有8 個(gè)選項(xiàng)。
如果沒(méi)有及時(shí)復(fù)位定時(shí)器,一旦時(shí)間超過(guò)復(fù)位周期, ATmega16 就復(fù)位,并執(zhí)行復(fù)位向量指向的程序。
為了防止無(wú)意之間禁止看門(mén)狗定時(shí)器,在看門(mén)狗禁用后必須跟一個(gè)特定的修改序列。
1. 在同一個(gè)指令內(nèi)對(duì)WDTOE 和WDE 寫(xiě)"1“,即使WDE 已經(jīng)為"1“
2. 在緊接的4 個(gè)時(shí)鐘周期之內(nèi)對(duì)WDE 寫(xiě)"0”
看門(mén)狗定時(shí)器控制寄存器-WDTCR
Bit 4 – WDTOE: 看門(mén)狗修改使能
清零WDE 時(shí)必須置位WDTOE,否則不能禁止看門(mén)狗。
一旦置位,硬件將在緊接的4個(gè)時(shí)鐘周期之后將其清零。請(qǐng)參考有關(guān)WDE 的說(shuō)明來(lái)禁止看門(mén)狗。
Bit 3 – WDE: 使能看門(mén)狗
WDE為"1“ 時(shí),看門(mén)狗使能,否則看門(mén)狗將被禁止。
只有在WDTOE為"1“ 時(shí)WDE 才能清零。以下為關(guān)閉看門(mén)狗的步驟:
1. 在同一個(gè)指令內(nèi)對(duì)WDTOE 和WDE 寫(xiě)"1“,即使WDE 已經(jīng)為"1“
2. 在緊接的4 個(gè)時(shí)鐘周期之內(nèi)對(duì)WDE 寫(xiě)"0”
Bits 2..0 – WDP2, WDP1, WDP0: 看門(mén)狗定時(shí)器預(yù)分頻器2, 1 和 0
WDP2、WDP1 和WDP0 決定看門(mén)狗定時(shí)器的預(yù)分頻器
WDP2 WDP1 WDP0 看門(mén)狗振蕩器周期 VCC=3.0V時(shí)典型的溢出周期 VCC=5.0V時(shí)典型的溢出周期
0 0 0 16K (16384) 17.1ms 16.3ms
0 0 1 32K (32768) 34.3ms 32.5ms
0 1 0 64K (65536) 68.5ms 65ms
0 1 1 128K (131072) 0.14s 0.13s
1 0 0 256K (262144) 0.27s 0.26s
1 0 1 512K (524288) 0.55s 0.52s
1 1 0 1024K (1048576) 1.1 s 1.0 s
1 1 1 2048K (2097152) 2.2 s 2.1 s
掉電檢測(cè)BOD的誤解
AVR自帶的BOD(Brown-out Detection)電路,作用是在電壓過(guò)低(低于設(shè)定值)時(shí)產(chǎn)生復(fù)位信號(hào),防止CPU意外動(dòng)作.
對(duì)EEPROM的保護(hù)作用是當(dāng)電壓過(guò)低時(shí)保持RESET信號(hào)為低,防止CPU意外動(dòng)作,錯(cuò)誤修改了EEPROM的內(nèi)容
而我們所理解的掉電檢測(cè)功能是指 具有預(yù)測(cè)功能的可以進(jìn)行軟件處理的功能。
例如,用戶(hù)想在電源掉電時(shí)把SRAM數(shù)據(jù)轉(zhuǎn)存到EEPROM,可行的方法是
外接一個(gè)在4.5V翻轉(zhuǎn)的電壓比較器(VCC=5.0V,BOD=2.7V),輸出接到外部中斷引腳(或其他中斷)
一但電壓低于4.5V,馬上觸發(fā)中斷,在中斷服務(wù)程序中把數(shù)據(jù)寫(xiě)到EEPROM中保護(hù)起來(lái)
注意: 寫(xiě)一個(gè)字節(jié)的EEPROM時(shí)間長(zhǎng)達(dá)8mS,所以不能寫(xiě)入太多數(shù)據(jù),電源濾波電容也要選大一些
*/