-2

我有一块 Nordic nRF52840DK 板,需要连接到LSM6DSL 加速度计。我正在使用 Zephyr RTOS,Zephyr 的示例代码如下所示:

/*
 * Copyright (c) 2018 STMicroelectronics
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr.h>
#include <device.h>
#include <drivers/sensor.h>
#include <stdio.h>
#include <sys/util.h>

static inline float out_ev(struct sensor_value *val)
{
    return (val->val1 + (float)val->val2 / 1000000);
}

static int print_samples;
static int lsm6dsl_trig_cnt;

static struct sensor_value accel_x_out, accel_y_out, accel_z_out;
static struct sensor_value gyro_x_out, gyro_y_out, gyro_z_out;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
static struct sensor_value magn_x_out, magn_y_out, magn_z_out;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
static struct sensor_value press_out, temp_out;
#endif

#ifdef CONFIG_LSM6DSL_TRIGGER
static void lsm6dsl_trigger_handler(const struct device *dev,
                    struct sensor_trigger *trig)
{
    static struct sensor_value accel_x, accel_y, accel_z;
    static struct sensor_value gyro_x, gyro_y, gyro_z;
#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
    static struct sensor_value magn_x, magn_y, magn_z;
#endif
#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
    static struct sensor_value press, temp;
#endif
    lsm6dsl_trig_cnt++;

    sensor_sample_fetch_chan(dev, SENSOR_CHAN_ACCEL_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_X, &accel_x);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Y, &accel_y);
    sensor_channel_get(dev, SENSOR_CHAN_ACCEL_Z, &accel_z);

    /* lsm6dsl gyro */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_GYRO_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_X, &gyro_x);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Y, &gyro_y);
    sensor_channel_get(dev, SENSOR_CHAN_GYRO_Z, &gyro_z);

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
    /* lsm6dsl external magn */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_MAGN_XYZ);
    sensor_channel_get(dev, SENSOR_CHAN_MAGN_X, &magn_x);
    sensor_channel_get(dev, SENSOR_CHAN_MAGN_Y, &magn_y);
    sensor_channel_get(dev, SENSOR_CHAN_MAGN_Z, &magn_z);
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
    /* lsm6dsl external press/temp */
    sensor_sample_fetch_chan(dev, SENSOR_CHAN_PRESS);
    sensor_channel_get(dev, SENSOR_CHAN_PRESS, &press);

    sensor_sample_fetch_chan(dev, SENSOR_CHAN_AMBIENT_TEMP);
    sensor_channel_get(dev, SENSOR_CHAN_AMBIENT_TEMP, &temp);
#endif

    if (print_samples) {
        print_samples = 0;

        accel_x_out = accel_x;
        accel_y_out = accel_y;
        accel_z_out = accel_z;

        gyro_x_out = gyro_x;
        gyro_y_out = gyro_y;
        gyro_z_out = gyro_z;

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
        magn_x_out = magn_x;
        magn_y_out = magn_y;
        magn_z_out = magn_z;
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
        press_out = press;
        temp_out = temp;
#endif
    }

}
#endif

void main(void)
{
    int cnt = 0;
    char out_str[64];
    struct sensor_value odr_attr;
    const struct device *lsm6dsl_dev = device_get_binding(DT_LABEL(DT_INST(0, st_lsm6dsl)));

    if (lsm6dsl_dev == NULL) {
        printk("Could not get LSM6DSL device\n");
        return;
    }

    /* set accel/gyro sampling frequency to 104 Hz */
    odr_attr.val1 = 104;
    odr_attr.val2 = 0;

    if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_ACCEL_XYZ,
                SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
        printk("Cannot set sampling frequency for accelerometer.\n");
        return;
    }

    if (sensor_attr_set(lsm6dsl_dev, SENSOR_CHAN_GYRO_XYZ,
                SENSOR_ATTR_SAMPLING_FREQUENCY, &odr_attr) < 0) {
        printk("Cannot set sampling frequency for gyro.\n");
        return;
    }

#ifdef CONFIG_LSM6DSL_TRIGGER
    struct sensor_trigger trig;

    trig.type = SENSOR_TRIG_DATA_READY;
    trig.chan = SENSOR_CHAN_ACCEL_XYZ;

    if (sensor_trigger_set(lsm6dsl_dev, &trig, lsm6dsl_trigger_handler) != 0) {
        printk("Could not set sensor type and channel\n");
        return;
    }
#endif

    if (sensor_sample_fetch(lsm6dsl_dev) < 0) {
        printk("Sensor sample update error\n");
        return;
    }

    while (1) {
        /* Erase previous */
        printk("\0033\014");
        printf("LSM6DSL sensor samples:\n\n");

        /* lsm6dsl accel */
        sprintf(out_str, "accel x:%f ms/2 y:%f ms/2 z:%f ms/2",
                              out_ev(&accel_x_out),
                              out_ev(&accel_y_out),
                              out_ev(&accel_z_out));
        printk("%s\n", out_str);

        /* lsm6dsl gyro */
        sprintf(out_str, "gyro x:%f dps y:%f dps z:%f dps",
                               out_ev(&gyro_x_out),
                               out_ev(&gyro_y_out),
                               out_ev(&gyro_z_out));
        printk("%s\n", out_str);

#if defined(CONFIG_LSM6DSL_EXT0_LIS2MDL)
        /* lsm6dsl external magn */
        sprintf(out_str, "magn x:%f gauss y:%f gauss z:%f gauss",
                               out_ev(&magn_x_out),
                               out_ev(&magn_y_out),
                               out_ev(&magn_z_out));
        printk("%s\n", out_str);
#endif

#if defined(CONFIG_LSM6DSL_EXT0_LPS22HB)
        /* lsm6dsl external press/temp */
        sprintf(out_str, "press: %f kPa - temp: %f deg",
            out_ev(&press_out), out_ev(&temp_out));
        printk("%s\n", out_str);
#endif

        printk("loop:%d trig_cnt:%d\n\n", ++cnt, lsm6dsl_trig_cnt);

        print_samples = 1;
        k_sleep(K_MSEC(2000));
    }
}

根据我之前使用 Arduino 的经验,您需要在 main 函数之前定义引脚,但在此代码示例中没有任何引脚定义。所以我的问题是:电路板如何知道连接到传感器时要使用哪些引脚?

提前致谢!

4

1 回答 1

3

在嵌入式 C(裸机和一些 RTOS)中,开发人员应该知道什么连接在哪里,以及使用哪些寄存器通过驱动正确的引脚来访问连接的硬件。

在 Zephyr(以及某些架构上的Das U-BootLinux)的特定情况下,系统配置(除其他外,但不仅限于引脚)由device-tree描述。它是一种“用于描述硬件的数据结构”,它允许固件代码独立于实际硬件。

设备树将描述很多东西,最重要的是:

  • 设备的内存映射
  • CPU 列表及其属性(频率、缓存等)
  • 外围设备,以及它们的配置

Zephyr对 device-tree 有很好的介绍


在您发布的代码中,Zephyr 在执行以下行时确实从设备树中检索设备信息:

const struct device *lsm6dsl_dev = device_get_binding(DT_LABEL(DT_INST(0, st_lsm6dsl)));
于 2021-07-27T09:39:07.083 回答