eefocus_3914144 发表于 2026-2-11 11:10:13

【瑞萨AI挑战赛】RA6E2移植BMI270获取加速度

【前言】
在瑞萨AI作业中,他的示例是使用ICM-42670-P模块,而我手上没有这个模块,因此花重金从某宝购买BMI270来实现读取三轴加速度。
【外设分配】
1、UASRT,我使用板载jlinkob转ttl,根据原理图,我配置SCI0作为串口输出。
2、I2C,我使用sci9与BMI270进行连接
【RASC配置】
1、I2C配置:
!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110208k4r03h4qdd3sn4rr.png)

2、USART配置:

!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110227symbf1jmlbhc3rfm.png)
3、在stack中添加I2C填写从机地址与回调函数:
!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110242s88to9tl9fa7m7oy.png)

4、添加uart

!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110255wo5mu95o5ndue80v.png)
【代码移植】
1、从网下载到BMI270的linux驱动库,在工程的src中新建一个bmi270,将驱动复制到这个目录中。

!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110311mlqt67twspnrrc5p.png)
2、修改bmi270.c适配RA6E2的I2C读写操作,代码如下:

```
/**
* @file bmi270.c
* @brief BMI270 6-axis motion sensor driver for RA6E2 with FSP
* @note Based on Bosch BMI270 Sensor API and bmi270-c-main reference
*/

#include "bmi270.h"
#include "bmi270_defs.h"
#include "bmi270_config_file.h"
#include "hal_data.h"
#include <string.h>

/* External I2C event tracking */
volatile i2c_master_event_t g_i2c_event = I2C_MASTER_EVENT_ABORTED;

/* Forward declarations */
static fsp_err_t wait_for_i2c_event(i2c_master_event_t event);
void bmi2_delay_us(uint32_t period);

/**
* @brief I2C master callback for event tracking
*/
void sci_i2c_master_callback(i2c_master_callback_args_t *p_args)
{
    if (p_args != NULL) {
      g_i2c_event = p_args->event;
    }
}

/**
* @brief Wait for I2C event with timeout
*/
static fsp_err_t wait_for_i2c_event(i2c_master_event_t event)
{
    uint32_t timeout = R_FSP_SystemClockHzGet(FSP_PRIV_CLOCK_ICLK) / 1000;
    while (timeout-- && (g_i2c_event != event)) {
      __NOP();
    }
    return timeout ? FSP_SUCCESS : FSP_ERR_TIMEOUT;
}

/**
* @brief Read 8-bit register value
*/
uint8_t read_register(struct bmi270 *sensor, uint8_t reg_addr)
{
    (void)sensor;
    fsp_err_t err;
    uint8_t addr_buf;
    uint8_t data_buf;

    /* Write register address */
    addr_buf = reg_addr;
    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->write(g_i2c9.p_ctrl, addr_buf, 1, false);
    if (FSP_SUCCESS != err) {
      return 0xFF;
    }

    /* Wait for TX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_TX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return 0xFF;
    }

    /* Read data */
    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->read(g_i2c9.p_ctrl, data_buf, 1, false);
    if (FSP_SUCCESS != err) {
      return 0xFF;
    }

    /* Wait for RX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_RX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return 0xFF;
    }

    return data_buf;
}

/**
* @brief Read block of registers
*/
int read_register_block(struct bmi270 *sensor, uint8_t reg_addr, uint8_t *data, uint8_t len)
{
    (void)sensor;
    fsp_err_t err;
    uint8_t addr_buf;

    /* Write register address */
    addr_buf = reg_addr;
    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->write(g_i2c9.p_ctrl, addr_buf, 1, false);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    /* Wait for TX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_TX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    /* Read data */
    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->read(g_i2c9.p_ctrl, data, len, false);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    /* Wait for RX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_RX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    return 0;
}

/**
* @brief Write 8-bit value to register
*/
int write_register(struct bmi270 *sensor, uint8_t reg_addr, uint8_t value)
{
    (void)sensor;
    fsp_err_t err;
    uint8_t write_buf;

    write_buf = reg_addr;
    write_buf = value;

    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->write(g_i2c9.p_ctrl, write_buf, 2, false);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    /* Wait for TX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_TX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    return 0;
}

/**
* @brief Write block of data to registers
*/
int write_register_block(struct bmi270 *sensor, uint8_t reg_addr, uint8_t len, const uint8_t *data)
{
    (void)sensor;
    fsp_err_t err;
    uint8_t write_buf;/* reg_addr + max 32 bytes data */

    if (len > 32) {
      return -1;
    }

    write_buf = reg_addr;
    memcpy(&write_buf, data, len);

    g_i2c_event = I2C_MASTER_EVENT_ABORTED;
    err = g_i2c9.p_api->write(g_i2c9.p_ctrl, write_buf, len + 1, false);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    /* Wait for TX complete */
    err = wait_for_i2c_event(I2C_MASTER_EVENT_TX_COMPLETE);
    if (FSP_SUCCESS != err) {
      return -1;
    }

    return 0;
}

/**
* @brief Load config file into sensor
*/
int load_config_file(struct bmi270 *sensor)
{
    uint8_t status;
    uint8_t write_buf;
    fsp_err_t err;

    /* Check internal status */
    status = read_register(sensor, INTERNAL_STATUS);

    if (status & 0x01) {
      /* Already initialized */
      return 0;
    }

    if (status & 0x02) {
      /* Needs power cycle - can't proceed */
      return -1;
    }

    /* Power down the sensor */
    write_register(sensor, PWR_CONF, 0x00);
    bmi2_delay_us(450);

    /* Disable init */
    write_register(sensor, INIT_CTRL, 0x00);

    /* Load 8KB config file in 32-byte chunks */
    for (uint16_t i = 0; i < 256; i++) {
      /* Set page number */
      write_register(sensor, INIT_ADDR_1, (uint8_t)i);

      /* Write 32 bytes of config data */
      write_buf = INIT_DATA;
      memcpy(&write_buf, &bmi270_config_file, 32);

      g_i2c_event = I2C_MASTER_EVENT_ABORTED;
      err = g_i2c9.p_api->write(g_i2c9.p_ctrl, write_buf, 33, false);
      if (FSP_SUCCESS != err) {
            return -1;
      }

      err = wait_for_i2c_event(I2C_MASTER_EVENT_TX_COMPLETE);
      if (FSP_SUCCESS != err) {
            return -1;
      }

      bmi2_delay_us(20);
    }

    /* Enable init */
    write_register(sensor, INIT_CTRL, 0x01);
    bmi2_delay_us(20000);

    /* Verify initialization */
    status = read_register(sensor, INTERNAL_STATUS);
    if (!(status & 0x01)) {
      return -1;
    }

    return 0;
}

/**
* @brief Initialize BMI270 sensor
*/
int bmi270_init(struct bmi270 *sensor)
{
    uint8_t chip_id;

    /* Set I2C address in sensor struct */
    sensor->i2c_addr = I2C_PRIM_ADDR;

    /* Verify chip ID */
    chip_id = read_register(sensor, CHIP_ID_ADDRESS);
    if (chip_id != BMI270_CHIP_ID) {
      return -1;
    }
    sensor->chip_id = chip_id;

    /* Load configuration file */
    if (load_config_file(sensor) != 0) {
      return -1;
    }

    /* Set default ranges */
    sensor->acc_range = 4.0;   /* +/- 4G */
    sensor->gyr_range = 2000.0; /* +/- 2000 dps */

    return 0;
}

/**
* @brief Delay function
*/
void bmi2_delay_us(uint32_t period)
{
    for (uint32_t i = 0; i < period * 10; i++) {
      __NOP();
    }
}

/**
* @brief Set sensor mode
*/
void set_mode(struct bmi270 *sensor, uint8_t mode)
{
    if (mode == LOW_POWER_MODE) {
      /* Low power: accel only at 50Hz */
      write_register(sensor, PWR_CTRL, 0x04);/* gyro off */
      write_register(sensor, ACC_CONF, 0x17);/* 50Hz, OSR4 */
      write_register(sensor, GYR_CONF, 0x28);/* 100Hz, OSR4 */
      write_register(sensor, PWR_CONF, 0x03);/* advanced power save */
      sensor->acc_odr = 50;
      sensor->gyr_odr = 100;
    } else if (mode == NORMAL_MODE) {
      /* Normal: both sensors on */
      write_register(sensor, PWR_CTRL, 0x0E);/* aux + acc + gyro on */
      write_register(sensor, ACC_CONF, 0xA8);/* 100Hz, normal filter */
      write_register(sensor, GYR_CONF, 0xA9);/* 200Hz, normal filter */
      write_register(sensor, PWR_CONF, 0x02);/* normal power */
      sensor->acc_odr = 100;
      sensor->gyr_odr = 200;
    } else if (mode == PERFORMANCE_MODE) {
      /* Performance: both sensors on, optimized */
      write_register(sensor, PWR_CTRL, 0x0E);
      write_register(sensor, ACC_CONF, 0xA8);
      write_register(sensor, GYR_CONF, 0xE9);/* 200Hz, noise perf */
      write_register(sensor, PWR_CONF, 0x02);
      sensor->acc_odr = 100;
      sensor->gyr_odr = 200;
    }
}

/**
* @brief Get raw accelerometer data
*/
void get_acc_raw(struct bmi270 *sensor, int16_t *acc_x_raw, int16_t *acc_y_raw, int16_t *acc_z_raw)
{
    uint8_t buffer;
    (void)sensor;

    read_register_block(sensor, ACC_X_7_0, buffer, 6);

    *acc_x_raw = (int16_t)(buffer << 8) | buffer;
    *acc_y_raw = (int16_t)(buffer << 8) | buffer;
    *acc_z_raw = (int16_t)(buffer << 8) | buffer;
}

/**
* @brief Get raw gyroscope data
*/
void get_gyr_raw(struct bmi270 *sensor, int16_t *gyr_x_raw, int16_t *gyr_y_raw, int16_t *gyr_z_raw)
{
    uint8_t buffer;
    (void)sensor;

    read_register_block(sensor, GYR_X_7_0, buffer, 6);

    *gyr_x_raw = (int16_t)(buffer << 8) | buffer;
    *gyr_y_raw = (int16_t)(buffer << 8) | buffer;
    *gyr_z_raw = (int16_t)(buffer << 8) | buffer;
}

/**
* @brief Get raw temperature data
*/
void get_temp_raw(struct bmi270 *sensor, int16_t *temp)
{
    uint8_t buffer;
    (void)sensor;

    read_register_block(sensor, TEMP_7_0, buffer, 2);
    *temp = (int16_t)(buffer << 8) | buffer;
}

/**
* @brief Get accelerometer data in m/s^2
*/
void get_acc(struct bmi270 *sensor, double *acc_x, double *acc_y, double *acc_z)
{
    int16_t raw_x, raw_y, raw_z;
    double scale;

    get_acc_raw(sensor, &raw_x, &raw_y, &raw_z);

    /* Scale factor: 4G range = 8192 LSB/g, g = 9.80665 m/s^2 */
    scale = GRAVITY / 8192.0 * sensor->acc_range / 4.0;

    *acc_x = raw_x * scale;
    *acc_y = raw_y * scale;
    *acc_z = raw_z * scale;
}

/**
* @brief Get gyroscope data in deg/s
*/
void get_gyr(struct bmi270 *sensor, double *gyr_x, double *gyr_y, double *gyr_z)
{
    int16_t raw_x, raw_y, raw_z;
    double scale;

    get_gyr_raw(sensor, &raw_x, &raw_y, &raw_z);

    /* Scale factor: 2000 dps = 16.4 LSB/dps */
    scale = 16.4 * 2000.0 / sensor->gyr_range;

    *gyr_x = raw_x / scale;
    *gyr_y = raw_y / scale;
    *gyr_z = raw_z / scale;
}

/**
* @brief Get temperature in Celsius
*/
void get_temp(struct bmi270 *sensor, double *temp)
{
    int16_t raw_temp;

    get_temp_raw(sensor, &raw_temp);

    /* Temperature: 0x86C0 = 23°C, 1 LSB = 0.125°C, offset = 23°C */
    *temp = 23.0 + (raw_temp - 0x86C0) * 0.125;
}
```

【测试代码】
在hal_entry.c中添加测试代码:

```
/*
* Copyright (c) 2020 - 2025 Renesas Electronics Corporation and/or its affiliates
*
* SPDX-License-Identifier: BSD-3-Clause
*/

#include "hal_data.h"
#include "bmi270/bmi270.h"
#include <stdio.h>
#include <stdlib.h>

extern bsp_leds_t g_bsp_leds;

/* BMI270 device structure */
struct bmi270 bmi270_dev;

/* UART buffer for debug output */
static char g_uart_buffer;

/**
* @brief UART send string
*/
static void uart_send_string(const char *p_str)
{
    uint16_t len = 0;
    while (p_str) len++;
    g_uart0.p_api->write(g_uart0.p_ctrl, (uint8_t *)p_str, len);
}

/**
* @brief UART callback (required by FSP configuration)
*/
void usart_callback(uart_callback_args_t *p_args)
{
    (void)p_args;
}



/*******************************************************************************************************************//**
* @briefBMI270 test example application
*
* Tests BMI270 6-axis motion sensor by reading accelerometer and gyroscope data.
*
**********************************************************************************************************************/
void hal_entry (void)
{
#if BSP_TZ_SECURE_BUILD

    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif

    /* Open I2C master */
    fsp_err_t err = g_i2c9.p_api->open(g_i2c9.p_ctrl, g_i2c9.p_cfg);
    if (FSP_SUCCESS != err)
    {
      while (1)
      {
            ; /* I2C open failed */
      }
    }

    /* Open UART0 for debug output */
    err = g_uart0.p_api->open(g_uart0.p_ctrl, g_uart0.p_cfg);
    if (FSP_SUCCESS != err)
    {
      while (1)
      {
            ; /* UART open failed */
      }
    }

    /* Send startup message */
    uart_send_string("\r\nBMI270 Test Started\r\n");

    /* Initialize BMI270 sensor */
    int result = bmi270_init(&bmi270_dev);
    if (result != 0)
    {
      uart_send_string("ERR: BMI270 init failed\r\n");
      while (1)
      {
            ; /* BMI270 initialization failed */
      }
    }
    uart_send_string("BMI270 init OK\r\n");

    /* Configure sensor for performance mode (accel + gyro) */
    set_mode(&bmi270_dev, PERFORMANCE_MODE);
    uart_send_string("BMI270 config OK\r\n");

    /* LED type structure */
    bsp_leds_t leds = g_bsp_leds;

    /* Holds level to set for pins */
    bsp_io_level_t pin_level = BSP_IO_LEVEL_LOW;

    /* Small delay for sensors to stabilize */
    R_BSP_SoftwareDelay(200, BSP_DELAY_UNITS_MILLISECONDS);

    while (1)
    {
      /* Read raw sensor data */
      int16_t acc_x, acc_y, acc_z;
      int16_t gyr_x, gyr_y, gyr_z;

      get_acc_raw(&bmi270_dev, &acc_x, &acc_y, &acc_z);
      get_gyr_raw(&bmi270_dev, &gyr_x, &gyr_y, &gyr_z);

      /* Convert to physical units */
      /* Accelerometer: 4G range = 8192 LSB/g */
      float acc_x_g = (float)acc_x / 8192.0f;
      float acc_y_g = (float)acc_y / 8192.0f;
      float acc_z_g = (float)acc_z / 8192.0f;

      /* Gyroscope: 2000 dps = 16.4 LSB/dps */
      float gyr_x_dps = (float)gyr_x / 16.4f;
      float gyr_y_dps = (float)gyr_y / 16.4f;
      float gyr_z_dps = (float)gyr_z / 16.4f;

      /* Print sensor data via UART */
      int len = sprintf(g_uart_buffer,
            "RAW: ACC=%d,%d,%d GYRO=%d,%d,%d | "
            "ACC: X=%.2fG Y=%.2fG Z=%.2fG | "
            "GYR: X=%.1f Y=%.1f Z=%.1f deg/s\r\n",
            (int)acc_x, (int)acc_y, (int)acc_z,
            (int)gyr_x, (int)gyr_y, (int)gyr_z,
            acc_x_g, acc_y_g, acc_z_g,
            gyr_x_dps, gyr_y_dps, gyr_z_dps);
      g_uart0.p_api->write(g_uart0.p_ctrl, (uint8_t *)g_uart_buffer, (uint32_t)len);

      /* LED toggle for visual feedback */
      R_BSP_PinAccessEnable();
      for (uint32_t i = 0; i < leds.led_count; i++)
      {
            uint32_t pin = leds.p_leds;
            R_BSP_PinWrite((bsp_io_port_pin_t) pin, pin_level);
      }
      R_BSP_PinAccessDisable();

      /* Toggle LED */
      if (BSP_IO_LEVEL_LOW == pin_level)
      {
            pin_level = BSP_IO_LEVEL_HIGH;
      }
      else
      {
            pin_level = BSP_IO_LEVEL_LOW;
      }

      /* Delay 100ms */
      R_BSP_SoftwareDelay(100, BSP_DELAY_UNITS_MILLISECONDS);
    }
}
```

【测试效果】
下载到开发板后,连接BMI270,打印日志信息如下:
!(https://www.eefocus.com/forum/data/attachment/forum/202602/11/110646ubnrg22grrjkp24q.png)

接下来,就可以匹配AI的数据采集了。

页: [1]
查看完整版本: 【瑞萨AI挑战赛】RA6E2移植BMI270获取加速度