电子产业一站式赋能平台

PCB联盟网

搜索
查看: 3075|回复: 3
收起左侧

RT-Thread DS18B20温度传感器驱动程序

[复制链接]

131

主题

512

帖子

1666

积分

三级会员

Rank: 3Rank: 3

积分
1666
发表于 2021-4-10 12:12:04 | 显示全部楼层 |阅读模式







[color=rgb(51, 102, 153) !important]复制代码



//首先查到到相关的DS18b20驱动
//然后打开驱动  打开方式为RT_NULL
//打开成功就可以调用rt_device_read函数读取温度
//

#include <rtdevice.h>
#include <rthw.h>
#include <board.h>

//还没有添加调试信息
//应该添加一个.h文件


#IF 0 /* 库函数方式 */
        #define DQ_0(PORT_DQ,PIN_DQ)                GPIO_ResetBits(PORT_DQ, PIN_DQ)
        #define DQ_1(PORT_DQ,PIN_DQ)                GPIO_SetBits(PORT_DQ, PIN_DQ)

        /* 判断DQ输入是否为低 */
        #define DQ_IS_HIGH()                    GPIO_ReadInputDataBit(PORT_DQ, PIN_DQ)
#else        /* 直接操作寄存器,提高速度 */
        #define DQ_0(PORT_DQ,PIN_DQ)                PORT_DQ->BSRR |= (PIN_DQ<<16)
        #define DQ_1(PORT_DQ,PIN_DQ)                PORT_DQ->BSRR |= (PIN_DQ)

        /* 判断DQ输入是否为低 */
        #define DQ_IS_HIGH(PORT_DQ,PIN_DQ)        (PORT_DQ->IDR & PIN_DQ)
#endif


//设置IO口方向
#define _IO_IN(CR,BIT_AND,BIT_OR)  {*CR&=BIT_AND;*CR|=BIT_OR;}
#define _IO_OUT(CR,BIT_AND,BIT_OR) {*CR&=BIT_AND;*CR|=BIT_OR;}

//驱动名字
#define HARD_DEVICE_NAME_FORMAT     "18b20_%d"
#define HARD_DEVICE_NAME_SIZE       (sizeof(HARD_DEVICE_NAME_FORMAT) + 2)

//获得数组元素个数
#ifndef ARRAY_SIZE
#define ARRAY_SIZE(arr)     (sizeof(arr)/sizeof(arr[0]))
#endif

//IO口相关信息
struct ds18b20_gpio_desc
{
    uint32_t rcc;
    GPIO_TypeDef *gpio;
    uint32_t pin;
};

//在这里添加DS18B20相关引脚信息
//如果有多个DS18B20,依次添加即可
//目前只支持一个引脚上挂一个DS18B20
const static struct ds18b20_gpio_desc _hard_desc[] =
{
    {RCC_APB2Periph_GPIOA, GPIOA, GPIO_Pin_3},
};
//其他地方不需要修改





//设置IO方向
struct _IO_
{
    uint32_t _IO_IN_and;
    uint32_t _IO_IN_or;
    uint32_t _IO_OUT_and;
    uint32_t _IO_OUT_or;
    volatile uint32_t * _CRx;
};

//DS18B20驱动
struct _ds18b20_drv
{
    struct rt_device device;
    struct _IO_ io;
    const struct ds18b20_gpio_desc * hard_desc;
    rt_mutex_t mutex;
};

//内部使用,左移四位
static uint32_t _crol_(uint32_t c)
{
    uint32_t temp;

    temp = c<<4;
    c = c>>(sizeof(uint32_t)*8-4);
    return c |= temp;
}

//DS18B20复位
static rt_err_t _ds18b20_reset(struct _ds18b20_drv * _drv)
{
    uint8_t retry = 0;

    _IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
    DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
    rt_delay_us(750);//拉低750us
    DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
    rt_delay_us(10);
        _IO_IN(_drv->io._CRx,_drv->io._IO_IN_and,_drv->io._IO_IN_or);
    while(DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin)&&retry<200)
        {
                retry++;
                rt_delay_us(1);
        }

        if(retry>=200)
        return RT_ERROR;

    while((!DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin))&&retry<240)
        {
                retry++;
                rt_delay_us(1);
        }

        if(retry>=240)
        return RT_ERROR;

        return RT_EOK;
}

//DS18B20读一个字节
static rt_err_t _ds18b20_read_byte(struct _ds18b20_drv * _drv, uint8_t * data)
{
    uint8_t bit = 0,result = 0;
    uint8_t i = 0;

    for(i = 0;i<8;i++)
    {
        _IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
        DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
        rt_delay_us(1);
        DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
        _IO_IN(_drv->io._CRx,_drv->io._IO_IN_and,_drv->io._IO_IN_or);
        rt_delay_us(12);
        if(DQ_IS_HIGH(_drv->hard_desc->gpio,_drv->hard_desc->pin)) bit=1;
        else bit=0;               
        result=(bit<<7)|(result>>1);

        rt_delay_us(50);
    }
    *data = result;

    return RT_EOK;
}

//DS18B20写一个字节
static uint8_t _ds18b20_write_byte(struct _ds18b20_drv * _drv, uint8_t data)
{
    uint8_t i, testb;

        _IO_OUT(_drv->io._CRx,_drv->io._IO_OUT_and,_drv->io._IO_OUT_or);
    for (i=0;i<8;i++)
        {
        testb=data&0x01;
        data=data>>1;
        if (testb)
        {
            DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
            rt_delay_us(2);                           
            DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
            rt_delay_us(60);
        }
        else
        {
            DQ_0(_drv->hard_desc->gpio,_drv->hard_desc->pin);
            rt_delay_us(60);                           
            DQ_1(_drv->hard_desc->gpio,_drv->hard_desc->pin);
            rt_delay_us(2);                          
        }
    }

    return RT_EOK;
}

//DS18B20转换一次
static rt_err_t _ds18b20_start(struct _ds18b20_drv * _drv)
{
    rt_base_t level;

    if(_ds18b20_reset(_drv) == RT_EOK)
    {
        level = rt_hw_interrupt_disable();
        _ds18b20_write_byte(_drv,0xcc);        // skip rom
        _ds18b20_write_byte(_drv,0x44);        // convert
        rt_hw_interrupt_enable(level);

        return RT_EOK;
    }

    return RT_ERROR;
}

//ds18b20读取温度
static rt_err_t _ds18b20_read_data(struct _ds18b20_drv * _drv, float * result)
{
    rt_base_t level;
    uint8_t  data_H, data_L;
    short data;

    _ds18b20_reset(_drv);
    level = rt_hw_interrupt_disable();
    _ds18b20_write_byte(_drv,0xcc);        // skip rom
    _ds18b20_write_byte(_drv,0xbe);        // convert            
    _ds18b20_read_byte(_drv, &data_L);         // LSB   
    _ds18b20_read_byte(_drv, &data_H);         // MSB
    rt_hw_interrupt_enable(level);
    data = data_H;
    data <<= 8;
    data |=  data_L;
    if(data&0xF800)
        *result=(~data+1)*0.0625*10;
    else
        *result=data*0.0625;

    if(*result>-55 && *result<125)
        return RT_EOK;
    else
        return RT_ERROR;

}

static rt_err_t STM32_ds18b20_init(rt_device_t dev)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    uint32_t TempInAnd,TempInOr,TempOutAnd,TempOutOr;
    uint16_t GPIO_Pin_x = 0;

    struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;

    RCC_APB2PeriphclockCmd(ds18b20->hard_desc->rcc, ENABLE);         //使能时钟
    GPIO_InitStructure.GPIO_Pin = ds18b20->hard_desc->pin;             // 推挽输出
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(ds18b20->hard_desc->gpio, &GPIO_InitStructure);
    GPIO_SetBits(ds18b20->hard_desc->gpio,ds18b20->hard_desc->pin);//输出1

    TempInAnd  = 0xFFFFFFF0;
    TempOutAnd = 0xFFFFFFF0;
    TempInOr   = 0x00000008;
    TempOutOr  = 0x00000003;

    if (((uint32_t)GPIO_InitStructure.GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
    {
        ds18b20->io._CRx = &(ds18b20->hard_desc->gpio->CRL);
        GPIO_Pin_x = ds18b20->hard_desc->pin>>1;
    }
    if((GPIO_InitStructure.GPIO_Pin > 0x00FF))
    {
        ds18b20->io._CRx = &(ds18b20->hard_desc->gpio->CRH);
        GPIO_Pin_x = ds18b20->hard_desc->pin>>9;
    }

    while(GPIO_Pin_x)
    {
        TempInAnd  = _crol_(TempInAnd);
        TempOutAnd = _crol_(TempOutAnd);
        TempInOr   = _crol_(TempInOr);
        TempOutOr  = _crol_(TempOutOr);
        GPIO_Pin_x >>= 1;
    }

    ds18b20->io._IO_IN_and  = TempInAnd;
    ds18b20->io._IO_IN_or   = TempInOr;
    ds18b20->io._IO_OUT_and = TempOutAnd;
    ds18b20->io._IO_OUT_or  = TempOutOr;

    return RT_EOK;
}
static rt_err_t stm32_ds18b20_open(rt_device_t dev, rt_uint16_t oflag)
{   
    struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;

    return _ds18b20_reset(ds18b20);
}

static rt_err_t stm32_ds18b20_close(rt_device_t dev)
{

    return RT_EOK;
}

static rt_size_t stm32_ds18b20_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size)
{
    float temp;
    int count = 0,i = 0;
    float * data = (float *)buffer;
    struct _ds18b20_drv * ds18b20 = (struct _ds18b20_drv *)dev;

    while(i<(size/sizeof(float)))
    {
        rt_mutex_take(ds18b20->mutex,RT_WAITING_FOREVER);
        if(_ds18b20_start(ds18b20) == RT_EOK)
        {
            rt_thread_delay(800);
            if(_ds18b20_read_data(ds18b20, &temp) == RT_EOK)
            {
                data = temp;
                count++;
            }
            else
            {
                data = 85;
            }

        }
        rt_mutex_release(ds18b20->mutex);
        i++;
    }

    return count;
}

static rt_err_t stm32_ds18b20_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{

    return RT_EOK;
}

int ds18b20_drv_init(void)
{
    int i = 0, count = 0;
    char dev_name[HARD_DEVICE_NAME_SIZE] = "";
    struct _ds18b20_drv *_dev = RT_NULL;

    for(i=0; i<ARRAY_SIZE(_hard_desc);i++)
    {
        _dev = (struct _ds18b20_drv *)rt_malloc(sizeof(struct _ds18b20_drv));
        if (RT_NULL == _dev)
        {
            continue;
        }
        rt_sprintf(dev_name, HARD_DEVICE_NAME_FORMAT, i);
        if(RT_NULL ==rt_device_find(dev_name))
        {
            _dev->hard_desc = &(_hard_desc);
            _dev->device.init      = stm32_ds18b20_init;
            _dev->device.open      = stm32_ds18b20_open;
            _dev->device.close     = stm32_ds18b20_close;
            _dev->device.read      = stm32_ds18b20_read;
            _dev->device.write     = RT_NULL;
            _dev->device.control   = stm32_ds18b20_control;
            _dev->device.user_data = RT_NULL;
            rt_device_register(&(_dev->device),dev_name,RT_DEVICE_FLAG_RDONLY);

            _dev->mutex =  rt_mutex_create(dev_name,RT_IPC_FLAG_FIFO); //创建信号量没有判断是否成功

            count++;
        }
    }

    return count;
}


INIT_DEVICE_EXPORT(ds18b20_drv_init);

回复

使用道具 举报

131

主题

512

帖子

1666

积分

三级会员

Rank: 3Rank: 3

积分
1666
发表于 2021-4-10 12:12:18 | 显示全部楼层
需要做PCB线路板的可以联系我

13651479995
回复 支持 反对

使用道具 举报

3

主题

2721

帖子

3052

积分

四级会员

Rank: 4

积分
3052
发表于 2021-6-4 13:45:11 | 显示全部楼层
11111111111111111111111111
回复 支持 反对

使用道具 举报

lyl

1

主题

1119

帖子

3525

积分

四级会员

Rank: 4

积分
3525
发表于 2021-6-25 11:26:02 | 显示全部楼层
资料很好,学习学习
回复 支持 反对

使用道具 举报

发表回复

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

本版积分规则

关闭

站长推荐上一条 /1 下一条


联系客服 关注微信 下载APP 返回顶部 返回列表