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