侧边栏壁纸
    • 累计撰写 296 篇文章
    • 累计收到 520 条评论
    HAL_STM32_DS18B20开发
    我的学记|刘航宇的博客

    HAL_STM32_DS18B20开发

    刘航宇
    2022-02-03 / 3 评论 / 865 阅读 / 正在检测是否收录...

    1.设置一个如PA0作为DS18B20模块接口

    2.添加下面2个文件,注意程序已经集成us延时

    ds18b20.c

    #include "ds18b20.h"
    
    static inline void delay_ms(uint32_t delay)
    {
        HAL_Delay(delay);
    }
    
    #define CPU_FREQUENCY_MHZ 72                // CPU主频,根据实际进行修改
    static void delay_us(uint32_t delay)
    {
        int last, curr, val;
        int temp;
    
        while (delay != 0)
        {
            temp = delay > 900 ? 900 : delay;
            last = SysTick->VAL;
            curr = last - CPU_FREQUENCY_MHZ * temp;
            if (curr >= 0)
            {
                do
                {
                    val = SysTick->VAL;
                }
                while ((val < last) && (val >= curr));
            }
            else
            {
                curr += CPU_FREQUENCY_MHZ * 1000;
                do
                {
                    val = SysTick->VAL;
                }
                while ((val <= last) || (val > curr));
            }
            delay -= temp;
        }
    }
    
    //复位DS18B20
    void DS18B20_Rst(void)       
    {                 
        DS18B20_IO_OUT(); //SET PA0 OUTPUT
        DS18B20_DQ_OUT=0; //拉低DQ
        delay_us(750);    //拉低750us
        DS18B20_DQ_OUT=1; //DQ=1 
        delay_us(15);     //15US
    }
    //等待DS18B20的回应
    //返回1:未检测到DS18B20的存在
    //返回0:存在
    uint8_t DS18B20_Check(void)
    {   
        uint8_t retry=0;
        DS18B20_IO_IN();//SET PA0 INPUT     
        while (DS18B20_DQ_IN&&retry<200)
        {
            retry++;
            delay_us(1);
        };     
        if(retry>=200)return 1;
        else retry=0;
        while (!DS18B20_DQ_IN&&retry<240)
        {
            retry++;
            delay_us(1);
        };
        if(retry>=240)return 1;        
        return 0;
    }
    //从DS18B20读取一个位
    //返回值:1/0
    uint8_t DS18B20_Read_Bit(void)              // read one bit
    {
        uint8_t data;
        DS18B20_IO_OUT();//SET PA0 OUTPUT
        DS18B20_DQ_OUT=0; 
        delay_us(2);
        DS18B20_DQ_OUT=1; 
        DS18B20_IO_IN();//SET PA0 INPUT
        delay_us(12);
        if(DS18B20_DQ_IN)data=1;
        else data=0;     
        delay_us(50);           
        return data;
    }
    //从DS18B20读取一个字节
    //返回值:读到的数据
    uint8_t DS18B20_Read_Byte(void)    // read one byte
    {        
        uint8_t i,j,dat;
        dat=0;
        for (i=1;i<=8;i++) 
        {
            j=DS18B20_Read_Bit();
            dat=(j<<7)|(dat>>1);
        }                            
        return dat;
    }
    //写一个字节到DS18B20
    //dat:要写入的字节
    void DS18B20_Write_Byte(uint8_t dat)
     {             
        uint8_t j;
        uint8_t testb;
        DS18B20_IO_OUT();//SET PA0 OUTPUT;
        for (j=1;j<=8;j++) 
        {
            testb=dat&0x01;
            dat=dat>>1;
            if (testb) 
            {
                DS18B20_DQ_OUT=0;// Write 1
                delay_us(2);                            
                DS18B20_DQ_OUT=1;
                delay_us(60);             
            }
            else 
            {
                DS18B20_DQ_OUT=0;// Write 0
                delay_us(60);             
                DS18B20_DQ_OUT=1;
                delay_us(2);                          
            }
        }
    }
    //开始温度转换
    void DS18B20_Start(void)// ds1820 start convert
    {                                          
        DS18B20_Rst();       
        DS18B20_Check();     
        DS18B20_Write_Byte(0xcc);// skip rom
        DS18B20_Write_Byte(0x44);// convert
    } 
    //初始化DS18B20的IO口 DQ 同时检测DS的存在
    //返回1:不存在
    //返回0:存在         
    uint8_t DS18B20_Init(void)
    {
        DS18B20_Rst();
        return DS18B20_Check();
    }  
    //从ds18b20得到温度值
    //精度:0.1C
    //返回值:温度值 (-550~1250) 
    short DS18B20_Get_Temp(void)
    {
        uint8_t temp;
        uint8_t TL,TH;
        short tem;
        DS18B20_Start ();                    // ds1820 start convert
        DS18B20_Rst();
        DS18B20_Check();     
        DS18B20_Write_Byte(0xcc);// skip rom
        DS18B20_Write_Byte(0xbe);// convert        
        TL=DS18B20_Read_Byte(); // LSB   
        TH=DS18B20_Read_Byte(); // MSB  
                  
        if(TH>7)
        {
            TH=~TH;
            TL=~TL; 
            temp=0;//温度为负  
        }else temp=1;//温度为正            
        tem=TH; //获得高八位
        tem<<=8;    
        tem+=TL;//获得底八位
        tem=(float)tem*0.625;//转换     
        if(temp)return tem; //返回温度值
        else return -tem;    
    } 

    ds18b20.h

    #ifndef __DS18B20_H
    #define __DS18B20_H 
    
    #include "main.h"
    #include "stm32f1xx_hal.h"       
    //#include "delay.h"
    
    #define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2))
    #define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr))
    #define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum))
    
    #define GPIOA_ODR_Addr    (GPIOA_BASE+12)
    #define GPIOB_ODR_Addr    (GPIOB_BASE+12)
    #define GPIOC_ODR_Addr    (GPIOC_BASE+12)
    #define GPIOD_ODR_Addr    (GPIOD_BASE+12)
    #define GPIOE_ODR_Addr    (GPIOE_BASE+12)
    #define GPIOF_ODR_Addr    (GPIOF_BASE+12)
    #define GPIOG_ODR_Addr    (GPIOG_BASE+12)
    
    #define GPIOA_IDR_Addr    (GPIOA_BASE+8)
    #define GPIOB_IDR_Addr    (GPIOB_BASE+8)
    #define GPIOC_IDR_Addr    (GPIOC_BASE+8)
    #define GPIOD_IDR_Addr    (GPIOD_BASE+8)
    #define GPIOE_IDR_Addr    (GPIOE_BASE+8)
    #define GPIOF_IDR_Addr    (GPIOF_BASE+8)
    #define GPIOG_IDR_Addr    (GPIOG_BASE+8)
    
    #define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)
    #define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)
    
    #define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)
    #define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)
    
    #define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)
    #define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)
    
    #define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)
    #define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)
    
    #define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)
    #define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)
    
    #define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)
    #define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)
    
    #define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)
    #define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)
    
    
    //IO方向设置
    #define DS18B20_IO_IN()  {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=8<<0;}
    #define DS18B20_IO_OUT() {GPIOA->CRL&=0XFFFFFFF0;GPIOA->CRL|=3<<0;}
    
    //IO操作函数
    #define    DS18B20_DQ_OUT PAout(0) //数据端口    PA0
    #define    DS18B20_DQ_IN  PAin(0)  //数据端口    PA0 
           
    uint8_t DS18B20_Init(void);            //初始化DS18B20
    short DS18B20_Get_Temp(void);        //获取温度
    void DS18B20_Start(void);            //开始温度转换
    void DS18B20_Write_Byte(uint8_t dat);//写入一个字节
    uint8_t DS18B20_Read_Byte(void);    //读出一个字节
    uint8_t DS18B20_Read_Bit(void);        //读出一个位
    uint8_t DS18B20_Check(void);        //检测是否存在DS18B20
    void DS18B20_Rst(void);                //复位DS18B20
    #endif

    程序进行调用

    使用温度=DS18B20_Get_Temp();进行调用数值,可见精度达到要求了

    10
    泰戈尔《生如夏花》
    « 上一篇 2022-02-10
    【10】基于STM32CubeMX-STM32ADC与OLED开发
    下一篇 » 2022-01-31

    评论 (3)

    取消
    1. 头像
      天天
      Windows 10 · Google Chrome

      为什么显示这个问题呀startup_stm32f103x6.s(43): error: A1355U: A Label was found which was in no AREA

      回复
    2. 头像
      老柠檬
      Windows 10 · Google Chrome

      请问这个delay.h在哪

      回复
      1. 头像
        刘航宇 作者
        Windows 10 · Google Chrome
        @ 老柠檬

        可以注释掉,本程序已经集成us延时,直接注释掉即可

        回复