找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3380|回复: 8
收起左侧

全网首发SCD40二氧化碳传感器源程序

  [复制链接]
ID:397211 发表于 2022-1-11 16:56 | 显示全部楼层 |阅读模式
本程序芯片为STM32F103C8T6,使用HAL库,通过官方的库GITHUP移植而来,源代码可以到GITHUP中搜索SCD40。
此模块因为有速度要求,每5秒刷新一次数据,所以都懂的。
0.png

单片机源程序如下:
  1. #include "scd4x_i2c.h"
  2. #include "sensirion_common.h"
  3. #include "sensirion_i2c.h"
  4. #include "sensirion_i2c_hal.h"

  5. #define SCD4X_I2C_ADDRESS 98

  6. int16_t scd4x_start_periodic_measurement() {
  7.     int16_t error;
  8.     uint8_t buffer[2];
  9.     uint16_t offset = 0;
  10.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x21B1);

  11.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  12.     if (error) {
  13.         return error;
  14.     }
  15.     sensirion_i2c_hal_sleep_usec(1000);
  16.     return NO_ERROR;
  17. }

  18. int16_t scd4x_read_measurement_ticks(uint16_t* co2, uint16_t* temperature,
  19.                                      uint16_t* humidity) {
  20.     int16_t error;
  21.     uint8_t buffer[9];
  22.     uint16_t offset = 0;
  23.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xEC05);

  24.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  25.     if (error) {
  26.         return error;
  27.     }

  28. //    sensirion_i2c_hal_sleep_usec(1000);

  29.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 6);
  30.     if (error) {
  31.         return error;
  32.     }
  33.     *co2 = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  34.     *temperature = sensirion_common_bytes_to_uint16_t(&buffer[2]);
  35.     *humidity = sensirion_common_bytes_to_uint16_t(&buffer[4]);
  36.     return NO_ERROR;
  37. }
  38. //需要5秒才能再次调用,传感器的响应时间为5秒
  39. int16_t scd4x_read_measurement(uint16_t* co2, int32_t* temperature_m_deg_c,
  40.                                int32_t* humidity_m_percent_rh) {
  41.     int16_t error;
  42.     uint16_t temperature;
  43.     uint16_t humidity;
  44.     error = scd4x_read_measurement_ticks(co2, &temperature, &humidity);
  45.     if (error) {
  46.         return error;
  47.     }
  48. #if 1
  49.     *temperature_m_deg_c = ((21875 * (int32_t)temperature) >> 13) - 45000;
  50.     *humidity_m_percent_rh = ((12500 * (int32_t)humidity) >> 13);
  51. #else
  52.     *temperature_m_deg_c = ((175000 * (int32_t)temperature) >> 15) - 45000;
  53.     *humidity_m_percent_rh = ((100000 * (int32_t)humidity) >> 15);
  54. #endif
  55.     return NO_ERROR;
  56. }

  57. //int16_t scd4x_stop_periodic_measurement() {
  58. //    int16_t error;
  59. //    uint8_t buffer[2];
  60. //    uint16_t offset = 0;
  61. //    offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3F86);

  62. //    error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  63. //    if (error) {
  64. //        return error;
  65. //    }
  66. //    sensirion_i2c_hal_sleep_usec(500000);
  67. //    return NO_ERROR;
  68. //}

  69. int16_t scd4x_get_temperature_offset_ticks(uint16_t* t_offset) {
  70.     int16_t error;
  71.     uint8_t buffer[3];
  72.     uint16_t offset = 0;
  73.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2318);

  74.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  75.     if (error) {
  76.         return error;
  77.     }

  78.     sensirion_i2c_hal_sleep_usec(1000);

  79.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  80.     if (error) {
  81.         return error;
  82.     }
  83.     *t_offset = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  84.     return NO_ERROR;
  85. }

  86. int16_t scd4x_get_temperature_offset(int32_t* t_offset_m_deg_c) {
  87.     int16_t error;
  88.     uint16_t t_offset;

  89.     error = scd4x_get_temperature_offset_ticks(&t_offset);
  90.     if (error) {
  91.         return error;
  92.     }
  93.     *t_offset_m_deg_c = ((21875 * (int32_t)t_offset) >> 13);
  94.     return NO_ERROR;
  95. }

  96. int16_t scd4x_set_temperature_offset_ticks(uint16_t t_offset) {
  97.     int16_t error;
  98.     uint8_t buffer[5];
  99.     uint16_t offset = 0;
  100.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x241D);

  101.     offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset, t_offset);

  102.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  103.     if (error) {
  104.         return error;
  105.     }
  106.     sensirion_i2c_hal_sleep_usec(1000);
  107.     return NO_ERROR;
  108. }

  109. int16_t scd4x_set_temperature_offset(int32_t t_offset_m_deg_c) {
  110.     uint16_t t_offset = (uint16_t)((t_offset_m_deg_c * 12271) >> 15);
  111.     return scd4x_set_temperature_offset_ticks(t_offset);
  112. }

  113. int16_t scd4x_get_sensor_altitude(uint16_t* sensor_altitude) {
  114.     int16_t error;
  115.     uint8_t buffer[3];
  116.     uint16_t offset = 0;
  117.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2322);

  118.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  119.     if (error) {
  120.         return error;
  121.     }

  122.     sensirion_i2c_hal_sleep_usec(1000);

  123.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  124.     if (error) {
  125.         return error;
  126.     }
  127.     *sensor_altitude = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  128.     return NO_ERROR;
  129. }

  130. int16_t scd4x_set_sensor_altitude(uint16_t sensor_altitude) {
  131.     int16_t error;
  132.     uint8_t buffer[5];
  133.     uint16_t offset = 0;
  134.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2427);

  135.     offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
  136.                                                   sensor_altitude);

  137.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  138.     if (error) {
  139.         return error;
  140.     }
  141.     sensirion_i2c_hal_sleep_usec(1000);
  142.     return NO_ERROR;
  143. }

  144. int16_t scd4x_set_ambient_pressure(uint16_t ambient_pressure) {
  145.     int16_t error;
  146.     uint8_t buffer[5];
  147.     uint16_t offset = 0;
  148.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xE000);

  149.     offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
  150.                                                   ambient_pressure);

  151.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  152.     if (error) {
  153.         return error;
  154.     }
  155.     sensirion_i2c_hal_sleep_usec(1000);
  156.     return NO_ERROR;
  157. }

  158. int16_t scd4x_perform_forced_recalibration(uint16_t target_co2_concentration,
  159.                                            uint16_t* frc_correction) {
  160.     int16_t error;
  161.     uint8_t buffer[5];
  162.     uint16_t offset = 0;
  163.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x362F);

  164.     offset = sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset,
  165.                                                   target_co2_concentration);

  166.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  167.     if (error) {
  168.         return error;
  169.     }

  170.     sensirion_i2c_hal_sleep_usec(400000);

  171.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  172.     if (error) {
  173.         return error;
  174.     }
  175.     *frc_correction = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  176.     return NO_ERROR;
  177. }

  178. int16_t scd4x_get_automatic_self_calibration(uint16_t* asc_enabled) {
  179.     int16_t error;
  180.     uint8_t buffer[3];
  181.     uint16_t offset = 0;
  182.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2313);

  183.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  184.     if (error) {
  185.         return error;
  186.     }

  187.     sensirion_i2c_hal_sleep_usec(1000);

  188.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  189.     if (error) {
  190.         return error;
  191.     }
  192.     *asc_enabled = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  193.     return NO_ERROR;
  194. }

  195. int16_t scd4x_set_automatic_self_calibration(uint16_t asc_enabled) {
  196.     int16_t error;
  197.     uint8_t buffer[5];
  198.     uint16_t offset = 0;
  199.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2416);

  200.     offset =
  201.         sensirion_i2c_add_uint16_t_to_buffer(&buffer[0], offset, asc_enabled);

  202.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  203.     if (error) {
  204.         return error;
  205.     }
  206.     sensirion_i2c_hal_sleep_usec(1000);
  207.     return NO_ERROR;
  208. }

  209. int16_t scd4x_start_low_power_periodic_measurement() {
  210.     uint8_t buffer[2];
  211.     uint16_t offset = 0;
  212.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x21AC);

  213.     return sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  214. }

  215. int16_t scd4x_get_data_ready_status(uint16_t* data_ready) {
  216.     int16_t error;
  217.     uint8_t buffer[3];
  218.     uint16_t offset = 0;
  219.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0xE4B8);

  220.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  221.     if (error) {
  222.         return error;
  223.     }

  224.     sensirion_i2c_hal_sleep_usec(1000);

  225.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  226.     if (error) {
  227.         return error;
  228.     }
  229.     *data_ready = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  230.     return NO_ERROR;
  231. }

  232. int16_t scd4x_persist_settings() {
  233.     int16_t error;
  234.     uint8_t buffer[2];
  235.     uint16_t offset = 0;
  236.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3615);

  237.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  238.     if (error) {
  239.         return error;
  240.     }
  241.     sensirion_i2c_hal_sleep_usec(800000);
  242.     return NO_ERROR;
  243. }

  244. int16_t scd4x_get_serial_number(uint16_t* serial_0, uint16_t* serial_1,
  245.                                 uint16_t* serial_2) {
  246.     int16_t error;
  247.     uint8_t buffer[9];
  248.     uint16_t offset = 0;
  249.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3682);

  250.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  251.     if (error) {
  252.         return error;
  253.     }

  254.     sensirion_i2c_hal_sleep_usec(1000);

  255.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 6);
  256.     if (error) {
  257.         return error;
  258.     }
  259.     *serial_0 = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  260.     *serial_1 = sensirion_common_bytes_to_uint16_t(&buffer[2]);
  261.     *serial_2 = sensirion_common_bytes_to_uint16_t(&buffer[4]);
  262.     return NO_ERROR;
  263. }

  264. int16_t scd4x_perform_self_test(uint16_t* sensor_status) {
  265.     int16_t error;
  266.     uint8_t buffer[3];
  267.     uint16_t offset = 0;
  268.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3639);

  269.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  270.     if (error) {
  271.         return error;
  272.     }

  273.     sensirion_i2c_hal_sleep_usec(10000000);

  274.     error = sensirion_i2c_read_data_inplace(SCD4X_I2C_ADDRESS, &buffer[0], 2);
  275.     if (error) {
  276.         return error;
  277.     }
  278.     *sensor_status = sensirion_common_bytes_to_uint16_t(&buffer[0]);
  279.     return NO_ERROR;
  280. }

  281. int16_t scd4x_perform_factory_reset() {
  282.     int16_t error;
  283.     uint8_t buffer[2];
  284.     uint16_t offset = 0;
  285.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3632);

  286.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  287.     if (error) {
  288.         return error;
  289.     }
  290.     sensirion_i2c_hal_sleep_usec(800000);
  291.     return NO_ERROR;
  292. }

  293. int16_t scd4x_reinit() {
  294.     int16_t error;
  295.     uint8_t buffer[2];
  296.     uint16_t offset = 0;
  297.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x3646);

  298.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  299.     if (error) {
  300.         return error;
  301.     }
  302.     sensirion_i2c_hal_sleep_usec(20000);
  303.     return NO_ERROR;
  304. }

  305. int16_t scd4x_measure_single_shot() {
  306.     int16_t error;
  307.     uint8_t buffer[2];
  308.     uint16_t offset = 0;
  309.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x219D);

  310.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  311.     if (error) {
  312.         return error;
  313.     }
  314.     sensirion_i2c_hal_sleep_usec(5000000);
  315.     return NO_ERROR;
  316. }

  317. int16_t scd4x_measure_single_shot_rht_only() {
  318.     int16_t error;
  319.     uint8_t buffer[2];
  320.     uint16_t offset = 0;
  321.     offset = sensirion_i2c_add_command_to_buffer(&buffer[0], offset, 0x2196);

  322.     error = sensirion_i2c_write_data(SCD4X_I2C_ADDRESS, &buffer[0], offset);
  323.     if (error) {
  324.         return error;
  325.     }
  326.     sensirion_i2c_hal_sleep_usec(50000);
  327.     return NO_ERROR;
  328. }


复制代码
51hei.png
以上11个文件下载,请自行加入到您的工程中:
SCD4xco2.zip (24.32 KB, 下载次数: 120)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:1023701 发表于 2022-5-4 13:06 | 显示全部楼层
你的最终数据变量是哪一个啊 可不可以给一下main.c的代码 求求了
回复

使用道具 举报

ID:1024381 发表于 2022-5-6 18:50 | 显示全部楼层
谢谢,正需要,调试。官方Git下载的运行不正常
回复

使用道具 举报

ID:397211 发表于 2022-6-2 17:04 | 显示全部楼层
北道无辙 发表于 2022-5-4 13:06
你的最终数据变量是哪一个啊 可不可以给一下main.c的代码 求求了

我这个是官方移植的
回复

使用道具 举报

ID:397211 发表于 2022-6-2 17:05 | 显示全部楼层
ws51dhy 发表于 2022-5-6 18:50
谢谢,正需要,调试。官方Git下载的运行不正常

我这个是叫我们传感器厂商移植的,采样时间在5秒一次才不会出现问题
回复

使用道具 举报

ID:667696 发表于 2022-9-28 16:28 | 显示全部楼层
谢谢,正需要,调试
回复

使用道具 举报

ID:667696 发表于 2022-10-10 11:46 | 显示全部楼层
上面SCD的MAIN.c有吗?能不能一起发出来一下
回复

使用道具 举报

ID:272926 发表于 2023-8-18 14:12 | 显示全部楼层
拿官方的代码有什么意义? CO2的值都是1000多,哪个能准吗
回复

使用道具 举报

ID:162723 发表于 2023-10-25 17:54 | 显示全部楼层
谢谢,正好需要,官方的例子调了一下午没调通
回复

使用道具 举报

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

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表