下面是EEPROM里面的数据储存结构[嘻嘻,图画得有点不好,技术问题请见谅啦..]
首先从主控入口代码处进行分析:
#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;
代码首先会从EEPROM里面读取0x4E位里面的数据来和EEPROM起始数据位标志进行对比,判断这个EEPROM的数据格式的正确性,由于没有让
主控芯片对每一个数据位进行校验,那么这就是一个简单的验证方法,要是对每一位数据都要进行的验证的话得需要一个可靠,高效的算法,这样虽
然安全,不过会对主控芯片初始化有一定的性能影响
判断起始数据位失败后,主控芯片会进入到卡死状态[见代码 while(1); ,死循环,处理器永远也跳不出这个循环到外面]
判断起始数据位成功后,下一步就从EEPROM的0x4F位读取出需要控制温度的项目总数,然后再按照这个项目总数来进行数据位偏移来读取将要
控制的温度数值和警报控制端口,注意两个控制数据结构中间需要用一个NULL[即0x00]来隔开来,防止数据结构被打乱
从EEPROM里面读取完成数据后,主控芯片工作指示灯发光,开始进入温度控制
主要代码:
while(1)
{
TempData=get_temp();
BitData=(TempData%1000/100)*10;//十位温度。
BitData=(TempData%1000%100/10)+BitData;//个位温度。
for(i=0;i<ListTotal;i++)
{
CtrlElec=(CtrlList[i].AlarmTemp>=BitData)?0:1;
CtrlListPort=CtrlList[i].CtrlPort;
CtrlPort(CtrlListPort,CtrlElec); //符合条件输出底电,不符合输出高电
delayb(100);
}
delayb(200);
}
这个可不像SetTimer()一样,用SetTimer()指定了的函数不需要加上while 循环,仅且把上面的代码当作线程来看待,让这个线程运行的代码段永远
都是这个,假如线程的代码一旦执行完毕[也就是说跳出了while 死循环],那么它就会关闭掉自己和释放属于自己的TLS[线程本地储存]
先从DS18B02里面读取出来温度值,然后再对温度进行转换,把转换好的温度再和从EEPROM里面读取出来的数据结构进行比较
一个温度控制判断周期约一秒[以12MHz来计算的话,应该是略大于一秒而不会小于一秒]..
下面是温度控制器的电路:
5V供电电路:
主控芯片及外围器件电路:
电路中用继电器来控制外部电路的开闭,G[公共端] B[常闭端] K[常开端] 就是让继电器控制外部电路的开关,5V电压和P1^0端口是用来控制继电器
的G端和B,K端通路.原理如下:
单片机通过引脚输出 1 0来实现控制外围电路,以P1^0[P1端口的第1位引脚]为例,当P1^0输出1的时候,引脚会产生一个5V的高电平.当P1^0输出0
的时候,引脚会产生一个0V的低电平
注:继电器原理图来自百度百科-> http://baike.baidu.com/view/39560.htm
继电器原理:当控制电路两端有电流通过时,电和金属发生电磁感应,使得衔铁被磁力吸引而控制工作电路的开关
下面是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个数据总数x3个数据位
//EEPROM_EndAddr=0x4E+2+8x03 每个数据占3字节(两个主要数据和一个NULL),0x49系获得数据项目总数
*/
typedef int CTRL_TOTAL;//列表总项目
typedef struct EEPROM_DataList//EEPROM数据结构
{
int AlarmTemp;//报警温度
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; // 测试用,可略
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位数据缓存
int i; // 计数循环变量
int TempData; // 当前温度值
int CtrlListPort; // 将要控制的引脚
int CtrlElec; // 将要控制的引脚输出电平
LED=1;
init();
BitData=read_add(EEPROM_StartAddr);
if (BitData!=EEPROM_StartFlag){while(1);} // 卡住它,不要让它重新运行
// 关于EEPROM获取数据信息可以从同文件夹中图片有指导
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;//个位温度。
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;
}
}