简体   繁体   English

如何为嵌入式 C 中的传感器定义引脚?

[英]How are pins defined for sensors in embedded C?

I have a Nordic nRF52840DK board that needs to be connected to an LSM6DSL accelerometer .我有一个 Nordic nRF52840DK 板,需要连接到LSM6DSL 加速度计 I am using the Zephyr RTOS and the sample code from Zephyr is shown below:我正在使用 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));
    }
}

From my previous experience working with Arduino, you need to define the pins before the main function, but there isn't any definition on pins in this code example.根据我之前使用 Arduino 的经验,您需要在 main 函数之前定义管脚,但在此代码示例中没有对管脚的任何定义。 So my question is: How does the board know which pins to use when connected to the sensor?所以我的问题是:当连接到传感器时,电路板如何知道要使用哪些引脚?

Thanks in advance!提前致谢!

In embedded C (bare metal and some RTOS), the developer is expected to know what is connected where and which registers to use to access the connected hardware by driving the right pins.在嵌入式 C(裸机和一些 RTOS)中,开发人员需要知道连接到哪里以及使用哪些寄存器通过驱动正确的引脚来访问连接的硬件。

In the specific case of Zephyr (as well as Das U-Boot and Linux on some architectures), the system configuration (among other things pins, but not only) is described by a device-tree .在 Zephyr(以及某些体系结构上的Das U-BootLinux )的特定情况下,系统配置(包括引脚,但不仅限于)由设备树描述。 It is a "a data structure for describing hardware", which allows the firmware code to become independent of the actual hardware.它是一种“用于描述硬件的数据结构”,它允许固件代码独立于实际硬件。

The device-tree will describe many things, the most important being:设备树将描述许多事情,最重要的是:

  • the device's memory map设备的内存映射
  • the list of CPUs and their properties (frequency, caches, ...) CPU 列表及其属性(频率、缓存等)
  • the peripherals, as well as their configuration外围设备及其配置

Zephyr does have a very good introduction to device-tree . Zephyr 确实对 device-tree很好的介绍


In the code you posted, Zephyr does retrieve the device information from the device-tree when executing the following line:在您发布的代码中,Zephyr 在执行以下行时确实从设备树中检索设备信息:

const struct device *lsm6dsl_dev = device_get_binding(DT_LABEL(DT_INST(0, st_lsm6dsl)));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM