51单片机温度传感器DS18B20程序LCD1602显示.docx
《51单片机温度传感器DS18B20程序LCD1602显示.docx》由会员分享,可在线阅读,更多相关《51单片机温度传感器DS18B20程序LCD1602显示.docx(18页珍藏版)》请在冰点文库上搜索。
![51单片机温度传感器DS18B20程序LCD1602显示.docx](https://file1.bingdoc.com/fileroot1/2023-7/22/cc9608ab-12af-4a24-b624-bac024ae3570/cc9608ab-12af-4a24-b624-bac024ae35701.gif)
51单片机温度传感器DS18B20程序LCD1602显示
仿真截图:
//仿真文件网盘地址:
:
//pan.baidu/s/1qW8sGQK
//程序:
#include
#include
#defineucharunsignedchar
#defineuintunsignedint
sbitP00=P0^0;
sbitP01=P0^1;
sbitP02=P0^2;
sbitP03=P0^3;
sbitP04=P0^4;
sbitP05=P0^5;
sbitP06=P0^6;
sbitP07=P0^7;
sbitP10=P1^0;
sbitP11=P1^1;
sbitP12=P1^2;
sbitP13=P1^3;
sbitP14=P1^4;
sbitP15=P1^5;
sbitP16=P1^6;
sbitP17=P1^7;
sbitP20=P2^0;
sbitP21=P2^1;
sbitP22=P2^2;
sbitP23=P2^3;
sbitP24=P2^4;
sbitP25=P2^5;
sbitP26=P2^6;
sbitP27=P2^7;
sbitP30=P3^0;
sbitP31=P3^1;
sbitP32=P3^2;
sbitP33=P3^3;
sbitP34=P3^4;
sbitP35=P3^5;
sbitP36=P3^6;
sbitP37=P3^7;
//******DS18B20******
#defineDQP17
/*************精确延时函数*****************/
voiddelay10us(void)//误差0us
{
unsignedchara,b;
for(b=1;b>0;b--)
for(a=2;a>0;a--);
}
voiddelay20us(void)//误差0us
{
unsignedchara,b;
for(b=1;b>0;b--)
for(a=7;a>0;a--);
}
voiddelay30us()//误差0us
{
unsignedchara,b;
for(b=3;b>0;b--)
for(a=3;a>0;a--);
}
voiddelay100us()//误差0us
{
unsignedchara,b;
for(b=1;b>0;b--)
for(a=47;a>0;a--);
}
voiddelay200us(void)//误差0us
{
unsignedchara,b;
for(b=1;b>0;b--)
for(a=97;a>0;a--);
}
voiddelay500us()//误差0us
{
unsignedchara,b;
for(b=71;b>0;b--)
for(a=2;a>0;a--);
}
voidDS18B20_init()//DS18B20初始化复位
{
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();//延时几个时钟周期保证DQ引脚稳定在高电平
DQ=0;
delay500us();//最短为480us的低电平信号复位
DQ=1;//拉高总线15-60us
delay30us();
delay200us();//延时足够时间复位基本上都会成功因此不必再判断是否复位成功
DQ=1;//释放总线
}
ucharRead_One_Byte()
{
uchari;
ucharbyte=0;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();//延时几个时钟周期保证DQ引脚稳定在高电平
DQ=0;
byte>>=1;
delay20us();
DQ=1;//给脉冲产生读时间间隙
delay10us();//延时一定时间后,读DQ的值
if(DQ)
{byte|=0x80;}//读得DQ为1将1写到dat最高位;读得DQ为0不必处理
delay100us();
DQ=1;
}
return(byte);
}
voidWrite_One_Byte(ucharbyte)
{
uchari=0;
for(i=0;i<8;i++)
{
DQ=1;
_nop_();
_nop_();
_nop_();
_nop_();//延时几个时钟周期保证DQ引脚稳定在高电平
DQ=0;
DQ=byte&0x01;//写所给数据最低位
delay30us();
byte>>=1;
}
}
intRead_Temp()////////***读取温度值***********/////每次读写均要先复位
{
intt;
floattep;
uchara,b;
DS18B20_init();
Write_One_Byte(0xcc);//跳过ROM命令单个传感器所以不必读取ROM里的序列号
Write_One_Byte(0x44);//开始转换
DS18B20_init();
Write_One_Byte(0xcc);//跳过ROM命令
Write_One_Byte(0xbe);//读寄存器,共九字节,前两字节为转换值
a=Read_One_Byte();//a存低字节
b=Read_One_Byte();//b存高字节
t=b;
t<<=8;//高字节转换为10进制
t=t|a;
tep=t*0.0625;//转换精度为0.0625/LSB
t=tep*10+0.5;//保留1位小数并四舍五入****后面除10复原正确温度值〕
return(t);
}
/***********LCD************/
#defineRSP22
#defineRWP21
#defineLCDENP20
#defineLCD_DATAP0//P0口接LCD数据口
#defineLCD_BUSYP07//lcd1602忙碌标志位
ucharidatalcd_code[10];//用来标记lcd1602什么时候清显示每个页面都设一个code,code不想同时清显示
//*****************************************延时函数***************************************//
voiddelayms(uintms)//延时?
个ms
{
uchara,b,c;
while(ms--)
{
for(c=1;c>0;c--)
for(b=142;b>0;b--)
for(a=2;a>0;a--);
}
}
/*
//**********字符串复制函数**********
voidstring_copy(uchar*target,uchar*source)//字符串复制target:
目标source:
源
{
uchari=0;
for(i=0;source[i]!
='\0';i++)//注意target的长度无保护措施!
{
target[i]=source[i];
}
target[i]='\0';
}
//**********字符串比较函数**********
ucharstring_cmp(uchar*target,uchar*source)//字符串比较target:
目标source:
源
{
ucharrevalue;
uchari=0;
for(i=0;target[i]!
='\0'&&source[i]!
='\0';i++)//两个都不等于'\0'才执行出现一个等于'\0'就跳出
{
if(target[i]==source[i])
{
revalue=1;
}
else
{
revalue=0;
break;
}
}
if(revalue==1)
{
if(target[i]=='\0'&&source[i]=='\0')
revalue=1;
else
revalue=0;
}
return(revalue);
}
*/
//****************LCD********************
//LCD基本函数:
voidbusy_check()//忙碌检测
{
/*RW=1;//读
RS=0;//指令寄存器
LCD_DATA=0xFF;//实验证明读数时要将I/O口要置1
LCDEN=0;
_nop_();
_nop_();
_nop_();
_nop_();
LCDEN=1;//EN高电平读信息负跳变执行指令
_nop_();
_nop_();
_nop_();
_nop_();
while
(1)
{
if(LCD_BUSY==0)//P07==0跳出循环
break;
}*/
delayms
(2);//仿真时用延时法下载到真实单片机上时,将这句注释掉,采用上面的语句。
}
voidlcdwrcom(ucharcommand)//写指令
{
busy_check();
RW=0;//写
RS=0;//指令寄存器
LCD_DATA=command;
LCDEN=1;//负跳变写入指令
_nop_();
_nop_();
_nop_();
_nop_();
LCDEN=0;
}
voidlcdwrdata(ucharlcd_data)//写数据数字、字母、标点符号都是数据
{
busy_check();
RW=0;//写
RS=1;//数据寄存器
LCD_DATA=lcd_data;
LCDEN=1;//负跳变写入指令
_nop_();
_nop_();
_nop_();
_nop_();
LCDEN=0;
}
voidlcd_init()
{
delayms(15);//必要lcd1602上电到电压稳定需要时间
RW=0;//写
RS=0;//指令寄存器
LCD_DATA=0x38;//0x38设置显示模式为:
16X2显示,5X7点阵,8位数据接口'
LCDEN=1;
_nop_();
_nop_();
_nop_();
_nop_();
LCDEN=0;
delayms(5);
lcdwrcom(0x0c);//打开显示无光标不闪烁
lcdwrcom(0x06);//指令3光标右移屏幕所有文字移动无效
lcdwrcom(0x01);//清显示,光标复位到地址00H位置。
}
//LCD扩展函数:
voidaddress(ucharx,uchary)//定位下一步要写数的地址
{
ucharlocation;
if(x==0)
location=0x80|y;
else
location=0xC0|y;
lcdwrcom(location);
}
voidprintchar(ucharx,uchary,ucharletter)//显示字母、单个字符
{
address(x,y);
lcdwrdata(letter);
}
voidprintword(ucharx,uchary,uchar*word)//显示单词〔字符数组〕
{
uchari=0;
for(i=0;word[i]!
='\0';i++)
{
address(x,y+i);
lcdwrdata(word[i]);
}
}
/*
voidprintuint(ucharx,uchary,ucharnum_ws_max,uintnum)//显示无符号整形0~65535x:
行y:
列num_ws_max变量的最大位数
{
uchari=0;
ucharstr[5]={0x20,0x20,0x20,0x20,0x20};
if(num>=10000)
{
str[0]=num/10000+'0';
str[1]=num%10000/1000+'0';
str[2]=num%1000/100+'0';
str[3]=num%100/10+'0';
str[4]=num%10+'0';
//str[5]='\0';//手动加字符串结束标志
}
elseif(num>=1000)
{
str[0]=num/1000+'0';
str[1]=num%1000/100+'0';
str[2]=num%100/10+'0';
str[3]=num%10+'0';
str[4]='\0';
}
elseif(num>=100)
{
str[0]=num/100+'0';
str[1]=num%100/10+'0';
str[2]=num%10+'0';
str[3]='\0';
}
elseif(num>=10)
{
str[0]=num/10+'0';
str[1]=num%10+'0';
str[2]='\0';
}
elseif(num>=0)
{
str[0]=num+'0';
str[1]='\0';
}
for(i=0;i<=5;i++)//uint类型最大值65535为5位数
{
if(str[i]!
='\0'&&i{
address(x,y+i);
lcdwrdata(str[i]);
}
elseif(str[i]=='\0'&&i{
address(x,y+i);
lcdwrdata('');//空格//实现功能:
在此变量的位数范围内,把没数字的位存0x20〔空格〕
//例如:
最大有3位:
999当变为99时,存为9+'0'9+'0'0x20
}
}
}
*/
voidprinttemp(ucharx,uchary,uinttemp)//显示温度显示一位小数【显示效果相当于将一个数除以10并保存一位小数】
{
if(temp<100)
{
address(x,y);
lcdwrdata(temp/10+'0');
address(x,y+1);
lcdwrdata('.');
address(x,y+2);
lcdwrdata(temp%10+'0');
address(x,y+3);
lcdwrdata('');
address(x,y+4);
lcdwrdata('');
}
elseif(temp<1000)
{
address(x,y);
lcdwrdata(temp/100+'0');
address(x,y+1);
lcdwrdata(temp%100/10+'0');
address(x,y+2);
lcdwrdata('.');
address(x,y+3);
lcdwrdata(temp%10+'0');
address(x,y+4);
lcdwrdata('');
}
elseif(temp<10000)
{
address(x,y);
lcdwrdata(temp/1000+'0');
address(x,y+1);
lcdwrdata(temp%1000/100+'0');
address(x,y+2);
lcdwrdata(temp%100/10+'0');
address(x,y+3);
lcdwrdata('.');
address(x,y+4);
lcdwrdata(temp%10+'0');
}
}
voidmain()
{
inttemp;//温度值
lcd_init();
printword(0,0,"temp:
");
while
(1)
{
temp=Read_Temp();
if(temp>0)
{
printchar(0,5,'+');
printtemp(0,6,temp);
}
elseif(temp==0)
{
printchar(0,5,'');
printchar(0,6,'0');
}
else
{
temp=-temp;
printchar(0,5,'-');
printtemp(0,6,temp);
}
}
}