单片机控制DS18B20及LCD1602的温度采集系统
程序
/******************************************************************** *文件名:温度测试LCD1602显示
*创作人:孔子先生2011-9-6
********************************************************************/ #include
#include
#define uchar unsigned char
#define uint unsigned int
#define t 6 //t表示从第二行的第t个位置开始写入温度值
sbit E=P2^7; //片选信号
sbit RW=P2^6; //LCD1602读/写信号,H读,L写
sbit RS=P2^5; //LCD1602寄存器选择信号,L为指令寄存器,H为数据寄存器sbit DQ=P2^3; //DS18B20 I/O口
uchar TMPH,TMPL,REMAIN,PER_C; //温度高位,温度低位,门周期值,每度计数值
uchar a[]={"Temperature is:"}; //第一行显示数据
/**********************************************
LCD1602 读取忙标志(BF)和地址指令
***********************************************/
void LCD_busy()
{
unsigned char i;
RW=1;
RS=0;
Loop:
P0=0xff;
E=1;
i=P0;
E=0;
if(i&0x80)
{
goto Loop;
}
}
/*********************************************
LCD1602 指令写入程序,入口为n
**********************************************/
void write(unsigned int n)
{
LCD_busy();
RS=0;
RW=0;
P0=n;
E=1;
E=0;
}
/******************************************************************** *延时子程序延时n*20 us
********************************************************************/ void delay(int n)
{
int s;
for(s=0;s } /******************************************************************** 18B20 *复位子程序 ********************************************************************/ uchar reset() { uchar ready; DQ=0; delay(30); DQ=1; delay(3); ready=DQ; delay(30); return ready; } /******************************************************************** 18B20 *位写入子程序 *形参为val ********************************************************************/ void writebit(char val) { DQ=0; if(val==1) DQ=1; else DQ=0; delay(5); DQ=1; } /******************************************************************** 12B20 *字节写入子程序 *形参为val void writebyte(char val) { uchar i; uchar temp; for (i=0;i<8;i++) { temp=val>>i; temp&=0x01; writebit(temp); } delay(5); } /******************************************************************** 18B20 *位读取子程序 ********************************************************************/ uchar readbit(void) { uchar i; DQ=0; DQ=1; for(i=0;i<3;i++); return DQ; } /******************************************************************** 18B20 *字节读取子程序 入口无,出口为value ********************************************************************/ uchar readbyte(void) { uchar i; uchar value=0; for(i=0;i<8;i++) { if(readbit()) value|=0x01< delay(7); } return (value); } /******************************************************************** *LCD-1602显示字符串程序 X为从某行的第X个位置开始写,Y为显示在第1或第2行,*ddata为字符串首地址 void LCD_string(uchar x,uchar y,uchar *ddata) { uchar i=0; if(y==1) //写在第一行 x=x+0x7f; else if(y==2) //写在第二行 x=x+0xbf; else ; write(x); //设定DDRAM-AC到第Y行第X个位置 while(*ddata!='\0') //遇到字符串末尾则退出 { LCD_busy(); P0=*ddata; RS=1; RW=0; E=1; E=0; ddata++; } } /******************************************************************** *LCD-1602显示数据程序 X为从某行的第X个位置开始写,Y为显示在第1或第2行,ddata为要显示的数据 ********************************************************************/ void LCD_Display(uchar x,uchar y,uchar ddata) { if(y==1) //写在第一行 x=x+0x7f; else if(y==2) //写在第二行 x=x+0xbf; else ; write(x); //设定DDRAM-AC到第Y行第X个位置 LCD_busy(); P0=ddata+48; //ddata+48是查字符库 RS=1; RW=0; E=1; E=0; } /******************************************************************** *LCD-1602初始化程序 ********************************************************************/ void LCD_Init() { write(0x01);//清屏:DDRAM填满20H(0)并且DDRAM-AC到00H write(0x38);//功能设置:0000DLXREXX DL=1为8位MPU控制方式;RE=0为基本指令集; write(0x0c);//显示开关设置:00001DCB D=1整体显示打开;C=1游标显示关闭;B=0游标反白关闭 write(0x14);//移位:00001S/CR/LXX S/C=0,R/L=1游标向右移动; write(0x06);//输入方式设置:000001I/DS I/D=1游标右移;S=0画面不整体移位LCD_string(1,1,a);//显示字符串Temperature is: LCD_Display(t+5,2,(0xdf-0x30));//显示温度单位° LCD_Display(t+6,2,(0x43-0x30));//显示温度单位C } void main() { uchar i,j,m,n; uint temp; float temp_read; LCD_Init(); while(1) { reset(); writebyte(0xcc);//跳过ROM序列号命令 writebyte(0x44);//温度转换命令 reset(); writebyte(0xcc);//跳过ROM序列号命令 writebyte(0xbe);//读暂存器命令 TMPL=readbyte();//读出温度低位 TMPH=readbyte();//读出温度高位 readbyte();//空读 readbyte();//空读 readbyte();//空读 readbyte();//空读 REMAIN=readbyte();//读出门周期结束后保留下来的值 PER_C=readbyte();//读出对应温度下每度的计数值 TMPL=TMPL&0xfe;//将0.5℃位(LSB)从读取的值中截去 temp_read=((TMPL+TMPH*256)*0.0625)-0.25+((PER_C-REMAIN)/PER_C); temp=temp_read*100;//先放大100倍,方便整型运算显示 i=temp/1000%10; j=temp/100%10; m=temp/10%10; n=temp%10; LCD_Display(t,2,i);//显示温度十位 LCD_Display(t+1,2,j);//显示温度个位 LCD_Display(t+2,2,(0x2e-0x30));//显示高精度温度小数点. LCD_Display(t+3,2,m);//显示温度十分位 LCD_Display(t+4,2,n);//显示温度百分位 } } 接线图 单总线温度传感器接线图 LCD1602接线图