下面是EEPROM里面的數(shù)據(jù)儲(chǔ)存結(jié)構(gòu)[嘻嘻,圖畫得有點(diǎn)不好,技術(shù)問題請(qǐng)見諒啦..]
首先從主控入口代碼處進(jìn)行分析:
#define EEPROM_StartAddr 0x4E
#define EEPROM_StartFlag 0xB0
LED=1;
BitData=read_add(EEPROM_StartAddr);
if (BitData!=EEPROM_StartFlag) while(1);
ListTotal=read_add(EEPROM_StartAddr+1);
for(i=0;i<ListTotal;i++)
{
CtrlList[i].AlarmTemp=read_add((EEPROM_StartAddr+2)+i*3);
CtrlList[i].CtrlPort =read_add((EEPROM_StartAddr+2)+i*3+1);
}
LED=0;
代碼首先會(huì)從EEPROM里面讀取0x4E位里面的數(shù)據(jù)來和EEPROM起始數(shù)據(jù)位標(biāo)志進(jìn)行對(duì)比,判斷這個(gè)EEPROM的數(shù)據(jù)格式的正確性,由于沒有讓
主控芯片對(duì)每一個(gè)數(shù)據(jù)位進(jìn)行校驗(yàn),那么這就是一個(gè)簡(jiǎn)單的驗(yàn)證方法,要是對(duì)每一位數(shù)據(jù)都要進(jìn)行的驗(yàn)證的話得需要一個(gè)可靠,高效的算法,這樣雖
然安全,不過會(huì)對(duì)主控芯片初始化有一定的性能影響
判斷起始數(shù)據(jù)位失敗后,主控芯片會(huì)進(jìn)入到卡死狀態(tài)[見代碼 while(1); ,死循環(huán),處理器永遠(yuǎn)也跳不出這個(gè)循環(huán)到外面]
判斷起始數(shù)據(jù)位成功后,下一步就從EEPROM的0x4F位讀取出需要控制溫度的項(xiàng)目總數(shù),然后再按照這個(gè)項(xiàng)目總數(shù)來進(jìn)行數(shù)據(jù)位偏移來讀取將要
控制的溫度數(shù)值和警報(bào)控制端口,注意兩個(gè)控制數(shù)據(jù)結(jié)構(gòu)中間需要用一個(gè)NULL[即0x00]來隔開來,防止數(shù)據(jù)結(jié)構(gòu)被打亂
從EEPROM里面讀取完成數(shù)據(jù)后,主控芯片工作指示燈發(fā)光,開始進(jìn)入溫度控制
主要代碼:
while(1)
{
TempData=get_temp();
BitData=(TempData%1000/100)*10;//十位溫度。
BitData=(TempData%1000%100/10)+BitData;//個(gè)位溫度。
for(i=0;i<ListTotal;i++)
{
CtrlElec=(CtrlList[i].AlarmTemp>=BitData)?0:1;
CtrlListPort=CtrlList[i].CtrlPort;
CtrlPort(CtrlListPort,CtrlElec); //符合條件輸出底電,不符合輸出高電
delayb(100);
}
delayb(200);
}
這個(gè)可不像SetTimer()一樣,用SetTimer()指定了的函數(shù)不需要加上while 循環(huán),僅且把上面的代碼當(dāng)作線程來看待,讓這個(gè)線程運(yùn)行的代碼段永遠(yuǎn)
都是這個(gè),假如線程的代碼一旦執(zhí)行完畢[也就是說跳出了while 死循環(huán)],那么它就會(huì)關(guān)閉掉自己和釋放屬于自己的TLS[線程本地儲(chǔ)存]
先從DS18B02里面讀取出來溫度值,然后再對(duì)溫度進(jìn)行轉(zhuǎn)換,把轉(zhuǎn)換好的溫度再和從EEPROM里面讀取出來的數(shù)據(jù)結(jié)構(gòu)進(jìn)行比較
一個(gè)溫度控制判斷周期約一秒[以12MHz來計(jì)算的話,應(yīng)該是略大于一秒而不會(huì)小于一秒]..
下面是溫度控制器的電路:
5V供電電路:
主控芯片及外圍器件電路:
電路中用繼電器來控制外部電路的開閉,G[公共端] B[常閉端] K[常開端] 就是讓繼電器控制外部電路的開關(guān),5V電壓和P1^0端口是用來控制繼電器
的G端和B,K端通路.原理如下:
單片機(jī)通過引腳輸出 1 0來實(shí)現(xiàn)控制外圍電路,以P1^0[P1端口的第1位引腳]為例,當(dāng)P1^0輸出1的時(shí)候,引腳會(huì)產(chǎn)生一個(gè)5V的高電平.當(dāng)P1^0輸出0
的時(shí)候,引腳會(huì)產(chǎn)生一個(gè)0V的低電平
注:繼電器原理圖來自百度百科-> http://baike.baidu.com/view/39560.htm
繼電器原理:當(dāng)控制電路兩端有電流通過時(shí),電和金屬發(fā)生電磁感應(yīng),使得銜鐵被磁力吸引而控制工作電路的開關(guān)
下面是main.c 文件:
#include <reg51.h>
#define uchar unsigned char
#define uint unsigned int
#define EEPROM_StartAddr 0x4E
#define EEPROM_StartFlag 0xB0
/*
#define EEPROM_EndFlag 0xC0
#define EEPROM_EndAddr 0x4E+2+24 //8個(gè)數(shù)據(jù)總數(shù)x3個(gè)數(shù)據(jù)位
//EEPROM_EndAddr=0x4E+2+8x03 每個(gè)數(shù)據(jù)占3字節(jié)(兩個(gè)主要數(shù)據(jù)和一個(gè)NULL),0x49系獲得數(shù)據(jù)項(xiàng)目總數(shù)
*/
typedef int CTRL_TOTAL;//列表總項(xiàng)目
typedef struct EEPROM_DataList//EEPROM數(shù)據(jù)結(jié)構(gòu)
{
int AlarmTemp;//報(bào)警溫度
int CtrlPort; //控制端口
} CTRL_DATALIST;
uint get_temp();
void tmpchange(void);
void delayb(uint count);
void init();
void write_add(uchar address,uchar date);
uchar read_add(uchar address);
void CtrlPort(int PortCode,int Ctrl);
sbit Beep=P3^4; // 測(cè)試用,可略
sbit LED=P2^7;
sbit CtrlPort1=P1^0;
sbit CtrlPort2=P1^1;
sbit CtrlPort3=P1^2;
sbit CtrlPort4=P1^3;
sbit CtrlPort5=P1^4;
sbit CtrlPort6=P1^5;
sbit CtrlPort7=P1^6;
sbit CtrlPort8=P1^7;
CTRL_TOTAL ListTotal;
CTRL_DATALIST CtrlList[8];
void delayb(uint count) ;
void main()
{
int BitData; // EEPROM位數(shù)據(jù)緩存
int i; // 計(jì)數(shù)循環(huán)變量
int TempData; // 當(dāng)前溫度值
int CtrlListPort; // 將要控制的引腳
int CtrlElec; // 將要控制的引腳輸出電平
LED=1;
init();
BitData=read_add(EEPROM_StartAddr);
if (BitData!=EEPROM_StartFlag){while(1);} // 卡住它,不要讓它重新運(yùn)行
// 關(guān)于EEPROM獲取數(shù)據(jù)信息可以從同文件夾中圖片有指導(dǎo)
ListTotal=read_add(EEPROM_StartAddr+1);
for(i=0;i<ListTotal;i++)
{
CtrlList[i].AlarmTemp=read_add((EEPROM_StartAddr+2)+i*3);
CtrlList[i].CtrlPort =read_add((EEPROM_StartAddr+2)+i*3+1);
}
tmpchange();
for(i=0;i<=7;i++) CtrlPort(i,1); //輸出高電位
LED=0; //工作指示燈開啟
while(1)
{
TempData=get_temp();
BitData=(TempData%1000/100)*10; //十位溫度。
BitData=(TempData%1000%100/10)+BitData;//個(gè)位溫度。
for(i=0;i<ListTotal;i++)
{
CtrlElec=(CtrlList[i].AlarmTemp>=BitData)?0:1;
CtrlListPort=CtrlList[i].CtrlPort;
CtrlPort(CtrlListPort,CtrlElec); //符合條件輸出底電,不符合輸出高電
delayb(100);
}
delayb(200);
}
}
void CtrlPort(int PortCode,int Ctrl)//控制P1.0-P1-7
{
switch(PortCode)
{
case 1: CtrlPort1=Ctrl;
case 2: CtrlPort2=Ctrl;
case 3: CtrlPort3=Ctrl;
case 4: CtrlPort4=Ctrl;
case 5: CtrlPort5=Ctrl;
case 6: CtrlPort6=Ctrl;
case 7: CtrlPort7=Ctrl;
case 8: CtrlPort8=Ctrl;
}
}