STM32CAN总线发送接收异常的问题解决方案及相关知识详解
目录
一、外部CAN总线断线或异常时如何监控
在STM32中监控外部CAN断线或异常时,可以通过以下几种方法实现:
-
自动离线管理(ABOM):STM32的CAN外设支持自动离线管理功能,当节点检测到它发送错误或接收错误超过一定值时,会自动进入离线状态(Bus-Off)。在这种状态下,CAN不能接收或发送报文。可以通过配置CAN的MCU寄存器来启用这个功能,例如在STM32CubeMX中配置或者直接在代码中设置CAN_MCR寄存器的ABOM位。
-
错误中断:STM32的CAN外设提供了错误中断功能,可以在CAN控制器检测到错误时产生中断。这包括发送错误、接收错误、警告状态等。通过使能CAN的错误中断(CAN_IT_ERROR),可以在CAN控制器进入Bus-Off状态时得到通知,并在中断服务函数中进行相应的处理。
-
Bus-Off中断:STM32的CAN外设还提供了专门的Bus-Off中断(CAN_IT_BUSOFF)。当CAN控制器进入Bus-Off状态时,这个中断会被触发。在初始化CAN时添加代码使能Bus-Off中断,例如使用__HAL_CAN_ENABLE_IT(&hcan,CAN_IT_BUSOFF);。
-
错误状态寄存器(ESR):STM32的CAN外设有一个错误状态寄存器(ESR),其中包含了各种错误状态标志,如EWGF(错误警告标志)、EPVF(错误被动标志)和BOFF(总线关闭标志)。通过监控这些标志位,可以检测到CAN总线的状态变化。
-
接收错误计数器(REC)和发送错误计数器(TEC):STM32的CAN外设提供了接收错误计数器和发送错误计数器,当这些计数器的值超过一定阈值时,CAN控制器会进入Bus-Off状态。通过监控这些计数器的值,可以提前检测到CAN总线的错误趋势。
-
CAN总线活动监控:在某些情况下,可以通过监控CAN总线的电平活动来检测断线情况。例如,如果CAN_H或CAN_L引脚的电平长时间保持不变(例如,长时间高电平或低电平),可能表明总线断线。
小结:STM32提供了多种机制来监控和处理CAN总线的断线情况,包括自动离线管理、错误中断、Bus-Off中断以及监控错误状态寄存器和错误计数器。通过合理配置和编程,可以有效监控外部CAN总线的连接状态。
二、 Cubemx中can总线Basic Parameters参数详解
在STM32CubeMX中配置CAN总线时,“Basic Parameters”(基本参数)是一系列关键的设置,它们定义了CAN通信的基本特性。以下是这些参数的详细解释:
-
Time Triggered Communication Mode:时间触发通信模式。这个选项用于设置是否启用时间触发功能,该功能在某些CAN标准中会使用到。
-
Automatic Bus-off Management:自动离线管理。这个选项用于设置是否启用自动离线管理功能,启用后,CAN控制器在出错时会自动离线,并在适当的时候自动尝试恢复,无需软件干预。
-
Automatic Wake-Up Mode:自动唤醒模式。这个选项用于设置是否启用自动唤醒功能,启用后,CAN控制器会在检测到总线活动后自动唤醒。
-
No-Automatic Retransmission:无自动重传。这个选项用于设置是否启用自动重传功能,启用后,CAN控制器会一直尝试发送报文直到成功为止。
-
Receive Fifo Locked Mode:接收FIFO锁定模式。这个选项用于设置是否启用锁定接收FIFO,启用后,如果FIFO溢出,会丢弃新数据;否则,在FIFO溢出时会用新数据覆盖旧数据。
-
Transmit Fifo Priority:发送FIFO优先级。这个选项用于设置发送报文的优先级判定方法,启用时,以报文存入发送邮箱的先后顺序来发送;否则,按照报文ID的优先级来发送。
小结:这些基本参数对于CAN通信的稳定性和可靠性至关重要,它们影响着CAN网络的行为和性能。在STM32CubeMX中正确配置这些参数,可以确保CAN通信按照预期工作。
三、Cubemxcan总线Operating Mode参数详解
在STM32CubeMX中配置CAN总线时,“Advanced Parameters”中的“Operating Mode”选项允许你选择CAN模块的不同工作模式,以下是这些模式的详细解释:
- Normal Mode(正常模式):在正常模式下,CAN外设会正常地向CAN总线发送数据并从CAN总线上接收数据。这是大多数应用中使用的模式,适用于标准的CAN通信。
- Loopback Mode(回环模式):在回环模式下,CAN外设会正常向CAN总线发送数据,同时接收自己发送的数据,但不从CAN总线上接收其他设备的数据。这种模式在学习CAN外设的时候非常有用,特别是在没有专门的USB转CAN模块也没有两块开发板的时候。
- Silent Mode(静默模式):在静默模式下,CAN外设不向CAN总线发送数据,仅从CAN总线上接收数据,但不会应答。这种模式一般用于检测CAN总线的流量,因为它不会对总线上的数据进行应答,因此不会影响总线上的其他通信。
- Loopback combined with Silent Mode(静默回环模式):在静默回环模式下,CAN外设不会往CAN总线发送或接收数据,仅给自己发送。这种模式一般用于自检,因为它允许CAN控制器在不干扰总线的情况下测试其发送和接收功能。
小结:这些模式主要用于调试和测试CAN通信。在实际应用中,大多数情况下会使用正常模式。其他模式可以根据特定的测试或诊断需求来选择。
四、STM32中CAN总线ESR寄存器相关字段含义详解
在STM32的CAN总线通信中,ESR(Error Status Register,错误状态寄存器)包含了多个用于错误管理的字段,以下是这些字段的含义:
- REC[7:0](接收错误计数器):这是对CAN协议的故障界定机制接收部分的实现。按照CAN的标准,当接收出错时,根据出错的情况该计数器加1或加8;而在每次接收成功后,该计数器减1,或减少其值为120-当该计数器的值大于127时。当该计数器的值超过127时,CAN进入错误被动状态。
- TEC[7:0](发送错误计数器):与接收错误计数器相似,这是对CAN协议的故障界定机制发送部分的实现。发送错误计数器的值根据错误情况增加或减少。
- LEC[2:0](上次错误代码):在检测到CAN总线上发生错误时,硬件根据出错情况设置其为1~6的值。当报文被正确发送或接收后,硬件清除其值为0。硬件没有使用错误代码7,软件可以设置该值,从而可以检测代码的更新。
000: 没有错误;
001: 位填充错;
010: 格式错;
011: 确认(ACK)错;
100: 隐性位错;
101: 显性位错;
110: CRC错;
111: 由软件设置。 - BOFF(离线(Bus Off)标志):当进入离线状态时,硬件对该位置1。当发送错误计数器TEC溢出,即大于255时,CAN进入离线状态。
- EPVF(错误被动(Error Passive)标志):当出错次数达到错误被动的阈值时,硬件对该位置1。(接收错误计数器或发送错误计数器的值>127)。
- EWGF(错误警告标志):当出错次数达到警告的阈值时,硬件对该位置1。(接收错误计数器或发送错误计数器的值≥96)。
小结:这些字段共同构成了CAN控制器的错误状态寄存器,用于监控和管理CAN总线上的错误状态。通过检查这些字段的值,可以判断CAN总线的状态并采取相应的错误处理措施。
五、LEC值哪些状态表示发送异常,哪些状态表示接收异常
在STM32的CAN总线通信中,ESR寄存器的LEC(Last Error Code)字段用于指示最后一次错误的种类。LEC字段的值可以告诉我们是发送异常还是接收异常,以下是LEC值的具体含义:
- LEC = 000:没有错误。
- LEC = 001:位填充错误(Stuff Error)。这通常发生在发送过程中,如果发送节点发送的位序列违反了CAN协议的位填充规则。
- LEC = 010:格式错误(Form Error)。这通常发生在接收过程中,如果接收到的CAN帧格式不符合CAN协议的要求。
- LEC = 011:确认错误(Acknowledgment Error)。这通常发生在发送过程中,如果发送节点没有收到预期的应答位(ACK)。
- LEC = 100:隐性位错误(Recessive Bit Error)。这通常发生在接收过程中,如果接收到的位不是隐性位(逻辑1)。
- LEC = 101:显性位错误(Dominant Bit Error)。这通常发生在发送或接收过程中,如果检测到的位是显性位(逻辑0),但在该位置应该是隐性位。
- LEC = 110:CRC错误(CRC Error)。这通常发生在接收过程中,如果接收到的CAN帧的CRC校验和不正确。
小结:从上述LEC值的含义可以看出,LEC = 001、LEC = 010、LEC = 011和LEC = 101通常与发送异常相关,而LEC = 100和LEC = 110通常与接收异常相关。LEC = 101(显性位错误)既可以是发送异常也可以是接收异常,具体取决于错误发生的上下文。
六、STM32提取CAN总线的ESR寄存器中的TEC值和LEC值方法
在STM32中提取CAN总线的ESR寄存器中的TEC值和LEC值,可以通过直接读取CAN的ESR寄存器来实现。以下是具体的方法,以CAN1为例:
- TEC值提取:TEC(Transmit Error Counter)是ESR寄存器中位23:16的字段,用于记录发送错误的次数。要提取TEC值,可以直接读取ESR寄存器的这8位。例如,使用以下代码:
uint8_t TEC = (CAN1->ESR >> 16) & 0xFF; // 提取TEC值
这段代码将ESR寄存器的值右移16位,然后与0xFF(即255)进行位与操作,以获取TEC的值。
- LEC值提取:
LEC(Last Error Code)是ESR寄存器中位6:4的字段,用于指示最后一次错误的种类。要提取LEC值,可以直接读取ESR寄存器的这3位。例如,使用以下代码:
uint8_t LEC = (CAN1->ESR >> 4) & 0x7; // 提取LEC值
这段代码将ESR寄存器的值右移4位,然后与0x7(即7)进行位与操作,以获取LEC的值。
小结:以上代码可以直接在你的STM32项目中使用,以监控和诊断CAN总线的错误状态。通过分析TEC和LEC的值,可以更好地理解CAN总线的错误情况,并采取相应的措施。
七、ESR寄存器中的TEC和LEC值如何清空
在STM32中,CAN1的ESR寄存器中的TEC和LEC值可以通过软件进行清空。以下是具体的步骤和方法:
- 进入初始化模式:要清空TEC和LEC值,首先需要将CAN1置于初始化模式。这可以通过设置CAN_MCR寄存器中的INRQ位来实现:
CAN1->MCR |= CAN_MCR_INRQ;
等待直到CAN1进入初始化模式,可以通过检查MSR寄存器中的INAK位来确认:
while(CAN1->MSR & CAN_MSR_INAK);
- 清空TEC和LEC值:在初始化模式下,可以通过设置ESR寄存器中的LEC位来清空LEC值,同时可以通过设置ESR寄存器中的TEC位来清空TEC值:
CAN1->ESR |= CAN_ESR_LEC; // 清空LEC值
CAN1->ESR |= CAN_ESR_TEC; // 清空TEC值
以上操作会将LEC和TEC的值清零。
3.退出初始化模式:清空TEC和LEC值后,需要将CAN1退出初始化模式,回到正常工作模式:
CAN1->MCR &= ~CAN_MCR_INRQ;
等待直到CAN1退出初始化模式,可以通过检查MSR寄存器中的INAK位来确认:
while(!(CAN1->MSR & CAN_MSR_INAK));
小结:以上步骤可以帮助你清空STM32 CAN1总线的ESR寄存器中的TEC和LEC值,而无需重启整个MCU。
八、keil中debug监控的CAN状态举例
- 正常状态时,ESR寄存器的值均为0。
- 外部can总线断开,stm32对外发送一帧8字节长度数据时:TEC(发送错误计数器)值变为0x08,LEC(上次错误代码)值变为0x03。
- 外部can总线保持断开,连续发送三帧时:TEC(发送错误计数器)值递增为0x20、0x38、0x50,LEC(上次错误代码)值始终为0x03。
- 外部can总线保持断开,继续发送一帧:TEC(发送错误计数器)值递增为0x60,LEC(上次错误代码)值始终为0x03,EWGF(错误警告标志)标志位置1。
- 外部can总线保持断开,继续发送二帧:TEC(发送错误计数器)值递增为0x80,LEC(上次错误代码)值始终为0x03,EWGF(错误警告标志)标志位置1,EPVF(错误被动标志)标志位置1。
- 外部can总线插上,发送一帧:TEC(发送错误计数器)值递减为0x7F,LEC(上次错误代码)复位为0x00,EWGF(错误警告标志)标志位不变,仍为1,EPVF(错误被动标志)标志位复位0。
- 外部can总线插上,继续发送三帧:TEC(发送错误计数器)值递减为0x7C,LEC(上次错误代码)复位为0x00,EWGF(错误警告标志)标志位不变,仍为1,EPVF(错误被动标志)标志位复位0。
- 外部can总线插上,继续发送若干帧:TEC(发送错误计数器)值递减为0x5F后,LEC(上次错误代码)复位为0x00,EWGF(错误警告标志)标志位复位0,EPVF(错误被动标志)标志位复位0。
小结:通过对CAN1状态寄存器的监控,编写响应的控制函数,可以实现can总线异常时的报警、自动恢复等功能。
作者:stone_hefei