一、硬件了解
从手册可以得知,PB8、PB9可以用作I2C1接口:
对应开发板上,可以用如下位置的接口:
二、SHT30温湿度传感器
我手头有一个标准的最简化的SHT30温湿度传感器,具体如下:
这个SHT30用3.3V供电,I2C接口通讯。
连接到开发板:
三、zephyr配置
在 zephyr中,有一个示例samples/sensor/sht3xd,展示了从sht3xd读取数据,要在STM32C0的开发板上使用,需要做一些配置。
首先,从zephyr/boards/arm/nucleo_c031c6/nucleo_c031c6.dts中,查看i2c的dts配置:
&i2c1 {
pinctrl-0 = <&i2c1_scl_pb8 &i2c1_sda_pb9>;
pinctrl-names = "default";
status = "okay";
clock-frequency = <I2C_BITRATE_FAST>;
};
从上述配置,可以看到,i2c使用了pb8、pb9。
另外,配置中定义了i2c通讯速率I2C_BITRATE_FAST,其具体的定义在 zephyr/include/zephyr/dt-bindings/i2c/i2c.h 文件中:
#define I2C_BITRATE_STANDARD 100000 /* 100 Kbit/s */
#define I2C_BITRATE_FAST 400000 /* 400 Kbit/s */
#define I2C_BITRATE_FAST_PLUS 1000000 /* 1 Mbit/s */
#define I2C_BITRATE_HIGH 3400000 /* 3.4 Mbit/s */
#define I2C_BITRATE_ULTRA 5000000 /* 5 Mbit/s */
所以,对应的速率为400 Kbits/s。
另外,还需要编写 zephyr/samples/sensor/sht3xd/boards/nucleo_c031c6.overlay,用于定义sht3xd传感器:
&i2c1 { /* SDA CN5.9=PB9, SCL CN5.10=PB8, ALERT CN5.1=D8=PA9 */
/* &i2c3 { * SDA CN7.36=PC1, SCL CN7.38=PC0, ALERT CN7.34=PB0 */
sht3xd@44 {
compatible = "sensirion,sht3xd";
reg = <0x44>;
};
};
上述配置中,设置了传感器的具体类型,对应:zephyr/dts/bindings/sensor/sensirion,sht3xd.yaml
# Copyright (c) 2018, Peter Bigot Consulting, LLC
# SPDX-License-Identifier: Apache-2.0
description: Sensirion Humidity SHT3x-DIS humidity and temperature sensor
compatible: "sensirion,sht3xd"
include: [sensor-device.yaml, i2c-device.yaml]
properties:
alert-gpios:
type: phandle-array
description: |
ALERT pin.
This pin signals active high when produced by the sensor. The
property value should ensure the flags properly describe the
signal that is presented to the driver.
其对应的驱动位置:./drivers/sensor/sht3xd
./drivers/sensor/sht3xd
├── CMakeLists.txt
├── Kconfig
├── sht3xd.c
├── sht3xd.h
└── sht3xd_trigger.c
做完上述配置,就可以编写具体程序了。
四、代码编写
参考 samples/sensor/sht3xd/src/main.c,编写如下的代码:
#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>
#include <stdio.h>
const struct device *const dev = DEVICE_DT_GET_ONE(sensirion_sht3xd);
int main(void)
{
int rc;
if (!device_is_ready(dev)) {
printf("Device %s is not ready\n", dev->name);
return 0;
}
while (true) {
struct sensor_value temp, hum;
rc = sensor_sample_fetch(dev);
if (rc == 0) {
rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP,
&temp);
}
if (rc == 0) {
rc = sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY,
&hum);
}
if (rc != 0) {
printf("SHT3XD: failed: %d\n", rc);
break;
}
printf("SHT3XD: %d.%d=%.2f Cel ; %d.%d=%0.2f %%RH\n",
temp.val1,temp.val2,
sensor_value_to_double(&temp),
hum.val1,hum.val2,
sensor_value_to_double(&hum));
k_sleep(K_MSEC(2000));
}
return 0;
}
在上述代码中,通过别名 sensirion_sht3xd 来获得dts配置的设备,然后通过device_is_ready()检查设备是否准备去就绪。
因为前面做了dts配置,所以一旦系统启动,就会自动做好准备,提供服务。
然后,调用sensor_sample_fetch()进行数据采样,采样后,就可以调用sensor_channel_get()来获取数据了。
在 zephyr/include/zephyr/drivers/sensor.h 中,定义了传感器数据读取的结构,以及对应的数据通道:
struct sensor_value {
int32_t val1;
int32_t val2;
};
enum sensor_channel {
SENSOR_CHAN_ACCEL_X,
SENSOR_CHAN_ACCEL_Y,
SENSOR_CHAN_ACCEL_Z,
SENSOR_CHAN_ACCEL_XYZ,
SENSOR_CHAN_GYRO_X,
SENSOR_CHAN_GYRO_Y,
SENSOR_CHAN_GYRO_Z,
SENSOR_CHAN_GYRO_XYZ,
SENSOR_CHAN_MAGN_X,
SENSOR_CHAN_MAGN_Y,
SENSOR_CHAN_MAGN_Z,
SENSOR_CHAN_MAGN_XYZ,
SENSOR_CHAN_DIE_TEMP,
SENSOR_CHAN_AMBIENT_TEMP,
SENSOR_CHAN_PRESS,
SENSOR_CHAN_PROX,
SENSOR_CHAN_HUMIDITY,
SENSOR_CHAN_LIGHT,
SENSOR_CHAN_IR,
SENSOR_CHAN_RED,
SENSOR_CHAN_GREEN,
SENSOR_CHAN_BLUE,
SENSOR_CHAN_ALTITUDE,
SENSOR_CHAN_PM_1_0,
SENSOR_CHAN_PM_2_5,
SENSOR_CHAN_PM_10,
SENSOR_CHAN_DISTANCE,
SENSOR_CHAN_CO2,
SENSOR_CHAN_VOC,
SENSOR_CHAN_GAS_RES,
SENSOR_CHAN_VOLTAGE,
SENSOR_CHAN_VSHUNT,
SENSOR_CHAN_CURRENT,
SENSOR_CHAN_POWER,
SENSOR_CHAN_RESISTANCE,
SENSOR_CHAN_ROTATION,
SENSOR_CHAN_POS_DX,
SENSOR_CHAN_POS_DY,
SENSOR_CHAN_POS_DZ,
SENSOR_CHAN_RPM,
SENSOR_CHAN_GAUGE_VOLTAGE,
SENSOR_CHAN_GAUGE_AVG_CURRENT,
SENSOR_CHAN_GAUGE_STDBY_CURRENT,
SENSOR_CHAN_GAUGE_MAX_LOAD_CURRENT,
SENSOR_CHAN_GAUGE_TEMP,
SENSOR_CHAN_GAUGE_STATE_OF_CHARGE,
SENSOR_CHAN_GAUGE_FULL_CHARGE_CAPACITY,
SENSOR_CHAN_GAUGE_REMAINING_CHARGE_CAPACITY,
SENSOR_CHAN_GAUGE_NOM_AVAIL_CAPACITY,
SENSOR_CHAN_GAUGE_FULL_AVAIL_CAPACITY,
SENSOR_CHAN_GAUGE_AVG_POWER,
SENSOR_CHAN_GAUGE_STATE_OF_HEALTH,
SENSOR_CHAN_GAUGE_TIME_TO_EMPTY,
SENSOR_CHAN_GAUGE_TIME_TO_FULL,
SENSOR_CHAN_GAUGE_CYCLE_COUNT,
SENSOR_CHAN_GAUGE_DESIGN_VOLTAGE,
SENSOR_CHAN_GAUGE_DESIRED_VOLTAGE,
SENSOR_CHAN_GAUGE_DESIRED_CHARGING_CURRENT,
SENSOR_CHAN_ALL,
SENSOR_CHAN_COMMON_COUNT,
SENSOR_CHAN_PRIV_START = SENSOR_CHAN_COMMON_COUNT,
SENSOR_CHAN_MAX = INT16_MAX,
};
温度对应的通道为 SENSOR_CHAN_AMBIENT_TEMP,湿度对应的通道为SENSOR_CHAN_HUMIDITY,所以读取温湿度信息,使用如下代码:
rc = sensor_sample_fetch(dev);
if (rc == 0) {
rc = sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP,
&temp);
}
if (rc == 0) {
rc = sensor_channel_get(dev, SENSOR_CHAN_HUMIDITY,
&hum);
}
数据读取成功后,可以调用 sensor_value_to_double()将结构化数据转换为double浮点数据。
五、输出结果
将上述代码编译下载到开发板,运行后,即可输出温湿度信息:
用手捏住SHT30的传感器部分,温度就会上升。
对着它哈气,湿度就会上升了。