发布网友 发布时间:2022-05-13 14:50
共3个回答
热心网友 时间:2023-10-13 02:49
楼主你在时序上有些错误
1。在转换时没有留够足够的转换时间。根据DS18B20芯片手册,9位精度转换时间为93.75ms。12位精度转换时间为750ms。而DS18B20默认为12位精度。所以我加了750ms延时
2。在写函数的时候
void ds18b20_write_byte(uchar date) //写一个字节
{
uchar i;
for(i=0;i<8;i++) //一个字节八位
{
if((date&&0x01)==1) //写入1
{
ds18b20=0;
delay_15us();
ds18b20=1;
}
else //写入0
{
ds18b20=0;
delay_60us();
ds18b20=1;
}
date>>=1; //右移一位
}
}
应该是if((dat&0x01)==0x01)这里多了一个&号,导致结果错误。
3。我增加了用1602显示的模块,删除了用液晶显示的模块。
/**********************************
以下是程序,并附上仿真图一张
**********************************/
#include <reg52.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
uchar temp,tmph,tmpl;
sbit ds18b20=P2^3;
sbit rw=P2^6;
sbit lcde=P2^7;
sbit rs=P2^5;
//下面是1602的驱动程序
void delay(uint z)
{
uint x,y;
for(x=z;x>0;x--)
for(y=110;y>0;y--);
}
void write_com(uchar com,bit i) //是命令写0 数据写1
{
rs=i;
P0=com;
delay(5);
lcde=1;
delay(5);
lcde=0;
}
void lcd1602init(void)
{
rw=0;
write_com(0x01,0);
write_com(0x02,0);
write_com(0x06,0);
write_com(0x0c,0);
write_com(0x38,0);
}
void display(uchar x,uchar y,uchar date)
{
x&=0x01;
y&=0x0f;
if(x)
{
y+=0x40;
}
y+=0x80;
write_com(y,0);
write_com(date,1);
}
void delayms(uint xms)
{
uint i,j;
for(i=xms;i>0;i--)
for(j=110;j>0;j--);
}
/////////////////////////////////////////////////////////
/////DS18B20部分////////////
///////////////////////////
//延时部分
void delay_600us(void)
{
uchar i;
for(i=0;i<180;i++);
}//延时600us
void delay_400us(void)
{
uchar i;
for(i=0;i<120;i++);
}
void delay_60us(void)
{
uchar i;
for(i=0;i<18;i++);
}//延时60us
void delay_15us(void)
{
uchar i;
for(i=0;i<3;i++);
}//延时15us
//复位脉冲
bit resetpulse(void)
{
ds18b20=0;
delay_600us();
ds18b20=1;
delay_60us();
return ds18b20;
}
//ds18b20初始化
void ds18b20_init(void)
{
while(1)
{
if(!resetpulse()) //收到ds18b20的低电平信号
{
ds18b20=1;
delay_400us();
break;
}
else
resetpulse(); //继续发送复位信号
}
}
void ds18b20_write_byte(uchar date) //写一个字节
{
uchar i;
for(i=0;i<8;i++) //一个字节八位
{
// if((date&&0x01)==1) //写入1
//这里错了
if((date&0x01)==0x01)
{
ds18b20=0;
_nop_();
ds18b20=1;
delay_60us();
} //end if
else //写入0
{
ds18b20=0;
delay_60us();
ds18b20=1;
} //end else
delay_15us();
date>>=1; //右移一位
}
}
uchar ds18b20_read_byte(void) //读一个字节
{
uchar i,u;
for(i=0;i<8;i++)
{
u>>=1;
ds18b20=0;
_nop_();
//释放总线
ds18b20=1;
_nop_();
_nop_();
if(ds18b20==1) //读1
{
u|=0x80;
}
else
{ u=u&0x7f; //读0
}
delay_60us();
}
return u;
}
uchar read_temperaturn()
{
ds18b20_init(); //初始化;
ds18b20_write_byte(0xcc); //跳过ram;
ds18b20_write_byte(0x44); //启动温度测量 当为高电平时转换完成
delayms(750); //转换时间要求
ds18b20_init(); //初始化;
ds18b20_write_byte(0xcc); //跳过ram;
ds18b20_write_byte(0xbe); //采集温度
delayms(750);
tmpl=ds18b20_read_byte(); //低位温度数据
tmph=ds18b20_read_byte(); //高位温度数据
tmph<<=4; //左移4位
tmph+=(tmpl&0xf0)>>4;
return(tmph);
}
void main()
{
uchar temph=0;
uchar templ=0;
lcd1602init();
while(1)
{ temp=read_temperaturn();
temph=temp/10+'0';
templ=temp%10+'0';
delayms(20);
display(0,0,temph);
display(0,1,templ);
}
}
热心网友 时间:2023-10-13 02:50
(1) void display()函数中的显示顺序有问题,应该先显示最右边的位(即最低位,针对你这个程序是个位),必须先显示最右边的位,依次往左边的位显示,否则先试试有问题的。热心网友 时间:2023-10-13 02:50
先看硬件电路有没有问题,确认没问题再下步。首先你行调试你的显示程序,给个数值能否正常显示;仔细检查与18B20通讯的时序(那些延时程序必须计算的很准确)。