背景:
项目上需要把原先的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_OK
int 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));
}
}
验证结果:
发送正常;
接收还没测试;