R2_UP/User/device/can_use.c

401 lines
13 KiB
C
Raw Normal View History

2025-03-12 10:46:02 +08:00
/*
CAN总线上的设备1到7
CAN总线上挂载的设备抽象成单个设备进行管理和控制
*/
/* Includes ----------------------------------------------------------------- */
#include "can_use.h"
#include "user_math.h"
#include "device.h"
#include "error_detect.h"
#define CAN_MOTOR_ENC_RES (8191) /* 电机编码器分辨率 */
#define CAN_MOTOR_CUR_RES (16384)
#define CAN_GM6020_CTRL_ID_BASE (0x1ff)
#define CAN_PITCH6020_CTRL_ID (0x2ff)
#define CAN_G3508_CTRL_ALL_ID (0x200)
#define CAN_VESC_CTRL_ID_BASE (0x300)
#define CAN_MOTOR_TX_BUF_SIZE (8)
#define CAN_MOTOR_RX_BUF_SIZE (8)
/*电机最大电流绝对值*/
#define CAN_GM6020_MAX_ABS_CUR (20)
#define CAN_M3508_MAX_ABS_CUR (20)
#define CAN_M2006_MAX_ABS_CUR (10)
static CAN_RawRx_t raw_rx1;//原始的can数据
static CAN_RawRx_t raw_rx2;
CAN_RawTx_t raw_tx;
/*用于can原始数据传入消息队列*/
static CAN_t *gcan;
/* Private function -------------------------------------------------------- */
static void CAN_DJIMotor_Decode(CAN_MotorFeedback_t *feedback,
const uint8_t *raw) {
if (feedback == NULL || raw == NULL) return;
uint16_t raw_ecd = (uint16_t)((raw[0] << 8) | raw[1]);
int16_t raw_current = (int16_t)((raw[4] << 8) | raw[5]);
feedback->rotor_speed = (int16_t)((raw[2] << 8) | raw[3]);
feedback->temp = raw[6];
feedback->rotor_ecd = raw_ecd ;
feedback->torque_current =
raw_current * CAN_GM6020_MAX_ABS_CUR / (float)CAN_MOTOR_CUR_RES;
}
static void CAN_Sick_Receive(CAN_SickFeedback_t *feedback,
const uint8_t *raw) {
if (feedback == NULL || raw == NULL) return;
feedback->raw_dis[0] = (uint16_t)((raw[0] << 8) | raw[1]);
feedback->raw_dis[1] = (uint16_t)((raw[2] << 8) | raw[3]);
feedback->raw_dis[2] = (uint16_t)((raw[4] << 8) | raw[5]);
feedback->raw_dis[3]= (uint16_t)((raw[6] << 8) | raw[7]);
}
static void CAN_VescMotor_Decode_1(CAN_MotorFeedback_t *feedback,
const uint8_t *raw)
{
if (feedback == NULL || raw == NULL) return;
union
{
int x;
uint8_t data[4];
}speed;
speed.data[0]= raw[3];
speed.data[1]= raw[2];
speed.data[2]= raw[1];
speed.data[3]= raw[0];
feedback->rotor_speed = speed.x;
union
{
int16_t y;
uint8_t dat[2];
}current;
current.dat[0]= raw[5];
current.dat[1]= raw[4];
feedback->torque_current =(fp32)current.y/10;
}
static void CAN_CAN1RxFifoMsgPendingCallback(void) {
HAL_CAN_GetRxMessage(BSP_CAN_GetHandle(BSP_CAN_1), CAN_RX_FIFO0,
&raw_rx1.rx_header, raw_rx1.rx_data);
raw_rx1.hcan =BSP_CAN_GetHandle(BSP_CAN_1);
osMessageQueuePut(gcan->msgq_raw, &raw_rx1, 0, 0);
}
static void CAN_CAN2RxFifoMsgPendingCallback(void) {
HAL_CAN_GetRxMessage(BSP_CAN_GetHandle(BSP_CAN_2), CAN_RX_FIFO1,
&raw_rx2.rx_header, raw_rx2.rx_data);
raw_rx2.hcan =BSP_CAN_GetHandle(BSP_CAN_2);
osMessageQueuePut(gcan->msgq_raw, &raw_rx2, 0, 0);
}
/* Exported functions ------------------------------------------------------- */
int8_t CAN_Init(CAN_t *can, const CAN_Params_t *param) {
if (can == NULL) return DEVICE_ERR_NULL;
can->msgq_raw = osMessageQueueNew(32, sizeof(CAN_RawRx_t), NULL);
can->param = param;
CAN_FilterTypeDef can_filter = {0};
can_filter.FilterBank = 0;
can_filter.FilterIdHigh = 0;
can_filter.FilterIdLow = 0;
can_filter.FilterMode = CAN_FILTERMODE_IDMASK;
can_filter.FilterScale = CAN_FILTERSCALE_32BIT;
can_filter.FilterMaskIdHigh = 0;
can_filter.FilterMaskIdLow = 0;
can_filter.FilterActivation = ENABLE;
can_filter.SlaveStartFilterBank = 14;
can_filter.FilterFIFOAssignment = CAN_RX_FIFO0;
HAL_CAN_ConfigFilter(BSP_CAN_GetHandle(BSP_CAN_1), &can_filter);
HAL_CAN_Start(BSP_CAN_GetHandle(BSP_CAN_1));
BSP_CAN_RegisterCallback(BSP_CAN_1, HAL_CAN_RX_FIFO0_MSG_PENDING_CB,
CAN_CAN1RxFifoMsgPendingCallback);
HAL_CAN_ActivateNotification(BSP_CAN_GetHandle(BSP_CAN_1),
CAN_IT_RX_FIFO0_MSG_PENDING);
can_filter.FilterBank = 14;
can_filter.FilterFIFOAssignment = CAN_RX_FIFO1;
HAL_CAN_ConfigFilter(BSP_CAN_GetHandle(BSP_CAN_2), &can_filter);
HAL_CAN_Start(BSP_CAN_GetHandle(BSP_CAN_2));
BSP_CAN_RegisterCallback(BSP_CAN_2, HAL_CAN_RX_FIFO1_MSG_PENDING_CB,
CAN_CAN2RxFifoMsgPendingCallback);
HAL_CAN_ActivateNotification(BSP_CAN_GetHandle(BSP_CAN_2),
CAN_IT_RX_FIFO1_MSG_PENDING);
gcan = can;
return DEVICE_OK;
}
int8_t CAN_DJIMotor_Control(CAN_MotorGroup_e group, CAN_Output_t *output,
CAN_t *can) {
if (output == NULL) return DEVICE_ERR_NULL;
int16_t motor1, motor2, motor3, motor4, motor5 ;
switch (group) {
case CAN_MOTOR_CHASSIS6020:
motor1 =
(int16_t)(output->chassis6020.named.m1);
motor2 =
(int16_t)(output->chassis6020.named.m2);
motor3 =
(int16_t)(output->chassis6020.named.m3);
motor4 =
(int16_t)(output->chassis6020.named.m4);
raw_tx.tx_header.StdId = CAN_GM6020_CTRL_ID_BASE;
raw_tx.tx_header.IDE = CAN_ID_STD;
raw_tx.tx_header.RTR = CAN_RTR_DATA;
raw_tx.tx_header.DLC = CAN_MOTOR_TX_BUF_SIZE;
raw_tx.tx_data[0] = (uint8_t)((motor1 >> 8) & 0xFF);
raw_tx.tx_data[1] = (uint8_t)(motor1 & 0xFF);
raw_tx.tx_data[2] = (uint8_t)((motor2 >> 8) & 0xFF);
raw_tx.tx_data[3] = (uint8_t)(motor2 & 0xFF);
raw_tx.tx_data[4] = (uint8_t)((motor3 >> 8) & 0xFF);
raw_tx.tx_data[5] = (uint8_t)(motor3 & 0xFF);
raw_tx.tx_data[6] = (uint8_t)((motor4 >> 8) & 0xFF);
raw_tx.tx_data[7] = (uint8_t)(motor4 & 0xFF);
HAL_CAN_AddTxMessage(BSP_CAN_GetHandle(can->param->chassis6020),
&raw_tx.tx_header, raw_tx.tx_data,
&(can->mailbox.up_6020 ));
break;
case CAN_MOTOR_3508:
motor1 =
(int16_t)(output->motor3508.named.m1);
motor2 =
(int16_t)(output->motor3508.named.m2);
motor3 =
(int16_t)(output->motor3508.named.m3);
motor4 =
(int16_t)(output->motor3508.named.m4);
raw_tx.tx_header.StdId =CAN_G3508_CTRL_ALL_ID;
raw_tx.tx_header.IDE = CAN_ID_STD;
raw_tx.tx_header.RTR = CAN_RTR_DATA;
raw_tx.tx_header.DLC = CAN_MOTOR_TX_BUF_SIZE;
raw_tx.tx_data[0] = (uint8_t)((motor1 >> 8) & 0xFF);
raw_tx.tx_data[1] = (uint8_t)(motor1 & 0xFF);
raw_tx.tx_data[2] = (uint8_t)((motor2 >> 8) & 0xFF);
raw_tx.tx_data[3] = (uint8_t)(motor2 & 0xFF);
raw_tx.tx_data[4] = (uint8_t)((motor3 >> 8) & 0xFF);
raw_tx.tx_data[5] = (uint8_t)(motor3 & 0xFF);
raw_tx.tx_data[6] = (uint8_t)((motor4 >> 8) & 0xFF);
raw_tx.tx_data[7] = (uint8_t)(motor4 & 0xFF);
HAL_CAN_AddTxMessage(BSP_CAN_GetHandle(can->param->motor3508),
&raw_tx.tx_header, raw_tx.tx_data,
&(can->mailbox.up_3508 ));
break;
case CAN_MOTOR_PITCH6020:
motor5 =
(int16_t)(output->pitch6020.named.m1);
raw_tx.tx_header.StdId = CAN_PITCH6020_CTRL_ID;
raw_tx.tx_header.IDE = CAN_ID_STD;
raw_tx.tx_header.RTR = CAN_RTR_DATA;
raw_tx.tx_header.DLC = CAN_MOTOR_TX_BUF_SIZE;
raw_tx.tx_data[0] = (uint8_t)((motor5 >> 8) & 0xFF);
raw_tx.tx_data[1] = (uint8_t)(motor5 & 0xFF);
raw_tx.tx_data[2] = 0;
raw_tx.tx_data[3] = 0;
raw_tx.tx_data[4] = 0;
raw_tx.tx_data[5] = 0;
raw_tx.tx_data[6] = 0;
raw_tx.tx_data[7] = 0;
HAL_CAN_AddTxMessage(BSP_CAN_GetHandle(can->param->pitch6020),
&raw_tx.tx_header, raw_tx.tx_data,
&(can->mailbox.up_6020 ));
break;
default:
break;
}
return DEVICE_OK;
}
//用来问答接收来自sick的数据
void CAN_Sick_Control(CAN_t *can)
{
raw_tx.tx_header.StdId = 0x301;
raw_tx.tx_header.IDE = CAN_ID_STD;
raw_tx.tx_header.DLC = 0x08;
raw_tx.tx_header.RTR = CAN_RTR_DATA;//˽ߝ֡
raw_tx.tx_data[0] = 0x00;
raw_tx.tx_data[1] = 0x00;
raw_tx.tx_data[2] = 0x00;
raw_tx.tx_data[3] = 0x00;
raw_tx.tx_data[4] = 0x00;
raw_tx.tx_data[5] = 0x00;
raw_tx.tx_data[6] = 0x00;
raw_tx.tx_data[7] = 0x00;
HAL_CAN_AddTxMessage(BSP_CAN_GetHandle(can->param->sick),&raw_tx.tx_header,raw_tx.tx_data,&(can->mailbox.up_other ));
}
int8_t CAN_VESC_Control(int id,CAN_MotorGroup_e group, CAN_Output_t *output,CAN_t *can){
if (output == NULL) return DEVICE_ERR_NULL;
int Byte[4];
Vesc_ByteGet raw[4];
switch (group) {
case CAN_MOTOR_CHASSIS5065:
//将期望的四个电机输出值分别对应到四个联合体 为了下面的拆分字节
raw[0].as_array = output->chassis5065.named.m1;
raw[1].as_array = output->chassis5065.named.m2;
raw[2].as_array = output->chassis5065.named.m3;
raw[3].as_array = output->chassis5065.named.m4;
for(int i=0 ; i < 4 ; i ++)
{
if(i==2) //此处可能同时发送四个vesc导致只有三个轮子接收到数据 故加上delay
{
osDelay(1);
}
//将单个电机的期望输出值通过联合体拆分
Byte[0] = raw[i].byte.byte1;
Byte[1] = raw[i].byte.byte2;
Byte[2] = raw[i].byte.byte3;
Byte[3] = raw[i].byte.byte4;
raw_tx.tx_header.ExtId = id+i+CAN_VESC_CTRL_ID_BASE;
raw_tx.tx_header.IDE = CAN_ID_EXT;
raw_tx.tx_header.RTR = CAN_RTR_DATA;
raw_tx.tx_header.DLC = CAN_MOTOR_TX_BUF_SIZE;
raw_tx.tx_data[0] = Byte[3];
raw_tx.tx_data[1] = Byte[2];
raw_tx.tx_data[2] = Byte[1];
raw_tx.tx_data[3] = Byte[0];
raw_tx.tx_data[4] = 0;
raw_tx.tx_data[5] = 0;
raw_tx.tx_data[6] = 0;
raw_tx.tx_data[7] = 0;
HAL_CAN_AddTxMessage(BSP_CAN_GetHandle(can->param->chassis5065),
&raw_tx.tx_header, raw_tx.tx_data,
&(can->mailbox.up_5065 ));
}
}
return DEVICE_OK;
}
/**
* @brief CAN消息存储在CAN_t结构体中id冲突的进行can1和can2分类
* @param can CAN_t结构体
* @param can_rx CAN消息
* @return DEVICE_ERR_NULL can或can_rx为NULL
*/
int8_t CAN_StoreMsg(CAN_t *can, CAN_RawRx_t *can_rx) {
// 检查输入参数是否为空
if (can == NULL) return DEVICE_ERR_NULL;
if (can_rx == NULL) return DEVICE_ERR_NULL;
uint32_t index;
// 处理CAN1消息
if (can_rx->hcan == BSP_CAN_GetHandle(BSP_CAN_1)) {
switch (can_rx->rx_header.StdId) {
case CAN_G6020_AgvM1:
case CAN_G6020_AgvM2:
case CAN_G6020_AgvM3:
case CAN_G6020_AgvM4:
// 存储消息到对应的电机结构体中
index = can_rx->rx_header.StdId - CAN_G6020_AgvM1;
can->recive_flag |= 1 << (index);
CAN_DJIMotor_Decode(&(can->motor.chassis6020.as_array[index]), can_rx->rx_data);
break;
case CAN_M3508_M1_ID:
case CAN_M3508_M2_ID:
case CAN_M3508_M3_ID:
case CAN_M3508_M4_ID:
// 存储消息到对应的电机结构体中
index = can_rx->rx_header.StdId - CAN_M3508_M1_ID;
can->recive_flag |= 1 << (index);
CAN_DJIMotor_Decode(&(can->motor.motor3508.as_array[index]), can_rx->rx_data);
break;
default:
break;
}
}
// 处理CAN2消息
if (can_rx->hcan == BSP_CAN_GetHandle(BSP_CAN_2)) {
switch (can_rx->rx_header.StdId) {
case CAN_G6020_Pitch:
// 存储消息到对应的电机结构体中
index = can_rx->rx_header.StdId - CAN_G6020_Pitch;
can->recive_flag |= 1 << (index);
CAN_DJIMotor_Decode(&(can->motor.pit6020.as_array[index]), can_rx->rx_data);
break;
case CAN_SICK_ID:
// 存储消息到sickfed结构体中
CAN_Sick_Receive(&(can->sickfed), can_rx->rx_data);
break;
default:
break;
}
}
// 处理扩展ID消息
switch (can_rx->rx_header.ExtId) {
case CAN_VESC5065_M1_MSG1:
// 存储消息到对应的电机结构体中
CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[0]), can_rx->rx_data);
break;
case CAN_VESC5065_M2_MSG1:
// 存储消息到对应的电机结构体中
CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[1]), can_rx->rx_data);
break;
// case CAN_VESC5065_M3_MSG1:
// // 存储消息到对应的电机结构体中
// CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[2]), can_rx->rx_data);
// break;
// case CAN_VSEC5065_M4_MSG1:
// // 存储消息到对应的电机结构体中
// CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[3]), can_rx->rx_data);
break;
default:
break;
}
return DEVICE_OK;
}
bool_t CAN_CheckFlag(CAN_t *can, uint32_t flag) {
if (can == NULL) return false;
return (can->recive_flag & flag) == flag;
}
int8_t CAN_ClearFlag(CAN_t *can, uint32_t flag) {
if (can == NULL) return DEVICE_ERR_NULL;
can->recive_flag &= ~flag;
return DEVICE_OK;
}