回答

收藏

【瑞萨RRH62000-EVK套件】 基于野火启明6M5 编写RRH62000 的rtt驱动

瑞萨电子 瑞萨电子 1475 人阅读 | 0 人回复 | 2024-11-28

本帖最后由 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,如下图:

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

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



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


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



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


选择完毕后保存,并输入 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

bsp\renesas\libraries\HAL_Drivers\SConscript

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

配置完毕后保存,并输入 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支持的传感器类型全打通。

分享到:
回复

使用道具 举报

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

本版积分规则

嵌入式软件
1966 积分
3 主题
+ 关注
热门推荐
关闭

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