你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32的DS18B20的问题  

[复制链接]
H_JEN 提问时间:2016-5-2 17:21 /
阅读主题, 点击返回1楼
收藏 3 评论55 发布时间:2016-5-2 17:21
55个回答
Taonsh 回答时间:2016-5-9 08:58:36
H_JEN 发表于 2016-5-8 16:19
还没解决。现在能读数据了,但是读出来的数据,高八位要么全为0,要么全为1;低八位总是为0 ...

如果时序没有问题,很有可能是你延时没有正确造成的,要么就是你拿的器件有问题,可以换一个18B20看看,我上传部分我的代码,你参考一下;
/****************************************************************************************
Include file
****************************************************************************************/
#include "stm32f10x.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

#include "DS18B20.h"
#include "DS18B20_hal.h"

/****************************************************************************************
全局变量定义
****************************************************************************************/

/****************************************************************************************
函 数 名:static void DS18B20RccInit(void)
参数描述:
返回值描述:无
特殊算法:无
注意事项:
****************************************************************************************/
static void DS18B20RccInit(void)
{
        RCC->BitAPB2ENR.IOPCEN = 1;
        RCC->BitAPB2ENR.AFIOEN = 1;
}

/****************************************************************************************
函数名:static void SetDQPortOutput(void)
函数功能:设DQ为输出模式
参数描述:
返回值描述:无
特殊算法:无
注意事项:
****************************************************************************************/
static void SetDQPortOutput(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        //配置LED的管脚为开漏输出
        GPIO_InitStructure.GPIO_Pin = DS18B20_DQ_PIN;                        //DQ试制电路板PC0,(原PA1)
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                //GPIO_Mode_Out_PP;GPIO_Mode_AF_PP
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_Init(DS18B20_DQ_PORT, &GPIO_InitStructure);
}

/****************************************************************************************
函数名:static void  SetDQPortInput(void)
函数功能:设DQ为输入模式
参数描述:
返回值描述:无
特殊算法:无
注意事项:
****************************************************************************************/
static void SetDQPortInput(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

        GPIO_InitStructure.GPIO_Pin =DS18B20_DQ_PIN;                    //DQ(PA1)
        GPIO_InitStructure.GPIO_Mode =GPIO_Mode_IN_FLOATING;            // GPIO_Mode_IPU;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;       
        GPIO_Init(DS18B20_DQ_PORT, &GPIO_InitStructure);
}

/****************************************************************************************
函 数 名:static void DS12B20TimInit()
函数功能:定时器初始化配置
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static void DS18B20TimInit()
{
        TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
        //计数频率 72000000/72 = 1MHz
        TIM_TimeBaseStructure.TIM_Prescaler = 72-1;                     //时钟预分频数
        TIM_TimeBaseStructure.TIM_Period = 1;                           //arr 设置自动重装载寄存器 arr  1MHz  1us溢出时间
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;         //采样不分频  
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;         //向上计数模式
        TIM_TimeBaseInit(DS18B20_TIM, &TIM_TimeBaseStructure);
        TIM_ClearFlag(DS18B20_TIM, TIM_FLAG_Update);                         //清除溢出标志
}

/****************************************************************************************
函 数 名:static void DS18B20_5us(void)
函数功能:定时器延时5*byDelay个us
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static void DS18B20_5us(uint8_t byDelay)
{
        TIM_SetCounter(DS18B20_TIM, 0);                                 //清计数器
        TIM_SetAutoreload(DS18B20_TIM, 5*byDelay);                      //设置自动重载,定时器计时==5ms*byDelay;
        TIM_Cmd(DS18B20_TIM, ENABLE);

        while(TIM_GetFlagStatus(DS18B20_TIM, TIM_FLAG_Update) == RESET)
        {
                ;
        }
        TIM_ClearFlag(DS18B20_TIM,TIM_FLAG_Update);                     //清除溢出标志
        TIM_Cmd(DS18B20_TIM, DISABLE);
}

/****************************************************************************************
函 数 名:static void Init_DS18B20(void)
函数功能:
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static uint8_t Init_DS18B20(void)
{
        uint8_t byCount = 0;
        SetDQPortOutput();
        DS18B20_DQ_H;                                                   //DQ= 1复位
        DS18B20_5us(12);
        DS18B20_DQ_L;                                                   //DQ= 0
        DS18B20_5us(120);                                               //延时600微秒(该时间的时间范围可以从480到960微秒)

        DS18B20_DQ_H;
        DS18B20_5us(1);

        SetDQPortInput();

        while((GPIO_ReadInputDataBit(DS18B20_DQ_PORT, DS18B20_DQ_PIN)) && (byCount < 200))
        {
                byCount ++;
                DS18B20_5us(1);
        }

        DS18B20_5us(80);

        SetDQPortOutput();
        DS18B20_DQ_H;
        DS18B20_5us(1);

        return byCount;
}

/****************************************************************************************
函数名:void Ap3156Open(void)
函数功能:初始化Ap3156管脚电平
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
void DS18B20_Open(void)
{
        DS18B20RccInit();

        RCC->BitAPB1ENR.TIM2EN = 1;
        DS18B20TimInit();
        TIM_ClearITPendingBit(DS18B20_TIM, TIM_IT_Update);
        TIM_ClearFlag(DS18B20_TIM, TIM_FLAG_Update);
        TIM_Cmd(DS18B20_TIM, DISABLE);

        Init_DS18B20();
}

/****************************************************************************************
函数名:void WriteOneChar(void)
函数功能:写一个字节
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static void WriteOneChar(unsigned char dat)
{
         SetDQPortOutput();
         for(uint8_t i=8; i>0; i--)
         {
                 if(dat&0x01)     //写1
                 {
                        DS18B20_DQ_L;
                        DS18B20_5us(1);
                        DS18B20_DQ_H;
                        DS18B20_5us(16);
                 }
                 else             //写0
                 {
                         DS18B20_DQ_L;
                         DS18B20_5us(18);
                         DS18B20_DQ_H;
                         DS18B20_5us(1);
                 }
                 dat>>=1;
         }
}

/****************************************************************************************
函数名:void ReadOneChar(void)
函数功能:读一个字节
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static unsigned char ReadOneChar(void)
{
        unsigned char dat = 0;
        for(uint8_t ii=8; ii > 0; ii--)
        {
                SetDQPortOutput();
                DS18B20_DQ_L;
                for(uint8_t i = 0;i < 100; ++i);

                DS18B20_DQ_H;
                dat>>=1;

                SetDQPortInput();
                for(uint8_t i = 0;i < 20; ++i);         //75,50

                if(GPIO_ReadInputDataBit(DS18B20_DQ_PORT, DS18B20_DQ_PIN))
                {
                    dat |= 0x80;
                }
                SetDQPortOutput();
                DS18B20_DQ_H;
                DS18B20_5us(15);
        }
        return(dat);
}

/****************************************************************************************
函数名:short Read18B20(void)
函数功能:读18B20温度
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
static short Read18B20(void)
{
        uint8_t byDataL=0;
        uint8_t byDataH=0;
        short Temperature = 0;

        if(!(Init_DS18B20() < 200))                                     //初始化失败
                if(!(Init_DS18B20() < 200))
                        return 4000;
        WriteOneChar(0xCC);                                             //跳过读序号列号的操作
        WriteOneChar(0x44);                                             //启动温度转换

        if(!(Init_DS18B20() < 200))                                     //初始化失败
                if(!(Init_DS18B20() < 200))
                        return 4000;
        WriteOneChar(0xCC);                                             //跳过读序号列号的操作
        WriteOneChar(0xBE);                                             //读取温度寄存器

        byDataL = ReadOneChar();                                        //读低8位
        byDataH = ReadOneChar();                                        //读高8位
        DS18B20_5us(10);

        Temperature = (short)((byDataH << 8) | byDataL);

        return (Temperature * 5 / 8 - 10);                              //*0.625,1摄氏度校准
}

/****************************************************************************************
函数名:void ReadTemperature(void)
函数功能:读18B20温度
参数描述:
返回值描述:
特殊算法:
注意事项:
****************************************************************************************/
short ReadTemperature(void)
{
        short Temperature1 = 0;
        short Temperature2 = 0;

        Temperature1 = Read18B20();
        DS18B20_5us(200);
        Temperature2 = Read18B20();
        if((Temperature1 < Temperature2 - 10)||(Temperature1 > Temperature2 + 10))
        {
                Temperature1 = Read18B20();
                DS18B20_5us(200);
                Temperature2 = Read18B20();
                if((Temperature1 < Temperature2 - 10) || (Temperature1 > Temperature2 + 10))
                {
                        Temperature1 = Read18B20();
                        DS18B20_5us(200);
                        Temperature2 = Read18B20();
                        if((Temperature1 < Temperature2 - 10) || (Temperature1 > Temperature2 + 10))
                                return 4000;
                }
        }
        return (Temperature1 + Temperature2)/2;
}


sacq12 回答时间:2016-5-9 20:26:24
最后再找个逻辑分析仪看下波形。
程序里的时延可能需要再仔细推敲推敲。
埃斯提爱慕 回答时间:2016-5-13 21:08:17
提示: 作者被禁止或删除 内容自动屏蔽
欣辰天下 回答时间:2016-5-17 21:37:08
现在来签到
愚民点子 回答时间:2016-5-18 13:34:00
时序要对,103芯片我直接用ALIENTEK MINISTM32板的程序改成开漏,就读出了,L152直接改成开漏不行,通过示波器观察时序不对,调试发现用库函数总是调不对,改用寄存器操作时序对了,数据就读出来了。
愚民点子 回答时间:2016-5-18 13:57:39
用库函数延时比较长,至少在L152上就有点长了,用开漏的目的就是为了省时间,省去端口切换的时间,时序必须严格按18B20说明书,再就是引线电容,通过示波器观察在读数据的一刻,如果是1,波形必须升到1,
升不到1可适当减小上拉电阻,我接了一个10米长的引线,上拉电阻用的是1K。必须保证15us内数据线能拉到1.
H_JEN 回答时间:2016-5-24 20:54:35
LIUBEIHUA 发表于 2016-5-18 13:57
用库函数延时比较长,至少在L152上就有点长了,用开漏的目的就是为了省时间,省去端口切换的时间,时序必须 ...

谢谢。这个问题已经解决了,其实我也不知道为什么,是端口配置问题,我直接配置寄存器就可以读到数据了,但是用库函数来设置端口的话就不行,不管哪种输入方式。这个问题等我调试好整个东西,再来研究下库函数。
H_JEN 回答时间:2016-5-24 22:34:12
dsjsjf 发表于 2016-5-13 21:08
这个读时序要严格控制的,确认一下你的时钟频率,程序中的延时函数的精度 ...

嗯,谢谢!问题已经解决了,是端口配置问题,我换成直接写寄存器来配置端口就没问题了,本来是用库函数来配置的,还不知是什么原因,换成寄存器就可以了.......等调试整个东西再来研究库函数
依然自我 回答时间:2017-2-23 15:34:35
本帖最后由 依然自我 于 2017-2-23 15:36 编辑

STM32F103 DQ不用改变输入输出,只要初始化设置为推挽输出,外接上拉电阻,本人用PB8跟PB10作为DQ是可以的,正点原子例程改为下面两句。
#define DS18B20_IO_IN()    {;}//{GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=8<<8;}
#define DS18B20_IO_OUT() {;}//{GPIOB->CRH&=0XFFFFFFF0;GPIOB->CRH|=3<<8;}
zbber 回答时间:2017-2-23 19:40:20
设置成开漏输出,外接上拉电阻,使用时不需要切换输入输出,试试
oceane 回答时间:2018-3-12 17:05:15
学习了
1234

所属标签

相似问题

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32Cube扩展软件包
意法半导体边缘AI套件
ST - 理想汽车豪华SUV案例
ST意法半导体智能家居案例
STM32 ARM Cortex 32位微控制器
关注我们
st-img 微信公众号
st-img 手机版