RT-Thread 添加 DS18B20 详解

Posted raowz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了RT-Thread 添加 DS18B20 详解相关的知识,希望对你有一定的参考价值。

 

 

闲来无事,板子上有一个DS18B20的传感器,所以就在RT-Thread系统上小试一下。。。

 

1.新建工程,这次改使用bsp,操作图(1)

技术图片

 

 

               图 (1)

 

2.打开RT-Thread Settings,如图(2)添加ds18b20的软件包

技术图片

 

 

                           图(2)

 

3.可以先编译一下,会出如图(3)的错误信息

技术图片

 

 

                      图(3)

 

 出错很正常,不慌,先看看啥问题,根据错误提示和位置,应该是找不到GET_PIN这个宏引发的问题,在该文件头部加上该宏所在的头文件drv_gpio.h即可。

 这下就编译通过了,如图(4)。

技术图片

 

 

                    图(4)

4.接下来就是根据自己的板子来修改代码。查看原理图,找到ds18b20连接到mcu的那个gpio口

我的板子接的是PG9,所以不用修改

技术图片

 

 

5.下面就可以直接下载到板子运行了,如图(5)

 

 

 

 

 

 

 

经过上面的步骤,我们已经可以完成rtthread针对ds18b20的使用了,结果已经达到了,如果只需要结果的到此为止。

下面是看源码,rtthread是如何对ds18b20进行操作的。

 

 

 懒得自己写例程了,直接看rtthread软件包中写好的sample,也就是ds18b20_sample.c

 

  • (一)  首先,看 ds18b20_sample.c,rt_hw_ds18b20_port是针对ds18b20进行初始化,包括结构体填充和注册到rtthread系统中,标红字体需细看
     1 static int rt_hw_ds18b20_port(void)
     2 {
     3     struct rt_sensor_config cfg;
     4     /*user_data存放的是引脚信息,后面会用*/
     5     cfg.intf.user_data = (void *)DS18B20_DATA_PIN; //我们修改自己板子上引脚的宏
     6     rt_hw_ds18b20_init("ds18b20", &cfg);  
     7     
     8     return RT_EOK;
     9 }
    10 /*该函数启动时自动执行*/
    11 INIT_COMPONENT_EXPORT(rt_hw_ds18b20_port);

     

 

 1 int rt_hw_ds18b20_init(const char *name, struct rt_sensor_config *cfg)
 2 {
 3     rt_int8_t result;
 4     rt_sensor_t sensor_temp = RT_NULL; 
 5     
 6     if (!ds18b20_init((rt_base_t)cfg->intf.user_data))
 7     {
 8         /* temperature sensor register */
 9         sensor_temp = rt_calloc(1, sizeof(struct rt_sensor_device));
10         if (sensor_temp == RT_NULL)
11             return -1;
12         /*主要针对ds18b20的结构体进行初始化*/
13         sensor_temp->info.type       = RT_SENSOR_CLASS_TEMP;
14         sensor_temp->info.vendor     = RT_SENSOR_VENDOR_DALLAS;
15         sensor_temp->info.model      = "ds18b20";
16         sensor_temp->info.unit       = RT_SENSOR_UNIT_DCELSIUS;
17         sensor_temp->info.intf_type  = RT_SENSOR_INTF_ONEWIRE;
18         sensor_temp->info.range_max  = SENSOR_TEMP_RANGE_MAX;
19         sensor_temp->info.range_min  = SENSOR_TEMP_RANGE_MIN;
20         sensor_temp->info.period_min = 5;
21 
22         rt_memcpy(&sensor_temp->config, cfg, sizeof(struct rt_sensor_config));
23         sensor_temp->ops = &sensor_ops;   
24 
25         /*注册到rtthread系统*/
26         result = rt_hw_sensor_register(sensor_temp, name, RT_DEVICE_FLAG_RDONLY, RT_NULL); 
27         if (result != RT_EOK)
28         {
29             LOG_E("device register err code: %d", result);
30             goto __exit;
31         }
32 
33     }
34     return RT_EOK;
35     
36 __exit:
37     if (sensor_temp)
38         rt_free(sensor_temp);
39     return -RT_ERROR;     
40 }

 

 1 /*
 2  * sensor register
 3  */
 4 int rt_hw_sensor_register(rt_sensor_t sensor,
 5                           const char              *name,
 6                           rt_uint32_t              flag,
 7                           void                    *data)
 8 {
 9     rt_int8_t result;
10     rt_device_t device;
11     RT_ASSERT(sensor != RT_NULL);
12 
13     char *sensor_name = RT_NULL, *device_name = RT_NULL;
14 
15     /* Add a type name for the sensor device */
16     sensor_name = sensor_name_str[sensor->info.type];
17     device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name));
18     if (device_name == RT_NULL)
19     {
20         LOG_E("device_name calloc failed!");
21         return -RT_ERROR;
22     }
23 
24     rt_memcpy(device_name, sensor_name, rt_strlen(sensor_name) + 1);
25     strcat(device_name, name);
26 
27     if (sensor->module != RT_NULL && sensor->module->lock == RT_NULL)
28     {
29         /* Create a mutex lock for the module */
30         sensor->module->lock = rt_mutex_create(name, RT_IPC_FLAG_FIFO);
31         if (sensor->module->lock == RT_NULL)
32         {
33             rt_free(device_name);
34             return -RT_ERROR;
35         }
36     }
37 
38     device = &sensor->parent;
39 
40 #ifdef RT_USING_DEVICE_OPS
41     device->ops         = &rt_sensor_ops;
42 #else
43     device->init        = RT_NULL;
44     device->open        = rt_sensor_open;
45     device->close       = rt_sensor_close;
46     device->read        = rt_sensor_read;
47     device->write       = RT_NULL;
48     device->control     = rt_sensor_control;
49 #endif
50     device->type        = RT_Device_Class_Sensor;
51     device->rx_indicate = RT_NULL;
52     device->tx_complete = RT_NULL;
53     device->user_data   = data;
54 
55     result = rt_device_register(device, device_name, flag | RT_DEVICE_FLAG_STANDALONE);
56     if (result != RT_EOK)
57     {
58         rt_free(device_name);
59         LOG_E("rt_sensor register err code: %d", result);
60         return result;
61     }
62 
63     rt_free(device_name);
64     LOG_I("rt_sensor init success");
65     return RT_EOK;
66 }

 

 

*************************************************以上就完成了DS18B20对rtthread系统的适配********************************************

  • (二) 对ds18b20的实际使用,还是截图吧,可以在图上添解释

技术图片

 

 

 

 

如下图是对上图函数指针操作的实际函数,在上述注册过程中赋值,也就是这里:

技术图片

1.   rt_sensor_open: 主要执行标红处

/* RT-Thread Device Interface */

根据上面的截图,传入的参数是dev也就是ds18b20,oflag = RT_DEVICE_FLAG_RDWR static rt_err_t rt_sensor_open(rt_device_t dev, rt_uint16_t oflag) { rt_sensor_t sensor = (rt_sensor_t)dev; RT_ASSERT(dev != RT_NULL); rt_err_t res = RT_EOK; if (sensor->module) { /* take the module mutex */ rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); } if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf == RT_NULL) { /* Allocate memory for the sensor buffer */ sensor->data_buf = rt_malloc(sizeof(struct rt_sensor_data) * sensor->info.fifo_max); if (sensor->data_buf == RT_NULL) { res = -RT_ENOMEM; goto __exit; } } if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) { if (sensor->ops->control != RT_NULL) { /* If polling mode is supported, configure it to polling mode */ sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); } sensor->config.mode = RT_SENSOR_MODE_POLLING; } else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) { if (sensor->ops->control != RT_NULL) { /* If interrupt mode is supported, configure it to interrupt mode */ sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT); } /* Initialization sensor interrupt */ rt_sensor_irq_init(sensor); sensor->config.mode = RT_SENSOR_MODE_INT; } else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) { if (sensor->ops->control != RT_NULL) { /* If fifo mode is supported, configure it to fifo mode */ sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO); } /* Initialization sensor interrupt */ rt_sensor_irq_init(sensor); sensor->config.mode = RT_SENSOR_MODE_FIFO; } else { res = -RT_EINVAL; goto __exit; } /* Configure power mode to normal mode */ if (sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_NORMAL) == RT_EOK) { sensor->config.power = RT_SENSOR_POWER_NORMAL; } __exit: if (sensor->module) { /* release the module mutex */ rt_mutex_release(sensor->module->lock); } return res; }

 rt_sensor_read:


static rt_size_t rt_sensor_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) { rt_sensor_t sensor = (rt_sensor_t)dev; rt_size_t result = 0; RT_ASSERT(dev != RT_NULL); if (buf == NULL || len == 0) { return 0; } if (sensor->module) { rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); } /* The buffer is not empty. Read the data in the buffer first */ if (sensor->data_len > 0) { if (len > sensor->data_len / sizeof(struct rt_sensor_data)) { len = sensor->data_len / sizeof(struct rt_sensor_data); } rt_memcpy(buf, sensor->data_buf, len * sizeof(struct rt_sensor_data)); /* Clear the buffer */ sensor->data_len = 0; result = len; } else { /* If the buffer is empty read the data */ result = sensor->ops->fetch_data(sensor, buf, len); } if (sensor->module) { rt_mutex_release(sensor->module->lock); } return result; }

 上面的fetch_data函数指针也是在注册是赋值的,可以翻上去看标红部分。也就是这里 

技术图片

 

 

 

技术图片

 

顺便把fetch_data,也就是ds18b20传输温度数据的函数贴出来

 

 技术图片

 

 

 

 

 技术图片

 

 

 

 

 rt_sensor_control:

传过来的参数:dev是ds18b20,cmd = RT_SENSOR_CTRL_SET_ODR  args = 100 
static rt_err_t rt_sensor_control(rt_device_t dev, int cmd, void *args)
{
    rt_sensor_t sensor = (rt_sensor_t)dev;
    rt_err_t result = RT_EOK;
    RT_ASSERT(dev != RT_NULL);

    if (sensor->module)
    {
        rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER);
    }

    switch (cmd)
    {
    case RT_SENSOR_CTRL_GET_ID:
        if (args)
        {
            sensor->ops->control(sensor, RT_SENSOR_CTRL_GET_ID, args);
        }
        break;
    case RT_SENSOR_CTRL_GET_INFO:
        if (args)
        {
            rt_memcpy(args, &sensor->info, sizeof(struct rt_sensor_info));
        }
        break;
    case RT_SENSOR_CTRL_SET_RANGE:

        /* Configuration measurement range */
        result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_RANGE, args);
        if (result == RT_EOK)
        {
            sensor->config.range = (rt_int32_t)args;
            LOG_D("set range %d", sensor->config.range);
        }
        break;
    case RT_SENSOR_CTRL_SET_ODR:

        /* Configuration data output rate */
        result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_ODR, args);
        if (result == RT_EOK)
        {
            sensor->config.odr = (rt_uint32_t)args & 0xFFFF;
            LOG_D("set odr %d", sensor->config.odr);
        }
        break;
    case RT_SENSOR_CTRL_SET_POWER:

        /* Configuration sensor power mode */
        result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SET_POWER, args);
        if (result == RT_EOK)
        {
            sensor->config.power = (rt_uint32_t)args & 0xFF;
            LOG_D("set power mode code:", sensor->config.power);
        }
        break;
    case RT_SENSOR_CTRL_SELF_TEST:

        /* Device self-test */
        result = sensor->ops->control(sensor, RT_SENSOR_CTRL_SELF_TEST, args);
        break;
    default:
        return -RT_ERROR;
    }

    if (sensor->module)
    {
        rt_mutex_release(sensor->module->lock);
    }

    return result;
}

 

 

实验结果:

技术图片

 

 

以上是关于RT-Thread 添加 DS18B20 详解的主要内容,如果未能解决你的问题,请参考以下文章

Proteus51单片机+双DS18B20浮点数温度显示

温度传感器DS18B20

STM32 计算机课程设计技术点记录

MicroPython ESP32 读取DS18B20温度数据

Arduino DS18B20传感器温度读取

DS18B20温度传感器实现代码