mirror of
https://gitee.com/dlmu-cone/bf_original_balance_chassis
synced 2026-07-24 03:27:45 +08:00
修改freertos时基心跳为tim14,更新引脚lable
This commit is contained in:
@@ -3,3 +3,170 @@
|
||||
#include "stdlib.h"
|
||||
#include "memory.h"
|
||||
|
||||
#define REG 0
|
||||
#define DATA 1
|
||||
#define ERROR 2
|
||||
// BMI088初始化配置数组for accel,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错)
|
||||
static uint8_t BMI088_Accel_Init_Table[BMI088_WRITE_ACCEL_REG_NUM][3] =
|
||||
{
|
||||
{BMI088_ACC_PWR_CTRL, BMI088_ACC_ENABLE_ACC_ON, BMI088_ACC_PWR_CTRL_ERROR},
|
||||
{BMI088_ACC_PWR_CONF, BMI088_ACC_PWR_ACTIVE_MODE, BMI088_ACC_PWR_CONF_ERROR},
|
||||
{BMI088_ACC_CONF, BMI088_ACC_NORMAL | BMI088_ACC_800_HZ | BMI088_ACC_CONF_MUST_Set, BMI088_ACC_CONF_ERROR},
|
||||
{BMI088_ACC_RANGE, BMI088_ACC_RANGE_6G, BMI088_ACC_RANGE_ERROR},
|
||||
{BMI088_INT1_IO_CTRL, BMI088_ACC_INT1_IO_ENABLE | BMI088_ACC_INT1_GPIO_PP | BMI088_ACC_INT1_GPIO_LOW, BMI088_INT1_IO_CTRL_ERROR},
|
||||
{BMI088_INT_MAP_DATA, BMI088_ACC_INT1_DRDY_INTERRUPT, BMI088_INT_MAP_DATA_ERROR}};
|
||||
// BMI088初始化配置数组for gyro,第一列为reg地址,第二列为写入的配置值,第三列为错误码(如果出错)
|
||||
static uint8_t BMI088_Gyro_Init_Table[BMI088_WRITE_GYRO_REG_NUM][3] =
|
||||
{
|
||||
{BMI088_GYRO_RANGE, BMI088_GYRO_2000, BMI088_GYRO_RANGE_ERROR},
|
||||
{BMI088_GYRO_BANDWIDTH, BMI088_GYRO_2000_230_HZ | BMI088_GYRO_BANDWIDTH_MUST_Set, BMI088_GYRO_BANDWIDTH_ERROR},
|
||||
{BMI088_GYRO_LPM1, BMI088_GYRO_NORMAL_MODE, BMI088_GYRO_LPM1_ERROR},
|
||||
{BMI088_GYRO_CTRL, BMI088_DRDY_ON, BMI088_GYRO_CTRL_ERROR},
|
||||
{BMI088_GYRO_INT3_INT4_IO_CONF, BMI088_GYRO_INT3_GPIO_PP | BMI088_GYRO_INT3_GPIO_LOW, BMI088_GYRO_INT3_INT4_IO_CONF_ERROR},
|
||||
{BMI088_GYRO_INT3_INT4_IO_MAP, BMI088_GYRO_DRDY_IO_INT3, BMI088_GYRO_INT3_INT4_IO_MAP_ERROR}};
|
||||
// @attention : 以上两个数组配合各自的初始化函数使用. 若要修改请参照BMI088 datasheet
|
||||
|
||||
// ---------------------------以下私有函数,用于读写BMI088寄存器--------------------------------//
|
||||
/**
|
||||
* @brief 读取BMI088寄存器Accel
|
||||
*
|
||||
* @param bmi088 待读取的BMI088实例
|
||||
* @param reg 待读取的寄存器地址
|
||||
* @param dataptr 读取到的数据存放的指针
|
||||
* @param len 读取长度
|
||||
*/
|
||||
static void BMI088AccelRead(BMI088Instance *bmi088, uint8_t reg, uint8_t *dataptr, uint8_t len)
|
||||
{
|
||||
static uint8_t tx[8] = {0x80, 0}; // 读取,第一个字节为0x80 | reg,第二个是dummy data
|
||||
tx[0] |= reg;
|
||||
SPITransRecv(bmi088->spi_acc, dataptr, tx, 2); // 第一个先发送reg地址,第二个发送dummy data
|
||||
SPIRecv(bmi088->spi_acc, dataptr, len); // 第三个开始发送数据,别担心,会覆盖掉前面的数据(2个字节)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 读取BMI088寄存器Gyro
|
||||
*
|
||||
* @param bmi088 待读取的BMI088实例
|
||||
* @param reg 待读取的寄存器地址
|
||||
* @param dataptr 读取到的数据存放的指针
|
||||
* @param len 读取长度
|
||||
*/
|
||||
static void BMI088GyroRead(BMI088Instance *bmi088, uint8_t reg, uint8_t *dataptr, uint8_t len)
|
||||
{
|
||||
static uint8_t tx = 0x80; // 读取,第一个字节为0x80 | reg
|
||||
tx |= reg;
|
||||
SPITransRecv(bmi088->spi_gyro, dataptr, &tx, 1); // 发送reg地址
|
||||
SPIRecv(bmi088->spi_gyro, dataptr, len); // 别担心,会覆盖掉前面的数据(1个字节)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写accel寄存器.对spitransmit形式上的封装
|
||||
* @attention 只会向目标reg写入一个字节,因为只有1个字节所以直接传值(指针是32位反而浪费)
|
||||
*
|
||||
* @param bmi088 待写入的BMI088实例
|
||||
* @param reg 待写入的寄存器地址
|
||||
* @param data 待写入的数据(注意不是指针)
|
||||
*/
|
||||
static void BMI088AccelWrite(BMI088Instance *bmi088, uint8_t reg, uint8_t data)
|
||||
{
|
||||
SPITransmit(bmi088->spi_acc, &data, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 写gyro寄存器.形式上的封装
|
||||
* @attention 只会向目标reg写入一个字节,因为只有1个字节所以直接传值(指针是32位反而浪费)
|
||||
*
|
||||
* @param bmi088 待写入的BMI088实例
|
||||
* @param reg 待写入的寄存器地址
|
||||
* @param data 待写入的数据(注意不是指针)
|
||||
*/
|
||||
static void BMI088GyroWrite(BMI088Instance *bmi088, uint8_t reg, uint8_t data)
|
||||
{
|
||||
SPITransmit(bmi088->spi_gyro, &data, 1);
|
||||
}
|
||||
|
||||
// -------------------------以上为私有函数,用于读写BMI088寄存器--------------------------------//
|
||||
|
||||
// -------------------------以下为私有函数,用于初始化BMI088acc和gyro--------------------------------//
|
||||
|
||||
/**
|
||||
* @brief 初始化BMI088加速度计,提高可读性分拆功能
|
||||
*
|
||||
* @param bmi088 待初始化的BMI088实例
|
||||
* @return uint8_t ERROR CODE if any problems here
|
||||
*/
|
||||
static uint8_t BMI088AccelInit(BMI088Instance *bmi088)
|
||||
{
|
||||
// 后续添加reset和通信检查
|
||||
// code to go here ...
|
||||
|
||||
// 检查ID,如果不是0x1E(bmi088 whoami寄存器值),则返回错误
|
||||
uint8_t whoami_check = 0;
|
||||
BMI088AccelRead(bmi088, BMI088_ACC_CHIP_ID, &whoami_check, 1);
|
||||
if (whoami_check != BMI088_ACC_CHIP_ID_VALUE)
|
||||
return BMI088_NO_SENSOR;
|
||||
|
||||
// 初始化寄存器,提高可读性
|
||||
uint8_t reg = 0;
|
||||
uint8_t data = 1;
|
||||
uint8_t error = 2;
|
||||
// 使用sizeof而不是magic number,这样如果修改了数组大小,不用修改这里的代码;或者使用宏定义
|
||||
for (uint8_t i = 0; i < sizeof(BMI088_Accel_Init_Table) / sizeof(BMI088_Accel_Init_Table[0]); i++)
|
||||
{
|
||||
reg = BMI088_Accel_Init_Table[i][REG];
|
||||
data = BMI088_Accel_Init_Table[i][DATA];
|
||||
BMI088AccelWrite(bmi088, reg, data); // 写入寄存器
|
||||
BMI088AccelRead(bmi088, reg, &data, 1); // 写完之后立刻读回检查
|
||||
if (data != BMI088_Accel_Init_Table[i][DATA])
|
||||
error |= BMI088_Accel_Init_Table[i][ERROR];
|
||||
//{i--;} 可以设置retry次数,如果retry次数用完了,则返回error
|
||||
}
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 初始化BMI088陀螺仪,提高可读性分拆功能
|
||||
*
|
||||
* @param bmi088 待初始化的BMI088实例
|
||||
* @return uint8_t ERROR CODE
|
||||
*/
|
||||
static uint8_t BMI088GyroInit(BMI088Instance *bmi088)
|
||||
{
|
||||
// 后续添加reset和通信检查
|
||||
// code to go here ...
|
||||
|
||||
// 检查ID,如果不是0x0F(bmi088 whoami寄存器值),则返回错误
|
||||
uint8_t whoami_check = 0;
|
||||
BMI088GyroRead(bmi088, BMI088_GYRO_CHIP_ID, &whoami_check, 1);
|
||||
if (whoami_check != BMI088_GYRO_CHIP_ID_VALUE)
|
||||
return BMI088_NO_SENSOR;
|
||||
|
||||
// 初始化寄存器,提高可读性
|
||||
uint8_t reg = 0;
|
||||
uint8_t data = 1;
|
||||
uint8_t error = 2;
|
||||
// 使用sizeof而不是magic number,这样如果修改了数组大小,不用修改这里的代码;或者使用宏定义
|
||||
for (uint8_t i = 0; i < sizeof(BMI088_Gyro_Init_Table) / sizeof(BMI088_Gyro_Init_Table[0]); i++)
|
||||
{
|
||||
reg = BMI088_Gyro_Init_Table[i][REG];
|
||||
data = BMI088_Gyro_Init_Table[i][DATA];
|
||||
BMI088GyroWrite(bmi088, reg, data); // 写入寄存器
|
||||
BMI088GyroRead(bmi088, reg, &data, 1); // 写完之后立刻读回检查
|
||||
if (data != BMI088_Gyro_Init_Table[i][DATA])
|
||||
error |= BMI088_Gyro_Init_Table[i][ERROR];
|
||||
//{i--;} 可以设置retry次数,如果retry次数用完了,则返回error
|
||||
}
|
||||
return error;
|
||||
}
|
||||
// -------------------------以上为私有函数,用于初始化BMI088acc和gyro--------------------------------//
|
||||
|
||||
// 考虑阻塞模式和非阻塞模式的兼容性,通过条件编译(则需要在编译前修改宏定义)或runtime参数判断
|
||||
// runtime的开销不大(一次性判断),但是需要修改函数原型,增加参数,代码长度增加(但不多)
|
||||
// runtime如何修改callback?根据参数选择是否给spi传入callback,如果是阻塞模式,则不传入callback,如果是非阻塞模式,则传入callback(bsp会检查是否NULL)
|
||||
// 条件编译的开销小,但是需要修改宏定义,增加编译时间,同时人力介入
|
||||
// 根据实际情况选择(说了和没说一样!)
|
||||
|
||||
BMI088Instance *BMI088Register(BMI088_Init_Config_s *config)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#ifndef __BMI088_H__
|
||||
#ifndef __BMI088_H__ // 防止重复包含
|
||||
#define __BMI088_H__
|
||||
|
||||
#include "bsp_spi.h"
|
||||
@@ -7,17 +7,30 @@
|
||||
#include "bsp_pwm.h"
|
||||
#include "stdint.h"
|
||||
|
||||
#define BMI088_PRE_CALI_ACC_X_OFFSET 0.0f
|
||||
#define BMI088_PRE_CALI_ACC_Y_OFFSET 0.0f
|
||||
// macro to go here... 预设标定参数
|
||||
|
||||
// bmi088工作模式枚举
|
||||
typedef enum
|
||||
{
|
||||
BMI088_BLOCK_PERIODIC_MODE = 0, // 阻塞模式,周期性读取
|
||||
BMI088_BLOCK_TRIGGER_MODE, // 阻塞模式,触发读取(中断)
|
||||
} BMI088_Work_Mode_e;
|
||||
|
||||
// bmi088标定方式枚举,若使用预设标定参数,注意修改预设参数
|
||||
typedef enum
|
||||
{
|
||||
BMI088_CALIBRATE_MODE = 0, // 初始化时进行标定
|
||||
BMI088_LOAD_PRE_CALI_MODE, // 使用预设标定参数
|
||||
} BMI088_Work_Mode_e;
|
||||
BMI088_LOAD_PRE_CALI_MODE, // 使用预设标定参数,
|
||||
} BMI088_Calibrate_Mode_e;
|
||||
|
||||
/* BMI088实例结构体定义 */
|
||||
typedef struct
|
||||
{
|
||||
// 传输模式和工作模式控制
|
||||
BMI088_Work_Mode_e mode;
|
||||
BMI088_Work_Mode_e work_mode;
|
||||
BMI088_Calibrate_Mode_e cali_mode;
|
||||
// SPI接口
|
||||
SPIInstance *spi_gyro; // 注意,SPIInstnace内部也有一个GPIOInstance,用于控制片选CS
|
||||
SPIInstance *spi_acc; // 注意,SPIInstnace内部也有一个GPIOInstance,用于控制片选CS
|
||||
@@ -35,6 +48,9 @@ typedef struct
|
||||
float gyro_offset[3]; // 陀螺仪零偏
|
||||
float gNorm; // 重力加速度模长,从标定获取
|
||||
float acc_coef; // 加速度计原始数据转换系数
|
||||
// 传感器灵敏度,用于计算实际值(regNdef.h中定义)
|
||||
float BMI088_ACCELL_SEN;
|
||||
float BMI088_GYRO_SEN;
|
||||
// 用于计算两次采样的时间间隔
|
||||
uint32_t bias_dwt_cnt;
|
||||
} BMI088Instance;
|
||||
@@ -46,11 +62,20 @@ typedef struct
|
||||
SPI_Init_Config_s spi_acc_config;
|
||||
GPIO_Init_Config_s gyro_int_config;
|
||||
GPIO_Init_Config_s acc_int_config;
|
||||
BMI088_Work_Mode_e mode;
|
||||
BMI088_Work_Mode_e work_mode;
|
||||
BMI088_Calibrate_Mode_e cali_mode;
|
||||
PID_Init_Config_s heat_pid_config;
|
||||
PWM_Init_Config_s heat_pwm_config;
|
||||
} BMI088_Init_Config_s;
|
||||
|
||||
|
||||
/**
|
||||
* @brief 初始化BMI088,返回BMI088实例指针
|
||||
* @note 一般一个开发板只有一个BMI088,所以这里就叫BMI088Init而不是Register
|
||||
*
|
||||
* @param config bmi088初始化配置
|
||||
* @return BMI088Instance* 实例指针
|
||||
*/
|
||||
BMI088Instance *BMI088Register(BMI088_Init_Config_s *config);
|
||||
|
||||
#endif // !__BMI088_H__
|
||||
@@ -0,0 +1,52 @@
|
||||
# BMI088
|
||||
|
||||
## 数据读写规则(so called 16-bit protocol)
|
||||
|
||||
加速度计读取read:
|
||||
1. bit 0 :1 bit 1-7: reg address
|
||||
2. dummy read,加速度计此时返回的数据无效
|
||||
3. 真正的数据从第三个字节开始.
|
||||
|
||||
通过SPI传输三个字节(分三次)
|
||||
byte1: 1(读)+7位寄存器地址
|
||||
byte2: 没用
|
||||
byte3: 读取到的数据
|
||||
|
||||
write写入:
|
||||
1. bit 0: 0 bit1-7: reg address
|
||||
2. 要写入寄存器的数据(注意没有dummy byte)
|
||||
|
||||
---
|
||||
|
||||
**注意,陀螺仪和加速度计的读取不同**
|
||||
|
||||
陀螺仪gyro读取read:
|
||||
1. bit 0 :1 bit1-7: reg address
|
||||
2. 读回的数据
|
||||
|
||||
通过SPI传输两个字节(分两次)
|
||||
byte1: 1(读)+7位寄存器地址
|
||||
byte2: 读取到的数据
|
||||
|
||||
write写入:
|
||||
1. bit0 : 0 bit1-7 : reg address
|
||||
2. 写入的数据
|
||||
|
||||
|
||||
## IT非阻塞模式下BMI088读取流程
|
||||
|
||||
数据准备完成标志位:`uint8_t BMI088_READY_FLAG` 总共8个位 也可以用位域可读性更高
|
||||
|
||||
1. 当accel int中断发生,开启DMA SPI传输,完成后将acc ready置位
|
||||
2. 当gyro int中断发生,开启DMA SPI传输,完成后将gyro ready置位
|
||||
3. 当温度数据中断发生,开启DMA传输,完成后将温度标志位置位
|
||||
|
||||
> 由于DMA传输非阻塞,启动传输后只有到传输完成时才会拉高片选结束SPI transfer,因此需要在callback中加入标志位置位的操作.
|
||||
这可以通过条件编译完成.
|
||||
|
||||
温度数据不需要和accel和gyro同步,它不参与姿态解算,可以不用管.
|
||||
|
||||
当加速度数据和陀螺仪数据都准备完成之后,唤醒姿态解算任务INs_taSk,进行一次解算.唤醒可以通过软件开启EXTI中断,在中断中调用实时系统的vTaskNotifyFromISR()完成,也可以将任务ready标志位置位,当运行到对应位置时检查标志位判断是否要进行任务.时间间隔不是大问题,inS_TAsK中有dwt用于计算两次任务执行的间隔,它将会自动处理好bias的大小
|
||||
`__HAL_GPIO_EXTI_GENERATE_SWIT()` `HAL_EXTI_GENERATE_SWI()`
|
||||
|
||||
of course,两者的数据更新实际上可以异步进行,这里为了方便起见当两者数据都准备好以后再行融合
|
||||
|
||||
@@ -209,7 +209,7 @@
|
||||
#define BMI088_GYRO_125_SEN 0.000066579027251980956150958662738366f
|
||||
|
||||
/* BMI088错误码枚举 */
|
||||
enum
|
||||
typedef enum
|
||||
{
|
||||
BMI088_NO_ERROR = 0x00,
|
||||
BMI088_ACC_PWR_CTRL_ERROR = 0x01,
|
||||
@@ -229,6 +229,6 @@ enum
|
||||
BMI088_SELF_TEST_ACCEL_ERROR = 0x80,
|
||||
BMI088_SELF_TEST_GYRO_ERROR = 0x40,
|
||||
BMI088_NO_SENSOR = 0xFF,
|
||||
};
|
||||
} BMI088_ERORR_CODE_e;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -69,7 +69,7 @@ static void BMI088_read_muli_reg(uint8_t reg, uint8_t *buf, uint8_t len);
|
||||
#elif defined(BMI088_USE_IIC)
|
||||
#endif
|
||||
|
||||
static uint8_t write_BMI088_accel_reg_data_error[BMI088_WRITE_ACCEL_REG_NUM][3] =
|
||||
static uint8_t BMI088_Accel_Init_Table[BMI088_WRITE_ACCEL_REG_NUM][3] =
|
||||
{
|
||||
{BMI088_ACC_PWR_CTRL, BMI088_ACC_ENABLE_ACC_ON, BMI088_ACC_PWR_CTRL_ERROR},
|
||||
{BMI088_ACC_PWR_CONF, BMI088_ACC_PWR_ACTIVE_MODE, BMI088_ACC_PWR_CONF_ERROR},
|
||||
@@ -80,7 +80,7 @@ static uint8_t write_BMI088_accel_reg_data_error[BMI088_WRITE_ACCEL_REG_NUM][3]
|
||||
|
||||
};
|
||||
|
||||
static uint8_t write_BMI088_gyro_reg_data_error[BMI088_WRITE_GYRO_REG_NUM][3] =
|
||||
static uint8_t BMI088_Gyro_Init_Table[BMI088_WRITE_GYRO_REG_NUM][3] =
|
||||
{
|
||||
{BMI088_GYRO_RANGE, BMI088_GYRO_2000, BMI088_GYRO_RANGE_ERROR},
|
||||
{BMI088_GYRO_BANDWIDTH, BMI088_GYRO_2000_230_HZ | BMI088_GYRO_BANDWIDTH_MUST_Set, BMI088_GYRO_BANDWIDTH_ERROR},
|
||||
@@ -235,19 +235,18 @@ uint8_t bmi088_accel_init(void)
|
||||
{
|
||||
// check commiunication
|
||||
BMI088_accel_read_single_reg(BMI088_ACC_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
BMI088_accel_read_single_reg(BMI088_ACC_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
|
||||
DWT_Delay(0.001);
|
||||
// accel software reset
|
||||
BMI088_accel_write_single_reg(BMI088_ACC_SOFTRESET, BMI088_ACC_SOFTRESET_VALUE);
|
||||
HAL_Delay(BMI088_LONG_DELAY_TIME);
|
||||
|
||||
// HAL_Delay(BMI088_LONG_DELAY_TIME);
|
||||
DWT_Delay(0.08);
|
||||
// check commiunication is normal after reset
|
||||
BMI088_accel_read_single_reg(BMI088_ACC_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
BMI088_accel_read_single_reg(BMI088_ACC_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
// check the "who am I"
|
||||
if (res != BMI088_ACC_CHIP_ID_VALUE)
|
||||
@@ -257,17 +256,17 @@ uint8_t bmi088_accel_init(void)
|
||||
for (write_reg_num = 0; write_reg_num < BMI088_WRITE_ACCEL_REG_NUM; write_reg_num++)
|
||||
{
|
||||
|
||||
BMI088_accel_write_single_reg(write_BMI088_accel_reg_data_error[write_reg_num][0], write_BMI088_accel_reg_data_error[write_reg_num][1]);
|
||||
HAL_Delay(1);
|
||||
BMI088_accel_write_single_reg(BMI088_Accel_Init_Table[write_reg_num][0], BMI088_Accel_Init_Table[write_reg_num][1]);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
BMI088_accel_read_single_reg(write_BMI088_accel_reg_data_error[write_reg_num][0], res);
|
||||
HAL_Delay(1);
|
||||
BMI088_accel_read_single_reg(BMI088_Accel_Init_Table[write_reg_num][0], res);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
if (res != write_BMI088_accel_reg_data_error[write_reg_num][1])
|
||||
if (res != BMI088_Accel_Init_Table[write_reg_num][1])
|
||||
{
|
||||
// write_reg_num--;
|
||||
// return write_BMI088_accel_reg_data_error[write_reg_num][2];
|
||||
error |= write_BMI088_accel_reg_data_error[write_reg_num][2];
|
||||
// return BMI088_Accel_Init_Table[write_reg_num][2];
|
||||
error |= BMI088_Accel_Init_Table[write_reg_num][2];
|
||||
}
|
||||
}
|
||||
return BMI088_NO_ERROR;
|
||||
@@ -277,18 +276,19 @@ uint8_t bmi088_gyro_init(void)
|
||||
{
|
||||
// check commiunication
|
||||
BMI088_gyro_read_single_reg(BMI088_GYRO_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
BMI088_gyro_read_single_reg(BMI088_GYRO_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
// reset the gyro sensor
|
||||
BMI088_gyro_write_single_reg(BMI088_GYRO_SOFTRESET, BMI088_GYRO_SOFTRESET_VALUE);
|
||||
HAL_Delay(BMI088_LONG_DELAY_TIME);
|
||||
// HAL_Delay(BMI088_LONG_DELAY_TIME);
|
||||
DWT_Delay(0.08);
|
||||
// check commiunication is normal after reset
|
||||
BMI088_gyro_read_single_reg(BMI088_GYRO_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
BMI088_gyro_read_single_reg(BMI088_GYRO_CHIP_ID, res);
|
||||
HAL_Delay(1);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
// check the "who am I"
|
||||
if (res != BMI088_GYRO_CHIP_ID_VALUE)
|
||||
@@ -298,17 +298,17 @@ uint8_t bmi088_gyro_init(void)
|
||||
for (write_reg_num = 0; write_reg_num < BMI088_WRITE_GYRO_REG_NUM; write_reg_num++)
|
||||
{
|
||||
|
||||
BMI088_gyro_write_single_reg(write_BMI088_gyro_reg_data_error[write_reg_num][0], write_BMI088_gyro_reg_data_error[write_reg_num][1]);
|
||||
HAL_Delay(1);
|
||||
BMI088_gyro_write_single_reg(BMI088_Gyro_Init_Table[write_reg_num][0], BMI088_Gyro_Init_Table[write_reg_num][1]);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
BMI088_gyro_read_single_reg(write_BMI088_gyro_reg_data_error[write_reg_num][0], res);
|
||||
HAL_Delay(1);
|
||||
BMI088_gyro_read_single_reg(BMI088_Gyro_Init_Table[write_reg_num][0], res);
|
||||
DWT_Delay(0.001);
|
||||
|
||||
if (res != write_BMI088_gyro_reg_data_error[write_reg_num][1])
|
||||
if (res != BMI088_Gyro_Init_Table[write_reg_num][1])
|
||||
{
|
||||
write_reg_num--;
|
||||
// return write_BMI088_gyro_reg_data_error[write_reg_num][2];
|
||||
error |= write_BMI088_accel_reg_data_error[write_reg_num][2];
|
||||
// return BMI088_Gyro_Init_Table[write_reg_num][2];
|
||||
error |= BMI088_Accel_Init_Table[write_reg_num][2];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -3,16 +3,18 @@
|
||||
#include "memory.h"
|
||||
#include "stdlib.h"
|
||||
|
||||
static IST8310Instance *ist8310_instance = NULL;
|
||||
// 一般这个模块只有一个实例,所以直接保存在这里,实际上不保存也可以,application可以自己保存
|
||||
static IST8310Instance *ist8310_instance = NULL; // 用于存储IST8310实例的指针
|
||||
|
||||
#define IST8310_WRITE_REG_NUM 4 // 方便阅读
|
||||
#define IST8310_DATA_REG 0x03 // ist8310的数据寄存器
|
||||
#define IST8310_WHO_AM_I 0x00 // ist8310 id 寄存器值
|
||||
#define IST8310_WHO_AM_I_VALUE 0x10 // 用于检测是否连接成功,读取ist8310的whoami会返回该值
|
||||
|
||||
// -------------------初始化写入数组,只使用一次,详见datasheet-------------------------
|
||||
// the first column:the registers of IST8310. 第一列:IST8310的寄存器
|
||||
// the second column: the value to be writed to the registers.第二列:需要写入的寄存器值
|
||||
// the third column: return error value.第三列:返回的错误码
|
||||
#define IST8310_WRITE_REG_NUM 4
|
||||
#define IST8310_DATA_REG 0x03 // 数据寄存器
|
||||
#define IST8310_WHO_AM_I 0x00 // ist8310 id 寄存器值
|
||||
#define IST8310_WHO_AM_I_VALUE 0x10 // ist8310 id 寄存器值,用于检测是否连接成功
|
||||
static uint8_t ist8310_write_reg_data_error[IST8310_WRITE_REG_NUM][3] = {
|
||||
{0x0B, 0x08, 0x01}, // enalbe interrupt and low pin polarity.开启中断,并且设置低电平
|
||||
{0x41, 0x09, 0x02}, // average 2 times.平均采样两次
|
||||
@@ -27,64 +29,72 @@ static uint8_t ist8310_write_reg_data_error[IST8310_WRITE_REG_NUM][3] = {
|
||||
*/
|
||||
static void IST8310Decode(IICInstance *iic)
|
||||
{
|
||||
static int16_t temp[3];
|
||||
static IST8310Instance *ist;
|
||||
ist = (IST8310Instance *)(iic->id);
|
||||
static int16_t temp[3]; // 用于存储解码后的数据
|
||||
static IST8310Instance *ist; // 用于存储IST8310实例的指针
|
||||
ist = (IST8310Instance *)(iic->id); // iic的id保存了IST8310实例的指针(父指针)
|
||||
|
||||
memcpy(temp, ist->iic_buffer, 6 * sizeof(uint8_t));
|
||||
memcpy(temp, ist->iic_buffer, 6 * sizeof(uint8_t)); // 不要强制转换,直接cpy
|
||||
for (uint8_t i = 0; i < 3; i++)
|
||||
ist->mag[i] = (float)temp[i] * MAG_SEN;
|
||||
ist->mag[i] = (float)temp[i] * MAG_SEN; // 乘以灵敏度转换成uT(微特斯拉)
|
||||
}
|
||||
|
||||
// EXTI中断回调函数,说明DRDY拉低.主机启动传输并在结束后调用IST8310Decode进行数据解析
|
||||
// 注意IICAccessMem是阻塞的
|
||||
/**
|
||||
* @brief EXTI中断回调函数,说明DRDY拉低.主机启动传输并在结束后调用IST8310Decode进行数据解析
|
||||
* @note 注意IICAccessMem是阻塞的
|
||||
*
|
||||
* @param gpio 发生中断的GPIO实例
|
||||
*/
|
||||
static void IST8310StartTransfer(GPIOInstance *gpio)
|
||||
{
|
||||
// 先获取IST8310实例的指针(通过gpio实例的父指针id)
|
||||
IST8310Instance *ist_for_transfer = (IST8310Instance *)gpio->id;
|
||||
// 中断说明ist已经准备好读取数据寄存器;6个字节,读取后会进入IST8310Decode函数
|
||||
IICAccessMem(ist_for_transfer->iic, IST8310_DATA_REG, ist_for_transfer->iic_buffer, 6, IIC_READ_MEM);
|
||||
// 传输完成后会进入IST8310Decode函数进行数据解析
|
||||
IST8310Decode(ist_for_transfer->iic);
|
||||
}
|
||||
|
||||
IST8310Instance *IST8310Init(IST8310_Init_Config_s *config)
|
||||
{
|
||||
static const uint8_t sleepTime = 50;
|
||||
uint8_t check_who_i_am = 0;
|
||||
static const uint8_t sleepTime = 50; // 50ms,ist8310的复位时间
|
||||
uint8_t check_who_i_am = 0; // 用于检测ist8310是否连接成功
|
||||
// 这个变量只会用到一次,出了这个函数就没用了,所以不用分配空间,直接定义在栈上(因为多看一眼就会爆炸)
|
||||
|
||||
// 分配空间,清除flash
|
||||
// 分配空间,清除flash防止已经填充的垃圾值
|
||||
IST8310Instance *ist = (IST8310Instance *)malloc(sizeof(IST8310Instance));
|
||||
memset(ist, 0, sizeof(IST8310Instance));
|
||||
|
||||
// c语言赋值从右到左
|
||||
// c语言赋值从右到左,全部指向同一个地址(这些bspinstnace的父节点都是ist,即ist拥有这些instances)
|
||||
config->iic_config.id = config->gpio_conf_exti.id = config->gpio_conf_rst.id = ist;
|
||||
// 传入回调函数
|
||||
config->iic_config.callback = IST8310Decode;
|
||||
config->gpio_conf_exti.gpio_model_callback = IST8310StartTransfer;
|
||||
// 注册两个GPIO和IIC
|
||||
// 分别注册两个GPIO和IIC
|
||||
ist->iic = IICRegister(&config->iic_config);
|
||||
ist->gpio_exti = GPIORegister(&config->gpio_conf_exti);
|
||||
ist->gpio_rst = GPIORegister(&config->gpio_conf_rst);
|
||||
|
||||
// 重置IST8310,需要HAL_Delay等待完成Reset
|
||||
// 重置IST8310,需要HAL_Delay()等待传感器完成Reset
|
||||
GPIOReset(ist->gpio_rst);
|
||||
HAL_Delay(sleepTime);
|
||||
GPIOSet(ist->gpio_rst);
|
||||
HAL_Delay(sleepTime);
|
||||
|
||||
// 读取IST8310的ID,如果不是0x10,则返回错误
|
||||
// 读取IST8310的ID,如果不是0x10(whoami macro的值),则返回错误
|
||||
IICAccessMem(ist->iic, IST8310_WHO_AM_I, &check_who_i_am, 1, IIC_READ_MEM);
|
||||
if (check_who_i_am != IST8310_WHO_AM_I_VALUE)
|
||||
return NULL; // while(1)
|
||||
|
||||
// 进行初始化配置写入并检查是否写入成功
|
||||
// 进行初始化配置写入并检查是否写入成功,这里用循环把最上面初始化数组的东西都写进去
|
||||
for (uint8_t i = 0; i < IST8310_WRITE_REG_NUM; i++)
|
||||
{ // 写入配置
|
||||
{ // 写入配置,写一句就读一下看看ist8310是否仍然在线
|
||||
IICAccessMem(ist->iic, ist8310_write_reg_data_error[i][0], &ist8310_write_reg_data_error[i][1], 1, IIC_WRITE_MEM);
|
||||
IICAccessMem(ist->iic, ist8310_write_reg_data_error[i][0], &check_who_i_am, 1, IIC_READ_MEM); // 读回自身id
|
||||
if (check_who_i_am != ist8310_write_reg_data_error[i][1])
|
||||
while (1)
|
||||
ist8310_write_reg_data_error[i][2]; // 掉线/写入失败/未知错误,返回对应的错误码
|
||||
ist8310_write_reg_data_error[i][2]; // 掉线/写入失败/未知错误,会返回对应的错误码
|
||||
}
|
||||
|
||||
ist8310_instance = ist;
|
||||
ist8310_instance = ist; // 保存ist8310实例的指针
|
||||
return ist;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#pragma once
|
||||
#pragma once // 防止头文件重复包含,也可以用header guard
|
||||
|
||||
#include "bsp_iic.h"
|
||||
#include "bsp_gpio.h"
|
||||
@@ -14,15 +14,16 @@
|
||||
|
||||
/**
|
||||
* @brief IST8310 实例定义
|
||||
* @attention 配置GPIO Pin的时候注意使用GPIO_PIN_x(1,2,3,...,这是一个宏),而不是1,2,3的整形!
|
||||
*
|
||||
*/
|
||||
typedef struct tempist8310
|
||||
{
|
||||
IICInstance *iic; // iic实例
|
||||
GPIOInstance* gpio_rst; // gpio实例,用于复位
|
||||
GPIOInstance* gpio_exti; // gpio实例,用于获取MAG_DRDY引脚状态,判断数据是否准备好(EXTI外部中断)
|
||||
uint8_t iic_buffer[8]; // iic接收缓冲区
|
||||
float mag[3]; // 三轴磁力计数据,[x,y,z]
|
||||
IICInstance *iic; // iic实例
|
||||
GPIOInstance *gpio_rst; // gpio实例,用于复位
|
||||
GPIOInstance *gpio_exti; // gpio实例,用于获取MAG_DRDY引脚状态,判断数据是否准备好(EXTI外部中断)
|
||||
uint8_t iic_buffer[8]; // iic接收缓冲区
|
||||
float mag[3]; // 三轴磁力计数据,[x,y,z]
|
||||
|
||||
void (*ist_module_callback)(IICInstance *); // 模块回调函数
|
||||
// 后续有需要再添加
|
||||
@@ -31,22 +32,19 @@ typedef struct tempist8310
|
||||
|
||||
/**
|
||||
* @brief IST8310 初始化配置结构体
|
||||
* @attention 配置GPIO Pin的时候注意使用GPIO_PIN_x(1,2,3,...,这是一个宏),而不是1,2,3的整形!
|
||||
*
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
IIC_Init_Config_s iic_config; // iic初始化配置
|
||||
GPIO_Init_Config_s gpio_conf_rst; // gpio初始化配置,用于复位
|
||||
IIC_Init_Config_s iic_config; // iic初始化配置
|
||||
GPIO_Init_Config_s gpio_conf_rst; // gpio初始化配置,用于复位ist8310,看数据手册
|
||||
GPIO_Init_Config_s gpio_conf_exti; // gpio初始化配置,用于获取MAG_DRDY引脚状态,判断数据是否准备好(EXTI外部中断)
|
||||
} IST8310_Init_Config_s;
|
||||
|
||||
/**
|
||||
* @brief IST8310 初始化.
|
||||
* @note 一条i2c总线只能挂载一个IST8310
|
||||
* @note 注意一条i2c总线只能挂载一个IST8310,他们的地址是固定的,不能改变.
|
||||
*
|
||||
*/
|
||||
IST8310Instance *IST8310Init(IST8310_Init_Config_s *config);
|
||||
|
||||
void rest(int aa);
|
||||
|
||||
int nit(int bb);
|
||||
|
||||
Reference in New Issue
Block a user