背景:
项目上需要把原先的TMC5160电机驱动器替换为购买的电机控制模块(该模块采用canopen通信)
移植canopen的前提是can通信正常,现在添加一下can通信(先用标准帧,250K bit/S的波特率测试)
原理图:
软件实现:
1.cubemx配置can通信
参考博客:https://blog.csdn.net/weixin_43362027/article/details/132716496
1)如何计算波特率?
2)中断
2.实际配置
can1的时钟在APB1上,APB1的时钟为84MHZ;
所以250k = (84/21)/8 = 4M/8
3.生成代码验证功能:
生成的代码不能直接用;
1)can_init要修改
void MX_CAN1_Init(void)
{/* USER CODE BEGIN CAN1_Init 0 *//* USER CODE END CAN1_Init 0 *//* USER CODE BEGIN CAN1_Init 1 *//* USER CODE END CAN1_Init 1 */hcan1.Instance = CAN1;hcan1.Init.Prescaler = 21;hcan1.Init.Mode = CAN_MODE_NORMAL;hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;hcan1.Init.TimeSeg1 = CAN_BS1_2TQ;hcan1.Init.TimeSeg2 = CAN_BS2_5TQ;hcan1.Init.TimeTriggeredMode = DISABLE;hcan1.Init.AutoBusOff = DISABLE;hcan1.Init.AutoWakeUp = DISABLE;hcan1.Init.AutoRetransmission = DISABLE;hcan1.Init.ReceiveFifoLocked = DISABLE;hcan1.Init.TransmitFifoPriority = DISABLE;if (HAL_CAN_Init(&hcan1) != HAL_OK){Error_Handler();}/* USER CODE BEGIN CAN1_Init 2 */CAN_FilterTypeDef sFilterConfig;sFilterConfig.FilterBank = 0;sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK;sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT;sFilterConfig.FilterIdHigh = 0x0000;sFilterConfig.FilterIdLow = 0x0000;sFilterConfig.FilterMaskIdHigh = 0x0000;sFilterConfig.FilterMaskIdLow = 0x0000;sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0;sFilterConfig.FilterActivation = CAN_FILTER_ENABLE;sFilterConfig.SlaveStartFilterBank = 14;if (HAL_CAN_ConfigFilter(&hcan1, &sFilterConfig) != HAL_OK){/* Filter configuration Error */Error_Handler();}HAL_CAN_Start(&hcan1);HAL_CAN_ActivateNotification(&hcan1,CAN_IT_RX_FIFO0_MSG_PENDING);/* USER CODE END CAN1_Init 2 */}
``
区别在于要添加这个部分:
2)实现can发送,我增加了报错信息用于调试
uint32_t pTxMailbox;
CAN_TxHeaderTypeDef TxHeader= {.RTR = CAN_RTR_DATA,.IDE = CAN_ID_STD,.StdId = 1,.TransmitGlobalTime = DISABLE,.DLC = 8,
};
void CanSendData(uint32_t id,uint8_t *data)
{//HAL_OKint ret=0;TxHeader.StdId = id;TxHeader.ExtId = id;HAL_Delay(5);HAL_CAN_AddTxMessage(&hcan1,&TxHeader,data,&pTxMailbox);if(ret == HAL_OK)HAL_UART_Transmit(&huart2, "\r\ncan send HAL_OK\r\n", strlen("\r\ncan send HAL_OK\r\n"), 100);else if(ret ==HAL_ERROR)HAL_UART_Transmit(&huart2, "\r\ncan send HAL_ERROR\r\n", strlen("\r\ncan send HAL_ERROR\r\n"), 100);else if(ret ==HAL_BUSY)HAL_UART_Transmit(&huart2, "\r\ncan send HAL_BUSY\r\n", strlen("\r\ncan send HAL_BUSY\r\n"), 100);else if(ret ==HAL_TIMEOUT)HAL_UART_Transmit(&huart2, "\r\ncan send HAL_TIMEOUT\r\n", strlen("\r\ncan send HAL_TIMEOUT\r\n"), 100);}
3)实现can接收;我实现的业务逻辑是在can接收回调函数中串口打印接收到的can包
uint8_t User_CAN_RxData[10]=0;
uint32_t User_CAN_Rx_ID = 0;
CAN_RxHeaderTypeDef RxHeader;
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)
{if(hcan->Instance==CAN1){HAL_CAN_GetRxMessage(hcan,CAN_FILTER_FIFO0,&RxHeader,User_CAN_RxData);User_CAN_Rx_ID = RxHeader.StdId;User_CAN_RxData[8] = '\r';User_CAN_RxData[9] = '\n';HAL_UART_Transmit(&huart2, User_CAN_RxData, strlen(User_CAN_RxData), 100);memset(User_CAN_RxData,0,sizeof(User_CAN_RxData));}
}
验证结果:
发送正常;
接收还没测试;