R2_UP/User/device/can_use.c
2025-03-12 10:46:02 +08:00

401 lines
13 KiB
C
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
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;
}