查看: 280|回复: 0

[评测分享] 【瑞萨RRH62000-EVK套件】 基于野火启明6M5 编写RRH62000 的rtt驱动

[复制链接]
  • TA的每日心情
    开心
    7 小时前
  • 签到天数: 46 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2024-11-28 23:55:11 | 显示全部楼层 |阅读模式
    分享到:
    本帖最后由 oxlm 于 2024-11-28 23:59 编辑

        RRH62000目前释放出来的资料不多,但是搜索github上发现,其实瑞萨的fsp5.6已经有上传RRH62000的代码了(具体可以在链接中搜索RRH62000Releases · renesas/fsp),也就是说,如果要适配RRH62000,如果使用瑞萨主控,基于目前rtthread上瑞萨的代码逻辑,我们需要把板卡fsp升级到5.6,之后开启rrh62000,再将rrh62000对接到rtthread的传感器框架中,便能够实现适配。
    但是呢,通过查阅传感器部分的代码,我决定暂时放弃这一操作,原因是我并不认为目前fsp上的外围器件框架逻辑符合产品设计的需求。因为目前fsp上的rrh62000框架,I2C是独占式的,而实际项目设计中,I2C很少独占一路,而是多种器件共用一路I2C
    硬件配置
    由于RRH62000独特的架构设计(供电需要5V,但通信却使用3.3V),我手头上能直接供5V并操作3.3V的板子并不多,只有野火的启明6M5,因此就用启明6M5来做RRH6200的适配。
    I2C通信接口
    启明6M5typec端口上的串口可以配置成I2C1,如下图:
    2.jpg

    在调试时,仅仅需要将J35的跳冒拿开,并将RRH62000I2C口接到此处即可。
    供电部分
    启明6M5J29座子上有引出VCC_5VGND,因此可以将供电引至该口。
    2.jpg

    软件设置
    选定了硬件接口,那剩下的就是FSP的设置了,由于之前我已经把启明6M5大部分功能配好并合并到github主线仓库了,因此这里的配置,仅仅是通过FSP配置对应的硬件接口即可。
    串口部分
    FSP修改
    rtt主线上目前配置的串口和I2C1所使用的接口冲突,因此我将此路串口切换至JTAG上的串口,以便调试。具体配置如下:
    删除stacks中的uart4配置后,依次进行以下配置:
    4.jpg

    3.jpg

    2.jpg

    这部分配置完毕后,点击Generate Project Content生成配置。
    menuconfig配置
    fsp已经把uart4关闭,并打开了UART2,但是目前rtt默认的配置还是在uart4上,此时只需要进入menuconfig中,打开uart2,关闭uart4,并将调试口更换至uart2即可。具体修改如下:
    emu中输入menuconfig并回车,进行以下配置:
    3.jpg

    2.jpg

      选择完毕后保存,并输入 scons --target=mdk5 生成新工程。
    此时编译运行,可发现finsh串口变成了uart2
    I2C1部分
    FSP修改
    I2C1部分和配置类似,具体配置方法如下:
    3.jpg

    4.jpg

    2.jpg

    之后点击Generate Project Content便可生成I2C1相关的配置。
    menuconfig配置
    同样的,虽然FSP已经启用了I2C1,但是rtt目前并由没启用I2C1,此时需要在menuconfig中启用I2C1,启用方法同uart,但操作位置有细微差异,具体差异如下:
    2.jpg

    3.jpg

    选择完毕后保存,并输入 scons --target=mdk5 生成新工程。
    至此,I2C1也被添加至工程中。
    传感器代码添加
    文件添加
    所有驱动文件都按惯例,全部添加至bsp\renesas\libraries\HAL_Drivers\中,因为瑞萨所有的驱动看起来都是加在此处。
    rrh62000.c
    1. #include "rrh62000.h"

    2. #define RRH62000_ADDR               0x69

    3. /* Definitions of Timeout */
    4. #define RM_RRH62000_TIMEOUT                       (100)

    5. /* Definitions of Wait Time */
    6. #define RM_RRH62000_WAIT_TIME_1000                (1000)

    7. /* Definitions of Retry max counts */
    8. #define RM_RRH62000_RETRY_MAX_COUNTS              (5)
    9. #define RM_RRH62000_RETRY_ZMOD_CLEANING_COUNTS    (60 + 10) // ZMOD cleaning time (60s) + buffer (10s)

    10. /* Definitions of Command */
    11. #define RM_RRH62000_COMMAND_READ                  (0x00)
    12. #define RM_RRH62000_COMMAND_DATA                  (0x40)
    13. #define RM_RRH62000_COMMAND_RESET                 (0x52)
    14. #define RM_RRH62000_COMMAND_MAVE                  (0x53)
    15. #define RM_RRH62000_COMMAND_SPEEDFAN              (0x63)
    16. #define RM_RRH62000_COMMAND_ARGVER                (0x73)
    17. #define RM_RRH62000_COMMAND_CSTATUS               (0x74)
    18. #define RM_RRH62000_COMMAND_FWVAR                 (0x75)

    19. /* Definitions of Reset */
    20. #define RM_RRH62000_RESET_VALUE                   (0x81)

    21. /* Definitions of Cleaning Status */
    22. #define RM_RRH62000_ZMOD_CLEAN_NOT_COMPLETE       (0x00)
    23. #define RM_RRH62000_ZMOD_CLEAN_COMPLETE           (0x01)

    24. /* Definitions of data size */
    25. #define RM_RRH62000_LEN_MEASUREMENT_DATA          (37)

    26. /* Definitions of Mask */
    27. #define RM_RRH62000_STATUS_MASK                   (0x01)
    28. #define RM_RRH62000_HIGH_CONCENTRATION_MASK       (0x01)
    29. #define RM_RRH62000_DUST_ACCUMULATION_MASK        (0x02)
    30. #define RM_RRH62000_FAN_SPEED_MASK                (0x04)
    31. #define RM_RRH62000_FAN_MASK                      (0x08)

    32. /* Definitions of Position */
    33. #define RM_RRH62000_POSITION_STATUS               (0)
    34. #define RM_RRH62000_POSITION_NC_0P3               (2)
    35. #define RM_RRH62000_POSITION_TEMPERATURE          (24)
    36. #define RM_RRH62000_POSITION_ECO2                 (30)
    37. #define RM_RRH62000_POSITION_IAQ                  (32)

    38. /* Definitions of Calculation */
    39. #define RM_RRH62000_CALC_CRC_INITIAL_VALUE        (0xFF)
    40. #define RM_RRH62000_CALC_CRC_DATA_LENGTH          (36)
    41. #define RM_RRH62000_CALC_DATA_STEP                (2)
    42. #define RM_RRH62000_CALC_CRC_8BITS_LENGTH         (8)
    43. #define RM_RRH62000_CACL_CRC_0X80                 (0x80)
    44. #define RM_RRH62000_CACL_CRC_MASK_MSB             (0x80)
    45. #define RM_RRH62000_CALC_CRC_POLYNOMIAL           (0x31)
    46. #define RM_RRH62000_CALC_CRC_FINAL_XOR            (0x00)
    47. #define RM_RRH62000_CALC_DECIMAL_VALUE_100        (100)
    48. #define RM_RRH62000_CALC_DECIMAL_VALUE_10         (10)

    49. /* Definitions of Shift */
    50. #define RM_RRH62000_SHIFT_24                      (24)
    51. #define RM_RRH62000_SHIFT_16                      (16)
    52. #define RM_RRH62000_SHIFT_8                       (8)


    53. static rt_err_t rrh62000_read(struct rt_i2c_bus_device *bus, uint8_t reg, uint8_t *data, uint16_t len)
    54. {
    55.     rt_uint8_t        tmp = reg;
    56.     struct rt_i2c_msg msgs[2];

    57.     msgs[0].addr  = RRH62000_ADDR;      /* Slave address */
    58.     msgs[0].flags = RT_I2C_WR; /* Write flag */
    59.     msgs[0].buf   = &tmp;      /* Slave register address */
    60.     msgs[0].len   = 1;         /* Number of bytes sent */

    61.     msgs[1].addr  = RRH62000_ADDR;      /* Slave address */
    62.     msgs[1].flags = RT_I2C_RD; /* Read flag */
    63.     msgs[1].buf   = data;      /* Read data pointer */
    64.     msgs[1].len   = len;       /* Number of bytes read */

    65.     if (rt_i2c_transfer(bus, msgs, 2) != 2)
    66.     {
    67.         return -RT_ERROR;
    68.     }

    69.     return RT_EOK;
    70. }

    71. static rt_err_t rrh62000_write(struct rt_i2c_bus_device *bus, uint8_t reg, uint8_t *data, uint16_t len)
    72. {
    73.     struct rt_i2c_msg msgs[2];
    74.     uint8_t           data1[5];
    75.     uint16_t          i;

    76.     data1[0] = reg;
    77.     for (i = 0; i < len; i++)
    78.     {
    79.         data1[i + 1] = data[i];
    80.     }

    81.     msgs[0].addr  = RRH62000_ADDR;      /* Slave address */
    82.     msgs[0].flags = RT_I2C_WR; /* Write flag */
    83.     msgs[0].buf   = data1;     /* Slave register address */
    84.     msgs[0].len   = len + 1;   /* Number of bytes sent */

    85.     if (rt_i2c_transfer(bus, msgs, 1) != 1)
    86.     {
    87.         return -RT_ERROR;
    88.     }

    89.     return RT_EOK;
    90. }

    91. static rt_err_t rm_rrh62000_crc_execute (const uint8_t * const p_raw_data)
    92. {
    93.     uint8_t         crc;
    94.     const uint8_t * p_input_data;
    95.     uint8_t         i;
    96.     uint8_t         j;

    97.     /* Set pointer to input data */
    98.     p_input_data = &p_raw_data[0];

    99.     /* Set initial value */
    100.     crc = RM_RRH62000_CALC_CRC_INITIAL_VALUE;

    101.     /* Execute CRC */
    102.     for (i = 0; i < RM_RRH62000_CALC_CRC_DATA_LENGTH; i++)
    103.     {
    104.         /* Calculate XOR with input value */
    105.         crc ^= *p_input_data;

    106.         for (j = 0; j < RM_RRH62000_CALC_CRC_8BITS_LENGTH; j++)
    107.         {
    108.             if (RM_RRH62000_CACL_CRC_0X80 == (crc & RM_RRH62000_CACL_CRC_MASK_MSB))
    109.             {
    110.                 /* If MSB is 1, calculate XOR with the polynomial. */
    111.                 crc = (uint8_t) (crc << 1) ^ RM_RRH62000_CALC_CRC_POLYNOMIAL;
    112.             }
    113.             else
    114.             {
    115.                 crc <<= 1;
    116.             }
    117.         }

    118.         p_input_data++;
    119.     }

    120.     /* Final XOR */
    121.     crc ^= RM_RRH62000_CALC_CRC_FINAL_XOR;
    122.     if(p_raw_data[RM_RRH62000_CALC_CRC_DATA_LENGTH] == crc)
    123.     {
    124.         return RT_EOK;   
    125.     }
    126.     else
    127.     {
    128.         return -RT_ERROR;   
    129.     }
    130. }

    131. static rt_err_t RM_RRH62000_DataCalculate (uint8_t * p_raw_data, struct rrh62000_data *p_rrh62000_data)
    132. {
    133.     rt_err_t err = RT_EOK;
    134.     rt_uint32_t tmp_u32;
    135.     rm_air_sensor_single_data_t * p_sensor_data;
    136.     rt_uint32_t position;

    137.     /* Execute CRC */
    138.     err = rm_rrh62000_crc_execute(p_raw_data);
    139.     if(err != RT_EOK)
    140.     {
    141.         return err;   
    142.     }

    143.     /* Set status data */
    144.     p_rrh62000_data->status =
    145.         (uint32_t) (((uint32_t) p_raw_data[1] << RM_RRH62000_SHIFT_8) | (uint32_t) p_raw_data[0]);

    146.     /* Set measurement results */
    147.     p_sensor_data = &p_rrh62000_data->nc_0p3;
    148.     for (position = RM_RRH62000_POSITION_NC_0P3;
    149.          position < RM_RRH62000_LEN_MEASUREMENT_DATA;
    150.          position += RM_RRH62000_CALC_DATA_STEP)
    151.     {
    152.         /* Calculate sensor data from measurement results (big-endian). */
    153.         tmp_u32 = (uint32_t) (((uint32_t) p_raw_data[position] << RM_RRH62000_SHIFT_8) |
    154.                               (uint32_t) p_raw_data[position + 1]);
    155.         if (RM_RRH62000_POSITION_TEMPERATURE > position)
    156.         {
    157.             /* NC_x and PMx_x data. One decimal place. */
    158.             p_sensor_data->integer_part = tmp_u32 / RM_RRH62000_CALC_DECIMAL_VALUE_10;
    159.             p_sensor_data->decimal_part = tmp_u32 % RM_RRH62000_CALC_DECIMAL_VALUE_10;
    160.         }
    161.         else if ((RM_RRH62000_POSITION_ECO2 > position) || (RM_RRH62000_POSITION_IAQ == position))
    162.         {
    163.             /* Temperature, humidity, TVOC and IAQ data. Two decimal places. */
    164.             p_sensor_data->integer_part = tmp_u32 / RM_RRH62000_CALC_DECIMAL_VALUE_100;
    165.             p_sensor_data->decimal_part = tmp_u32 % RM_RRH62000_CALC_DECIMAL_VALUE_100;
    166.         }
    167.         else
    168.         {
    169.             /* eCO2 and Relative IAQ data. These data does not have a decimal part. */
    170.             p_sensor_data->integer_part = tmp_u32;
    171.             p_sensor_data->decimal_part = 0;
    172.         }

    173.         p_sensor_data++;
    174.     }

    175.     return RT_EOK;
    176. }

    177. rt_err_t rrh62000_read_measured_value(struct rt_i2c_bus_device *bus, struct rrh62000_data *data)
    178. {
    179.     rt_uint8_t buf[37];
    180.     rt_uint32_t len = 37;

    181.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_READ, buf, len) != RT_EOK) {
    182.         return -RT_ERROR;
    183.     }

    184.     return RM_RRH62000_DataCalculate(buf, data);
    185. }

    186. rt_err_t rrh62000_read_data_status(struct rt_i2c_bus_device *bus, rt_bool_t *isDataReady)
    187. {
    188.     rt_uint8_t buf[1];
    189.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_DATA, buf, 1) != RT_EOK) {
    190.         return -RT_ERROR;
    191.     }

    192.     *isDataReady = buf[0];

    193.     return RT_EOK;
    194. }

    195. rt_err_t rrh62000_sleep_set(struct rt_i2c_bus_device *bus, rt_bool_t isSleep)
    196. {
    197.     rt_uint8_t buf[1];

    198.     if(isSleep)
    199.     {
    200.         buf[0] = 0x00;
    201.     }
    202.     else
    203.     {
    204.         buf[0] = 0x80;
    205.     }

    206.     if(rrh62000_write(bus, 0x50, buf, 1) != RT_EOK) {
    207.         return -RT_ERROR;
    208.     }

    209.     return RT_EOK;
    210. }

    211. rt_err_t rrh62000_sleep_get(struct rt_i2c_bus_device *bus, rt_bool_t *isSleep)
    212. {
    213.     rt_uint8_t buf[1];

    214.     if(rrh62000_read(bus, 0x50, buf, 1) != RT_EOK) {
    215.         return -RT_ERROR;
    216.     }

    217.     if(buf[0])
    218.     {
    219.         *isSleep = 0;
    220.     }
    221.     else
    222.     {
    223.         *isSleep = 1;
    224.     }

    225.     return RT_EOK;
    226. }

    227. rt_err_t rrh62000_start_dust_cleaning(struct rt_i2c_bus_device *bus)
    228. {
    229.     rt_uint8_t buf[1] = {0x01};
    230.     if(rrh62000_write(bus, 0x51, buf, 1) != RT_EOK) {
    231.         return -RT_ERROR;
    232.     }

    233.     return RT_EOK;
    234. }

    235. rt_err_t rrh62000_reset(struct rt_i2c_bus_device *bus)
    236. {
    237.     rt_uint8_t buf[1] = {0x81};
    238.     if(rrh62000_write(bus, RM_RRH62000_COMMAND_RESET, buf, 1) != RT_EOK) {
    239.         return -RT_ERROR;
    240.     }

    241.     return RT_EOK;
    242. }

    243. rt_err_t rrh62000_moving_average_set(struct rt_i2c_bus_device *bus, uint8_t time)
    244. {
    245.     rt_uint8_t buf[1];

    246.     if(time > 60)
    247.     {
    248.         time = 60;
    249.     }
    250.     else if(time < 1)
    251.     {
    252.         time = 1;
    253.     }
    254.     buf[0] = time;

    255.     if(rrh62000_write(bus, RM_RRH62000_COMMAND_MAVE, buf, 1) != RT_EOK) {
    256.         return -RT_ERROR;
    257.     }

    258.     return RT_EOK;
    259. }

    260. rt_err_t rrh62000_moving_average_get(struct rt_i2c_bus_device *bus, uint8_t *time)
    261. {
    262.     rt_uint8_t buf[1];

    263.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_MAVE, buf, 1) != RT_EOK) {
    264.         return -RT_ERROR;
    265.     }

    266.     *time = buf[0];

    267.     return RT_EOK;
    268. }

    269. rt_err_t rrh62000_clean_interval_time_set(struct rt_i2c_bus_device *bus, uint16_t time)
    270. {
    271.     rt_uint8_t buf[1];

    272.     if(time > 60480)
    273.     {
    274.         time = 60480;
    275.     }
    276.     buf[0] = (time >> 8);
    277.     if(rrh62000_write(bus, 0x5A, buf, 1) != RT_EOK) {
    278.         return -RT_ERROR;
    279.     }

    280.     buf[0] = (time & 0x00FF);
    281.     if(rrh62000_write(bus, 0x5B, buf, 1) != RT_EOK) {
    282.         return -RT_ERROR;
    283.     }
    284.     return RT_EOK;
    285. }

    286. rt_err_t rrh62000_clean_interval_time_get(struct rt_i2c_bus_device *bus, uint16_t *time)
    287. {
    288.     rt_uint8_t buf[2];

    289.     if(rrh62000_read(bus, 0x5A, buf, 1) != RT_EOK) {
    290.         return -RT_ERROR;
    291.     }

    292.     if(rrh62000_read(bus, 0x5B, buf + 1, 1) != RT_EOK) {
    293.         return -RT_ERROR;
    294.     }

    295.     *time = ((uint16_t)buf[0] << 8) + buf[1];

    296.     return RT_EOK;
    297. }

    298. rt_err_t rrh62000_auto_clean_time_set(struct rt_i2c_bus_device *bus, uint8_t time)
    299. {
    300.     rt_uint8_t buf[1];

    301.     if(time > 60)
    302.     {
    303.         time = 60;
    304.     }
    305.     buf[0] = time;

    306.     if(rrh62000_write(bus, 0x5C, buf, 1) != RT_EOK) {
    307.         return -RT_ERROR;
    308.     }

    309.     return RT_EOK;
    310. }

    311. rt_err_t rrh62000_auto_clean_time_get(struct rt_i2c_bus_device *bus, uint8_t *time)
    312. {
    313.     rt_uint8_t buf[1];

    314.     if(rrh62000_read(bus, 0x5C, buf, 1) != RT_EOK) {
    315.         return -RT_ERROR;
    316.     }

    317.     *time = buf[0];

    318.     return RT_EOK;
    319. }

    320. rt_err_t rrh62000_fan_speed_set(struct rt_i2c_bus_device *bus, uint8_t speed)
    321. {
    322.     rt_uint8_t buf[1];

    323.     if(speed > 100)
    324.     {
    325.         speed = 100;
    326.     }
    327.     else if(speed < 60)
    328.     {
    329.         speed = 60;
    330.     }
    331.     buf[0] = speed;

    332.     if(rrh62000_write(bus, RM_RRH62000_COMMAND_SPEEDFAN, buf, 1) != RT_EOK) {
    333.         return -RT_ERROR;
    334.     }

    335.     return RT_EOK;
    336. }

    337. rt_err_t rrh62000_fan_speed_get(struct rt_i2c_bus_device *bus, uint8_t *speed)
    338. {
    339.     rt_uint8_t buf[1];

    340.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_SPEEDFAN, buf, 1) != RT_EOK) {
    341.         return -RT_ERROR;
    342.     }

    343.     *speed = buf[0];

    344.     return RT_EOK;
    345. }

    346. rt_err_t rrh62000_read_mox_resistance(struct rt_i2c_bus_device *bus, uint32_t *data)
    347. {
    348.     rt_uint8_t buf[4];
    349.     if(rrh62000_read(bus, 0x71, buf, 4) != RT_EOK) {
    350.         return -RT_ERROR;
    351.     }

    352.     *data  = (uint32_t)buf[0] << 24;
    353.     *data += (uint32_t)buf[1] << 16;
    354.     *data += (uint32_t)buf[2] << 8;
    355.     *data += (uint32_t)buf[3] << 0;

    356.     return RT_EOK;
    357. }

    358. rt_err_t rrh62000_read_uid(struct rt_i2c_bus_device *bus, struct rrh62000_uid *data)
    359. {
    360.     rt_uint8_t buf[6];
    361.     if(rrh62000_read(bus, 0x72, buf, 6) != RT_EOK) {
    362.         return -RT_ERROR;
    363.     }

    364.     rt_memcpy(&data->uid, buf, 6);

    365.     return RT_EOK;
    366. }

    367. rt_err_t rrh62000_read_algoritm_verison(struct rt_i2c_bus_device *bus, struct rrh62000_algoversion *data)
    368. {
    369.     rt_uint8_t buf[3];
    370.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_ARGVER, buf, 3) != RT_EOK) {
    371.         return -RT_ERROR;
    372.     }

    373.     data->major = buf[0];
    374.     data->minor = buf[1];
    375.     data->patch = buf[2];

    376.     return RT_EOK;
    377. }

    378. rt_err_t rrh62000_read_TVOC_sensor_clean_status(struct rt_i2c_bus_device *bus, rt_bool_t *isComplete)
    379. {
    380.     rt_uint8_t buf[1];
    381.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_CSTATUS, buf, 1) != RT_EOK) {
    382.         return -RT_ERROR;
    383.     }

    384.     *isComplete = buf[0];

    385.     return RT_EOK;
    386. }

    387. rt_err_t rrh62000_read_firmware_verison(struct rt_i2c_bus_device *bus, struct rrh62000_firmwareversion *data)
    388. {
    389.     rt_uint8_t buf[2];
    390.     if(rrh62000_read(bus, RM_RRH62000_COMMAND_FWVAR, buf, 2) != RT_EOK) {
    391.         return -RT_ERROR;
    392.     }

    393.     data->major = buf[0];
    394.     data->minor = buf[1];

    395.     return RT_EOK;
    396. }
    复制代码

    rrh_62000.h
    1. #include <rtdevice.h>
    2. #include <rtthread.h>

    3. typedef struct st_rm_air_sensor_single_data
    4. {
    5.     uint32_t integer_part;             ///< Integer part of sensor data.
    6.     uint32_t decimal_part;             ///< Decimal part of sensor data.
    7. } rm_air_sensor_single_data_t;

    8. /** AIR SENSOR data block */
    9. struct rrh62000_data
    10. {
    11.     uint32_t status;
    12.     rm_air_sensor_single_data_t nc_0p3;      ///< Number concentration of particle size 0.3 um - 10 um [1/cm3]
    13.     rm_air_sensor_single_data_t nc_0p5;      ///< Number concentration of particle size 0.5 um - 10 um [1/cm3]
    14.     rm_air_sensor_single_data_t nc_1;        ///< Number concentration of particle size 1 um - 10 um [1/cm3]
    15.     rm_air_sensor_single_data_t nc_2p5;      ///< Number concentration of particle size 2.5 um - 10 um [1/cm3]
    16.     rm_air_sensor_single_data_t nc_4;        ///< Number concentration of particle size 4 um - 10 um [1/cm3]
    17.     rm_air_sensor_single_data_t pm1_1;       ///< Mass concentration of particle size 0.3 um - 1 um with reference to KCl particle [um/cm3]
    18.     rm_air_sensor_single_data_t pm2p5_1;     ///< Mass concentration of particle size 0.3 um - 2.5 um with reference to KCl particle [um/cm3]
    19.     rm_air_sensor_single_data_t pm10_1;      ///< Mass concentration of particle size 0.3 um - 10 um with reference to KCl particle [um/cm3]
    20.     rm_air_sensor_single_data_t pm1_2;       ///< Mass concentration of particle size 0.3 um - 1 um with reference to cigarette smoke [um/cm3]
    21.     rm_air_sensor_single_data_t pm2p5_2;     ///< Mass concentration of particle size 0.3 um - 2.5 um with reference to cigarette smoke [um/cm3]
    22.     rm_air_sensor_single_data_t pm10_2;      ///< Mass concentration of particle size 0.3 um - 10 um with reference to cigarette smoke [um/cm3]
    23.     rm_air_sensor_single_data_t temperature; ///< Temperature [Celsius]
    24.     rm_air_sensor_single_data_t humidity;    ///< Humidity [%RH]
    25.     rm_air_sensor_single_data_t tvoc;        ///< Total volatile organic compounds (TVOC) concentrations [mg/m3]
    26.     rm_air_sensor_single_data_t eco2;        ///< Estimated carbon dioxide (eCO2) level [ppm]
    27.     rm_air_sensor_single_data_t iaq;         ///< Indoor Air Quality level according to UBA
    28.     rm_air_sensor_single_data_t rel_iaq;     ///< Relative IAQ
    29. };

    30. rt_err_t rrh62000_read_measured_value(struct rt_i2c_bus_device *bus, struct rrh62000_data *data);
    31. rt_err_t rrh62000_read_data_status(struct rt_i2c_bus_device *bus, rt_bool_t *isDataReady);
    32. rt_err_t rrh62000_sleep_set(struct rt_i2c_bus_device *bus, rt_bool_t isSleep);
    33. rt_err_t rrh62000_sleep_get(struct rt_i2c_bus_device *bus, rt_bool_t *isSleep);
    34. rt_err_t rrh62000_start_dust_cleaning(struct rt_i2c_bus_device *bus);
    35. rt_err_t rrh62000_reset(struct rt_i2c_bus_device *bus);
    36. rt_err_t rrh62000_moving_average_set(struct rt_i2c_bus_device *bus, uint8_t time);
    37. rt_err_t rrh62000_moving_average_get(struct rt_i2c_bus_device *bus, uint8_t *time);
    38. rt_err_t rrh62000_clean_interval_time_set(struct rt_i2c_bus_device *bus, uint16_t time);
    39. rt_err_t rrh62000_clean_interval_time_get(struct rt_i2c_bus_device *bus, uint16_t *time);
    40. rt_err_t rrh62000_auto_clean_time_set(struct rt_i2c_bus_device *bus, uint8_t time);
    41. rt_err_t rrh62000_auto_clean_time_get(struct rt_i2c_bus_device *bus, uint8_t *time);
    42. rt_err_t rrh62000_fan_speed_set(struct rt_i2c_bus_device *bus, uint8_t speed);
    43. rt_err_t rrh62000_fan_speed_get(struct rt_i2c_bus_device *bus, uint8_t *speed);
    44. rt_err_t rrh62000_read_mox_resistance(struct rt_i2c_bus_device *bus, uint32_t *data);

    45. struct rrh62000_uid{
    46.     char uid[6];
    47. };

    48. rt_err_t rrh62000_read_uid(struct rt_i2c_bus_device *bus, struct rrh62000_uid *data);

    49. struct rrh62000_algoversion{
    50.     char major;
    51.     char minor;
    52.     char patch;
    53. };

    54. rt_err_t rrh62000_read_algoritm_verison(struct rt_i2c_bus_device *bus, struct rrh62000_algoversion *data);
    55. rt_err_t rrh62000_read_TVOC_sensor_clean_status(struct rt_i2c_bus_device *bus, rt_bool_t *isComplete);

    56. struct rrh62000_firmwareversion{
    57.     char major;
    58.     char minor;
    59. };

    60. rt_err_t rrh62000_read_firmware_verison(struct rt_i2c_bus_device *bus, struct rrh62000_firmwareversion *data);
    复制代码

    drv_rrh62000.c
    1. #include <drivers/sensor.h>
    2. #include "hal_data.h"
    3. #include "rrh62000.h"

    4. struct sensor_device {
    5.     rt_bool_t openCount;
    6.     struct rt_i2c_bus_device * dev;
    7.     struct rrh62000_data data;
    8. };

    9. static rt_ssize_t _get_data(rt_sensor_t sensor, struct rt_sensor_data *data)
    10. {
    11.     struct sensor_device *dev = sensor->parent.user_data;
    12.     rt_bool_t isDataReady = RT_FALSE;

    13.     if (sensor->info.type == RT_SENSOR_CLASS_TEMP)
    14.     {
    15.         if((rrh62000_read_data_status(dev->dev, &isDataReady) == RT_EOK) && (isDataReady))
    16.         {
    17.             rrh62000_read_measured_value(dev->dev, &dev->data);
    18.         }

    19.     }

    20.     if (sensor->info.type == RT_SENSOR_CLASS_TEMP)
    21.     {
    22.         data->data.temp = (dev->data.temperature.integer_part << 16) + dev->data.temperature.decimal_part;
    23.         data->timestamp = rt_sensor_get_ts();
    24.         return 1;
    25.     }
    26.    
    27.     return 0;
    28. }

    29. static rt_ssize_t fetch_data(struct rt_sensor_device *sensor, void *buf, rt_size_t len)
    30. {
    31.     RT_ASSERT(buf);

    32.     if (sensor->config.mode == RT_SENSOR_MODE_POLLING)
    33.         return _get_data(sensor, buf);
    34.     else
    35.         return 0;
    36. }

    37. static rt_err_t _set_power(struct rt_sensor_device *sensor, void *args)
    38. {
    39.     struct sensor_device *dev = sensor->parent.user_data;
    40.     rt_uint8_t power = *(uint8_t *)args;
    41.     //fsp_err_t ret;
    42.     rt_err_t ret;
    43.     rt_bool_t isTVOCCLean = RT_FALSE;
    44.     int count = 70; // 70s

    45.     if(power == RT_SENSOR_POWER_DOWN)
    46.     {
    47.         if(dev->openCount != 0)
    48.         {
    49.             dev->openCount--;
    50.         }
    51.     }
    52.     else
    53.     {
    54.         if(dev->openCount == 0)
    55.         {
    56.             do
    57.             {
    58.                 if(rrh62000_read_TVOC_sensor_clean_status(dev->dev, &isTVOCCLean) == RT_EOK)
    59.                 {
    60.                     if(isTVOCCLean == RT_FALSE)
    61.                     {
    62.                         rt_thread_mdelay(1000);
    63.                         count--;
    64.                     }
    65.                 }
    66.             }while((isTVOCCLean == RT_FALSE) && (count--));

    67.             if(count == 0)
    68.             {
    69.                 goto RET;
    70.             }

    71.             ret = rrh62000_reset(dev->dev);
    72.             if(ret != RT_EOK)
    73.             {
    74.                 rt_kprintf("open failed %d\n\r",ret);
    75.                 goto RET;
    76.             }
    77.             

    78.             rt_thread_mdelay(1000);

    79.             ret = rrh62000_moving_average_set(dev->dev, 1);
    80.             ret = rrh62000_fan_speed_set(dev->dev, 60);
    81.         }
    82.         dev->openCount++;
    83.     }

    84.     return RT_EOK;

    85. RET:
    86.     return -RT_ERROR;
    87. }

    88. static rt_err_t control(struct rt_sensor_device *sensor, int cmd, void *args)
    89. {
    90.     rt_err_t result = RT_EOK;
    91.    
    92.     switch (cmd)
    93.     {
    94.         case RT_SENSOR_CTRL_GET_ID:
    95.             // TODO:  get device id
    96.             // result = xxxx(sensor, args);
    97.             break;
    98.         case RT_SENSOR_CTRL_GET_INFO:
    99.             // TODO:  get info
    100.             // result = xxxx(sensor, args);
    101.             break;
    102.         case RT_SENSOR_CTRL_SET_RANGE:
    103.             // TODO: set test range
    104.             // result = xxxx(sensor, args);
    105.             break;
    106.         case RT_SENSOR_CTRL_SET_ODR:
    107.             // TODO: set frequency
    108.             // result = xxxx(sensor, args);
    109.             break;
    110.         case RT_SENSOR_CTRL_SET_MODE:
    111.             // TODO: set work mode
    112.             // result = xxxx(sensor, args);
    113.             break;
    114.         case RT_SENSOR_CTRL_SET_POWER:
    115.             // TODO: set power mode
    116.             result = _set_power(sensor, args);
    117.             break;

    118.         case RT_SENSOR_CTRL_SELF_TEST:
    119.             // TODO: process self test
    120.             // result = xxxx(sensor);
    121.             break;
    122.         default:
    123.             return -RT_ERROR;
    124.     }
    125.    
    126.     return result;
    127. }

    128. static struct rt_sensor_ops sensor_ops =
    129. {
    130.     fetch_data,
    131.     control
    132. };

    133. struct sensor_device * rrh62000_param_init(void)
    134. {
    135.     struct sensor_device *dev;
    136.     struct rrh62000_firmwareversion fwVersion;
    137.     struct rrh62000_algoversion algoVersion;

    138.     dev = rt_calloc(1, sizeof(struct sensor_device));
    139.     if(!dev)
    140.     {
    141.         goto exit;
    142.     }
    143.     rt_memset(dev, 0x00, sizeof(struct sensor_device));
    144.     dev->dev = (struct rt_i2c_bus_device *)rt_device_find("i2c1");
    145.     if(dev->dev == RT_NULL)
    146.     {
    147.         goto exit;
    148.     }


    149.     if(rrh62000_read_firmware_verison(dev->dev, &fwVersion) != RT_EOK)
    150.     {
    151.         goto exit;
    152.     }

    153.     if(rrh62000_read_algoritm_verison(dev->dev, &algoVersion) != RT_EOK)
    154.     {
    155.         goto exit;
    156.     }

    157.     rt_kprintf("rrh62000 firmware version %d.%d\n\r", fwVersion.major, fwVersion.minor);
    158.     rt_kprintf("rrh62000 algoritm version %d.%d.%d\n\r", algoVersion.major, algoVersion.minor, algoVersion.patch);

    159.     return dev;

    160. exit:
    161.     if(dev)
    162.         rt_free(dev);
    163.     return RT_NULL;
    164. }

    165. int rt_hw_init(const char *name, struct rt_sensor_config *cfg)
    166. {
    167.     rt_int8_t result;
    168.     rt_sensor_t sensor = RT_NULL;
    169.     struct sensor_device *dev;

    170.     dev = rrh62000_param_init();
    171.     if(dev == RT_NULL)
    172.     {
    173.         goto __exit;
    174.     }
    175.    
    176.     /* sensor register */
    177.     sensor = rt_calloc(1, sizeof(struct rt_sensor_device));
    178.     if (sensor == RT_NULL)
    179.         goto __exit;
    180.    
    181.     sensor->info.type       = RT_SENSOR_CLASS_TEMP; // Set real type
    182.     sensor->info.vendor     = RT_SENSOR_VENDOR_UNKNOWN; // Set real vendor
    183.     sensor->info.model      = name;  // set real model name
    184.     sensor->info.unit       = RT_SENSOR_UNIT_DCELSIUS; // set to real unit flag
    185.     sensor->info.intf_type  = RT_SENSOR_INTF_I2C; // Set interface type
    186.     sensor->info.range_max  = 0xFFFF; // Set to range max
    187.     sensor->info.range_min  = 0x0000; // Set to range min
    188.     sensor->info.period_min = 50; // Set frequency

    189.     rt_memcpy(&sensor->config, cfg, sizeof(struct rt_sensor_config));
    190.     sensor->ops = &sensor_ops;

    191.     result = rt_hw_sensor_register(sensor, name, RT_DEVICE_FLAG_RDONLY, dev);
    192.     if (result != RT_EOK)
    193.     {
    194.         goto __exit;
    195.     }

    196.     return RT_EOK;

    197. __exit:
    198.     if (sensor)
    199.         rt_free(sensor);
    200.     if(dev)
    201.         rt_free(dev);
    202.     return -RT_ERROR;
    203. }

    204. static int rrh62000_device_register(void)
    205. {
    206.     struct rt_sensor_config      cfg = {
    207.         .mode = RT_SENSOR_MODE_POLLING,
    208.         .power = RT_SENSOR_POWER_DOWN,
    209.     };

    210.     rt_hw_init("rrh62000", &cfg);

    211.     return RT_EOK;

    212. }
    213. INIT_DEVICE_EXPORT(rrh62000_device_register);

    214. #if 1
    215. #define RRH_TEMP_DEVICE_NAME "temp_rrh"
    216. void rrh6200_temp_read(void)
    217. {
    218.     rt_device_t dev = rt_device_find(RRH_TEMP_DEVICE_NAME);
    219.     rt_err_t result;
    220.     rt_uint32_t len;
    221.     struct rt_sensor_data data;

    222.     if(!dev)
    223.     {
    224.         rt_kprintf("No device name %s\n\r", RRH_TEMP_DEVICE_NAME);
    225.         return;
    226.     }
    227.     result = rt_device_open(dev,RT_DEVICE_FLAG_RDONLY);
    228.     if(result != RT_EOK)
    229.     {
    230.         rt_kprintf("Open %s Fail\n\r", RRH_TEMP_DEVICE_NAME);
    231.         return;

    232.     }
    233.    
    234.     len = rt_device_read(dev, 0 ,&data,1);
    235.     if(len)
    236.     {
    237.         rt_kprintf("Temp %d.%d \n\r", data.data.temp >> 16, data.data.temp & 0x0000FFFF);
    238.     }

    239.     result = rt_device_close(dev);
    240.     if(result != RT_EOK)
    241.     {
    242.         rt_kprintf("Close %s Fail\n\r", RRH_TEMP_DEVICE_NAME);
    243.         return;

    244.     }

    245. }
    246. MSH_CMD_EXPORT(rrh6200_temp_read, rrh62000 temprate sample);
    247. #endif
    复制代码


    编译选项修改
    虽然代码已经添加到目录里了,但是工程并不会编译,此时需要我们手动修改脚本,让工程自动将这些文件导入工程,具体修改如下:
    bsp\renesas\ebf_qi_min_6m5\board\Kconfig
    2.jpg

    bsp\renesas\libraries\HAL_Drivers\SConscript
    2.jpg

    menuconfig配置
    上面添加完毕后,我们还需要去menuconfig中将此传感器启用,具体修改方法如下:
    2.jpg

    配置完毕后保存,并输入 scons --target=mdk5生成新工程并编译
    运行结果
    1. \ | /
    2. - RT -     Thread Operating System
    3. / | \     5.2.0 build Nov 28 2024 22:19:37
    4. 2006 - 2024 Copyright by RT-Thread team
    5. [I/I2C] I2C bus [i2c1] registered
    6. rrh62000 firmware version 1.0
    7. rrh62000 algoritm version 3.2.0
    8. [I/sensor] rt_sensor[temp_rrh62000] init success

    9. Hello RT-Thread!
    10. msh >r
    11. reboot
    12. rrh6200_temp_read
    13. msh >rr
    14. rrh6200_temp_read
    15. msh >rrh6200_temp_read
    16. Temp 0.0
    17. msh >rrh6200_temp_read
    18. Temp 0.0
    19. msh >rrh6200_temp_read
    20. Temp 0.0
    21. msh >rrh6200_temp_read
    22. Temp 22.17
    23. msh >rrh6200_temp_read
    24. Temp 22.17
    25. msh >rrh6200_temp_read
    26. Temp 22.17
    27. msh >rrh6200_temp_read
    28. Temp 22.12
    29. msh >rrh6200_temp_read
    30. Temp 22.12
    31. msh >rrh6200_temp_read
    32. Temp 22.12
    33. msh >rrh6200_temp_read
    34. Temp 22.12
    35. msh >rrh6200_temp_read
    36. Temp 22.7
    37. msh >rrh6200_temp_read
    38. Temp 22.7
    39. msh >rrh6200_temp_read
    40. Temp 22.7
    41. msh >rrh6200_temp_read
    42. Temp 22.7
    43. msh >rrh6200_temp_read
    44. Temp 22.3
    45. msh >rrh6200_temp_read
    46. Temp 22.3
    复制代码


    **计划
    目前仅仅是初步把温度传感器部分打通了,**将陆续把剩余的RTT支持的传感器类型全打通。

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

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

    手机版|小黑屋|与非网

    GMT+8, 2025-1-11 17:29 , Processed in 0.116421 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.