25_R1_chassis/User/device/can_use.c
2025-05-25 20:10:14 +08:00

357 lines
12 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<E8AE84>7
将所有CAN总线上挂载的设抽象成丢<E68890>设进行配和控刄1<E58884>7
*/
/* 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) /* 电机转矩电流分辨玄1<E78E84>7 */
#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)
/* 电机朢<E69CBA>大电流绝对<E7BB9D><E5AFB9>1<EFBFBD>7 */
#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;
static CAN_RawRx_t raw_rx2;
CAN_RawTx_t raw_tx;
static CAN_t *gcan;//有什么用1<EFBC84>7
/* Private function -------------------------------------------------------- */
static void CAN_DJIMotor_Decode(CAN_MotorFeedback_t *feedback,
const uint8_t *raw) {
if (feedback == NULL || raw == NULL) return;
uint16_t raw_angle = (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_angle = raw_angle / (float)CAN_MOTOR_ENC_RES * 360.0f;
feedback->torque_current =
raw_current * CAN_GM6020_MAX_ABS_CUR / (float)CAN_MOTOR_CUR_RES;
}
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;
}
//接收四个sick板的数据
static void CAN_Sick_Receive(CAN_SickFeedback_t *feedback,const uint8_t *raw) {
if (feedback == NULL || raw == NULL) return;
feedback->sick_distance = (uint16_t)(raw[0] << 8| raw[1]);
}
//接收一个sick_mini板的数据
static void CAN_Sick_Receive_mini(CAN_SickFeedback_mini_t *feedback,const uint8_t *raw) {
if (feedback == NULL || raw == NULL) return;
feedback->sick_distance[0] = (uint16_t)(raw[0] << 8| raw[1]);
feedback->sick_distance[1] = (uint16_t)(raw[2] << 8| raw[3]);
feedback->sick_distance[2] = (uint16_t)(raw[4] << 8| raw[5]);
feedback->sick_distance[3] = (uint16_t)(raw[6] << 8| raw[7]);
}
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);
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);
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.chassis));
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.chassis));
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.chassis));
break;
default:
break;
}
return DEVICE_OK;
}
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;
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.chassis));
}
}
return DEVICE_OK;
}
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;
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);
detect_hook(CHASSIS6020M1_TOE+index);
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;
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;
//接收四个sick小板数据
// case CAN_SICK_ID1:
// case CAN_SICK_ID2:
// case CAN_SICK_ID3:
// case CAN_SICK_ID4:
// index = can_rx->rx_header.StdId - CAN_SICK_ID1;
// can->recive_flag |= 1 << (index);
// CAN_Sick_Receive(&(can->sickfed.as_array[index]), can_rx->rx_data);
// break;
//接收sick mini数据
case CAN_SICK_ID0:
CAN_Sick_Receive_mini(&(can->sicked_mini), can_rx->rx_data);
break;
default:
break;
}
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);
detect_hook(CHASSIS5065M1_TOE);
break;
case CAN_VESC5065_M2_MSG1:
CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[1]), can_rx->rx_data);
detect_hook(CHASSIS5065M2_TOE);
break;
case CAN_VESC5065_M3_MSG1:
CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[2]), can_rx->rx_data);
detect_hook(CHASSIS5065M3_TOE);
break;
case CAN_VSEC5065_M4_MSG1:
CAN_VescMotor_Decode_1(&(can->motor.chassis5065.as_array[3]), can_rx->rx_data);
detect_hook(CHASSIS5065M4_TOE);
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;
}