用1602LCD与DS18B20设计的温度报警器

#include
#include
#include
#define uchar unsigned char
#define uint unsigned int
sbit RW = P1^1; //定义LCD的读、写选择端
sbit RS = P1^0; //定义LCD的数据、命令选择端
sbit EN = P1^2; //定义LCD的使能信号端
sbit DS = P3^5; //定义DS18B20的IO口
sbit L=P1^3; //绿灯
sbit H=P1^4; //红灯
sbit LS=P3^4; //蜂鸣器
sbit k1=P2^4; //显示64位的ROM
sbit k2=P2^3; //显示当前温度
sbit k3=P2^0; //显示温度上限及下线,并支持调节
sbit k4=P2^1; // 上限加
sbit k5=P2^2; // 下限减
uchar k=2; //当前温度显示标志位
uchar table0[] = " Current Temp : "; //当前温度
uchar table1[] = " -- ROM CODE -- "; //显示DS18B20的ROM
uchar table2[] = "ALARM TEMP Hi Lo"; //显示上下限温度
uchar table3[] = "Hi: Lo: ";
uchar table4[] = {0,0,0,0,0,0,0,0};
uchar tempHL[] = { 20, 1}; //上下限温度的初始值
void delayms(uint a) //延时函数
{
uint i,j;
for(i = a; i > 0; i--) for(j = 100; j > 0; j--);
}
void writecom(uchar com) //写地址,也就是显示的数据的位置
{
RS = 0;
P0 = com;
EN = 1;
delayms(1);
EN = 0;
}
void writedata(uchar dat) //写数据,也就是显示的数据
{
RS = 1;
P0 = dat;
EN = 1;
delayms(1);
EN = 0;
}
void init() //LCD初始化
{
RW = 0;
writecom(0x38); //16*2显示,5*7点阵
writecom(0x0c);
writecom(0x06);
writecom(0x01); //清除LCD的显示内容
}

void writestring(uchar * str, uchar length) //写数据的过度函数。length:长度
{
uchar i;
for(i = 0; i < length; i++)
{
writedata(str[i]);
}
}
void delay(uint num) //延时函数
{
while( --num );
}

DSinit(void) //初始化ds1820
{
DS= 1; //DS复位
delay(8); //稍做延时
DS= 0; //将DS拉低
delay(90); //精确延时 大于 480u
DS= 1; //拉高总线
delay(110);
DS= 1;

}

uchar read_bit(void) //读一位(bit)
{
uchar i;
DS= 0; //将DS拉低开始读时间隙
DS= 1; // then return high
for (i=0; i<3; i++); // 延时15μs
return(DS); // 返回 DS线上的电平值
}

uchar readbyte() // 读一个字节
{
uchar i = 0;
uchar dat = 0;
for (i=0;i<8;i++)
{ // 读取字节,每次读取一个字节
if(read_bit()) dat|=0x01<delay(4);
}
return (dat);
}

void write_bit(char bitval) //写一位
{
DS= 0; // 将DS拉低开始写时间隙
if(bitval==1) DS=1; // 如果写1,DS返回高电平
delay(5); // 在时间隙内保持电平值,
DS= 1; // delay函数每次循环延时16μs,因此delay(5) = 104μs
}

void writebyte(uchar dat) //写一个字节
{
uchar i = 0;
uchar temp;
for (i=0; i<8; i++) // 写入字节, 每次写入一位
{

temp =

dat>>i;
temp &= 0x01;
write_bit(temp);

}
delay(5);
}
void sendchangecmd() //DS18B20?开始获取温度并转换
{
DSinit(); //DS18B20复位
delayms(1);
writebyte(0xcc); //写跳过读ROM指令
writebyte(0x44); //写温度转换指令
}

void sendreadcmd() //读取寄存器中存储的温度数据
{
DSinit(); //DS18B20复位
delayms(1);
writebyte(0xcc); //写跳过读ROM指令
writebyte(0xbe); //读取暂存器的内容
}

int gettmpvalue()
{
uint tmpvalue;
float t;
uchar low, high;
sendreadcmd(); //读取寄存器中存储的温度数据
low = readbyte(); //读取低八位
high = readbyte(); //读取高八位
tmpvalue = high;
tmpvalue <<= 8; //高八位左移八位
tmpvalue |= low; //两个字节组合为1个字
t = tmpvalue * 0.0625 * 100; //分辨率为0.0625,在此将值扩大100倍
return t;
}

void display(int v) //显示子函数
{
uchar i;
uchar datas[] = {0, 0, 0, 0, 0, 0, 0, 0}; //定义缓存数组datas
uint tmp = abs(v); //abs是求绝对值函数
datas[0] = tmp % 10000 / 1000;
datas[1] = tmp % 1000 / 100;
datas[2] = tmp % 100 / 10;
datas[3] = tmp % 10;
datas[4] = 80; //空格的前30的ASCALL码
datas[5] = 175; //温度符号的前30的ASCALL码
datas[6] = 19; //C的前30的ASCALL码
writecom(0xc0+3);
if(v < 0) //当V小于0则输出负号
{
writestring("- ", 2);
}
else
{
writestring("+ ", 2); //当V大于0则输出正号
}
for(i = 0; i != 7; i++)
{
writedata('0'+datas[i]); //显示温度
if(i == 1)
{
writedata('.'); //显示温度的小数点
}
}

}

void Read_RomCord() //读取64位序列码
{
unsigned char j;
DSinit();
writebyte(0x33); // 读序列码的操作
for (j = 0; j < 8; j++)
{
table4[j] = readbyte();
}
}

void Disp_RomCode() //数据转换与显示
{
uchar j,i;
writecom(0xc0); //LCD第二行初始位置
for(j=0;j<8;j++)
{
i=((table4[j]&0xf0)>>4);
if(i>9)
{ i=i+0x37;}
else{i=i+0x30;}
writedata(i); //高位数显示
i=(table4[j]&0x0f);
if(i>9)
{i=i+0x37;}
else {i=i+0x30;}
writedata(i); //低位数显示
}
}

void lcd_display() //按键扫描
{
uchar i,m;
uchar hl[]={0, 0, 0, 0, 0};
if(k1 == 0) k = 1;
if(k2 == 0) k = 2;
if(k3 == 0) k = 3;
if(tempHL[0]<=gettmpvalue()/100)
delayms(100),LS=!LS,H=~H;
else
LS=1,H=1;
if(m==1)
{
if(tempHL[1]>=gettmpvalue()/100)
delayms(100),LS=!LS,L=~L;
else
LS=1,L=1;
}
switch(k)
{
case 1: //显示64

位的ROM
writecom(0x01);
writecom(0x80);
writestring(table1, 16);
Read_RomCord(); //读取64位序列码
Disp_RomCode(); //显示64位序列
delayms(500); //温度转换时间需要750ms以上
break;
case 2: //显示当前温度
delayms(750); //温度转换时间需要750ms以上
sendchangecmd();
writecom(0x01);
writecom(0x80);
writestring(table0, 16);
display(gettmpvalue());
break;
case 3: //显示温度上限及下线,并支持调节
writecom(0x80);
writestring(table2, 16);
writecom(0xC0);
writestring(table3, 16);
if(k4==0) {tempHL[0]++;if(m==1) tempHL[1]++;if(m==0){tempHL[1]--;if(tempHL[1]==0)m=1;}delayms(100);}
if(k5==0) {tempHL[0]--;if(m==0) tempHL[1]++;if(m==1){tempHL[1]--;if(tempHL[1]==0)m=0;}delayms(100);}
hl[0] = tempHL[0] / 10;
hl[1] = tempHL[0] % 10;
if(m==1) hl[2] = 80;
if(m==0) hl[2] = 128;
hl[3] = tempHL[1] / 10;
hl[4] = tempHL[1] % 10;
writecom(0xC0+4);
for(i = 0; i != 2; i++)
{
writedata('0'+hl[i]); //显示上限温度
}
writecom(0xC0+11);
for(i = 2; i != 5; i++)
{
writedata('0'+hl[i]); //显示下限温度
}
break;
}
}
void main()
{
sendchangecmd(); //读取寄存器中存储的温度数据
init(); //LCD初始化
writecom(0x80); //选择LCD第一行
writestring(table0, 16); //显示当前温度的英文字母
while(1)
{
lcd_display(); //扫描按键
}
}

相关文档
最新文档