标题:
单片机多点温度控制程序和仿真
[打印本页]
作者:
bbxyzzj
时间:
2016-11-1 08:02
标题:
单片机多点温度控制程序和仿真
51单片机做的一个ds18b20多点温度控制程序源码和proteus仿真
0.png
(40.44 KB, 下载次数: 82)
下载附件
2016-11-1 11:15 上传
0.png
(75.69 KB, 下载次数: 89)
下载附件
2016-11-1 11:16 上传
仿真工程文件和源码打包下载:
单片机多点温度控制系统.zip
(92.29 KB, 下载次数: 50)
2016-11-1 08:01 上传
点击文件名下载附件
下载积分: 黑币 -5
单片机源程序:
//采用12MHz晶振
#include<AT89X51.h>
#define uchar unsigned char
#define FALSE 0;
#define TRUE 1;
sbit DQ =P3^0;//B20选择
sbit button1=P1^0;//定义通信端口
sbit button2=P1^1;//显示选择按钮
sbit button3=P1^2;//位选端
sbit button4=P1^3;//加1
unsigned char ROM[8];//ROM位 最前面是lsb
unsigned char FoundROM[3][8];//ROM代码表
unsigned char lastDiscrep=0; //上次差值
unsigned char doneFlag=0; //完成标志
unsigned int numROMs; //DS18B20个数
unsigned char dowcrc; //crc校验值
unsigned char DS_key=0;
uchar code LED[] ={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00};//0123456789
uchar code LED1[]={0xbf,0x86,0xdb,0xcf,0xe6,0xed,0xfd,0x87,0xff,0xef,0x00};//0-9的带小数点的段选码
uchar code tab[] ={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//P2选通数组
int temperature[2][11]={0x00,0x00,0x00,0x06,0x05,0x04,0x03,0x02,0x01,0x0a,0x00,
//十分 个 十 高温 低温
0x00,0x00,0x00,0x05,0x05,0x04,0x02,0x02,0x01,0x0a,0x00
}; //温度缓存数组
uchar data con=0x00,conk1=0x00;conk2=0x00,cont0=0x00,cont1=0x00;
//crc校验表
uchar code dscrc_table[]={0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53
};
void delay(unsigned int i);
unsigned char Init_DS18B20(void);
unsigned char Read_One_bit(void);
unsigned char Read_One_byte(void);
void Write_One_bit(char bitval);
void Write_One_byte(unsigned char dat);
unsigned char ow_crc(unsigned char x);
//void Read_Rom_Code(void);
unsigned char Next(void);
unsigned char First(void);
void Find_Devices(void);
unsigned char Send_Match_Rom(unsigned char DS_number);
void Read_Temperature(unsigned char number);
void Key_scan(void);
void DS_Key_scan(void);
void Show_Temp(void);
void Compare(void);
//延时函数
void delay(unsigned int i)//9us延迟,调用此程序4us
{
while(i--);
}
//初始化函数
unsigned char Init_DS18B20(void)
{
unsigned char presence;
DQ=1; //DQ复位
delay(8); //稍做延时
DQ=0; //单片机将DQ拉低
delay(80); //精确延时 大于 480us
DQ=1; //拉高总线
delay(5);
presence=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
delay(15);
return(presence);
}
//读一个位
unsigned char Read_One_bit(void)
{
uchar i;
DQ=0;
DQ=1;
for(i=0;i<3;i++); //延迟15微妙
return(DQ);
}
//读一个字节
unsigned char Read_One_byte(void)
{
unsigned char i=0;
unsigned char dat = 0;
for (i=0;i<8;i++)
{
if(Read_One_bit())
dat|=0x01<<i;
delay(9);
}
return(dat);
}
//写一个位
void Write_One_bit(char bitval)
{
DQ=0;
if(bitval==1)
DQ=1;
delay(5);
DQ=1;
}
//写一个字节
void Write_One_byte(unsigned char dat)
{
unsigned char i;
unsigned char temp;
for (i=0; i<8; i++)
{
temp=dat>>i;
temp&=0x01;
Write_One_bit(temp);
}
delay(9);
}
//crc校验函数
unsigned char ow_crc(unsigned char x)
{
dowcrc=dscrc_table[dowcrc^x];
return dowcrc;
}
/*
//读取单总线上的单个DS18B20的ROM,对于多个器件采用搜索ROM
void Read_Rom_Code(void)
{
int n;
if(!Init_DS18B20())
{
delay(20);
Write_One_byte(0x33);
for(n=0;n<8;n++)
{
ROM[n]=Read_One_byte();
}
}
}
*/
//搜索单总线上的下一个器件,如果没有则返回假
unsigned char Next(void)
{
unsigned char m=1;
unsigned char n=0;
unsigned char k=1;
unsigned char x=0;
unsigned char discrepMaker=0; //搜索定位到一个B20的标志位
unsigned char g;
unsigned char nxt;
int flag;
nxt=FALSE;
dowcrc=0;
flag=Init_DS18B20();
if(flag||doneFlag) //无器件,返回假值
{
lastDiscrep=0;
return FALSE;
}
Write_One_byte(0xf0);
do
{
x=0;
if(Read_One_bit()==1) x=2; //10 都为1
delay(10); //01 都为0
if(Read_One_bit()==1) x|=1; //00 存在两个以上,第一位不相等
delay(10); //11 没有器件
if(x==3) break;
else
{
if(x>0) g=x>>1; //x=1或x=2
else
{ //x=0
if(m<lastDiscrep) g=((ROM[n]&k)>0);
else g=(m==lastDiscrep);
if(g==0) discrepMaker=m;
}
if(g==1) ROM[n]|=k; //写1
else ROM[n]&=~k; //写0
Write_One_bit(g);
delay(10);
m++;
k=k<<1; //k循环右移1位,
if(k==0)
{
ow_crc(ROM[n]);
n++;k++;
}
}
}while(n<8);
if(m<65||dowcrc) lastDiscrep=0; //搜索未成功
else
{ //搜索成功,置各个标志位,返回还有其他器件,
lastDiscrep=discrepMaker;
doneFlag=(lastDiscrep==0); //完成置1
nxt=TRUE;
}
return(nxt);
}
//复位当前ROM搜索状态并调用Next函数搜索单总线的第一个器件
unsigned char First(void)
{
lastDiscrep=0;
doneFlag=FALSE;
return Next();
}
//复位单总线以确定是否存在任何器件,如果存在将其唤醒,然后调用First函数跟踪冲突位
//并返回Next函数,Next函数完成鉴别单总线上的每个器件唯一ROM代码的大部分工作
void Find_Devices(void)
{
unsigned char m;
if(!Init_DS18B20())
{
if(First())
{
numROMs=0;
do{
for(m=0;m<8;m++)
{
FoundROM[numROMs][m]=ROM[m];
}
numROMs++;
}while(Next()&&(numROMs<4)); //两个B20
}
}
}
//匹配单个DS18B20
unsigned char Send_Match_Rom(unsigned char DS_number)
{
unsigned char i;
if(Init_DS18B20())
return FALSE;
// delay(20);
Write_One_byte(0x55);
for(i=0;i<8;i++)
{
Write_One_byte(FoundROM[DS_number][i]);
}
return TRUE;
}
//读取温度
void Read_Temperature(unsigned char number)
{
unsigned char fu;
float m;
unsigned char temp_lsb=0;
unsigned char temp_msb=0;
unsigned int temp_value=0;
int show,n;
Init_DS18B20(); //初始化函数DS18B20
Send_Match_Rom(number);//匹配ROM
// Write_One_byte(0xCC); // 跳过读序号列号的操作
Write_One_byte(0x44); // 启动温度转换
Init_DS18B20();
Send_Match_Rom(number);//匹配ROM
// Write_One_byte(0xCC); //跳过读序号列号的操作
Write_One_byte(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度
temp_lsb=Read_One_byte(); //温度lsb
temp_msb=Read_One_byte(); //温度msb
temp_value=temp_msb;
temp_value<<=8; //左移8位
temp_value=temp_value|temp_lsb;
fu=temp_msb;
fu=fu&0x08;
if(fu!=0) //判断正负
{temp_value=~temp_value+1;}
m=temp_value*0.0625; //将十进制m向左移动4个小数点
show=m;
temperature[number][2]=show/10;//十位
temperature[number][1]=show%10;//个位
n=((m-show)*100+0.5);
temperature[number][0]=n/10;//十分位
}
//按钮扫描
void DS_Key_scan(void)
{
EA=0;
if(conk2==0)
{
if(button2==0) //按键1
{
delay(1000); //延迟9毫秒,消抖延迟
while(button2==0);
// TR1=0;ET1=0;TH1=0x3c;TL1=0xB0;
// TR1=1;ET1=1;
con=con+3;
if(con==9)
con=0;
}
}
if(con!=0) //按键2
{
if(con==3||con==6)
{
if(button3==0)
{
delay(1000); //消抖延迟
while(button3==0);
if(temperature[DS_key][con+conk1]==0x0a)
{
temperature[DS_key][10]=temperature[DS_key][con+conk1];
temperature[DS_key][con+conk1]=temperature[DS_key][9];
temperature[DS_key][9]=temperature[DS_key][10];
}
TR0=1;ET0=1;
// TR1=0;ET1=0;TH1=0x3c;TL1=0xB0;
// TR1=1;ET1=1;
conk1++;
conk2++;
if(conk1==3)
conk1=0;
if(conk2==4)
{
conk2=0;
con=0;
TR0=0;ET0=0;
conk1=0;
}
}
}
}
if(con!=0&&conk2!=0) //按键3
{
if(con==3||con==6)
{
if(button4==0)
{
delay(1000); //消抖延迟
while(button4==0);
if(temperature[DS_key][con+conk1]==10)
{
temperature[DS_key][10]=temperature[DS_key][con+conk1];
temperature[DS_key][con+conk1]=temperature[DS_key][9];
temperature[DS_key][9]=temperature[DS_key][10];
}
// TR1=0;ET1=0;TH1=0x3c;TL1=0xB0;
// TR1=1;ET1=1;
temperature[DS_key][con+conk1]++;
if(temperature[DS_key][con+conk1]>=10)
{
temperature[DS_key][con+conk1]=0;
}
temperature[DS_key][9]=0x0a;
}
}
}
EA=1;
}
//DS18B20选择
void Key_scan(void)
{
if(button1==0) //按键4
{
delay(1000); //延迟9毫秒,消抖延迟
while(button1==0);
DS_key++;
if(DS_key==2)
DS_key=0;
}
DS_Key_scan();
}
//定时器0中断0.4秒
void time_int0(void) interrupt 1
{
EA=0;TR0=0;TH0=0x3c;TL0=0xB0;TR0=1;
cont0++;
if(cont0==6)
{
cont0=0x00;
temperature[DS_key][10]=temperature[DS_key][con+conk1];
temperature[DS_key][con+conk1]=temperature[DS_key][9];
temperature[DS_key][9]=temperature[DS_key][10];
}
ET0=1;
}
//定时器1中断
/*void time_int1(void) interrupt 3
{
EA=0,TR1=0;TH1=0x3c;TL1=0xB0;TR1=1;
cont1++;
if(cont1==100) //延迟5秒,5秒后恢复到显示18B20值
{
if(temperature[con+conk1]==0x0a)
{
temperature[10]=temperature[con+conk1];
temperature[con+conk1]=temperature[9];
temperature[9]=temperature[10];
}
cont1=0x00;
con=0;
conk1=0;
conk2=0;
TR1=0;ET1=0;
TR0=0;ET0=0;
}
ET1=1;
}
*/
//输出显示函数
void Show_Temp(void)
{
int i,j,m,n;
for(i=0;i<3;i++)
{
if(DS_key==0)
{
j=con+i;
n=i;
}
else
{
j=i;
n=con+i;
}
m=i+3;
P2=tab[i];
if(i==1)
P0=LED1[temperature[0][j]];
else
P0=LED[temperature[0][j]];
delay(150);
P2=tab[m];
if(m==4)
P0=LED1[temperature[1][n]];
else
P0=LED[temperature[1][n]];
delay(150);
}
P2=tab[7];
P0=LED[DS_key+1];
delay(150);
P2=0xff;
}
//比较函数
void Compare(void)
{
unsigned int test1,high1,low1;
unsigned int test2,high2,low2;
test1=temperature[0][2]*100+temperature[0][1]*10+temperature[0][0];
high1=temperature[0][5]*100+temperature[0][4]*10+temperature[0][3];
low1=temperature[0][8]*100+temperature[0][7]*10+temperature[0][6];
test2=temperature[1][2]*100+temperature[1][1]*10+temperature[1][0];
high2=temperature[1][5]*100+temperature[1][4]*10+temperature[1][3];
low2=temperature[1][8]*100+temperature[1][7]*10+temperature[1][6];
P1_4=1;
P1_5=1;
P1_6=1;
P1_7=1;
if(test1>high1)
{
P1_7=0;
}
if(test2>high2)
{
P1_5=0;
}
if(test1<low1)
{
P1_6=0;
}
if(test2<low2)
{
P1_4=0;
}
}
void main()
{
//int num=0;
TH0=0x3C;TL0=0xB0; //50毫秒延迟
TH1=0x3C;TL1=0xB0; //50毫秒延迟
TMOD=0x11;ET0=0;TR0=0;ET1=0;TR1=0;
EA=0;
Init_DS18B20();
// Read_Rom_Code();
// First();
Find_Devices();
while(1)
{
Show_Temp();
Read_Temperature(0);
// delay(20);
Show_Temp();
Read_Temperature(1);
Key_scan();
// DS_Key_scan(0);
Compare();
}
}
复制代码
作者:
未已
时间:
2017-4-18 10:44
这个是不是无线的呢
作者:
平衡de交界面
时间:
2017-11-3 21:12
温度传感器接在同一个口会不会使程序复杂?
作者:
t459
时间:
2017-12-21 20:44
最近想做一个,简单的温度控制好做,改变一下是否可以
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1