前期通过对dp各方面的使用和测试,已初步感受到dp的强大。那么就尝试着通过一个实际案例来验证下dp生成程序代码的易用性与可用性。
为何要选择写BMI088的驱动作为测试用例呢?首先BMI088是一款性能优异的IMU芯片。其次,也是最主要的原因,BMI088是个很坑的缝合怪芯片,就像是强行用胶水把一个加速度计和一个陀螺仪粘一块的感觉。输出速率不一样、驱动方式不一样、片选引脚不一样、ID不一样……对比ICM42688,感觉就非常古怪。之前写过它的驱动,但没搞定也不确定究竟是软件还是硬件方面有问题,然后就一直搁置了(反正有ICM42688镇场子~~~)。
所以用BMI088这个缝合怪来测试DP的能力,既有一定难度,又符合实战条件。嗯,比较合适,开始动手。
经过几轮DP问答测试,精确限定驱动代码适用的软硬件环境后,最终给出的提示词:
适用于 stm32f4系列,通过spi读写,不使用dma,但要使用bmi088的fifo机制,数据刷新速率500hz以上,输出加速度及陀螺数据。应用于无人机产品,要对滤波器进行针对性设置。代码要完整,包括头文件内容,以及完整示例程序。
贴一下首次生成的代码,很漂亮,还有贴心且准确的注释,可惜移植到PH47框架下却无法正常运行,接下来会讲述其中的bug和坑(读者可快速掠过fifo相关部分)。
/* bmi088.h */
#ifndef __BMI088_H
#define __BMI088_H
#include "stm32f4xx_hal.h"
// 寄存器地址定义
#define BMI088_ACC_CHIP_ID 0x00
#define BMI088_ACC_CONF 0x40
#define BMI088_ACC_RANGE 0x41
#define BMI088_ACC_FIFO_CONFIG 0x48
#define BMI088_GYR_CHIP_ID 0x00
#define BMI088_GYR_RANGE 0x0F
#define BMI088_GYR_BANDWIDTH 0x10
#define BMI088_FIFO_LENGTH 0x22
// 传感器配置参数
#define ACC_ODR_1000HZ 0x05
#define ACC_RANGE_24G 0x03
#define GYRO_ODR_2000HZ 0x07
#define GYRO_RANGE_2000DPS 0x00
#define GYRO_BW_532HZ 0x04
typedef struct {
SPI_HandleTypeDef *hspi;
GPIO_TypeDef *acc_cs_port;
uint16_t acc_cs_pin;
GPIO_TypeDef *gyr_cs_port;
uint16_t gyr_cs_pin;
} BMI088_HandleTypeDef;
// 函数声明
void BMI088_Init(BMI088_HandleTypeDef *hdev);
void BMI088_ReadFIFO(BMI088_HandleTypeDef *hdev, int16_t *acc, int16_t *gyro);
#endif
.c 文件
/* bmi088.c */
#include "bmi088.h"
static void SPI_WriteRegister(SPI_HandleTypeDef *hspi, GPIO_TypeDef* cs_port,
uint16_t cs_pin, uint8_t reg, uint8_t data)
{
uint8_t tx[2] = {reg & 0x7F, data};
HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(hspi, tx, 2, 100);
HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_SET);
}
static uint8_t SPI_ReadRegister(SPI_HandleTypeDef *hspi, GPIO_TypeDef* cs_port,
uint16_t cs_pin, uint8_t reg)
{
uint8_t tx = reg | 0x80;
uint8_t rx[2] = {0};
HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(hspi, &tx, rx, 2, 100);
HAL_GPIO_WritePin(cs_port, cs_pin, GPIO_PIN_SET);
return rx[1];
}
void BMI088_Init(BMI088_HandleTypeDef *hdev)
{
// 加速度计SPI模式切换(伪读操作)
SPI_ReadRegister(hdev->hspi, hdev->acc_cs_port, hdev->acc_cs_pin, 0x7E);
HAL_Delay(50);
// 加速度计配置
SPI_WriteRegister(hdev->hspi, hdev->acc_cs_port, hdev->acc_cs_pin,
BMI088_ACC_CONF, ACC_ODR_1000HZ);
SPI_WriteRegister(hdev->hspi, hdev->acc_cs_port, hdev->acc_cs_pin,
BMI088_ACC_RANGE, ACC_RANGE_24G);
SPI_WriteRegister(hdev->hspi, hdev->acc_cs_port, hdev->acc_cs_pin,
BMI088_ACC_FIFO_CONFIG, 0x01); // FIFO流模式
// 陀螺仪配置
SPI_WriteRegister(hdev->hspi, hdev->gyr_cs_port, hdev->gyr_cs_pin,
BMI088_GYR_RANGE, GYRO_RANGE_2000DPS);
SPI_WriteRegister(hdev->hspi, hdev->gyr_cs_port, hdev->gyr_cs_pin,
BMI088_GYR_BANDWIDTH, (GYRO_ODR_2000HZ << 4) | GYRO_BW_532HZ);
}
void BMI088_ReadFIFO(BMI088_HandleTypeDef *hdev, int16_t *acc, int16_t *gyro)
{
uint8_t buffer[12];
// 读取加速度计数据
uint8_t reg = BMI088_FIFO_LENGTH | 0x80;
HAL_GPIO_WritePin(hdev->acc_cs_port, hdev->acc_cs_pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(hdev->hspi, ®, 1, 100);
HAL_SPI_Receive(hdev->hspi, buffer, 6, 100); // 包含伪字节[9]
acc[0] = (buffer[1] << 8) | buffer[2];
acc[1] = (buffer[3] << 8) | buffer[4];
acc[2] = (buffer[5] << 8) | buffer[6];
HAL_GPIO_WritePin(hdev->acc_cs_port, hdev->acc_cs_pin, GPIO_PIN_SET);
// 读取陀螺仪数据
reg = 0x02 | 0x80;
HAL_GPIO_WritePin(hdev->gyr_cs_port, hdev->gyr_cs_pin, GPIO_PIN_RESET);
HAL_SPI_Transmit(hdev->hspi, ®, 1, 100);
HAL_SPI_Receive(hdev->hspi, buffer, 6, 100);
gyro[0] = (buffer[0] << 8) | buffer[1];
gy

3万+

被折叠的 条评论
为什么被折叠?



