背景:
項目上需要把原先的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));}
}
驗證結果:
發送正常;
接收還沒測試;