請教,EEPROM存儲的數據,斷電后再上電,數據發生變化的原因。
#include"STC8G.H"
#include"intrins.H"
#include"ADC.h"
#include"NTC.h"
#include"GPIO.h"
#include"TIMER.h"
#include"HC595_DISPLAY.h"
//==================== 引腳定義 ====================
sbit KEY_ADD = P3^2; // 加鍵
sbit KEY_SUB = P1^4; // 減鍵
sbit KEY_OK = P1^7; // 確認鍵
sbit BEEP = P1^5; // 蜂鳴器
sbit ADC_TEMP = P1^1;
unsigned int temp_real; // 實際溫度值
unsigned int temp_high; // 高溫閾值
unsigned int temp_low; // 低溫閾值
unsigned char set_mode = 0; // 設置模式標志:0=正常模式,1=設置高溫,2=設置低溫
// EEPROM 地址定義
#define EEPROM_ADDR_H 0x0000
#define EEPROM_ADDR_L 0x0001
#define EEPROM_ADDR 0x0000
void IAP_IDLE(void);
unsigned char IAP_Read(unsigned int addr);
void IAP_Write(unsigned int addr,unsigned char dat);
void IAP_Erase(unsigned int addr);
// 延時函數
void Delay_ms(unsigned int ms)
{
unsigned int i,j;
for(i=0;i<ms;i++)
for(j=0;j<24*85;j++);
}
void IAP_IDLE(void)
{
IAP_CONTR = 0;
IAP_CMD = 0;
IAP_TRIG = 0;
IAP_ADDRH = 0x80;
IAP_ADDRL = 0;
}
// 單字節讀
unsigned char IAP_Read(unsigned int addr)
{
char dat;
IAP_CONTR = 0x80;
IAP_TPS = 24;
IAP_CMD = 0x01;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5a;
IAP_TRIG = 0xa5;
_nop_();
dat = IAP_DATA;
IAP_IDLE();
return dat;
}
// 單字節寫
void IAP_Write(unsigned int addr,unsigned char dat)
{
IAP_CONTR = 0x80;
IAP_TPS = 24;
IAP_CMD = 0x02;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_DATA = dat;
IAP_TRIG = 0x5a;
IAP_TRIG = 0xa5;
_nop_();
IAP_IDLE();
}
void IAP_Erase(unsigned int addr)
{
IAP_CONTR = 0x80;
IAP_TPS = 24;
IAP_CMD = 0x03;
IAP_ADDRL = addr;
IAP_ADDRH = addr >> 8;
IAP_TRIG = 0x5A;
IAP_TRIG = 0xA5;
_nop_();
IAP_IDLE();
}
void Key_Scan(void)
{
if(KEY_OK == 0) // 確認鍵按下
{
Delay_ms(20);
if(KEY_OK == 0)
{
set_mode++;
if(set_mode > 2) set_mode = 0;
// 退出設置模式時,保存參數到EEPROM
if(set_mode == 0)
{
IAP_Erase(EEPROM_ADDR); // 先擦除片區
IAP_Write(EEPROM_ADDR_H, temp_high); // 保存高溫
IAP_Write(EEPROM_ADDR_L, temp_low); // 保存低溫 }
while(KEY_OK == 0); // 等待松開
}
}
if(set_mode != 0) // 設置模式下才響應加減鍵
{
if(KEY_ADD == 0)
{
Delay_ms(20);
if(KEY_ADD == 0)
{
if(set_mode == 1) temp_high++; // 設置高溫
if(set_mode == 2) temp_low++; // 設置低溫
while(KEY_ADD == 0);
}
}
if(KEY_SUB == 0)
{
Delay_ms(20);
if(KEY_SUB == 0)
{
if(set_mode == 1 && temp_high > 0) temp_high--;
if(set_mode == 2 && temp_low > 0) temp_low--;
while(KEY_SUB == 0);
}
}
}
}
// 報警判斷函數
void Alarm_Check(void)
{
if(set_mode == 0) // 正常模式才報警
{
if(temp_real > temp_high || temp_real < temp_low)
BEEP = 0; // 超閾值,蜂鳴器響
else
BEEP = 1; // 正常,蜂鳴器關
}
else
{
BEEP = 1; // 設置模式關閉報警
}
}
// 主函數
void main(void)
{
unsigned char i;
unsigned int j;
// 初始化
GPIO_Init();
ADC_Init();// ADC初始化
Timer0_Init();
BEEP = 1;
for(i=0; i<8; i++) DisplayBuff [i] = 0xff; //上電消隱 1111 1111
temp_high = IAP_Read(EEPROM_ADDR_H);
temp_low = IAP_Read(EEPROM_ADDR_L);
// 上電默認值(防止首次使用EEPROM無數據)
if(temp_high == 0xFF || temp_high == 0) temp_high = 300;
if(temp_low == 0xFF || temp_low == 0) temp_low = 50;
while(1)
{
if(!AUTO_ISP) IAP_CONTR = 0x60;
Key_Scan(); // 按鍵掃描
while(!g_bSystemTime1Ms) ; //等待1ms到
g_bSystemTime1Ms = 0;
if(++j >= 40) //40ms到
{
j = 0;
temp_real = Get_temperature(ADC_Read_Oversample(1)); // 采集實際溫度
if(temp_real >= 0)
{
F0 = 0;
temp_real = temp_real;
}
else
{
F0 = 1;
temp_real = -temp_real;
}
DisplayBuff[7] = (temp_real / 1000); //顯示數值
DisplayBuff[6] = (temp_real / 100) % 10;
DisplayBuff[5] = (temp_real / 10) % 10 + DIS_DOT; //十位 + 小數點(帶小數點顯示)
DisplayBuff[4] = temp_real % 10;
// 千位為 0 時不顯示(消零),顯示黑位(不亮)
if(DisplayBuff[7] == 0)
DisplayBuff[7] = DIS_BLACK;
if(F0 == 1)
DisplayBuff[7] = DIS_;
if((temp_real > 1200) && (temp_real < TEMP_MIN*10))
{
for(i=0; i<4; i++) DisplayBuff[i] = DIS_;
}
if(temp_high >= 0)
{
F0 = 0;
temp_high = temp_high;
}
else
{
F0 = 1;
temp_high = -temp_high;
}
DisplayBuff[3] = (temp_high / 1000); //顯示數值
DisplayBuff[2] = (temp_high / 100) % 10;
DisplayBuff[1] = (temp_high / 10) % 10 + DIS_DOT; //十位 + 小數點(帶小數點顯示)
DisplayBuff[0] = temp_high % 10;
if(DisplayBuff[3] == 0)
DisplayBuff[3] = DIS_BLACK;
if(F0 == 1)
DisplayBuff[3] = DIS_;
if((temp_high > 1200) && (temp_high < TEMP_MIN*10))
{
for(i=0; i<4; i++) DisplayBuff[i] = DIS_;
}
}
Alarm_Check(); // 報警判斷
}
}
|