找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1504|回复: 8
收起左侧

AVR16单片机读取DS18B20的测量温度出现的问题

[复制链接]
ID:962686 发表于 2021-9-14 18:46 | 显示全部楼层 |阅读模式
附上关于DS18B20操作的部分源码读到temp是错误的!!!
然后我单独检验读到的MSB和LSB的值,结果竟然是一样的!!!!
搞了好久还没有解决,只能请教大佬们了
///////////////////////////////////////
AVR16
8M
//////////////////////////////////////
#include<iom16v.h>
#include"lcd1602.h"

#define DQ_OUT DDRA|=0X80
#define DQ_IN DDRA&=~0X80
#define DQ_ON PORTA|=0X80
#define DQ_OFF PORTA&=~0X80

void IO_init(void);
char DS18_init(void);
void Write_cmd(uchar cmd);
uchar Read_data(void);

const uchar num[]={"0123456789"};

void delay_us(uint us)//微妙延时
{
do{
us--;
}while(us>1);
}

void delay_ms(uint ms)//毫秒延时
{
while(ms != 0)
{
delay_us(999);
ms--;
}
}

void IO_init(void)//初始化lcd1602与avr的接口
{
DDRC = 0XFF;
PORTC = 0XFF;
DDRD |= (1<<7)|(1<<6)|(1<<5);
PORTD |= (1<<7)|(1<<6)|(1<<5);
}

char DS18_init(void)
{
char flag;
DQ_OUT;//输出
DQ_ON;//1
DQ_OFF;//0
delay_us(550);//>480us
DQ_ON;//1
DQ_IN;//输入
delay_us(68);
if(PINA & 0X80) flag = 0;
else flag = 1;//初始化成功
delay_us(420);
return flag;
}

void Write_cmd(uchar cmd)//写一个字节
{
char i,flag=0;
DQ_OUT;
DQ_ON;
for(i=0;i<8;i++)
{
flag = cmd & 0X01;
if(flag)
{
DQ_OFF;
delay_us(10);
DQ_ON;
delay_us(50);
}
else
{
DQ_OFF;
delay_us(60);
}
DQ_ON;
cmd>>=1;
}
}

uchar Read_data(void)//读一个字节
{
uchar i,flag=0,data=0;
DQ_OUT;
DQ_ON;
for(i=0;i<8;i++)
{
data>>=1;
DQ_OFF;
delay_us(5);
DQ_IN;
DQ_ON;
delay_us(5);
flag = PINA & 0X80;
delay_us(50);
if(flag) data |= 0X80;
DQ_OUT;
DQ_ON;
}
return data;
}

void Changtemp(void)//温度转换
{
DS18_init();
Write_cmd(0xcc);
Write_cmd(0x44);
delay_ms(800);
}

void Readtemp(void)//读取温度
{
DS18_init();
Write_cmd(0xcc);
Write_cmd(0xbe);
}

uchar ReadDS18temp(void)
{
uchar tmh = 0, tml = 0;
int temp = 0;
Changtemp();
Readtemp();
tml = Read_data();//先接收低位
tmh = Read_data();//再接收高位
//这里读到的高位和低位是一样的
temp = tmh;
temp <<= 8;
temp |= tml;
return temp;
}
//main省略




回复

使用道具 举报

ID:624769 发表于 2021-9-14 20:31 | 显示全部楼层
你初始化的判断, 有点问题……
DQ_IN;//输入
delay_us(68);
if(PINA & 0X80) flag = 0;
else flag = 1;//初始化成功
delay_us(420);
return flag;
你没有去读 18B20 的低点平……,你怎么确认初始化成功了? 也许压根没有拉低过呢?要先读到低电平然后他又变高电平,才是他告诉你,初始化已经成功,你傻等60微妙直接读到高电平没用的。
回复

使用道具 举报

ID:962686 发表于 2021-9-15 08:02 | 显示全部楼层
188610329 发表于 2021-9-14 20:31
你初始化的判断, 有点问题……
DQ_IN;//输入
delay_us(68);

我读了啊
if(PINA&0x80)//68us后还是高电平的话没有初始成功返回0
flag = 0;
else flag = 1;//若是低电平,成功,返回1
//如果延时没有太大误差那么第一次拉低电平>480us再次拉高电平的68us后这段时间是DS18B20返回初始信息的时间。实际我也单独测试了初始化函数,确实返回成功标志flag = 1;
//是不是我哪里了解错了
回复

使用道具 举报

ID:962686 发表于 2021-9-15 22:59 | 显示全部楼层
好久了还是卡在读到的高位和低位数据是一样的,在25°C时MSB是144,LSB也是
回复

使用道具 举报

ID:624769 发表于 2021-9-15 23:43 | 显示全部楼层
wzl570 发表于 2021-9-15 08:02
我读了啊
if(PINA&0x80)//68us后还是高电平的话没有初始成功返回0
flag = 0;

不是啊,你仔细看看你的代码:

DQ_ON;//1
DQ_IN;//输入
delay_us(68);
if(PINA & 0X80) flag = 0;
else flag = 1;//初始化成功
delay_us(420);
return flag;

你是直接 68 us 后 判断,是不是高电平, 你压根没有管, 68us 之前,有没有过 低电平。换句话说,就算前面一直是高电平,你也是判断的初始化成功, 而初始化成功的关键是, 68us 之前,必须出现过低电平,这么说你能理解么?
所以,你的判断逻辑 应该是, 拉高电平后,1us 之后 等待低电平,接受到低电平后,计时60us 后再判断是否变高电平,是的话,才算初始化成功。
回复

使用道具 举报

ID:962686 发表于 2021-9-19 10:47 | 显示全部楼层
188610329 发表于 2021-9-15 23:43
不是啊,你仔细看看你的代码:

DQ_ON;//1

有点不懂,给ds18一个480-960us低电平后拉高电平之后60us-75us(15-75,15-255,60-120,60-300的交集)不就是ds18返回初始化成功的信号时间段吗(前提延时误差不大)。请问大佬能不能给个代码参考。
4-2.png
回复

使用道具 举报

ID:419968 发表于 2021-9-20 18:28 | 显示全部楼层
主机拉低总线480-960us后释放总线,由上拉电阻拉高总线,过15-60us 18b20会拉低总行
所以延时68us后等待18b20拉低,
回复

使用道具 举报

ID:382454 发表于 2021-10-6 22:15 来自手机 | 显示全部楼层
其实就是瞠序和判断的问题,我发过一个类似的贴,你找找。
回复

使用道具 举报

ID:382454 发表于 2021-10-8 11:23 | 显示全部楼层
http://www.51hei.com/bbs/dpj-139513-1.html
这个贴子,你看看。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表