【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;
}

 

 

實驗結果:

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM