- //測試條件:TX-1C實驗板,MCU型號IAP15W4K58S4
- //注意:測試本示例時,需在ISP下載時將【低壓復位】功能和【低壓時禁止EEPROM操作】關閉
- //說明:本示例采用一個扇區寫滿再擦除的方式是嘗試延長EEPROM使用壽命,如需要頻繁寫
- //EEPROM,可改為所有扇區寫滿再擦除的方式。
- #include "STC15Fxxxx.H"
- #include <intrins.h> //庫頭文件
- #define uint unsigned int //宏定義數據類型uint
- #define uchar unsigned char //宏定義數據類型uchar
- //宏定義ISP的操作命令
- #define CMD_IDLE 0 //空閑模式
- #define CMD_READ 1 //IAP字節讀命令
- #define CMD_PROGRAM 2 //IAP字節編程命令
- #define CMD_ERASE 3 //IAP扇區擦除命令
- #define ENABLE_IAP 0x82 //CPU的等待時間
- #define IAP_ADDRESS 0x0800 //測試地址
- sbit duan=P2^6;
- sbit wein=P2^7;
- sbit buzzer=P2^3;
- //順序共陰極數碼管段碼表,段碼a-h順序接PX0-PX7
- uchar code table[]={//共陰數碼管段碼"0~f-."
- 0x3f,0x06,0x5b,0x4f,
- 0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,
- 0x39,0x5e,0x79,0x71,0x40,0x80};
- uchar data dis_buf[8]; //緩存數組
- uint num,sec;
- uchar i;
- uint sign;
- void Timer0Init(); //定時器初始化聲明
- void IapIdle(); //關閉IAP/EEPROM
- uchar IapReadByte(uint addr); //讀取EEPROM數據
- void IapProgramByte(uint addr, uchar dat);//寫入EEPROM數據
- void IapEraseSector(uint addr); //擦除EEPROM數據
- void main()
- {
- P0M0 = 0x00;
- P0M1 = 0x00;
- P1M0 = 0x00;
- P1M1 = 0x00;
- P2M0 = 0x00;
- P2M1 = 0x00;
- P3M0 = 0x00;
- P3M1 = 0x00;
- P4M0 = 0x00;
- P4M1 = 0x00;
- P5M0 = 0x00;
- P5M1 = 0x00;
- P6M0 = 0x00;
- P6M1 = 0x00;
- P7M0 = 0x00;
- P7M1 = 0x00;
- if(IapReadByte(IAP_ADDRESS)==0xff)//如果沒有保存過數據存儲器初始值=0xff
- {
- IapProgramByte(IAP_ADDRESS, 0);//扇區首地址寫0
- sec=0;
- sign=1;
- }
- else
- {
- // for(i=1;i<12;i++)//測試寫10次
- for(i=1;i<511;i++)//測試寫滿510個字節
- {
- if(IapReadByte(IAP_ADDRESS+i)==0xff)//如果遇到沒有保存數據的單元
- {
- sec=IapReadByte(IAP_ADDRESS+i-1);//讀取前一個字節保存的數據
- sign=i;//地址緩存
- break;//跳出循環
- }
- }
- }
- // if(sign==11)//測試寫10次
- if(sign==510)//如果寫滿510
- {
- IapEraseSector(IAP_ADDRESS);//擦除扇區
- IapProgramByte(IAP_ADDRESS, 0);//首地址寫0
- sign=1;
- buzzer=0;
- }
- PCON &= 0xDF;//清0掉電標志
- ELVD = 1;//開低壓中斷
- EA = 1;//開總中斷
- Timer0Init();//初始化定時器
- while(1)
- {
- if(TF0)//查詢T0中斷請求標志
- {
- TF0=0;//T0中斷請求標志清0
- if(++num>=1000)//1秒
- {
- buzzer=1;
- num=0;
- sec=++sec%250;
- }
- dis_buf[0]=table[sec/100%10];
- dis_buf[1]=table[sec/10%10];
- dis_buf[2]=table[sec%10];
- P0=0x00;duan=1;duan=0;
- P0=~(0x01<<i);wein=1;wein=0;
- P0=dis_buf[i];duan=1;duan=0;
- i=++i%3;
- }//耗時569us
- }
- }
- void Timer0Init(void) //1毫秒@11.0592MHz
- {
- AUXR |= 0x80; //定時器時鐘1T模式
- TMOD &= 0xF0; //設置定時器模式
- TL0 = 0xCD; //設置定時初始值
- TH0 = 0xD4; //設置定時初始值
- TF0 = 0; //清除TF0標志
- TR0 = 1; //定時器0開始計時
- }
- /*----------------------------
- 關閉IAP功能
- ----------------------------*/
- void IapIdle()
- {
- IAP_CONTR = 0; //關閉IAP功能
- IAP_CMD = 0; //清除命令寄存器
- IAP_TRIG = 0; //清除觸發寄存器
- IAP_ADDRH = 0x80; //將地址設置到非IAP區域
- IAP_ADDRL = 0;
- }
- /*----------------------------
- 從ISP/IAP/EEPROM區域讀取一字節
- ----------------------------*/
- uchar IapReadByte(uint addr)
- {
- uchar dat; //數據緩沖區
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_READ; //設置IAP命令
- IAP_ADDRL = addr; //設置IAP低地址
- IAP_ADDRH = addr >> 8; //設置IAP高地址
- IAP_TRIG = 0x5a; //寫觸發命令(0x5a)
- IAP_TRIG = 0xa5; //寫觸發命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- dat = IAP_DATA; //讀ISP/IAP/EEPROM數據
- IapIdle(); //關閉IAP功能
- return dat; //返回
- }
- /*-------------------------------
- 寫一字節數據到ISP/IAP/EEPROM區域
- --------------------------------*/
- void IapProgramByte(uint addr, uchar dat)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_PROGRAM; //設置IAP命令
- IAP_ADDRL = addr; //設置IAP低地址
- IAP_ADDRH = addr >> 8; //設置IAP高地址
- IAP_DATA = dat; //寫ISP/IAP/EEPROM數據
- IAP_TRIG = 0x5a; //寫觸發命令(0x5a)
- IAP_TRIG = 0xa5; //寫觸發命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle(); //關閉IAP功能
- }
- /*----------------------------
- ISP/IAP/EEPROM扇區擦除
- ----------------------------*/
- void IapEraseSector(uint addr)
- {
- IAP_CONTR = ENABLE_IAP; //使能IAP
- IAP_CMD = CMD_ERASE; //設置IAP命令
- IAP_ADDRL = addr; //設置IAP低地址
- IAP_ADDRH = addr >> 8; //設置IAP高地址
- IAP_TRIG = 0x5a; //寫觸發命令(0x5a)
- IAP_TRIG = 0xa5; //寫觸發命令(0xa5)
- _nop_(); //等待ISP/IAP/EEPROM操作完成
- IapIdle(); //關閉IAP功能
- }
- void PowerLost() interrupt 6
- {
- EA = 0; //關閉總中斷
- P0M1 = 0xff; //根據實際硬件環境,設置端口模式減少耗電
- P1M1 = 0xff;
- P2M1 = 0xff;
- P3M1 = 0xff;
- P4M1 = 0xff;
- P5M1 = 0xff;
- P6M1 = 0xff;
- P7M1 = 0xff;
- IapProgramByte(IAP_ADDRESS+sign,sec);//寫數據到EEPROM
- while((PCON & 0x20) != 0) //復查低壓標志
- {
- PCON &= 0xDF; //清除低壓標志
- _nop_();
- _nop_(); //坐等掉電
- }
- IAP_CONTR = 0x20; //發現是誤報,重啟單片機,恢復正常工作
- }
復制代碼
|