DS18B20为一线式温度传感器,单片机用一个I/O口与其通信采集数据,这是一个51单片机的仿真例程可以参考一下。
#include
#define uchar unsigned char
#define uint unsigned int
sbit DQ=P1^4; //ds18b20与单片机连接口
unsigned char code str[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40} ; //共阴数码管字码表
unsigned char code str1[]={0x0bf,0x86,0x0db,0x0cf,0x0e6,0x0ed,0x0fd,0x87,0x0ff,0x0ef}; //个位带小数点字码表
unsigned char code wei[]={0x0fe,0x0fd,0x0fb,0x0f7};
uchar data disdata[5];
uint tvalue; //温度值
uchar tflag; //温度正负标志
/**********ds1820程序************/
void delay_18B20(unsigned int i) //延时1微秒
{
while(i--);
}
void ds1820rst() /*ds1820复位*/
{
unsigned char x=0;
DQ = 1; //DQ复位
delay_18B20(4); //延时
DQ = 0; //DQ拉低
delay_18B20(100); //精确延时大于 480us
DQ = 1; //拉高
delay_18B20(40);
}
uchar ds1820rd() /*读数据*/
{
unsigned char i=0;
unsigned char dat = 0;
for (i=8;i>0;i--)
{
DQ = 0; //给脉冲信号
dat>>=1;
DQ = 1; //给脉冲信号
if(DQ) dat|=0x80;
delay_18B20(10);
}
return(dat);
}
void ds1820wr(uchar wdata) /*写数据*/
{
unsigned char i=0;
for (i=8; i>0; i--)
{
DQ = 0;
DQ = wdata&0x01;
delay_18B20(10);
DQ = 1;
wdata>>=1;
}
}
read_temp() /*读取温度值并转换*/
{
uchar a,b;
ds1820rst();
ds1820wr(0xcc); // 跳过读序列号
ds1820wr(0x44); // 启动温度转换
ds1820rst();
ds1820wr(0xcc); // 跳过读序列号
ds1820wr(0xbe); // 读取温度
a=ds1820rd();
b=ds1820rd();
tvalue=b;
tvalue<<=8;
tvalue=tvalue|a;
if(tvalue<0x0fff)
tflag=0;
else
{
tvalue=~tvalue+2; tflag=1; //负温度
}
tvalue=tvalue*(0.625); //温度值扩大10倍,精确到1位小数
return(tvalue);
}
/*********************************/
void ds1820disp() //温度值显示
{
uchar i;
disdata[0]=tvalue/1000; //百位数
disdata[1]=tvalue%1000/100; //十位数
disdata[2]=tvalue%100/10; //个位数
disdata[3]=tvalue%10; //小数位
if(tflag==0)
{
if(disdata[0]==0x00)
{
disdata[0]=0x0a; //百位数位为0不显示
if(disdata[1]==0x00) disdata[1]=0x0a; //十位数位为0不显示
}
}
else //负温度
{
disdata[0]=0x0b; //负温度百位显示负号:-
if(disdata[1]==0x00) disdata[1]=0x0a; //十位数位为0不显示
}
for(i=0;i<150;i++)
{
P2=wei[0];
P0=str[disdata[0]];
delay_18B20(20);
P2=wei[1];
P0=str[disdata[1]];
delay_18B20(20);
P2=wei[2];
P0=str1[disdata[2]];
delay_18B20(20);
P2=wei[3];
P0=str[disdata[3]];
delay_18B20(20);
}
}
/************主程序**********/
void main()
{
ds1820rst(); //初始化显示
while(1)
{
read_temp(); //读取温度
ds1820disp(); //显示
}
}
DS18B20是单总线通讯,IO口为输入或者双向口状态都是可以的。采集的数据一直位0xffff不一定就是硬件方面的问题,与你的程序也有关系,比如时序问题,延时时间等都有关系,建议首先检查软件,看看是否有这些问题,如果软件确保无误,那么再从硬件方面找答案。硬件方面首先看看总线,一般总线上接一个4.7K~10K的上拉电阻,数据读写才比较稳定,如果以前没有接上拉电阻,建议现在接一个试试。IO口配置我觉得问题不大,缺省状态下一般是输入口、或者准双向口。
DS18B20的读写时序和测温原理与DS1820相同,只是得到的温度值的位数因分辨率不同而不同,且温度转换时的延时时间由2s减为750ms。DS18B20测温原理如图3所示。图中低温度系数晶振的振荡频率受温度影响很小,用于产生固定频率的脉冲信号送给计数器1。高温度系数晶振随温度变化其振荡率明显改变,所产生的信号作为计数器2的脉冲输入。
计数器1和温度寄存器被预置在-55℃所对应的一个基数值。计数器1对低温度系数晶振产生的脉冲信号进行减法计数,当计数器1的预置值减到0时,温度寄存器的值将加1,计数器1的预置将重新被装入,计数器1重新开始对低温度系数晶振产生的脉冲信号进行计数,如此循环直到计数器2计数到0时,停止温度寄存器值的累加,此时温度寄存器中的数值即为所测温度。斜率累加器用于补偿和修正测温过程中的非线性,其输出用于修正计数器1的预置值。
同样的程序是什么意思?这个程序在别的单片机上跑正常?在MSP430别的型号上正常还是在其他品牌的单片机上?
如果是别的单片机上移过来的,首先看管脚对应的是哪一个,单片机程序里有没有对应的改过来,并配置好这个管脚;
DS18B20电路是否正常?正、负、信号是否接的牢靠?是否电源接反了或者接反过?反了会烧掉。
程序里有没有不能识别的其他单片机的一些寄存器、定时器什么的?
两个单片机分别是多少的晶振 多少的机器周日 对管脚的操作速度是否差异太大 超出DS18B20的时序范围?
换算表达程序有没有问题?
我能想到的故障点就这么多,希望能帮到你。
我也出现这个问题,目前找到的问题原因之一是:I/O口配置更换,在语句上来说是一句话,但在实际中,可能超过几十us,这样早过了主机采样时间了,所以出来的全部都是ffff,
而复位时序,时间量很多,所以出现复位OK,但读出来的全是ffff
希望对你有用