stm32 常见错误之can线通信
Posted thesoch
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了stm32 常见错误之can线通信相关的知识,希望对你有一定的参考价值。
前言
经过一段时间的stm32的学习,个人总结了一些常见问题,这篇文章就主要写一下在can线上遇到的问题。
can线问题具体表现形式:
1.程序能够运行,但是不能通信,接收不到连接设备的信息,原因:硬件的问题,观察电源线、can线是否正常;软件的问题:速率问题。
2.程序不能运行,卡在了can线的初始化,原因:管脚没有配置好。
3.程序能够运行,但不能通信,接收不到信息(和第一个比较像,但这里更主要指can1能通信,can2不能):原因:can1、can2使用的缓冲区是否不同,如不同,中断使能可能没有设置好。
软件问题:
1.速率
stm32要和某种设备进行can线通信,一定要了解此设备的can线通信速率,以robomaster的通用产品为例,例如G6020、3508的can线通信速率都为1Mbps,所以要将主控板的can线速率也设置为1Mbps,否则无法正常通信,
void MX_CAN1_Init(void)
{
hcan1.Instance = CAN1;
hcan1.Init.Prescaler = 3;
hcan1.Init.Mode = CAN_MODE_NORMAL;
hcan1.Init.SyncJumpWidth = CAN_SJW_1TQ;
hcan1.Init.TimeSeg1 = CAN_BS1_10TQ;
hcan1.Init.TimeSeg2 = CAN_BS2_3TQ;
hcan1.Init.TimeTriggeredMode = DISABLE;
hcan1.Init.AutoBusOff = ENABLE;
hcan1.Init.AutoWakeUp = ENABLE;
hcan1.Init.AutoRetransmission = DISABLE;
hcan1.Init.ReceiveFifoLocked = DISABLE;
hcan1.Init.TransmitFifoPriority = ENABLE;
if (HAL_CAN_Init(&hcan1) != HAL_OK)
{
Error_Handler();
}
}
速率配置在can1、can2的初始化时进行,具体就是 hcan1.Init.Prescaler、hcan1.Init.TimeSeg1、hcan1.Init.TimeSeg2三个变量决定,例如在以上的代码中,这三个变量的设定值分别是3、10、3,此时使用的stm32f427芯片速率设置为168Mhz,APB1的速率设置为42Mhz,所以配置后的速率为42/(3*(10+3+1)) 为1Mhz(此处速率计算可参考其他文章,比较常见),满足要求。
速率配置常见问题是,如在cube中直接配置速率,则新版cube不允许出现无限循环小数,则按主板168Mhz,无法在cube中配置成1Mhz,具体如下图所示,所以只能生成代码后自己去找到void MX_CAN1_Init(void)初始化函数进行速率修改。
2.管脚
can线的管脚包括TX管脚和RX管脚,一定要配置好,否则can线初始化是无法正常通过的。
这里的方法就是找到你所使用的板子的原理图,去寻找can线的管脚是那些,这里还是要提一下cube,cube大多会自动就生成两个管脚,但请注意这里的管脚并不是完全正确的,所以最好还是去自己找管脚进行配置。
3.中断回调
can线的通信也是通过中断回调函数的,cube生成的代码可以在stm32fxxx_it.c文件中看到,例如此处就是can1的Tx中断回调和Rx0的中断回调,
void CAN1_TX_IRQHandler(void)
{
/* USER CODE BEGIN CAN1_TX_IRQn 0 */
/* USER CODE END CAN1_TX_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_TX_IRQn 1 */
/* USER CODE END CAN1_TX_IRQn 1 */
}
/**
* @brief This function handles CAN1 RX0 interrupts.
*/
void CAN1_RX0_IRQHandler(void)
{
/* USER CODE BEGIN CAN1_RX0_IRQn 0 */
/* USER CODE END CAN1_RX0_IRQn 0 */
HAL_CAN_IRQHandler(&hcan1);
/* USER CODE BEGIN CAN1_RX0_IRQn 1 */
/* USER CODE END CAN1_RX0_IRQn 1 */
}
而调用can线输出的函数为
HAL_CAN_AddTxMessage(hcanx, &TxMessage, TxData, &pTxMailbox);
can线接收的函数为
void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan);
void HAL_CAN_RxFifo1MsgPendingCallback(CAN_HandleTypeDef *hcan);
这里的两个接收函数的区别就是使用的fifo缓冲区的不同,
一般来说,我们让can1使用FIFO0区,can2使用FIFO1区,这里就出现了一个问题,中断回调中TX只有一个,而RX却是两个,一个RX0,一个为RX1,这里的0、1之差就是使用缓冲区的不同导致的,
所以要想正常使用就是 用FIFO0就使能RX0中断,用FIFO1就使能RX1中断。
总结
本文主要针对我在stm32开发过程中遇到的can线问题做出的总结,期待补充,一起进步。
以上是关于stm32 常见错误之can线通信的主要内容,如果未能解决你的问题,请参考以下文章