马老师救救我啊,我的多个DS18B20测温时打架了阿
我做的测温系统由上位机和下位机组成。上位机用MFC编写,下位机用了AT89S51。下位机接了两个DS18b20,没有采用单总线方式,而是分别用一个脚控制一个传感器。上位机发送信息帧,下位机接收、判断地址然后开始测温。测得温度用液晶1602显示,并回传上位机。调试发现故障如下:
在不与上位机通行的情况下,读取两个传感器的温度值均能正常显示在1602上。
在与上位机通信情况下,单独读取任意一个传感器的温度时显示正常,但读取两个传感器的温度时数据打架,只有先读取的一个值正常。
我实在搞不清怎么回事,是谁与谁打架,为什么会打架,怎么打起来的。马老师救救我啊!!! 先读取两个传感器的温度值(注意不能被任何中断打断),然后再一个一个的送到上位机。
==============================================================================
在与上位机通信情况下,单独读取任意一个传感器的温度时显示正常,但读取两个传感器的温度时数据打架,只有先读取的一个值正常。我实在搞不清怎么回事,是谁与谁打架,为什么会打架,怎么打起来的。
估计你读第2个18b20时,时序被UART通信打乱了(UART在送第一个的数据),如果你用了UART中断,那么就更能肯定问题所在了。 我没有用UART中断,现经过测试发现液晶显示串行收发都没问题,问题出在18B20的函数,我发现我写的函数不稳定,代码贴这里了,马老师帮忙看一下,谢谢
#define SET_DQ_HighP2|=(1<<(n-1))
#define SET_DQ_LOW P2&=~(1<<(n-1))
void delay_ms(uint n)
{
uint i,j;
for(i=n;i>0;i--)
for(j=0;j<1140;j++);
}
void Init_DS18B20(uchar num) //初始化函数
{
uchar x=0;
uchar n;
n=num;
SET_DQ_High;
//DQ = 1; //DQ复位
delay(8);//稍做延时
SET_DQ_LOW;
// DQ = 0; //单片机将DQ拉低
delay(80); //精确延时 大于480us
SET_DQ_High;
// DQ = 1; //拉高总线
delay(14);
x=P2&(1<<(n-1));
// x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败
}
////////////////////////////////////////////////////////////////
char ReadOneChar(uchar num) //读一个字节
{
unsigned char i=0;
unsigned char dat = 0;
uchar n;
n=num;
for (i=8;i>0;i--)
{
SET_DQ_LOW;
// DQ = 0; // 给脉冲信号
dat>>=1;
SET_DQ_High;
// DQ = 1; // 给脉冲信号
if((P2&(1<<(n-1)))>>(n-1))
// if(DQ)
dat|=0x80;
delay(4);
}
return(dat);
}
/////////////////////////////////////////////////////////////
void WriteOneChar(uchar dat,uchar num)//写一个字节
{
unsigned char i=0;
uchar n;
n=num;
for (i=8; i>0; i--)
{
SET_DQ_LOW;
// DQ = 0;
if(dat&0x01)
{
P2|=(1<<(n-1));
}
else
P2&=~(1<<(n-1));
// DQ = dat&0x01;
delay(5);
SET_DQ_High;
// DQ = 1;
dat>>=1;
}
delay(4);
}
/////////////////////////////////////////////////////////////
uint ReadTemperature(uchar num)//读取温度
{
unsigned char a=0,c=0; //低字节
unsigned char b=0; //高字节
unsigned int t=0; //温度
uchar n;
n=num;
Init_DS18B20(n);
WriteOneChar(0xCC,n); // 跳过读序号列号的操作
WriteOneChar(0x44,n); // 启动温度转换
Init_DS18B20(n);
WriteOneChar(0xCC,n); //跳过读序号列号的操作
WriteOneChar(0xBE,n); //读取温度寄存器等(共可读9个寄存器)前两个就是温度
a=ReadOneChar(n); //Read the low byte of the temperature
b=ReadOneChar(n); // high
c=a;
a>>=4; //低字节右移四位
b<<=4; //高字节左移四位
t=a|b;
t<<=8;
c&=0x0F;
t|=c;
// tt=c;
// tt*=0.0625;
// c=tt*10+0.5;
// t=t*10+c;
return t;
}
/////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
void delay10ms(unsigned char time) //延时程序
{
uchar a,b,c;
for(a=0;a<time;a++)
for(b=0;b<10;b++)
for(c=0;c<12;c++);
}
///////////////////////////////////////////////////////////////
void delay(unsigned int i)//延时函数
{
while(i--);
} ReadTemperature(1)和ReadTemperature(2)都没有问题,ReadTemperature(3)开始就有问题,温度读出23.9375来,并始终保持不变,我知道这里面肯定有问题,但是就是看不出来 单总线的时序要求比较严格,可能你的定时会出问题。建议你,
1。使用外部晶体,不要使用内部的RC振荡。
2。使用CVAVR环境,它提供了专用的单总线函数供使用。 点击此处打开armok01158499.pdf
请注意写和读的时序!
页:
[1]