• 【STM32 CAN】STM32G47x 单片机FDCAN作为普通CAN外设使用教程


    STM32G47x 单片机FDCAN作为普通CAN外设使用教程

    控制器局域网总线(CAN,Controller Area Network)是一种用于实时应用的串行通讯协议总线,它可以使用双绞线来传输信号,是世界上应用最广泛的现场总线之一。CAN协议用于汽车中各种不同元件之间的通信,以此取代昂贵而笨重的配电线束。该协议的健壮性使其用途延伸到其他自动化和工业应用。CAN协议的特性包括完整性的串行数据通讯、提供实时支持、传输速率高达1Mb/s、同时具有11位的寻址以及检错能力。

    硬件说明

    这里使用的是STM32G473VET6主控芯片,具有三个CANFD外设,这些CAN外设同时支持传统CAN通信协议。

    时钟配置情况

    这里STM32主控的SYSCLK(系统时钟)为170MHz。使用外部晶振作为时钟源头。

    在这里插入图片描述

    CANFD外设作为普通CAN外设使用

    CANFD外设

    FDCAN外设子系统由一个CAN模块、一块共享的消息RAM和一个配置模块组成。可以参阅内存映射,以获取这些部分的基址。
    这些模块(FDCAN)符合ISO 11898-1:2015(CAN协议规范版本2.0部分A、B)和CAN FD协议规范版本1.0。
    每个FDCAN实例有0.8千字节的消息RAM,用于实现过滤器、接收FIFOs、传输事件FIFOs和传输FIFOs。

    • 符合CAN协议版本2.0部分A、B和ISO 11898-1:2015、-4
    • 支持最大64数据字节的CAN FD
    • 具有CAN错误日志
    • 支持AUTOSAR和J1939
    • 具有改进的接收过滤器
    • 具有两个接收FIFO,每个有三个有效载荷(每个有效载荷最多64字节)
    • 具有高优先级消息接收时的单独信号提示
    • 具有可配置的传输FIFO/队列,三个有效载荷(每个有效载荷最多64字节)
    • 具有传输事件FIFO
    • 具有可编程的环回测试模式
    • 具有可屏蔽的模块中断
    • 具有两个时钟域:APB总线接口和CAN核心内核时钟
    • 具有支持断电

    CANFD 通信速率计算

    前置知识
    要计算CAN的通信速率首先都了解CAN通信过程中每个bit的构成。
    一个电平位时间主要有以下4个段:

    SS段(SYNC SEG;同步段):若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围内,则表示节点与总线的时序是同步的;(固定1个Tq)
    PTS段(PROP SEG;传播段):这个时间段是用于补偿网络的物理延时时间,是总线上输入比较器延时和输出驱动器延时综合的两倍;(长度可编程:1~8个Tq)
    PBS1段(PHASE SEG1;相位缓冲段1):用于补偿节点间的晶振误差,允许通过重同步对该段加长,在这个时间段末端进行总线状态的采样;(长度可编程:1~8Tq)

    协议层-位时序
    意义:为了实现正确的总线电平采样,确保通讯正常。最小单位是Tq(Time Quantum),一个完整位由8~25个Tq组成,其中一个电平位时间主要有以下4个段:
    在这里插入图片描述

     段名   意义   作用   SS(1Tq)   Sync Seg;同步段  若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围内,则表示节点与总线的时序是同步的;(固定1个Tq)   PTS(1-8Tq)   Prob Seg;传播段   这个时间段是用于补偿网络的物理延时时间,,是传播时间、收发器延时之和的两倍   PBS1(1-8Tq)   Phase Seg1;相位缓冲段1  补偿变压阶段误差   PBS2(2-8Tq)   Phase Seg2;相位缓冲段2  补偿边沿阶段误差   SJW(1-4Tq)   再同步补偿宽度   补偿时钟频率偏差、传输延迟等 

     段名  意义  作用  SS(1Tq)  Sync Seg;同步段 若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围内,则表示节点与总线的时序是同步的;(固定1个Tq)  PTS(1-8Tq)  Prob Seg;传播段  这个时间段是用于补偿网络的物理延时时间,,是传播时间、收发器延时之和的两倍  PBS1(1-8Tq)  Phase Seg1;相位缓冲段1 补偿变压阶段误差  PBS2(2-8Tq)  Phase Seg2;相位缓冲段2 补偿边沿阶段误差  SJW(1-4Tq)  再同步补偿宽度  补偿时钟频率偏差、传输延迟等 " role="presentation" style="position: relative;"> 段名  意义  作用  SS(1Tq)  Sync Seg;同步段 若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围内,则表示节点与总线的时序是同步的;(固定1个Tq)  PTS(1-8Tq)  Prob Seg;传播段  这个时间段是用于补偿网络的物理延时时间,,是传播时间、收发器延时之和的两倍  PBS1(1-8Tq)  Phase Seg1;相位缓冲段1 补偿变压阶段误差  PBS2(2-8Tq)  Phase Seg2;相位缓冲段2 补偿边沿阶段误差  SJW(1-4Tq)  再同步补偿宽度  补偿时钟频率偏差、传输延迟等 
     段名  SS(1Tq)  PTS(1-8Tq)  PBS1(1-8Tq)  PBS2(2-8Tq)  SJW(1-4Tq)  意义  Sync Seg;同步段 Prob Seg;传播段  Phase Seg1;相位缓冲段1 Phase Seg2;相位缓冲段2 再同步补偿宽度  作用  若通讯节点检测到总线上信号的跳变沿被包含在SS段的范围内,则表示节点与总线的时序是同步的;(固定1Tq  这个时间段是用于补偿网络的物理延时时间,,是传播时间、收发器延时之和的两倍  补偿变压阶段误差  补偿边沿阶段误差  补偿时钟频率偏差、传输延迟等 

    在这里插入图片描述

    如下图所示:
    在这里插入图片描述
    C A N 波特率 = 1 1 b i t 所占用时间 = 1 T q ∗ 1 b i t 的 T q 个数 CAN波特率 = \frac{1}{1bit所占用时间} = \frac{1}{Tq*1bit的Tq个数} CAN波特率=1bit所占用时间1=Tq1bitTq个数1

    在这里插入图片描述
    在这里插入图片描述

    上面已经说明了一个数据位(1bit,准确来说是1baud)占**(SS+PTS+PBS1+PBS2+SJW)**个Tq。

    STM32CubeMX界面参数

    在这里插入图片描述
    分别为(Nominal 我不知道为什么是Nominal 这个词,但是如果是CAN FD模式的话,这里NominalPrescaler、NominalSyncJumpWidth 、NominalTimeSeg1 、NominalTimeSeg2 是用于配置仲裁阶段波特率的,DataPrescaler 、DataSyncJumpWidth 、DataTimeSeg1 、DataTimeSeg2 是用于配置数据阶段波特率的。)

    • Basic Parameters:

      • Clock Divider: CAN内核时钟分频系数。
      • Frame Format: 指定CAN帧格式,这里是经典CAN(CAN2.0 B)、FD模式没有比特率切换、FD模式有比特率切换。
      • Mode: 指定CAN控制器的工作模式,如正常模式、环回模式或静默模式。
      • Auto Retransmission: 是否使能自动重发。
      • Transmit Pause: 是否配置禁止传输暂停特性。
      • Protocol Exception: 协议异常处理使能。
      • Nominal Sync Jump Width: 规定名义重同步跳跃宽度,用于时间同步,,即位时序提到的SJW。用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大.
      • Data Prescaler: 数据速率预分频值。CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck),范围1-32。
      • Data Sync Jump Width: 数据阶段的同步跳跃宽度。用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大,范围1-16
      • Data Time Seg1: 数据位时间段1的长度。特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1。
      • Data Time Seg2: 数据位时间段2的长度。对应位时间特性图的 Phase_Seg2。(Pro_Seg + Phase_Seg1 = DataTimeSeg1, Phase_Seg2 = DataTimeSeg2)
      • Std Filters Nbr: 设置标准ID过滤器个数,范围0-128。是配置CAN接受时候使用的滤波器数量,用了多少个就写多少个。
      • Ext Filters Nbr: 设置扩展ID过滤器个数,范围0-64。
      • Tx Fifo Queue Mode: 发送FIFO队列模式。
    • Bit Timings Parameters 位定时参数:

      • Nominal Prescaler: 名义速率预分频器值。CAN时钟分配设置,一般设置为1即可,全部由PLL配置好,tq = NominalPrescaler x (1/ fdcan_ker_ck)。
      • Nominal Time Quantum: 名义时间量子的长度。
      • Nominal Time Seg1: 名义位时间段1的长度。用于动态调节 Phase_Seg1和 Phase_Seg1,所以不可以比Phase_Seg1和 Phase_Seg1大。
      • Nominal Time Seg2: 名义位时间段2的长度。特别注意这里的Seg1,这里是两个参数之和,对应位时间特性图的 Pro_Seg + Phase_Seg1.(Pro_Seg + Phase_Seg1 = NominalTimeSeg1, Phase_Seg2 = NominalTimeSeg2)
      • Nominal Time for one Bit: 名义单比特时间。
      • Nominal Baud Rate: 名义波特率。

    一般没有配置SJW,且STM32的CAN外设的Sync_Seg是固定值1,并且有:
    CAN 波特率 = CAN Freq / (Sync_Seg + Pro_Seg + Phase_Seg1 + Phase_Seg2)

    关于滤波器数量:

    在CAN协议里,报文的标识符不代表节点的地址,而是跟报文的内容相关的。因此,发送者以广播的形式把报文发送给所有的接收者。节点在接收报文时,根据标识符(CAN ID)的值决定软件是否需要该报文;如果需要,就拷贝到SRAM里;如果不需要,报文就被丢弃且无需软件的干预。
    为满足这一需求,bxCAN为应用程序提供了14个位宽可变的、可配置的过滤器组(13~0),以便只接收那些软件需要的报文。硬件过滤的做法节省了CPU开销,否则就必须由软件过滤从而占用一定的CPU开销。每个过滤器组x由2个32位寄存器,CAN_FxR0和CAN_FxR1组成。

    在这个案例中CAN模块的时钟源为PCLK1,为170MHz。
    在这里插入图片描述
    如下图是在CAN使用上图的时钟源的情况下配置125Kbps的波特率,配置为传统CAN模式的情况,作为传统CAN模式,参数DataPrescaler 、DataSyncJumpWidth 、DataTimeSeg1 、DataTimeSeg2没有作用。
    在这里插入图片描述

    测试代码

    
    /**
      * @brief  The application entry point.
      * @retval int
      */
    int main(void)
    {
      /* USER CODE BEGIN 1 */
      /* USER CODE END 1 */
      /* MCU Configuration--------------------------------------------------------*/
    
      /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
      HAL_Init();
      /* USER CODE BEGIN Init */
      /* USER CODE END Init */
      /* Configure the system clock */
      SystemClock_Config();
    
      /* USER CODE BEGIN SysInit */
      /* USER CODE END SysInit */
    
      /* Initialize all configured peripherals */
      MX_GPIO_Init();
      MX_FDCAN1_Init();
      /* USER CODE BEGIN 2 */
    
      HAL_FDCAN_Start(&hfdcan1);
    
      //CAN2.0B 拓展帧消息发送
      FDCAN_TxHeaderTypeDef TxHeader;
      uint8_t TxData[8];
      TxHeader.Identifier = 0x321;
      TxHeader.IdType = FDCAN_EXTENDED_ID;
      TxHeader.TxFrameType = FDCAN_DATA_FRAME;
      TxHeader.DataLength = FDCAN_DLC_BYTES_8;
      TxHeader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
      TxHeader.BitRateSwitch = FDCAN_BRS_OFF;
      TxHeader.FDFormat = FDCAN_CLASSIC_CAN;
      TxHeader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
      TxHeader.MessageMarker = 0;
    
      TxData[0] = 0x00;
      TxData[1] = 0x01;
      TxData[2] = 0x02;
      TxData[3] = 0x03;
      TxData[4] = 0x04;
      TxData[5] = 0x05;
      TxData[6] = 0x06;
      TxData[7] = 0x07;
    
      /* USER CODE END 2 */
    
      /* Infinite loop */
      /* USER CODE BEGIN WHILE */
      while (1)
      {
        /* USER CODE END WHILE */
    
        /* USER CODE BEGIN 3 */
        HAL_Delay(200);
        
        if (HAL_FDCAN_GetTxFifoFreeLevel(&hfdcan1) > 0)
        {
          if (HAL_FDCAN_AddMessageToTxFifoQ(&hfdcan1, &TxHeader, TxData) != HAL_OK)
          {
            Error_Handler();
          }
        }
      }
      /* USER CODE END 3 */
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    运行结果:
    在这里插入图片描述
    如图为CANH对CANL的波形,发送端接了120欧姆的终端电阻,接收测悬空,在接收测测量。(主要是我还没有看到为什么不接CAN隔离芯片或者没有给CAN隔离芯片上电的情况下测不到发送出来的波形。)
    在这里插入图片描述

    CANFD过滤器配置有个FDCAN_FILTER_RANGE_NO_EIDM,其中EIDM是扩展ID屏蔽寄存器

    /** @defgroup FDCAN_filter_type FDCAN Filter Type
      * @{
      */
    #define FDCAN_FILTER_RANGE         ((uint32_t)0x00000000U) /*!< Range filter from FilterID1 to FilterID2                        */
    #define FDCAN_FILTER_DUAL          ((uint32_t)0x00000001U) /*!< Dual ID filter for FilterID1 or FilterID2                       */
    #define FDCAN_FILTER_MASK          ((uint32_t)0x00000002U) /*!< Classic filter: FilterID1 = filter, FilterID2 = mask            */
    #define FDCAN_FILTER_RANGE_NO_EIDM ((uint32_t)0x00000003U) /*!< Range filter from FilterID1 to FilterID2, EIDM mask not applied */
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

  • 相关阅读:
    canvas note
    RegNet架构复现--CVPR2020
    创意电子学-小知识:如何使用面包板
    用Python和Pygame实现简单贪吃蛇游戏
    TienChin 活动管理-准备工作
    算法和数据结构解析-8 : 栈和队列相关问题
    【MySQL系列】使用C语言连接MySQL
    基于ITIL的ITSM工具
    Redis缓存面临的缓存穿透问题
    怎么将图片进行圆角处理?
  • 原文地址:https://blog.csdn.net/qq_42820594/article/details/134381794