1 比較器
斷電時立即產(chǎn)生中斷,通知CPU保存程序運行過程中的重要數(shù)據(jù)(由于電路板 上有電容存儲能量,外部斷電時單片機還可繼續(xù)運行一個短暫時間),我們選擇 數(shù)據(jù)保存位置為單片機內(nèi)部DataFlash存儲器,舉個例子:某產(chǎn)品需要進行壽命 測試,產(chǎn)品運行一個循環(huán)單片機記錄一次,但運行過程中可能會突然斷電,要求 重新上電后壽命測試繼續(xù)運行,并且要求實際運行次數(shù)準確,這就需要用到單片 機內(nèi)部比較器與DataFlash存儲器斷電瞬間存儲數(shù)據(jù)的功能。
表7-1 比較控制寄存器1:CMPCR1 (復位值是:0000 0000B)
位 | D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
位名稱 | CMPEN | CMPIF | PIE | NIE | PIS | NIS | CMPOE | CMPRES |
關(guān)閉。
n CMPIF :比較器中斷標志位。當比較器的比較結(jié)果由LOW變成HIGH時,若是PIE被設(shè)置成
1,那么內(nèi)部的一個 叫做CMPIF_p的位會被設(shè)置成1,當比較器的比較結(jié)果由HIGH變成LOW 時,若是NIE被設(shè)置成1,那么內(nèi)部的一個 叫做CMPIF_n的位會被設(shè)置成1,當CPU去讀此中斷 標志位CMPIF時,會讀到(CMPIF_p || CMPIF n),當CPU對此中斷標志位CMPIF寫0后, CMPIF_p以及CMPIF_n都會被清除為O,而中斷產(chǎn)生的條件是[(EA==1)&& (((PIE=l)&&(CMPIF_p==l)) || ((NIE==1)&&(CMPIF_n==l)))],CPU進入中斷函數(shù)后,并不 會自動清除此CMPIF標志,用戶必須用軟件寫”0”去清除它。
= 1產(chǎn)生中斷,0:禁用比較器由LOW變HIGH的事件引發(fā)CMPIF_p = 1產(chǎn)生中斷。
n NIE:比較器下降沿中斷使能位。1,使能比較器由HIGH變LOW的事件引發(fā)CMPIF_n
= 1產(chǎn)生中斷;0:禁用比較器由HIGH變LOW的事件引發(fā)CMPIF_n = 1產(chǎn)生中斷。
n PIS: 比較器正極選擇位。1:選擇ADC_CONTR[2:0]所選擇到的ADC輸入引腳作為比 較器的正極輸入源; 0:選擇外部P5.5為比較器的正極輸入源。
n NIS: 比較器負極選擇位。1:選擇外部管腳P5.4為比較器的負極輸入源,0:選擇 內(nèi)部約1.27V的BandGap參考電壓為比較器的負極輸入源。
n CMPOE:比較結(jié)果輸出控制位。1,使能比較器的比較結(jié)果輸出到P1.2, 0,禁止比 較器的比較結(jié)果輸出。
n CMPRES:比較器比較結(jié)果標志位。1: CMP+的電平高于CMP-的電平(或內(nèi)部1.27V 的BandGap參考電壓); 0: CMP+的電平低于CMP-的電平(或內(nèi)部1.27V的BandGap 參考電壓)。此bit是一個“只讀”的bit;軟件對它做寫入的動作沒有任何意義, 軟件所讀到的結(jié)果是“經(jīng)過延時控制后的結(jié)果”,而非模擬比較器的直接輸出結(jié) 果。
出,比較器的輸出是經(jīng)過延時控制后的結(jié)果,而非模擬比較器的直接輸出結(jié)果。
n DISFLT:去除比較器輸出的0.luS 延時控制。1:去除比較器輸出的O.luS延時控制(可以 讓比較器速度有少許提升);0:比較器的輸出有O.luS延時控制。
n LCDTY[5:0]:比較器輸出端 Level-Change control的延時時鐘選擇,假設(shè)設(shè)置值為 bbbbbb,當比較器由LOW變HIGH后必須偵測到HIGH持續(xù)至少bbbbbb個時鐘,此芯片線路才認定 比較器的輸出是由LOW轉(zhuǎn)成HIGH,如果在bbbbbb個時鐘內(nèi),模擬比較器的輸出又回復到LOW, 此線路認為甚么都沒發(fā)生,視同比較器的輸出一直維持在LOW,當比較器由HIGH變LOW,必須 偵測到LOW持續(xù)至少bbbbbb個時鐘,此線路才認定比較器的輸出是由HIGH轉(zhuǎn)成LOW,如果在 bbbbbb個時鐘內(nèi),比較器的輸出又回復到HIGH,此線路認為甚么都沒發(fā)生,視同比較器的輸 出一直維持在HIGH. 若是設(shè)定成000000,代表沒有Level-Change Control。
CMPCR2=0x00; // 0000 0000,比較器只延時0.1uS
STC15F2K60S2單片機內(nèi)部集成了1K字節(jié)的數(shù)據(jù)Flash存儲器(也稱作DataFlash)可當作EEPROM使 用,地址范圍是0000H~03FFH,與程序Flash存儲器空間是分開的,這1K字節(jié)的數(shù)據(jù)Flash存儲器分 為2個扇區(qū),每個扇區(qū)包含512字節(jié),對應(yīng)的地址范圍分別為:第一扇區(qū):0000H~01FFH,第二扇區(qū):
Flash存儲器的操作提示:
① 對Flash存儲器進行字節(jié)編程時,只能將1改為0,或1保持為1、0保持為0。如果該字節(jié)是
② 如果在一個扇區(qū)中存放了大量的數(shù)據(jù),某次只需要修改其中的一個字節(jié)或一部分字節(jié)時,則另外 的不需要修改的數(shù)據(jù)須先讀出放在單片機的RAM中,然后擦除整個扇區(qū),再將需要保留的數(shù)據(jù)和需修 改的數(shù)據(jù)一并寫回該扇區(qū)中,這時,每個扇區(qū)使用的字節(jié)數(shù)越少越方便(不需讀出一大堆需保留數(shù) 據(jù))。
7.2.2 DataFlash操作實驗(斷電瞬間存儲數(shù)據(jù)) 例7.3 STC15F2K60S2單片機內(nèi)部DataFlash讀寫測試
本程序上電時先擦除DataFlash的第1個扇區(qū),然后將第1個扇區(qū)的前半扇區(qū)與后半扇區(qū)分別寫入數(shù) 據(jù)0~255,然后讀出數(shù)據(jù)并判斷與寫入的數(shù)據(jù)是否一致,并通過串口助手顯示程序運行過程中的數(shù) 據(jù)與最終結(jié)果是否正常,R/C時鐘頻率22.1184MHz,串口通信波特率9600。
#define EEP_address 0x0000 // 主程序從0000地址開始讀寫數(shù)據(jù)
/////////////////////////// 主程序:Flash_Test.C ///////////////////////////////
#include "FLASH.H"
#include "uart_debug.h" void main()
{
unsigned char a;
unsigned int i;
UART_init(); // 波特率:9600 /22.1184MHZ(占用定時器1) UART_Send_Str("開始擦除\n");
EEPROM_SectorErase(EEP_address); // 扇區(qū)擦除 UART_Send_Str("擦除完畢\n");
for (i=0; i<512; i++) // 檢測是否擦除成功(全FF檢測)
說明:IAP15W4K58S4與STC15F2K60S2內(nèi)部DataFlash唯一不同的只有地址值不一樣,為了防 止誤寫有效程序區(qū),程序編譯完成后進入軟件調(diào)試環(huán)境,打開存儲器窗口,我們會看到有 效的程序代碼都存放在存儲單元地址的低端,從原則上來說,凡是地址高端的FLASH空白區(qū) 域都可以當做EEPROM使用,對于IAP15W4K58S4芯片,具有58K字節(jié)的FLASH存儲空間,由于
1K=1024字節(jié),58×1024=59392字節(jié),存儲單元地址從0開始算起,地址范圍是0~59391, 用16進制表示為0000H~E7FFH,因為每個扇區(qū)包含512個字節(jié),59392/512=116個扇區(qū),最 后3個扇區(qū)地址范圍如表7-6所示,一般我們使用最后3個扇區(qū)地址已經(jīng)夠用了,比如本例, 我們使用最后一個扇區(qū),程序中使用代碼:
#define EEP_address 0xE600 即可。
表7-6 IAP15W4K58S4單片機內(nèi)部DataFlash地址末尾3個扇區(qū)地址
第114扇區(qū) |
| 第115扇區(qū) |
| 第116扇區(qū) |
|
起始地址 | 結(jié)束地址 | 起始地址 | 結(jié)束地址 | 起始地址 | 結(jié)束地址 |
E200H | E3FFH | E400H | E5FFH | E600H | E7FFH |
void cmp()interrupt 21 | // | 較器中斷函數(shù) |
{ |
|
|
CMPCR1 &=0xBF; | // | 清除中斷標志, 1011 1111 |
LED0 = CMPCR1&0x01; | // | 將比較器結(jié)果CMPRES輸出到測試口顯示 |
if (LED0==0) |
| // 掉電 |
{ |
|
|
EA=0; | // | 防止更高級的中斷打斷 |
EA=1; // 進入正常工作時打開總中斷 EEPROM_SectorErase(EEP_address); // 當?shù)綦姾箅妷航德浔容^快時,在這里先擦除 UART_Send_StrNum("計數(shù)值:",Power_up.times);
// 串口輸出計數(shù)值,波特率:9600 /22.1184MHZ
{
delay1S();
Power_up.times++; // 秒計時器加1
UART_Send_StrNum("計數(shù)值:",Power_up.times);
}
}
歡迎光臨 (http://www.torrancerestoration.com/bbs/) | Powered by Discuz! X3.1 |