STM32 - CAN问题总结

一、CAN基础知识

CAN协议 简介

CAN (Controller Area Network )是 ISO 国际标准化的串行半双工异步(位时序同步)通信协议。

(1)由于系统之间通信所用的数据类型及对可靠性的要求不尽相同,由多条总线构成的情况很多,线束的数量也随之增加。为适应“减少线束的数量”、“通过多个 LAN,进行大量数据的高速通信”的需要。

(2)CAN 控制器根据两根线(CAN_H、CAN_L)上的电位差,产生的差分信号来判断总线电平。


CAN协议- 电平特性

在这里插入图片描述

隐性电平(Recessiveness -简称 R):逻辑值0,CAN_H 和 CAN_L 之差为 2.5V 左右。 显性电平(Dominance -简称 D):逻辑值1,CAN_H 和 CAN_L 之差为 0V。

在总线上显性电平具有优先权,只要有一个单元输出显性电平,总线上即为显性电平。而隐形电平则具有包容的意味,只有所有的单元都输出隐性电平,总线上才为隐性电平(显性电平比隐性电平更强)。

协议规范,这么设计是有一定的技巧的:

显性或者隐性的优先级可以看成是每个 CAN单元unit 与 CAN总线Bus 通信时,电平逻辑关系 相与&的关系
(1)显性电平(电平 = 0)优先级高是因为 CAN独立单元 和 CAN总线相与&后,把CAN总线的电平,也同时拉低了。只要有一个 CAN独立单元为显性电平,则整个CAN总线就被拉高。

(2)但是CAN独立单元隐形电平(电平 = 1)和CAN总线相与&后,CAN总线电平状态保持不变。因此只有所有的CAN独立单元全为隐形电平时,CAN总线电平才为隐性电平。
另外,在 CAN 总线的起止端都有一个 120Ω终端电阻来做阻抗匹配,以减少回波反射。

注意:120Ω的终端电阻,在CAN通信中是必不可少的。
因为很多情况下,CAN通信在正常模式调试时,MCU片上CAN设备接收不到消息,有一种失败原因是CAN分析仪上面的 120Ω终端电阻拨片没有打开ON。

二、STM32Fxxx CAN控制器

设计目标是:以最小的 CPU 负荷来高效处理大量收到的报文
支持报文发送的优先级要求(优先级特性可软件配置)。对于安全紧要的应用,bxCAN 提供所有支持时间触发通信模式所需的硬件功能。

(1)STM32F4 bxCAN 的主要特点

  • 支持 CAN 协议 2.0A 和 2.0B 主动模式
    各个行业的协议遵循的规范
  • 波特率最高达 1Mbps
    相对于其它通信协议的通信速度,已经算很高了
  • 支持时间触发通信
    暂时没用过
  • 具有 3 个发送邮箱
    主CAN1和从CAN2都各自有自己的3个发送邮箱,发送消息时,哪个邮箱空闲idle,就选择哪个邮箱发送消息。
  • 具有 2 个 3 级深度的接收 FIFO
    相当于主CAN1和从CAN2各有自己的2个接收邮箱:FIFO0,FIFO1。而每个接收邮箱又都可以细分3块FIFO缓存区,每接收一个消息可以挂载在指定的接收邮箱上,逐次填充3个FIFO缓存区,也就是3级深度的意思。
  • 可变的过滤器组(CAN1 和 CAN2 共享 28组过滤器,一组过滤器又分为含有2个32位的寄存器)
    过滤器的意思就是MCU的片上外设-CAN设备从CAN_BUS总线接收到消息(也就是报文),但是我也不能什么消息都接收过来对吧,因此需要一个东西去过滤掉那些对我无用的消息,选择提炼接收那些对我有用的消息,那么这个过滤的东西就是过滤器。但是过滤的过程不仅仅有一个器件就行了,他还需要其他器件的配合,因此一个过滤器组含有2个32位寄存器。那么到底按照什么条件去筛选呢,这里引入标识符ID,也就是消息报文中仲裁段id,通过设置过滤时只允许通过我们指定的id而过滤掉别的id,从而达到过滤消息的作用。过滤器(筛选器)的作用是:减少了 CPU 处理 CAN 通信的开销

CAN发送/接收消息 框图
从框图中,总结出CAN通信主要分为三大部分:

  • CAN 控制和状态:控制CAN通信过程中的发送和接收,中断,其它各种状态以及工作的各种模式。
  • CAN 邮箱:发送和接收的用来放消息(报文)的邮箱,其实也就是缓存存储区。
  • CAN 过滤器(筛选器):过滤消息(报文)中仲裁段ID的寄存器组。

(2)过滤器作用 详细分析

为什么要使用 过滤器(filter)?
此部分内容参考文章: 过滤器详解.
此文章讲的透彻、浅显易懂


bxCAN 工作模式

bxCAN 主要有三种工作模式: 初始化(Initialize)、 正常(Normal)和睡眠(Sleeping,低功耗)

CAN主要工作模式

测试模式:环回模式,静默模式,环回与静默组合模式

(1)环回模式
在这里插入图片描述
(2)静默模式
在这里插入图片描述
(3)环回与静默组合模式
在这里插入图片描述

  • 调试模式

bxCAN 发送消息

CAN邮箱发送时需设置的寄存器

(1)CAN 发送状态寄存器 (CAN_TSR)

  • RQCPx : 邮箱 x 请求完成 (Request completed mailbox x)
    最后一个请求(发送或中止)执行完毕时,由硬件置 1。由软件通过写入“1”清零,或是在发生发送请求(CAN_TI1R 寄存器中的 TXRQx位)时由硬件清零。
    如果将此位清零,邮箱 x 的所有状态位(TXOK1、ALST1 和 TERR1)都将清零。

  • TXOKx :邮箱 x 发送成功 (Transmission OK of mailbox x)
    每次发送成功后,硬件都将更新此位。
    0:上一次发送失败
    1:上一次发送成功
    当邮箱 x 的发送请求成功完成时,此位由硬件置 1。

  • TMEx : 发送邮箱 x 为空状态 (Transmit mailbox x empty)
    当 x 邮箱为空,即邮箱没有挂起发送请求时,硬件自动置1。

  • ABRQx :邮箱 x 中止请求 (Abort request for mailbox x)
    由软件置 1,用于中止相应邮箱的发送请求。
    邮箱变为空后,此位由硬件清零。邮箱未挂起等待发送时,将此位置 1 没有任何作用。

(2)CAN 发送邮箱标识符寄存器(CAN_TIxR)

  • TXRQ : 发送邮箱请求 (Transmit mailbox request)
    由软件置 1,用于请求发送相应邮箱的内容。
    邮箱变为空后,此位由硬件清零。
    在这里插入图片描述

最开始发送报文时,x邮箱TMPx = 1 表示邮箱内容为空,此时需要把报文(数据帧等)填充 x发送邮箱,紧接着将 TXRQ = 1,请求发送x邮箱中的内容,此时 x邮箱 进入挂号(挂起 pending)状态,等待成为优先级最高的邮箱,相应的状态寄存器的TMPx位清零,表明x邮箱有数据不为空。

此过程可以被中止ABRQx = 1,中止相应邮箱的发送请求,进入发送失败状态,邮箱置空 TMPx = 1;RQCPx = 1;TXOKx = 0.

此后由调度器统一调度选择具有最高优先级的邮箱,安排发送。当x邮箱成为优先级最高的邮箱时,会将邮箱内的数据进行打包(报文),待CAN 总线变为空闲后,被安排好的邮箱将开始发送报文(进入发送态)。邮箱一旦发送成功,则邮箱立即恢复 空状态TMPx = 1;RQCPx = 1;TXOKx = 1.

如果发送失败,失败原因将由 CAN_TSR 寄存器的 ALST位( 邮箱 x 仲裁丢失)和 TERR位 (邮箱x 发送错误)提示,进入发送失败状态,邮箱置空 TMPx = 1;RQCPx = 1;TXOKx = 0.

如果设置了自动重发送模式,则会重新回到等待调度器再次调度重发。


bxCAN 接收消息

在这里插入图片描述

过滤器总结

通过CAN_TOOL和CAN分析仪测试发现:

(一)列表模式

0、0x7FF 、 0x1FFFFFFF 为独立单一的can_id

(二)掩码模式

(1)配置情形1

			配置一	配置二					配置三
filter_id	0		0						0x7FF / 0x1FFFFFFF
mask_id		0		0x7FF / 0x1FFFFFFF		0

只要 filter_id / mask_id 有一个配置为0,则过滤器组将会使所有id都可以通过过滤,不屏蔽任何id,任何id都可以通过筛选。

(2)配置情形2

			配置				
filter_id	0x7FF / 0x1FFFFFFF		
mask_id		0x7FF / 0x1FFFFFFF	

此时过滤器可以屏蔽所有id,不让任何id通过筛选(包括 0 和 0x7FF / 0x1FFFFFFF)。这种模式可以用于过滤器不想使用(即关闭过滤器)时,全部以 0x7FF / 0x1FFFFFFF 填充filter_id 和 mask_id 对应的2组寄存器。

三、CAN问题总结

(一)CAN初始化失败原因
(1)Check acknowledge error
CAN收发器在CAN初始化之前,CAN收发器要处于正常供电状态。
如果CAN收发器没有正常供电(5V和3.3V供电),任何一路没有正常供电都会造成CAN收发器无法正常工作,从而导致软件程序CAN初始化的失败。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

 /* Wait the acknowledge */
   wait_ack = 0;

   while (((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK) && (wait_ack != INAK_TIMEOUT))
   {
     wait_ack++;
   }

    /* ...and check acknowledged */
    if ((CANx->MSR & CAN_MSR_INAK) == CAN_MSR_INAK)
    {
      InitStatus = CAN_InitStatus_Failed;
      printf("Check acknowledge error 2\n");
    }
    else
    {
      InitStatus = CAN_InitStatus_Success ;
    }

CAN收发器在CAN初始化之前,没有供电,会造成INAK位,CAN_Rx引脚无法检测到连续11位的隐形电平,使得硬件无法清零,导致CAN初始化失败

(2)boot0引脚是否默认接地,启动模式为:选择主 Flash 作为自举空间
在这里插入图片描述
(3)CAN因波特率不同导致初始化失败
CAN因波特率不同导致初始化失败

(4)CAN的Rx和Tx引脚外接上拉电阻导致初始化失败
外接上拉电阻初始化失败

(5) 检查CAN收发器的STB引脚是否正常接地或者程序里面是否将STB引脚拉为低电平
STB引脚低电平有效或默认接地:此时为正常工作状态
STB引脚拉高时:此时为低功耗工作状态,CAN收发器无法正常工作:即无法正常接收/发送数据帧。在这里插入图片描述
(6)电源供电电压不足:BAT-12V,电源电压不足或者电源电压不稳定,导致CAN初始化失败,内部晶振无法工作。

(7)CAN引脚复用重映射,导致GPIO引脚的初始化参数不对
重映射CAN引脚需要打开RCC_AFIO时钟:以stm32f10x为例
注意:复用为默认引脚时,不需要开启此RCC_AFIO时钟。

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,  EABLE);

在这里插入图片描述
(8)如果以上问题都没有,且硬件确保无问题。请仔细检查程序,对应引脚和配置参数是否正确,有时候很可能是因为某一个变量的名称在拷贝时,忘记更改正确变量名导致的。

(9)CAN波特率:两个设备必须设置相同,一般500KHZ

(二)CAN2 (Slave CAN)通信失败原因
在初始化CAN2之前,没有先初始化和打开主CAN1的RCC时钟。因为CAN2通信依赖于主CAN1片上器件的使能。
经测试,在使用CAN2之前,一般只需要打开主CAN1的RCC时钟,CAN2即可正常工作。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_CAN1 | RCC_APB1Periph_CAN2, ENABLE);
// void CAN_SlaveStartBank(uint8_t CAN_BankNumber); 
CAN_SlaveStartBank(14); // 此时需要初始化过滤器,并打开CAN2

在这里插入图片描述
(三)CAN收发器供电不正常,造成的初始化问题

(四)过滤器初始化过程中,出现初始化卡死,停止不动问题
一般是开启了CAN中断,但是中断服务函数并没有写或者写的有问题。
(1)设备刚上电,CAN过滤器初始化进行中程序卡住阻塞,现象:
在这里插入图片描述
(2)设备刚上电,CAN和过滤器初始化也都完成,但是在CAN_TEST_TOOL测试上位机发送 id 时,主程序继续卡住阻塞,CAN_TEST_TOOL测试上位机停止发送id时,主进程仍然退不出来。添加打印信息也无法检测出问题所在的地方。

原因分析:经过检查发现,CAN初始化过程中,打开了CAN中断,但是并没有写CAN的中断处理函数,导致程序一直: B . (跳转到当前位置,查看汇编时发现),即在当时现场一直跳转到当前位置,无法退出。

(五)发送邮箱出现 No Mailbox
这个问题也是最常见的问题:
(1)接线:检查硬件连接是否正确,一般是板子的CAN_H和CAN_L两条线,没有接入CAN_BUS总线,即没有连接外设(PC端的CAN分析仪),CAN_H和CAN_L不接外部设备会导致邮箱满或溢出,导致新的消息无法获得邮箱。

(2)CAN收发器是否正常供电和STB引脚是否拉低:如果软件配置没有问题,则需要用示波器检查CAN收发器的Rx和Tx引脚是否有数据波形,其次还需要检查CAN收发器的VCC供电电压是否开启,以及不同CAN收发器芯片的VCC供电电压不同(一般是3.3V,但是也有5V供电的),需要查看一下数据手册是否满足其要求。

(3)仔细检查程序

  • 配置引脚的参数是否正确,三个引脚:Tx、Rx、STB
  • 是否开启时钟:RCC_GPIO时钟,RCC_CAN的时钟,复用重映射还需开启RCC_AFIO

(六)CAN时钟分析
STM32系统时钟 CAN时钟配置分析:参考 CAN时钟配置.

(七)关闭(不激活)不想使用的CAN过滤器
使已经激活的CAN过滤器失效:禁止已经打开的过滤器的范围。
前提是:先打开CAN1的RCC时钟

void close_filter(int can_dev)
{
    CAN_FilterInitTypeDef CAN_FilterInitStructure;
    u8 f_i = 0;
    
    if (can_dev == CAN_DEV1) {
        for (f_i = 0; f_i < 13; f_i++) {
            CAN_FilterInitStructure.CAN_FilterNumber = f_i;
            CAN_FilterInitStructure.CAN_FilterFIFOAssignment = FIFO0; 
            CAN_FilterInitStructure.CAN_FilterActivation = DISABLE;
            CAN_FilterInit(&CAN_FilterInitStructure);
        }
    } else if (can_dev == CAN_DEV2) {
            for (f_i = CAN2_FILTER_S; f_i < 27; f_i++) {
            CAN_FilterInitStructure.CAN_FilterNumber = f_i;
            CAN_FilterInitStructure.CAN_FilterFIFOAssignment = FIFO1; 
            CAN_FilterInitStructure.CAN_FilterActivation = DISABLE;
            CAN_FilterInit(&CAN_FilterInitStructure);
        }
    } else {
        printf("close_filter can_dev is error \n");
    }
}

(八)CAN接收的数据出现帧丢失问题
前提:已经开启CAN的NVIC接收中断CAN1_RX0_IRQHandler,在中断服务函数里接收CAN_BUS上的数据帧。整个系统,开启了串口打印调试。

void CAN1_RX0_IRQHandler(void)
{
    can_msg_t can_msg;
    p_can_read(CAN_DEV1, &can_msg);
}

分析:Keil5调试发现,由于串口打印调试cpu处理占用的时间大于下一次接收到can数据帧的时间,因此会导致接收到的最新can数据帧会覆盖掉之前的数据帧,导致 old frame 来不及被处理就被最新的数据替换掉,因此会导致CAN接收的数据出现帧丢失。

(九)CAN总线中节点ID相同会怎样?
问题描述:在写CAN测试程序的时候,内部程序向CAN总线上发送数据帧的同时也接受CAN总线上的数据帧。当用CAN-Test上位机工具模拟发送 连续帧,单帧,首帧,设置发送间隔和帧间隔都为0发送时,会出现发送失败。
在线调试时,发现出现硬件CAN总线离线错误,LEC = 5;导致CAN功能无法接收数据,也无法发送数据。
后面经过几天的分段调试,发现如果同一时段,CAN发送数据帧同时也接收CAN总线上的数据,如果接收和发送can_id相同则会造成CAN总线离线。
详细可参考:链接 CAN总线中节点ID相同会怎样?.

在这里插入图片描述

总结:当两节点同时发送ID相同数据不同的报文时,将发生数据场填充错误;当两节点同时发送ID相同数据也相同的报文时,若有其他节点应答则不发生错误,若无其他节点应答则发生应答错误。因此,我们在设计CAN总线时应避免ID段相同的情况出现。

在这里插入图片描述
与此同时,CAN初始化时,设置参数最好是使能ABOM,同时开启自动重发可降低丢帧概率。

  • 12
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32-ISO是一种特殊的STM32微控制器系列,其设计用于在噪声环境下提供高级别的电气隔离。这种电气隔离机制可以防止电感耦合、电容耦合和共模干扰等问题,从而增强系统的稳定性和可靠性。 使用零角度玩STM32-ISO,首先需要了解STM32-ISO的特点和功能。这些特点包括:双核设计、电气隔离技术、安全表面和故障保护等。双核设计使得STM32-ISO同时具备应用处理器和实时核,可以分别处理不同种类的任务,提高系统性能。电气隔离技术则确保信号在不同部分之间传输时不会相互干扰。安全表面保护系统免受未经授权的访问和攻击。故障保护机制可以防止系统在电气隔离失效时毁坏。 零角度玩STM32-ISO可以通过以下步骤实现: 1. 学习STM32-ISO的技术文档和参考手册,了解其硬件结构、内部模块和功能特性。同时要熟悉相关的开发工具和软件。 2. 了解使用STM32-ISO的典型应用场景。根据自己的需求,选择适合的开发板和模块。 3. 使用STM32CubeMX等工具进行代码生成和项目配置。根据实际应用需求,选择合适的外设模块和接口,配置GPIO、串口、定时器等功能。 4. 编写应用程序代码。使用C语言或其他支持的编程语言,结合STM32的开发库和驱动程序,实现特定的功能和算法。 5. 调试和测试应用程序。使用调试器或仿真器连接开发板,逐步调试代码并验证功能的正确性和稳定性。 6. 进一步优化和完善应用程序。根据测试结果和实际应用反馈,修复bug、改进性能或增加新功能。 通过以上步骤,我们可以全面了解STM32-ISO的特性,并在零角度上进行开发。这样能够最大限度地发挥STM32-ISO的性能优势,且保证系统的稳定性和可靠性,为特定的应用问题提供解决方案。 ### 回答2: STM32-ISO是一种基于ST Microelectronics的STM32微控制器的开发板,它专门设计用于开发与隔离有关的应用。隔离是指在电气和功能上分离电气系统的一种技术,以提高系统的安全性和可靠性。 使用STM32-ISO,可以便捷地实现对外部设备的隔离,从而保护主控器和其他关键部件免受电气干扰、过电压和过电流等问题的影响。这可以在很多应用场景中派上用场,比如工业自动化、医疗仪器、电力系统等。 要零角度玩STM32-ISO开发板,首先需要了解其硬件和软件特性。硬件方面,STM32-ISO集成了隔离电源电路和可编程逻辑电源电路,以分离主控器和外部设备。它还提供了丰富的接口,包括GPIO、I2C、SPI、UART等,方便与其他设备进行通信。 在软件方面,可以使用STM32Cube软件开发套件来编写代码。STM32Cube提供了丰富的开发工具和例程,可以帮助开发者快速上手。此外,还可以使用Keil MDK或者IAR Embedded Workbench等集成开发环境来进行开发。 零角度玩STM32-ISO可以从简单的实验开始,比如点亮LED灯。可以配置GPIO口为输出模式,并将其连接到板上的LED灯。通过编写相应的代码,可以控制LED灯的亮灭。 对于更复杂的应用,可以结合不同的外设模块,如传感器和执行器,同时进行阻隔控制和数据通信。例如,可以使用I2C接口与温度传感器进行通信,并将读取到的温度数据显示在液晶显示屏上。 总结而言,要零角度玩STM32-ISO,首先需要熟悉开发板的硬件和软件特性,然后通过简单的实验来熟悉开发流程。逐渐加深对开发板的理解,探索更多的应用场景,并结合外设进行更复杂的控制和通信操作。请开发者尝试使用STM32-ISO来实现自己感兴趣的项目,并通过不断学习和实践,进一步提高技术水平。 ### 回答3: STMicroelectronics的STM32系列是一款广泛应用于嵌入式系统的32位微控制器,具有高性能、低功耗和强大的扩展能力。而STM32-ISO则是基于STM32系列的特殊版本,能够实现隔离和保护,提供高级别的抗干扰能力和可靠性。 首先,STM32-ISO采用了进一步优化的硬件设计,以实现电气隔离,即通过在电路中添加隔离层来避免信号干扰和电气噪声的影响。这样可以确保系统在电气噪声较大的环境中仍能正常工作。 其次,STM32-ISO还配备了特殊的接口电路和通信协议,以实现与外部设备之间的隔离和保护。这些接口包括CAN总线、UART、SPI等,能够使STM32-ISO与其他设备进行安全可靠的通信。 另外,STM32-ISO还具备高级别的抗干扰能力,能够有效地抵御来自外界的电磁干扰和电气噪声。这是通过在电路设计中采用抗干扰措施和高质量的隔离材料来实现的。 最后,STM32-ISO支持丰富的软件开发工具和资源。开发者可以使用ST提供的官方开发环境和软件库来进行开发,同时还可以借助ST社区和论坛获取更多的技术支持和资源。 综上所述,STM32-ISO是一款强劲的嵌入式微控制器,通过电气隔离、接口保护、抗干扰能力以及软件开发工具的支持,能够在想要保证系统稳定性和可靠性的应用中发挥重要作用。无论在工业自动化、通信设备还是其他领域,STM32-ISO都是一个值得选择和使用的芯片。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值