• STM32个人笔记-CAN总线通讯


    ​​​​​ 大四实习那年记忆颇深,进入一家公司当嵌入式软件工程师实习生,项目正是船载通讯,学习的内容一部分正是CAN和J1939。虽然实习期间匆匆忙忙缝缝补补,但现在还是按着流程学一遍。

    目录

    CAN物理层:闭环总线和开环总线。

    闭环总线网络

    开环总线网络

    通讯节点 

    差分信号(差模信号)

    CAN协议层

    位时序分解

    CAN的报文

    CAN外设

    CAN_BTR寄存器

    CAN结构体

    CAN_InitTypeDef初始化结构体

    CANTxMsg发送结构体

    CANRxMsg接收结构体

    CAN_FilterInitTypeDef筛选器结构体


    CAN协议广泛用于汽车控制服务行业。

    CAN物理层:闭环总线和开环总线。

    异步通讯,半双工(只有一双差分线,在一个时刻只能表示一个信号),CAN_HighCAN_Low,共同构成一组差分信号线,以差分信号的形式进行通讯(CAN的可靠性主要来源)

    闭环总线网络

    适用于高速短距离通讯。总线最大长度为40M通信速度最高1Mbps(并非很高,多用汽车行业),总线两端各要求有一个“120欧”的电阻。120欧是因为电缆的特性阻抗为120欧,主要为了模拟无限远的传输线。

    开环总线网络

    适用于低速远距离通讯。总线最大长度为1KM通信速度最高125kbps,两端总线是独立的、不形成闭环,要求每根总线上各串联一个“2.2千欧”的电阻

    通讯节点 

    CAN总线上可以挂载多个通讯节点,节点之间的信号经过总线传输,实现节点间通讯。由于CAN通讯协议不对节点进行地址编码,而是对数据内容进行编码,所以网络中的节点个数理论上不受限制,只要总线的负载足够即可,可以通过中继器增强负载。

    CAN通讯节点由一个CAN控制器及CAN收发器组成,控制器和收发器之间通过CAN_Tx和CAN_Rx信号线相连,收发器与CAN总线之间使用CAN_High及CAN_Low信号线相连。其中CAN_Tx和CAN_Rx信号线使用普通的类似TTL逻辑信号,而CAN_High及CAN_Low信号线是一对差分信号线,使用比较特别的差分信号。

    当CAN节点需要发送数据时,控制器把要发送的二进制编码通过CAN_Tx线发送到收发器,然后由收发器把这个普通的逻辑电平信号转化成差分信号,通过差分线CAN_High和CAN_Low输出到CAN总线网络。而通过收发器接收总线上的数据到控制器时,收发器把总线上收到的CAN_High和CAN_Low信号转换成普通的逻辑电平信号,通过CAN_Rx输出到控制器中。

    差分信号(差模信号)

    使用差分信号传输时,需要两根信号线,这两个信号线的振幅相等,相位相反,通过两根信号线的电压差值来表示逻辑0和逻辑1。

    相对于单信号线传输的方式,使用差分信号传输具有以下优点:

    抗干扰性强。当外界存在噪声干扰时,几乎会同时耦合到两条信号线上,而接收端只关心两个信号的差值,所有外界的共模噪声可以被完全抵消。

    能有效抑制它对外部的电磁干扰。由于两根信号的极性相反,它们对外辐射的电磁场可以相互抵消,耦合的越紧密,泄放到外界的电磁能量越少。

    时序定位精确。由于差分信号的开关变化是位于两个信号的交点,而不像普通单端信号依靠高低两个阈值电压判断,因而受工艺、温度的影响小,能降低时序上的误差,同时也更适合于低幅度信号的电路。

    由于差分信号线具有这些优点,所以在USB协议、485协议、以太网协议和CAN协议的物理层中,都使用了差分信号传输。

    在CAN总线中,必须使它处于隐性电平(逻辑1)或显性电平 (逻辑0)中的其中一个状态。

    假如有两个CAN通讯节点,在同一时间,一个节点输出隐性电平,另一个输出显性电平,类似于I2C总线的"线与"特性将使它处于显性电平状态。

    显性电平的名字就是这样来的,即可以认为显性具有优先的意味。

    在CAN的通讯网络中,因为共用总线,在整个网络中同一时刻只能有一个通讯节点发送信号,其余的节点在该时刻都只能接收。

    CAN协议层

    节点间除了使用约定好的波特率进行通讯,也会使用“位同步”的方式来抗干扰、吸收误差,实现对总线电平信号进行正确的采样,确保通讯正常。

    位时序分解

    为了实现位同步,CAN协议把每一个数据位的时序分解成SS段、PTS段、PBS1段和PBS2段,这四段的长度加起来即为一个CAN数据位的长度。分解后最小的时间单位是Tq,而一个完整的位由8~25个Tq组成。

    信号的采样点位于PBS1段和PBS2段之间,通过控制各段的长度,可以对采样点的位置进行偏移,以便准确地采样。

    SS段(SYNC SEG,同步段)。若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围之内,则表示节点与总线的时序是同步的,当节点和总线同步时,采样点采集到的总线电平即可被确定为该位的电平。SS段的大小固定为1Tq。

    PTS段(PROP SER,传播时间段)。用来补偿网络的物理延时时间。是总线上输入比较器延时和输出驱动器延时总和的两倍。PTS段的大小可以为1~8Tq。这概念看看就行,在STM32中,PTS段和PBS1段合在一起的。

    PBS1段(PHASE SER1,相位缓冲段)。用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以加长。PBS1段的初始大小可以为1~8Tq。这概念看看就行,在STM32中,PTS段和PBS1段合在一起的。

    PBS2段(PHASE SER2,相位缓冲段)。用来补偿边沿阶段的误差,它的时间长度在重新同步的时候可以缩短。PBS1段的初始大小可以为2~8Tq。

    总线上的各个通讯节点只要约定好1个Tq的时间长度和每一个数据位占据多少个Tq,就可以确定CAN通讯的波特率。

    例如,假设上图中的1Tq=1us,而每个数据位由19个Tq组成,则传输一位数据需要时间T1=19us,从而每秒可以传输的数据位个数为:1*16^6/19=52631.6(bps),这个每秒可传输的数据位的个数即为通讯中的波特率。

    CAN的报文

    当使用CAN协议进行通讯时,需要对数据、操作命令(如读/写)和同步信号进行打包,打包后的这些内容称为报文。

    在原始数据段的前面加上传输起始标签、片选(识别)标签和控制标签,在数据的尾段加上CRC校验标签、应答标签和传输结束标签。把这些内容按特定的格式打包好,就可以用一个通道表达各种信号,各种各样的标签就如同SPI中各种通道上的信号,起到了协调传输的作用。当整个数据包被传输到其他设备时,只要这些设备按格式去解读,就能还原出原始数据,这样的报文就被称为CAN的“数据帧”。

    为了更有效地控制通讯,CAN一共规定了5种类型的帧。

    用途
    数据帧用于节点向外传送数据
    遥控帧用于向远端节点请求数据
    错误帧用于向远端节点通知校验错误,请求重新发送上一个数据
    过载帧用于通知远端节点:本节点尚未做好接受准备
    帧间隔用于将数据帧及遥控帧与前面的帧分离开来

    数据帧

    数据帧以一个显性位(逻辑0)开始,以7个连续的隐性位(逻辑1)结束。

    帧开始(SOF段,Start Of Frame)。帧起始信号只有一个数据位,是一个显性电平,用于通知各个节点将有效数据传输,其它节点通过帧开始信号的电平跳变沿来进行硬同步。

    仲裁段。当同时有两个报文被发送时,总线会根据仲裁段的内容决定哪个数据包能被传输。仲裁段的主要内容为本数据帧的ID信息(标识符)。数据帧具有标准格式和扩展格式两种,区别就在于ID信息的长度。标准格式的ID为11位,扩展格式的ID为29位,扩展格式ID是在标准格式ID的基础上多出18位。

    在CAN协议中,ID决定着数据帧发送的优先级,也决定着其它节点是否会接收这个数据帧。CAN协议不对挂载在它之上的节点分配优先级和地址,对总线的占有权是由信息的重要性决定的,即对于重要的信息,可给它打包成一个优先级高的ID,使它能够及时地发送出去。

    RTR位(Remote Transmission Request Bit,远程传输请求位)。用于区分数据帧和遥控帧。当它为显性电平时表示数据帧,隐性电平时表示遥控帧。

    IDE位(ID Extension Bit,标识符扩展位)。用于区分标准格式和扩展格式。当它为显性电平时表示标准格式,隐性电平时表示扩展格式。

    SRR位(Substitute Remote Request Bit)。只存在于扩展格式,用于替代标准格式中的RTR位。由于扩展帧中的SRR位为隐性位,RTR在数据帧为显性位,所以在两个ID相同的标准格式报文与扩展格式报文中,标准格式的优先级较高。

    控制段。在控制段中的r1和r0为保留位,默认设置为显性位。它最主要的是DLC段(Data Length Code,数据长度码),由4个数据位组成,用于表示本报文中的数据段含有多少个字节,DLC段表示的数字为0~8。

    数据段。由0~8个字节组成,MSB先行。

    CAN外设

    STM32芯片中具有bxCAN(Basic Extended CAN),它支持CAN协议2.0A和2.0B标准。

    外设中有三个发送邮箱,发送报文的优先级可以使用软件控制,还可以记录发送的时间;

    具有两个3级深度的接收FIFO,可使用过滤功能只接收或不接收某些ID号的报文;

    可配置成自动重发;

    不支持使用DMA进行数据收发。

    STM32的CAN外设位时序中只包含3段,同步段SYNC_SEG、位段BS1和位段BS2。采样点位于BS1和BS2的交界处。

    BS1和BS2段的时间长度可由位时序寄存器CAN_BTR:TS2、TS1设置。BS1和BS2段的时间长度可以在重新同步期间增长或缩短,可由位时序寄存器CAN_BTR:SJW配置。

    CAN_BTR寄存器

     

     

    假设:BS1段设置为5Tq,BS2段设置为3Tq,Tpclk=1/36M,CAN外设时钟分频设置为4分频。

    则Tq=4*1/36M=1/9M,T_1bit=1Tq+5Tq+3Tq=9Tq,波特率=1/NTq=1/(1/9M * 9)=1Mbps。

    CAN结构体

    CAN_InitTypeDef初始化结构体

    1. typedef struct{
    2. uint16_t CAN_Prescaler; //CAN外设的时钟分频,可设置为1-1024
    3. uint8_t CAN_Mode; //工作模式,回环或正常模式
    4. uint8_t CAN_SJW; //SJW极限值
    5. uint8_t CAN_BS1; //BS1段长度
    6. uint8_t CAN_BS2; //BS2段长度
    7. FunctionalState CAN_TTCM; //是否使能TTCM时间触发功能
    8. FunctionalState CAN_ABOM; //是否使能ABOM自动离线管理功能
    9. FunctionalState CAN_AWUM; //是否使能AWUM自动唤醒功能
    10. FunctionalState CAN_NART; //是否使能NART自动重传功能
    11. FunctionalState CAN_RFLM; //是否使能RFLM锁定FIFO功能
    12. FunctionalState CAN_TXFP; //配置TXFP报文优先级的判定条件
    13. }CAN_InitTypeDef;

    时间触发功能在某些CAN标准中会使用到。

    使用自动离线管理可以在节点出错离线后适时自动恢复,不需要软件干预。

    使能自动唤醒功能后它会在监测到总线活动后自动唤醒。

    使用自动重传功能,会一直发送报文直到成功为止。

    锁定FIFO后,若FIFO溢出时会丢弃新数据,否则在FIFO溢出时以新数据覆盖旧数据。

    CAN_TXFP使能时,以报文存入发送邮箱的先后顺序来发送,否则按照报文ID的优先级来发送。

    CANTxMsg发送结构体

    1. typedef struct{
    2. uint32_t StdId; //标准标识符11位,0~0x7FF
    3. uint32_t ExtId; //扩展标识符29位,0~0x1FFFFFFF
    4. uint8_t IDE; //存储IDE扩展标志
    5. uint8_t RTR; //存储RTR远程帧标志
    6. uint8_t DLC; //存储报文数据段的长度,0~8
    7. uint8_t Data[8]; //存储报文数据段的内容
    8. }CanTxMsg;

    IDE选择宏:CAN_Id_Standard、CAN_Id_Extended。根据宏选择StdId或ExtId。

    RTR选择宏:CAN_RTR_Data、CAN_RTR_Remote。由于遥控帧没有数据段,所以当RTR选择CAN_RTR_Remote时,Data[8]成员的内容是无效的。

    CANRxMsg接收结构体

    1. typedef struct{
    2. uint32_t StdId; //标准标识符11位,0~0x7FF
    3. uint32_t ExtId; //扩展标识符29位,0~0x1FFFFFFF
    4. uint8_t IDE; //存储IDE扩展标志
    5. uint8_t RTR; //存储RTR远程帧标志
    6. uint8_t DLC; //存储报文数据段的长度,0~8
    7. uint8_t Data[8]; //存储报文数据段的内容
    8. uint8_t FMI; //存储了本报文是由经过筛选器存储进FIFO的,0~0xFF
    9. }CanRxMsg;

    FMI,存储了筛选器的编号,表示本报文是经过哪个筛选器存储进接收FIFO的,可以用它简化软件处理。

    CAN_FilterInitTypeDef筛选器结构体

    1. typedef struct{
    2. uint16_t CAN_FilterIdHigh; //CAN_FxR1寄存器的高16位
    3. uint16_t CAN_FilterIdLow; //CAN_FxR1寄存器的低16位
    4. uint16_t CAN_FilterMaskIdHigh; //CAN_FxR2寄存器的高16位
    5. uint16_t CAN_FilterMaskIdLow; //CAN_FxR2寄存器的低16位
    6. uint16_t CAN_FilterFIFOAssignment; //设置经过筛选后数据存储到哪个接收FIFO
    7. uint8_t CAN_FilterNumber; //筛选器编号
    8. uint8_t CAN_FilterMode; //筛选器模式
    9. uint8_t CAN_FilterScale; //设置筛选器的尺度
    10. FunctionalState CAN_FilterActivation; //是否使能本筛选器
    11. }CAN_FilterInitTypeDef;
     模式CAN_FilterIdHighCAN_FilterIdLowCAN_FilterMaskIdHighCAN_FilterMaskIdLow
    32位列表模式ID1的高16位ID1的低16位ID2的高16位ID2的低16位
    16位列表模式ID1的完整数值ID2的完整数值ID3的完整数值ID4的完整数值
    32位掩码模式ID1的高16位ID1的低16位ID1掩码的高16位ID1掩码的低16位
    16位掩码模式ID1的完整数值ID2的完整数值ID1掩码的完整数值ID2掩码的完整数值

    CAN_FilterFIFOAssignment选择宏:CAN_Filter_FIFO0、CAN_Filter_FIFO1。

    CAN_FilterMode选择宏:CAN_FilterMode_IdList、CAN_FilterMode_IdMask。

    CAN_FilterScale选择宏:CAN_FilterScale_32bit、CAN_FilterScale_16bit。

    CAN OPEN在汽车行业用的比较多,有空可以学习一下。

  • 相关阅读:
    spring使用@Value标签读取.properties文件的中文乱码问题的解决
    Scrum敏捷开发培训团队和组织来说的重要性
    React报错之useNavigate() may be used only in context of Router
    零基础学ptyhon之字典
    内网穿透的应用-通过内网穿透快速搭建公网可访问的Spring Boot接口调试环境
    万字详文,剖析企业数字化的降“本”增效
    机器学习 | 模型评估和选择 各种评估指标总结——错误率精度-查准率查全率-真正例率假正例率 PR曲线ROC曲线
    JavaWeb-使用session机制和cookie机制改造JavaWeb基础项目
    React技术栈 --》文件模块化和按钮绑定事件 ## Day5
    Git 操作流程与命令汇总
  • 原文地址:https://blog.csdn.net/weixin_47077788/article/details/127807133