【瑞萨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]