STM32F429I-DISC1【读取板载运动传感器数据】
一、硬件介绍
本次开发使用的是STM32F429I-DISC1开发板,是基于STM32F429ZIT6U的MCU,具有Arm Cortex-M4内核,配备2.4英寸QVGA TFT LCD、64-Mbit SDRAM、ST-MEMS陀螺仪(I3G4250D)等。
陀螺仪MEMS(ST-MEMS I3G4250D)
I3G4250D 是一款低功耗、三轴角速率传感器;I3G4250D 具有 ±245 / ±500 / ±2000 dps 的满量程,并且能够以用户可选择的带宽测量速率。
STM32F429ZIT6 通过SPI_5接口控制此运动传感器。
主要特性:
输出类型 | I2C / SPI |
---|---|
特性 | 可调带宽,可选量程,温度传感器 |
封装/外壳 | 16-TFLGA |
工作温度 | -40°C ~ 85°C(TA) |
轴 | X(俯仰),Y(偏转),Z(横滚) |
电流-供电 | 6.1mA |
范围°/s | ±245,500,2000 |
灵敏度(mV/°/s) | - |
带宽 | - |
电压-供电 | 2.4V ~ 3.6V |
灵敏度(LSB/(°/s)) | 8.75 ~ 70 |
类型 | 数字 |
数据 | • 16-bit 原始数据 • 8-bit 温度数据 |
SPI通讯时序图:
I2C通讯时序图:
FIFO / Bypass mode模式:
原理图:
若要选择 SPI 接口,CS线必须低电平。
INT2:数据就绪 / FIFO中断
INT1:可编程中断
CS:SPI / I2C模式选择
0: SPI
1: I2C
传感器 -> MCU硬件连接:
SPI5_SCK -> PF7
SPI5_MISO -> PF8
SPI5_MOSI -> PF9
MEMS_CS -> PC1
MEMS_INT2 -> PA2 (可配置)
MEMS_INT1 -> PA1 (可配置)
二、功能实现思想
实现效果:读取运动传感器的数据,并通过串口将数据显示出来;
1、配置I3G4250D传感器,将其通过SPI与STM32F429ZIT6U进行通讯,用于获取传感器数据;
2、配置串口功能,用于将获取到的传感器相关数据输出;
3、移动开发板时,传感器所获取数据发生变化,将数据通过串口打印出来;
三、功能实现步骤
功能配置
在Task_1.ioc的基础上,进行如下的相关配置;
1、配置I3G4250D传感器相关功能;
未配置INT1 / INT2引脚(若有需要可自行配置)
2、配置串口相关功能;
代码编写
1、创建 I3G4250D文件夹,存储ST相关的I3G4250D传感器的驱动函数;
git clone --recursive https://github.com/STMicroelectronics/STMems_Standard_C_drivers
✔在轮询模式下读取陀螺仪传感器数据:i3g4250d_read_data_polling.c
从 FIFO 读取陀螺仪传感器数据:i3g4250d_fifo_read.c
从睡眠事件中唤醒:i3g4250d_wakeup.c
2、打开i3g4250d_read_data_polling.c
在此基础上,重新编写定义相关的接口函数;
-
取消
#define STEVAL_MKI109V3
注释,以STEVAL_MKI109V3E_Demo的基础上进行相关修改; -
修改
#if defined(STEVAL_MKI109V3)
下的相关宏定义;#if defined(STEVAL_MKI109V3) /* MKI109V3: Define communication interface */ #define SENSOR_BUS hspi5 #define CS_up_GPIO_Port MEMS_CS_GPIO_Port #define CS_up_Pin MEMS_CS_Pin /* MKI109V3: Vdd and Vddio power supply values */ //#define PWM_3V3 915
-
重新编写以下函数接口
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len);
Write:0x40
Bit 0: WRITE bit. The value is 0.
Bit 1: MS bit. When 0, does not increment address; when 1, increments address in multiple writes.
static int32_t platform_write(void *handle, uint8_t reg, const uint8_t *bufp,uint16_t len)
{
#if defined(NUCLEO_F411RE)HAL_I2C_Mem_Write(handle, I3G4250D_I2C_ADD_L, reg,I2C_MEMADD_SIZE_8BIT, (uint8_t*) bufp, len, 1000);
#elif defined(STEVAL_MKI109V3)reg |= 0x40;HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Transmit(handle, (uint8_t*) bufp, len, 1000);HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_SET);
#elif defined(SPC584B_DIS)i2c_lld_write(handle, I3G4250D_I2C_ADD_L & 0xFE, reg, (uint8_t*) bufp, len);
#endifreturn 0;
}
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len);
Read:0xC0
Bit 0: READ bit. The value is 1.
Bit 1: MS bit. When 0, does not increment address; when 1, increments address in multiple reads.
static int32_t platform_read(void *handle, uint8_t reg, uint8_t *bufp,uint16_t len)
{
#if defined(NUCLEO_F411RE)HAL_I2C_Mem_Read(handle, I3G4250D_I2C_ADD_L, reg,I2C_MEMADD_SIZE_8BIT, bufp, len, 1000);
#elif defined(STEVAL_MKI109V3)reg |= 0xC0; HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_RESET);HAL_SPI_Transmit(handle, ®, 1, 1000);HAL_SPI_Receive(handle, bufp, len, 1000);HAL_GPIO_WritePin(CS_up_GPIO_Port, CS_up_Pin, GPIO_PIN_SET);
#elif defined(SPC584B_DIS)i2c_lld_read(handle, I3G4250D_I2C_ADD_L & 0xFE, reg, bufp, len);
#endifreturn 0;
}
static void platform_delay(uint32_t ms);
static void platform_delay(uint32_t ms)
{
#if defined(NUCLEO_F411RE) | defined(STEVAL_MKI109V3)HAL_Delay(ms);
#elif defined(SPC584B_DIS)osalThreadDelayMilliseconds(ms);
#endif
}
static void platform_init(void);
static void platform_init(void)
{
#if defined(STEVAL_MKI109V3)
// TIM3->CCR1 = PWM_3V3;
// TIM3->CCR2 = PWM_3V3;
// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_1);
// HAL_TIM_PWM_Start(&htim3, TIM_CHANNEL_2);HAL_Delay(1000);
#endif
}
Demo示例:获取温度 / X、Y、Z轴dps;
陀螺仪检测的温度会受自身芯片发热的影响,严格来说它测量的是自身芯片的温度,所以用它来测量气温是不太准确的
static int16_t temp_raw;
static float Temp; /* Main Example --------------------------------------------------------------*/
void i3g4250d_read_data_polling(void)
{stmdev_ctx_t dev_ctx;/* Uncomment to use interrupts on drdy *///i3g4250d_int2_route_t int2_reg;/* Initialize mems driver interface */dev_ctx.write_reg = platform_write;dev_ctx.read_reg = platform_read;dev_ctx.handle = &SENSOR_BUS;/* Initialize platform specific hardware */platform_init();/* Wait sensor boot time */platform_delay(BOOT_TIME);/* Check device ID */i3g4250d_device_id_get(&dev_ctx, &whoamI);if (whoamI != I3G4250D_ID)//while (1); /*manage here device not found */printf("Mems_Init_Error\r\n");/* Configure filtering chain - Gyroscope - High Pass */i3g4250d_filter_path_set(&dev_ctx, I3G4250D_LPF1_HP_ON_OUT);i3g4250d_hp_bandwidth_set(&dev_ctx, I3G4250D_HP_LEVEL_3);/* Uncomment to use interrupts on drdy *///i3g4250d_pin_int2_route_get(&dev_ctx, &int2_reg);//int2_reg.i2_drdy = PROPERTY_ENABLE;//i3g4250d_pin_int2_route_set(&dev_ctx, int2_reg);/* Set Output Data Rate */i3g4250d_data_rate_set(&dev_ctx, I3G4250D_ODR_100Hz); //10ms/* Read samples in polling mode (no int) */while (1) {uint8_t reg;/* Read output only if new value is available */i3g4250d_flag_data_ready_get(&dev_ctx, ®);i3g4250d_temperature_raw_get(&dev_ctx,&temp_raw); Temp = i3g4250d_from_lsb_to_celsius(temp_raw); if (reg) {/* Read angular rate data */memset(data_raw_angular_rate, 0x00, 3 * sizeof(int16_t));i3g4250d_angular_rate_raw_get(&dev_ctx, data_raw_angular_rate);angular_rate_mdps[0] = i3g4250d_from_fs245dps_to_mdps(data_raw_angular_rate[0]) / 1000.0f;angular_rate_mdps[1] = i3g4250d_from_fs245dps_to_mdps(data_raw_angular_rate[1]) / 1000.0f;angular_rate_mdps[2] = i3g4250d_from_fs245dps_to_mdps(data_raw_angular_rate[2]) / 1000.0f;printf("X = %4.2f Y = %4.2f Z = %4.2f\r\n",angular_rate_mdps[0],angular_rate_mdps[1],angular_rate_mdps[2]);printf("Temp = %f\r\n",Temp);}HAL_Delay(300);}
}
main.c:int main(void)
{.../* USER CODE BEGIN 2 */i3g4250d_read_data_polling();/* USER CODE END 2 *//* Infinite loop *//* USER CODE BEGIN WHILE */while (1){}/* USER CODE END 3 */
}