Nordic芯片对于驱动传感器这方面我感觉对新手来说是很友好的,因为它的底层驱动集成了市面上 常见的大部分的传感器的驱动,比如说你如果使用I2C接口的传感器,使用 软件I2C的话,根本不用去拼凑时序,六段基本时序还有传感器读数据的时许都不用写,只需要去调用接口函数就行,下面我将驱动SHT40的代码给出来

我这里是使用的SDK版本是2.9.1

首先要修改prj.conf文件

CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_SERIAL=y
CONFIG_PRINTK=y

CONFIG_I2C=y
CONFIG_SENSOR=y
CONFIG_SHT4X=y

其次是需要在设备树中添加I2C节点,由于我这里串口使用的是uart21,所以iic节点就不能用21,使用22,这里面不能冲突

设备树内容和如下

/ {
    /* 串口仍然用 uart21(现在已经能正常打印的那个) */
    chosen {
        zephyr,console     = &uart21;
        zephyr,shell-uart  = &uart21;
        zephyr,uart-mcumgr = &uart21;
    };

    /* 给 SHT40 起一个别名,代码里用 DT_ALIAS(sht40) 获取设备 */
    aliases {
        sht40 = &sht40;
    };
};

/* 串口 21 配置:P2.08 = TX, P2.07 = RX */
&pinctrl {
    /* UART21 引脚 */
    uart21_custom_default: uart21_custom_default {
        group1 {
            /* TX 引脚 - P2.08 */
            psels = <NRF_PSEL(UART_TX, 2, 8)>;
        };
        group2 {
            /* RX 引脚 - P2.07 */
            psels = <NRF_PSEL(UART_RX, 2, 7)>;
            bias-pull-up;
        };
    };

    uart21_custom_sleep: uart21_custom_sleep {
        group1 {
            psels = <NRF_PSEL(UART_TX, 2, 8)>,
                    <NRF_PSEL(UART_RX, 2, 7)>;
            low-power-enable;
        };
    };

    /* I2C22 引脚:P1.11 = SCL, P1.12 = SDA */
    /omit-if-no-ref/ i2c22_default: i2c22_default {
        group1 {
            psels = <NRF_PSEL(TWIM_SCL, 1, 11)>,
                    <NRF_PSEL(TWIM_SDA, 1, 12)>;
            bias-pull-up;      
        };
    };

    /omit-if-no-ref/ i2c22_sleep: i2c22_sleep {
        group1 {
            psels = <NRF_PSEL(TWIM_SCL, 1, 11)>,
                    <NRF_PSEL(TWIM_SDA, 1, 12)>;
            low-power-enable;
        };
    };
};

/* 串口 21:保持你原来的配置 */
&uart21 {
    status = "okay";
    current-speed = <115200>;
    pinctrl-0 = <&uart21_custom_default>;
    pinctrl-1 = <&uart21_custom_sleep>;
    pinctrl-names = "default", "sleep";
};

/* I2C 控制器:i2c22,挂 SHT40(I2C 地址 0x44) */
&i2c22 {
    status = "okay";
    //compatible = "nordic,nrf-twim";
    clock-frequency = <I2C_BITRATE_STANDARD>;   /* 100 kHz */

    pinctrl-0 = <&i2c22_default>;
    pinctrl-1 = <&i2c22_sleep>;
    pinctrl-names = "default", "sleep";

    sht40: sht40@44 {
        compatible = "sensirion,sht4x";
        reg = <0x44>;          /* SHT40 默认地址 */
        repeatability = <1>;   /* 中等重复度,可按需要改 0/1/2 */
        status = "okay";
    };
};

然后就是main.c文件

#include <zephyr/kernel.h>
#include <zephyr/sys/printk.h>
#include <zephyr/device.h>
#include <zephyr/drivers/sensor.h>

/* 通过 devicetree alias 获取 SHT40 设备句柄 */
static const struct device *const sht40_dev =
    DEVICE_DT_GET(DT_ALIAS(sht40));

int main(void)
{
    struct sensor_value temp, hum;
    //检查设备是否驱动成功
    if (!device_is_ready(sht40_dev)) {
        printk("SHT40 device not ready!\n");
    } else {
        printk("SHT40 device ready.\n");
    }

    while (1) {
        printk("Hello World!\n");//判断是否进入循环

        if (!device_is_ready(sht40_dev)) {
            printk("SHT40 device not ready (loop)!\n");
        } else {
            //sensor_sample_fetch() 必须先执行,否则 sensor_channel_get() 读取的是旧数据或无效数据
            int err = sensor_sample_fetch(sht40_dev);//采集数据,如果返回值是0,说明采集成功
            if (err)//采集不成功 
            {
                printk("SHT40: sensor_sample_fetch failed: %d\n", err);
            } 
            else 
            {
                err = sensor_channel_get(sht40_dev,SENSOR_CHAN_AMBIENT_TEMP, &temp);//将驱动内部存储的温度数据提取到 temp 变量中
                if (!err) 
                {
                    err = sensor_channel_get(sht40_dev,SENSOR_CHAN_HUMIDITY, &hum);//将驱动内部存储的湿度数据提取到 hum 变量中
                }
                if (!err) {
                    printk("SHT40: Temp = %d.%02d C, RH = %d.%02d %%\n",
                           temp.val1, temp.val2 / 10000, hum.val1, hum.val2 / 10000);
                } else {
                    printk("SHT40: channel_get failed: %d\n", err);
                }
            }
        }
        k_sleep(K_MSEC(1000));
    }
}

更多推荐