Correct spi chip selection

This commit is contained in:
chenfu
2023-12-23 11:09:36 +08:00
parent b052126648
commit 9dd0057563
8 changed files with 125 additions and 110 deletions

View File

@@ -137,7 +137,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
hdma_spi1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_rx.Init.Mode = DMA_NORMAL;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_rx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi1_rx.Init.FIFOMode = DMA_FIFOMODE_ENABLE;
hdma_spi1_rx.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_spi1_rx.Init.MemBurst = DMA_MBURST_SINGLE;
@@ -158,7 +158,7 @@ void HAL_SPI_MspInit(SPI_HandleTypeDef* spiHandle)
hdma_spi1_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi1_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi1_tx.Init.Mode = DMA_NORMAL;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_HIGH;
hdma_spi1_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_spi1_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi1_tx) != HAL_OK)
{

View File

@@ -50,48 +50,48 @@ BMI088Instance *bmi088_test; // 云台IMU
BMI088_Data_t bmi088_data;
void RobotCMDInit()
{
BMI088_Init_Config_s bmi088_config = {
.cali_mode = BMI088_CALIBRATE_ONLINE_MODE,
.work_mode = BMI088_BLOCK_TRIGGER_MODE,
.spi_acc_config = {
.spi_handle = &hspi1,
.GPIOx = GPIOA,
.cs_pin = GPIO_PIN_4,
.spi_work_mode = SPI_DMA_MODE,
},
.acc_int_config = {
.GPIOx = GPIOC,
.GPIO_Pin = GPIO_PIN_4,
.exti_mode = GPIO_EXTI_MODE_RISING,
},
.spi_gyro_config = {
.spi_handle = &hspi1,
.GPIOx = GPIOB,
.cs_pin = GPIO_PIN_0,
.spi_work_mode = SPI_DMA_MODE,
},
.gyro_int_config = {
.GPIO_Pin = GPIO_PIN_5,
.GPIOx = GPIOC,
.exti_mode = GPIO_EXTI_MODE_RISING,
},
.heat_pwm_config = {
.htim = &htim10,
.channel = TIM_CHANNEL_1,
.period = 1,
},
.heat_pid_config = {
.Kp = 0.5,
.Ki = 0,
.Kd = 0,
.DeadBand = 0.1,
.Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
.IntegralLimit = 100,
.MaxOut = 100,
},
};
bmi088_test = BMI088Register(&bmi088_config);
rc_data = RemoteControlInit(&huart3); // 修改为对应串口,注意如果是自研板dbus协议串口需选用添加了反相器的那个
// BMI088_Init_Config_s bmi088_config = {
// .cali_mode = BMI088_CALIBRATE_ONLINE_MODE,
// .work_mode = BMI088_BLOCK_TRIGGER_MODE,
// .spi_acc_config = {
// .spi_handle = &hspi1,
// .GPIOx = GPIOA,
// .cs_pin = GPIO_PIN_4,
// .spi_work_mode = SPI_DMA_MODE,
// },
// .acc_int_config = {
// .GPIOx = GPIOC,
// .GPIO_Pin = GPIO_PIN_4,
// .exti_mode = GPIO_EXTI_MODE_RISING,
// },
// .spi_gyro_config = {
// .spi_handle = &hspi1,
// .GPIOx = GPIOB,
// .cs_pin = GPIO_PIN_0,
// .spi_work_mode = SPI_DMA_MODE,
// },
// .gyro_int_config = {
// .GPIO_Pin = GPIO_PIN_5,
// .GPIOx = GPIOC,
// .exti_mode = GPIO_EXTI_MODE_RISING,
// },
// .heat_pwm_config = {
// .htim = &htim10,
// .channel = TIM_CHANNEL_1,
// .period = 1,
// },
// .heat_pid_config = {
// .Kp = 0.5,
// .Ki = 0,
// .Kd = 0,
// .DeadBand = 0.1,
// .Improve = PID_Trapezoid_Intergral | PID_Integral_Limit | PID_Derivative_On_Measurement,
// .IntegralLimit = 100,
// .MaxOut = 100,
// },
// };
//bmi088_test = BMI088Register(&bmi088_config);
rc_data = RemoteControlInit(&huart3); // 修改为对应串口,注意如果是自研板dbus协议串口需选用添加了反相器的那个
vision_recv_data = VisionInit(&huart1); // 视觉通信串口
gimbal_cmd_pub = PubRegister("gimbal_cmd", sizeof(Gimbal_Ctrl_Cmd_s));
@@ -319,7 +319,7 @@ static void EmergencyHandler()
/* 机器人核心控制任务,200Hz频率运行(必须高于视觉发送频率) */
void RobotCMDTask()
{
BMI088Acquire(bmi088_test,&bmi088_data) ;
// BMI088Acquire(bmi088_test,&bmi088_data) ;
// 从其他应用获取回传数据
#ifdef ONE_BOARD
SubGetMessage(chassis_feed_sub, (void *)&chassis_fetch_data);

View File

@@ -17,29 +17,7 @@ static Gimbal_Ctrl_Cmd_s gimbal_cmd_recv; // 来自cmd的控制信息
static BMI088Instance *bmi088; // 云台IMU
void GimbalInit()
{
//gimba_IMU_data = INS_Init(); // IMU先初始化,获取姿态数据指针赋给yaw电机的其他数据来源
BMI088_Init_Config_s imu_config = {
.work_mode = BMI088_BLOCK_PERIODIC_MODE,
.spi_acc_config = {
.spi_handle = &hspi1,
.GPIOx = GPIOA,
.cs_pin = GPIO_PIN_4,
.spi_work_mode = SPI_BLOCK_MODE,
},
.spi_gyro_config = {
.spi_handle = &hspi1,
.GPIOx = GPIOA,
.cs_pin = GPIO_PIN_4,
.spi_work_mode = SPI_BLOCK_MODE,
},
.heat_pwm_config = {
.htim = &htim10,
.channel = TIM_CHANNEL_1,
.period = 1,
}
};
bmi088=BMI088Register(&imu_config);
gimba_IMU_data = INS_Init(); // IMU先初始化,获取姿态数据指针赋给yaw电机的其他数据来源
// YAW
Motor_Init_Config_s yaw_config = {
.can_init_config = {

View File

@@ -31,12 +31,12 @@ void RobotInit()
#if defined(ONE_BOARD) || defined(GIMBAL_BOARD)
RobotCMDInit();
//GimbalInit();
//ShootInit();
GimbalInit();
ShootInit();
#endif
#if defined(ONE_BOARD) || defined(CHASSIS_BOARD)
//ChassisInit();
ChassisInit();
#endif
OSTaskInit(); // 创建基础任务
@@ -49,12 +49,12 @@ void RobotTask()
{
#if defined(ONE_BOARD) || defined(GIMBAL_BOARD)
RobotCMDTask();
//GimbalTask();
//ShootTask();
GimbalTask();
ShootTask();
#endif
#if defined(ONE_BOARD) || defined(CHASSIS_BOARD)
//ChassisTask();
ChassisTask();
#endif
}

View File

@@ -17,13 +17,13 @@
#include "bsp_log.h"
// osThreadId insTaskHandle;
osThreadId insTaskHandle;
osThreadId robotTaskHandle;
osThreadId motorTaskHandle;
osThreadId daemonTaskHandle;
osThreadId uiTaskHandle;
// void StartINSTASK(void const *argument);
void StartINSTASK(void const *argument);
void StartMOTORTASK(void const *argument);
void StartDAEMONTASK(void const *argument);
void StartROBOTTASK(void const *argument);
@@ -35,8 +35,8 @@ void StartUITASK(void const *argument);
*/
void OSTaskInit()
{
// osThreadDef(instask, StartINSTASK, osPriorityAboveNormal, 0, 1024);
// insTaskHandle = osThreadCreate(osThread(instask), NULL); // 由于是阻塞读取传感器,为姿态解算设置较高优先级,确保以1khz的频率执行
osThreadDef(instask, StartINSTASK, osPriorityAboveNormal, 0, 1024);
insTaskHandle = osThreadCreate(osThread(instask), NULL); // 由于是阻塞读取传感器,为姿态解算设置较高优先级,确保以1khz的频率执行
// // 后续修改为读取传感器数据准备好的中断处理,
osThreadDef(motortask, StartMOTORTASK, osPriorityNormal, 0, 256);
@@ -54,24 +54,24 @@ void OSTaskInit()
HTMotorControlInit(); // 没有注册HT电机则不会执行
}
// __attribute__((noreturn)) void StartINSTASK(void const *argument)
// {
// static float ins_start;
// static float ins_dt;
// INS_Init(); // 确保BMI088被正确初始化.
// LOGINFO("[freeRTOS] INS Task Start");
// for (;;)
// {
// // 1kHz
// ins_start = DWT_GetTimeline_ms();
// //INS_Task();
// ins_dt = DWT_GetTimeline_ms() - ins_start;
// if (ins_dt > 1)
// LOGERROR("[freeRTOS] INS Task is being DELAY! dt = [%f]", &ins_dt);
// VisionSend(); // 解算完成后发送视觉数据,但是当前的实现不太优雅,后续若添加硬件触发需要重新考虑结构的组织
// osDelay(1);
// }
// }
__attribute__((noreturn)) void StartINSTASK(void const *argument)
{
static float ins_start;
static float ins_dt;
INS_Init(); // 确保BMI088被正确初始化.
LOGINFO("[freeRTOS] INS Task Start");
for (;;)
{
// 1kHz
ins_start = DWT_GetTimeline_ms();
INS_Task();
ins_dt = DWT_GetTimeline_ms() - ins_start;
if (ins_dt > 1)
LOGERROR("[freeRTOS] INS Task is being DELAY! dt = [%f]", &ins_dt);
VisionSend(); // 解算完成后发送视觉数据,但是当前的实现不太优雅,后续若添加硬件触发需要重新考虑结构的组织
osDelay(1);
}
}
__attribute__((noreturn)) void StartMOTORTASK(void const *argument)
{

View File

@@ -4,7 +4,8 @@
/* 所有的spi instance保存于此,用于callback时判断中断来源*/
static SPIInstance *spi_instance[SPI_DEVICE_CNT] = {NULL};
static uint8_t idx = 0; // 配合中断以及初始化
static uint8_t idx = 0; // 配合中断以及初始化
uint8_t SPIDeviceOnGoing[SPI_DEVICE_CNT] = {1}; // 用于判断当前spi是否正在传输,防止多个模块同时使用一个spi总线 (0: 正在传输, 1: 未传输)
SPIInstance *SPIRegister(SPI_Init_Config_s *conf)
{
@@ -20,7 +21,19 @@ SPIInstance *SPIRegister(SPI_Init_Config_s *conf)
instance->spi_work_mode = conf->spi_work_mode;
instance->callback = conf->callback;
instance->id = conf->id;
if (instance->spi_handle->Instance == SPI1)
{
instance->cs_pin_state = &SPIDeviceOnGoing[0];
}
else if (instance->spi_handle->Instance == SPI2)
{
instance->cs_pin_state = &SPIDeviceOnGoing[1];
}
else
{
while (1)
;
}
spi_instance[idx++] = instance;
return instance;
}
@@ -78,11 +91,28 @@ void SPIRecv(SPIInstance *spi_ins, uint8_t *ptr_data, uint8_t len)
void SPITransRecv(SPIInstance *spi_ins, uint8_t *ptr_data_rx, uint8_t *ptr_data_tx, uint8_t len)
{
// 用于稍后回调使用,请保证ptr_data_rx在回调函数被调用之前仍然在作用域内,否则析构之后的行为是未定义的!!!
spi_ins->rx_size = len;
spi_ins->rx_buffer = ptr_data_rx;
// 等待上一次传输完成
if (spi_ins->spi_handle->Instance == SPI1)
{
while (!SPIDeviceOnGoing[0])
{
};
}
else if (spi_ins->spi_handle->Instance == SPI2)
{
while (!SPIDeviceOnGoing[1])
{
};
}
// 拉低片选,开始传输
HAL_GPIO_WritePin(spi_ins->GPIOx, spi_ins->cs_pin, GPIO_PIN_RESET);
*spi_ins->cs_pin_state =
spi_ins->CS_State =
HAL_GPIO_ReadPin(spi_ins->GPIOx, spi_ins->cs_pin);
switch (spi_ins->spi_work_mode)
{
case SPI_DMA_MODE:
@@ -95,6 +125,9 @@ void SPITransRecv(SPIInstance *spi_ins, uint8_t *ptr_data_rx, uint8_t *ptr_data_
HAL_SPI_TransmitReceive(spi_ins->spi_handle, ptr_data_tx, ptr_data_rx, len, 1000); // 默认50ms超时
// 阻塞模式不会调用回调函数,传输完成后直接拉高片选结束
HAL_GPIO_WritePin(spi_ins->GPIOx, spi_ins->cs_pin, GPIO_PIN_SET);
*spi_ins->cs_pin_state =
spi_ins->CS_State =
HAL_GPIO_ReadPin(spi_ins->GPIOx, spi_ins->cs_pin);
break;
default:
while (1)
@@ -130,6 +163,9 @@ void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
{
// 先拉高片选,结束传输,在判断是否有回调函数,如果有则调用回调函数
HAL_GPIO_WritePin(spi_instance[i]->GPIOx, spi_instance[i]->cs_pin, GPIO_PIN_SET);
*spi_instance[i]->cs_pin_state =
spi_instance[i]->CS_State =
HAL_GPIO_ReadPin(spi_instance[i]->GPIOx, spi_instance[i]->cs_pin);
// @todo 后续添加holdon模式,由用户自行决定何时释放片选,允许进行连续传输
if (spi_instance[i]->callback != NULL) // 回调函数不为空, 则调用回调函数
spi_instance[i]->callback(spi_instance[i]);

View File

@@ -24,7 +24,8 @@ typedef struct spi_ins_temp
SPI_TXRX_MODE_e spi_work_mode; // 传输工作模式
uint8_t rx_size; // 本次接收的数据长度
uint8_t *rx_buffer; // 本次接收的数据缓冲区
uint8_t CS_State; // 片选信号状态,用于中断模式下的片选控制
uint8_t * cs_pin_state; // 片选信号状态,用于中断模式下的片选控制
void (*callback)(struct spi_ins_temp *); // 接收回调函数
void *id; // 模块指针
} SPIInstance;

View File

@@ -4,6 +4,7 @@
#include "daemon.h"
static DaemonInstance *bmi088_daemon_instance;
// ---------------------------以下私有函数,用于读写BMI088寄存器封装,blocking--------------------------------//
/**
* @brief 读取BMI088寄存器Accel. BMI088要求在不释放CS的情况下连续读取
@@ -42,12 +43,9 @@ static void BMI088GyroRead(BMI088Instance *bmi088, uint8_t reg, uint8_t *dataptr
// 一次读取最多6个字节,加上一个dummy data ,第一个字节的第一个位是读写位,1为读,0为写,1-7bit是寄存器地址
static uint8_t tx[7] = {0x80}; // 读取,第一个字节为0x80 | reg ,之后是dummy data
static uint8_t rx[7]; // 第一个是dummy data,第三个开始是真正的数据
tx[0] = 0x80 | reg;
//SPITransRecv(bmi088->spi_gyro, rx, tx, len + 1);
do
{
SPITransRecv(bmi088->spi_gyro, rx, tx, len + 1);
}while (rx[1] == 0 && rx[2] == 128 && rx[6] == 129); //@todo我也不知道哪来的错误帧 先这样吧。。。。。
SPITransRecv(bmi088->spi_gyro, rx, tx, len + 1);
memcpy(dataptr, rx + 1, len); // @todo : memcpy有额外开销,后续可以考虑优化,在SPI中加入接口或模式,使得在一次传输结束后不释放CS,直接接着传输
}
@@ -97,7 +95,7 @@ static uint8_t BMI088_Accel_Init_Table[BMI088_WRITE_ACCEL_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},
{BMI088_GYRO_BANDWIDTH, BMI088_GYRO_1000_116_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},
@@ -224,18 +222,18 @@ static void BMI088AccINTCallback(GPIOInstance *gpio)
static void BMI088GyroINTCallback(GPIOInstance *gpio)
{
static BMI088Instance *bmi088;
static uint8_t buf[6] = {0}; // 最多读取6个byte(gyro/acc,temp是2)
bmi088 = (BMI088Instance *)(gpio->id);
bmi088->update_flag.imu_ready = 1;
bmi088->update_flag.gyro = 1;
uint8_t whoami_check = 0;
//do{BMI088GyroRead(bmi088, BMI088_GYRO_CHIP_ID, &whoami_check, 1);}while(whoami_check != BMI088_GYRO_CHIP_ID_VALUE);
BMI088GyroRead(bmi088, BMI088_GYRO_X_L, buf, 6);
for (uint8_t i = 0; i < 3; i++)
bmi088->gyro[i] = bmi088->BMI088_GYRO_SEN * (float)(int16_t)(((buf[2 * i + 1]) << 8) | buf[2 * i]);
if(bmi088->gyro[0] < -20)
{
bmi088->update_flag.temp = 1;
}
// 启动陀螺仪数据读取,并转换为实际值
// 读取完毕会调用BMI088GyroSPIFinishCallback
}
@@ -277,13 +275,15 @@ uint8_t BMI088Acquire(BMI088Instance *bmi088, BMI088_Data_t *data_store)
{
memcpy(data_store->acc,bmi088->acc,3*sizeof(float));
bmi088->update_flag.acc = 0;
bmi088->update_flag.imu_ready = 0;
}
if(bmi088->update_flag.gyro == 1)
{
memcpy(data_store->gyro,bmi088->gyro,3*sizeof(float));
bmi088->update_flag.gyro = 0;
bmi088->update_flag.imu_ready = 0;
}
bmi088->update_flag.imu_ready = 0;
return 1;
}