基于STM32的DS18B20的问题
本人现在在做基于STM32的DS18B20的测温,但是一直不成功。就拿初始化来说,按照时序图是先给低电平480us或以上,再给15us的高电平,然后就放开总线,18B20就开始复位。我的初始化程序时要看18B20有没有复位完成。但是我用示波器来看的时候前面给的开始信号是正确的,但是后面读18B20的复位输出的时候,18B20一直处于高电平.......为什么呢?char ds18b20_Reset(void)
{
uint8_t count = 0,i = 0;
GPIO_Out_Config();
DQ_L;
Delay_us(480);
DQ_H;
Delay_us(15);
GPIO_In_Config();//IPU模式能读数,但是一直为1,18b20可能坏了
Delay_us(10);
while(count < 100)
{
i = DQ_Read;
if(i == 1)
{
NOP();
count++;
}
else
break;
}
if(count >= 100)
return 0;
else
count = 0;
while(count <240)
{
i = DQ_Read;
if(i ==0)
{
NOP();
count++;
}
break;
}
if(count >= 240)
return 0;
else
return 1;
}以上是初始化的,GPIO的输出模式是PP推挽,GPIO的输入模式是IPU上拉输入;
求大神指点一二啊
单片机是STM32F103ZET的,现在经过修改后,能读出数据,但是高八位要么全0,要么全1;低八位总是全0。而且18b20复位完成后,不发送任何指令,直接读数据口,读出来的有时是1,有时是0。根据时序图,复位完成后,数据口应该是一直高电平才对。
完整的程序如下:
#include "stm32_18b20.h"
void ds18b20_Config(void)
{
unsigned char Init_Flag;
Init_Flag = ds18b20_Reset();
if(Init_Flag)
printf("\r\n 1 \r\n");//复位成功
else
{
printf("\r\n -1 \r\n");//复位失败
while(1);
}
}
void ds18b20_WriteCmd(uint8_t cmd)
{
uint8_t i, ch;
GPIO_Out_Config();
for(i = 0; i < 8; i++)
{
ch = cmd;
ch = ch & 0x01;
cmd = cmd >> 1;
DQ_L;
Delay_us(15);//起始15us低电平
if(ch)//写入1
{
DQ_H;
NOP();NOP();NOP();NOP();NOP();
DQ_L;
Delay_us(65);
}
else//写入0
{
DQ_L;
Delay_us(65);
DQ_H;
NOP();NOP();NOP();NOP();NOP();
}
}
}
uint8_t ds18b20_ReadData(void)
{
uint8_t i,s = 0, dat = 0, data = 0;
ds18b20_Config();
for(i = 0; i < 8; i++)
{
data = data >> 1;
DQ_L;
NOP();
DQ_H;
Delay_us(12);//放开总线
s = DQ_Read;
if(s)
dat = 1;
else
dat = 0;
Delay_us(45);
s = 0;
data = data | (dat << 7);
}
return data;
}
char ds18b20_Reset(void)
{
uint8_t count = 0,i = 0;
GPIO_Out_Config();
DQ_L;
Delay_us(480);//复位信号
DQ_H;
Delay_us(15);//释放总线
while(count < 100)
{
i = DQ_Read;
if(i == 1)
{
Delay_us(1);
count++;
}
else
break;
}
if(count >= 100)
return 0;
else
count = 0;
while(count <240)
{
i = DQ_Read;
if(i ==0)
{
Delay_us(1);
count++;
}
break;
}
if(count >= 240)
return 0;
else
{
Delay_us(750);
i = DQ_Read;
printf("\r\n i = %d\r\n ",i);
return 1;
}
}
void ds18b20_TransCmd(void)
{
ds18b20_Config();
ds18b20_WriteCmd(0xcc);//1100 1100
ds18b20_WriteCmd(0x44);//0100 0100
}
void ds18b20_ReadCmd(void)
{
ds18b20_Config();
ds18b20_WriteCmd(0xcc);//1100 1100
ds18b20_WriteCmd(0xbe);//1011 1110
}
float ds18b20_GetTemp(void)
{
uint8_t tempH = 0, tempL = 0, temp = 0;
float tem = 0;
ds18b20_TransCmd();
Delay_ms(1000);
ds18b20_ReadCmd();
tempL = ds18b20_ReadData();
tempH = ds18b20_ReadData();
// printf("\r\n 0x%d \r\n", tempH);
// printf("\r\n 0x%d \r\n", tempL);
temp = (tempH << 8) + tempL;
tem =temp * 0.0625;
printf("\r\n tem %f \r\n", tem);
return tem;
}
void NOP(void)
{
uint8_t i = 1;
i--;
}
用示波器看过延时程序的实现是正确的。复位函数里的复位信号给的也是正确的。
电路图里左边是电源线,中间是数据线,右边是地线
:):(:D:D:'(:P 设置成开漏输出,外接上拉电阻,使用时不需要切换输入输出,试试 应该配置为输入浮空。 DS18B20数据端是否加了上拉电阻。 GPIO应设置为漏极开路 其实这种Onewire的,要注意时序问题 确定总线时间和手册给出的时间是否严格匹配,最好留有余量。。。 检查电路,DQ是否做了上拉 帮顶