一、硬件介绍
本次开发使用的是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接口控制此运动传感器。
主要特性:
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);
#endif
return 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);
#endif
return 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 */
}
四、实现现象
————————————————
版权声明:本文为CSDN博主「今日待办」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_44929802/article/details/151937078
|
|