STM32(HAL)——CAN通信

8. CAN

8.1 基本概念

全稱Controller Area Network,是一種半雙工,異步通訊。沒有主從的說法,每個設備都可以發送和接收。

8.1.1 物理層

兩條信號線,CAN_High和CAN_Low兩條差分信號線,以差分形式通訊

兩種網絡形式:

閉環:允許總線最長40m,最高速1Mbps

在這裏插入圖片描述

\circ 規定總線兩端各有一個120Ω電阻。

\circ CAN控制器是各個連接到總線上的設備的控制器,一般需要配備一個CAN收發器(比如咱們戰隊碼盤上的CAN收發器用的是TJA1050),用於將CAN控制器的二進制碼流轉換爲CAN總線的差分電平,在兩條有差分電壓的總線電纜上傳輸數據

開環:最大傳輸距離1Km,最高速125Kbps
在這裏插入圖片描述

\circ 規定每根線串聯一個2.2kΩ的電阻

CAN協議差分信號

在這裏插入圖片描述

\circ 顯性電平對應“0”,隱性電平對應“1”。隱性電平(1)兩條線電壓都是2.5V,即壓差爲0;顯性電平(0)CAN_High和CAN_Low分別爲3.5V和1.5V,壓差爲2V。

\circ 總線上,只要有一個節點輸出顯性,則總線上爲顯性電平;只有所有節點都是隱性電平,總線才爲隱性電平

\circ 由於CAN是半雙工的,收發分開進行,且是總線通訊,所以一個時刻只能有一個節點發送,其他節點在此時只能接收

8.1.2 協議層

位時序

意義:爲了實現正確的總線電平採樣,確保通訊正常。最小單位是Tq(Time Quantum),一個完整位由8~25個Tq組成

組成:SS段、PTS 段、PBS1段、PBS2段

段名 意義 作用
SS(1Tq) 同步段 使總線各節點同步
PTS(1~8Tq) 傳播時間段 補償物理延時,是傳播時間、收發器延時之和的兩倍
PBS1(1~8Tq) 相位緩衝段1 補償變壓階段誤差
PBS2(2~8Tq) 相位緩衝段2 補償邊沿階段誤差
SJW(1~4Tq) 再同步補償寬度 補償時鐘頻率偏差、傳輸延遲等

例如

在這裏插入圖片描述

通訊波特率的計算:CAN使用的時鐘線是APB1 peripheral clocks(假設是APC),即一般是SYSCLK的四分頻。而CAN通訊還要對此進行預分頻(假設是Prescaler),則一個Tq爲 Prescaler / APC(單位s)。而一個數據位佔(SS+PTS+PBS1+PBS2+SJW)個Tq。則一秒可以傳輸的位數就是1TqTq\frac{1}{Tq*一個位得Tq數}

例如:在時鐘樹查得APB1 peripheral clocks是45MHz,預分頻爲5,則一個Tq爲 445MHz=111.1111(ns)\frac{4}{45MHz}=111.1111\dots(ns) ,上圖中有19個Tq,則此時波特率爲119111.11109473689(bps)\frac{1}{19*111.11*10^{-9}}\approx473689(bps)

報文

幀類型:

類型 用途
數據幀 發送單元向接收單元信息內容
遙控幀 接收單元發送單元請求數據
錯誤幀 通知其他單元檢測到錯誤
過載幀 通知還沒有準備好接收
間隔幀 將數據幀或遙控幀前面的幀隔開

數據幀結構:

以一個顯性位(0)開始,以一個7個連續隱形位(1)結束。中間依次是仲裁段、控制段、數據段、CRC段、ACK段,一共7段

在這裏插入圖片描述

幀起始(SOF):一個顯性電平。用於通知各個節點將有數據傳輸

仲裁段:用於表示優先級。標準格式和擴展格式得區別就是在這裏,標準格式ID爲11位,擴展格式爲11+18=29位。RTR(遠程傳輸請求位),用顯隱性電平區別數據幀和遙控幀。

​ IDR(標識符擴展位),顯性是標準形式,隱性是擴展形式。

​ SSR,即標準格式的RTR,是隱性位。

​ ID決定數據幀的優先級,當兩個節點同時競爭總線,則先出現隱性電平的節點失去佔有權,進入接收狀態

控制段:r1和r0是保留位,默認顯性。DLC,數據數組長度,0~8

數據段:08個字節(064位)

CRC段:共16位。15位的CRC校驗碼,1位的界定符,隱性

ACK段:共2位。一位是ACK槽位,發送端發送隱性,接收端發送顯性表示應答;一位是與幀結束的界定符

幀結束(ROF):7個隱形位

8.1.3 過濾器

目的:過濾掉不感興趣的消息,即與本節點無關的消息

兩種模式:列表模式和掩碼模式

過濾器個數:使用一個CAN時可選013號過濾器;使用兩個CAN是,可選用037號過濾器

模式

列表模式:將關注的報文ID做成一張表,當收到的報文ID符合時則接收,否則不接收

優點,精確,能完全過濾掉不需要的報文

缺點,列表數量有限,當感興趣的消息數量過多時則無法全部包含

掩碼模式通過與操作,將部分ID符合的報文接收

優點,感興趣的範圍可以更大

缺點,並不一定能完全過濾掉不關注的報文,精確程度取決於屏蔽碼

位寬

過濾器有32位和16位兩種可選。其中16位只能過濾標準幀,不能過濾擴展幀。

8.2 STM32的CAN

STM32有兩組CAN控制器,CAN1是主設備,負責管理bxCAN(基本擴展CAN,就是CAN)和512字節的SRAM。CAN2是從控制器,不能直接訪問SRAM。使用CAN2必須使能CAN1外設時鐘

STM32中,當CAN接收過濾器使用32位時,掩碼和驗證碼分別拆分成兩個寄存器,每個16位,分別代表高16位和低16位

8.3 CubeMX配置步驟

  1. 左側目錄>Connectivity>點CAN1/CAN2~> Mode勾選Master Mode / Slave Mode

  2. 配置參數,含義如下:
    在這裏插入圖片描述

    參數 意思
    Prescaler 預分頻,即位時序提到的APB1 peripheral clocks繼續分一次頻
    Time Quantum 最小時間單位Tq,自動計算出來的,不需要填寫
    Time Quanta in Bit Segment 1 PBS1段長度
    Time Quanta in Bit Segment 2 PBS2段長度
    ReSynchronization Jump Width 重同步跳躍寬度,即位時序提到的SJW
    Time Triggered Communication Mode 是否使能時間觸發
    Automatic Bus-Off Management 是否使能自動離線管理
    Automatic Wake-Up Mode 是否使能自動喚醒
    Qutomatic Retransmission 是否使能自動重傳
    Receive Fifo Locked Mode 是否使能鎖定FIFO
    Transmit Fifo Priority 配置報文優先級的判斷方法
    Oprating Mode 操作模式

    這些參數也可以在can.c中自行修改

  3. 中斷(NVIC)設置,根據需要設置,一般勾上CAN1 RX0 Interrupt

8.4 編程

HAL庫關於CAN的所有函數定義和結構體定義分別在 Drivers/STM32F4xx_HAL_Driver 文件夾下 stm32f4xx_hal_can.c 和 stm32f4xx_hal_spi.h 中

下面列舉一些基本的和常用的

8.4.1 CAN基本結構體

發送報文定義結構體(CAN_TxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;    /*!標準ID。參數值只能是 0 到 0x7FF(二進制的11位1) */

  uint32_t ExtId;    /*!擴展ID。參數值只能是 0 到 0x1FFFFFFF(二進制的29位1)*/

  uint32_t IDE;      /*!IDE。HAL庫編程時,標準幀填寫CAN_ID_STD,擴展幀填寫CAN_ID_EXT */

  uint32_t RTR;      /*!RTR。HAL庫編程時,數據幀填寫CAN_RTR_DATA,遙控幀填寫CAN_RTR_REMOTE */

  uint32_t DLC;      /*!DLC。數據長度,參數值只能是 0 到 8 */

  FunctionalState TransmitGlobalTime; /*!< Specifies whether the timestamp counter value captured on start
                          of frame transmission, is sent in DATA6 and DATA7 replacing pData[6] and pData[7].
                          @note: Time Triggered Communication Mode must be enabled.
                          @note: DLC must be programmed as 8 bytes, in order these 2 bytes are sent.
                          This parameter can be set to ENABLE or DISABLE. */

} CAN_TxHeaderTypeDef;

接收報文定義結構體(CAN_RxHeaderTypeDef)

typedef struct
{
  uint32_t StdId;   

  uint32_t ExtId;    

  uint32_t IDE;      

  uint32_t RTR;      

  uint32_t DLC;      

  uint32_t Timestamp; /*!< Specifies the timestamp counter value captured on start of frame reception.
                          @note: Time Triggered Communication Mode must be enabled.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFFFF. */

  uint32_t FilterMatchIndex; /*!< Specifies the index of matching acceptance filter element.
                          This parameter must be a number between Min_Data = 0 and Max_Data = 0xFF. */

} CAN_RxHeaderTypeDef;

接收過濾器類型定義結構體(CAN_FilterTypeDef)

typedef struct
{
  uint32_t FilterIdHigh;          /*!過濾器驗證碼ID高16位,只能填0到0xFFFF 中間的數值 */

  uint32_t FilterIdLow;           /*!過濾器ID低16位,只能填0到0xFFFF 中間的數值*/

  uint32_t FilterMaskIdHigh;      /*!過濾器掩碼ID高16位,只能填0到0xFFFF中間的數值 */

  uint32_t FilterMaskIdLow;       /*!過濾器掩碼ID低16位,只能填0到0xFFFF中間的數值 */

  uint32_t FilterFIF(x)Assignment;  /*!將通過的報文放入哪個FIFOx中,填寫FIFO(x) */

  uint32_t FilterBank;            /*!使用過濾器編號。使用一個CAN,則可選 0~13;使用兩個CAN可選                                        0~27 */

  uint32_t FilterMode;            /*!過濾器模式選擇。掩碼模式填寫 CAN_FILTERMODE_IDMASK,列表模
                                     式填寫 CAN_FILTERMODE_IDLIST */

  uint32_t FilterScale;           /*!過濾器位寬,32位是CAN_FILTERSCALE_32BIT,
                                               16位是CAN_FILTERSCALE_16BIT */

  uint32_t FilterActivation;      /*!是否使能過濾器,DISABLE 或 ENABLE */

  uint32_t SlaveStartFilterBank;  /*!< Select the start filter bank for the slave CAN instance.
                                       For single CAN instances, this parameter is meaningless.
                                       For dual CAN instances, all filter banks with lower index are assigned to master
                                       CAN instance, whereas all filter banks with greater index are assigned to slave
                                       CAN instance.
                                       This parameter must be a number between Min_Data = 0 and Max_Data = 27. */

} CAN_FilterTypeDef;

注意:FilterIdHigh、FilterIdLow、FilterMaskIdLow、FilterMaskIdLow這四個成員不是它的名字那麼簡單,

​ 他們的功能取決於使用的過濾器模式。若爲列表模式,則不管是FilterId還是FilterMaskId都表示的是列

​ 表成員。

​ 上述四個成員都是16位的,一定注意下面說的移位操作

​ 在32位過濾器中,一組High和Low檢驗同一個CAN ID;16位過濾器,則可分別獨立檢驗一個ID

過濾器寄存器如下:(使用HAL庫可以不必深挖具體的寄存器,只需注意Mapping每一位的內容)

​ 32位列表模式

在這裏插入圖片描述

​ 16位列表模式

在這裏插入圖片描述
​ 32位掩碼模式
16位掩碼模式
在這裏插入圖片描述

標準幀用16位過濾器表示:FilterIdHigh、FilterIdLow、FilterMaskIdLow、FilterMaskIdLow各可以表示一個列表成員。由於標準幀的ID是11位的,所以需要將其ID左移5位

標準幀用32位過濾器表示:FilterIdHigh、FilterIdLow共同表示一個ID,FilterMaskIdLow、FilterMaskIdLow共同表示一個ID。由於標準幀ID是11位的,故表示時其ID需左移5位存入High,且LOW = 0 | CAN_ID_STD (意思是將IDE位置爲0)

擴展幀用32位過濾器表示:擴展幀的ID是29位的,所以將擴展幀ID先左移3位與32位按高位對齊,再右移16位並取低16位,存入High;將擴展幀ID左移3位與32位對齊,再取低16位存入Low。具體操作如下

CAN_FilterTypeDef sFilterConfig                                 //定義過濾器設置結構體變量
uint32_t StdId =0x321;				                            //一個標準CAN ID
uint32_t ExtId =0x1800f001;			                            //一個擴展CAN ID

sFilterConfig.FilterIdHigh = StdId<<5;			                //標準ID放入FilterIdHigh
sFilterConfig.FilterIdLow = 0|CAN_ID_STD;			            //標準ID,故設置IDE位爲0

sFilterConfig.FilterMaskIdHigh = ((ExtId<<3)>>16)&0xffff;       //擴展幀ID高16位放入                                                                           FilterMaskIdHigh
sFilterConfig.FilterMaskIdLow = (ExtId<<3)&0xffff|CAN_ID_EXT;	//擴展幀ID高16位放入                                                                           FilterMaskIdLow,並設置                                                                     IDE位爲1

關於驗證碼和掩碼:假設有一個關注列表,裏面全是感興趣的報文。驗證碼可以是關注列表中任意一個成員的ID(經上述處理),而掩碼是所有感興趣的成員的同或的結果

在這裏插入圖片描述

綜上,兩種位寬,兩種模式,共四種過濾模式,特點總結如下:

模式 特點
16位列表 可包含四個列表成員
32位列表 可包含兩個列表成員
16位掩碼 可檢驗兩對驗證碼和掩碼
32位掩碼 可檢驗一對驗證碼和掩碼

8.4.2 CAN 基本函數

控制函數如下表

函數 功能
HAL_CAN_Start 開啓CAN通訊
HAL_CAN_Stop 關閉CAN通訊
HAL_CAN_RequestSleep 嘗試進入休眠模式
HAL_CAN_WakeUp 從休眠模式中喚醒
HAL_CAN_IsSleepActive 檢查是否成功進入休眠模式
HAL_CAN_AddTxMessage 向 Tx 郵箱中增加一個消息,並且激活對應的傳輸請求
HAL_CAN_AbortTxRequest 請求中斷傳輸
HAL_CAN_GetTxMailboxesFreeLevel Return Tx mailboxes free level
HAL_CAN_IsTxMessagePending 檢查是否有傳輸請求在指定的 Tx 郵箱上等待
HAL_CAN_GetRxMessage 從Rx FIFO 收取一個 CAN 幀
HAL_CAN_GetRxFifoFillLevel Return Rx FIFO fill level
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)**

功能:開啓CAN,一般一開始就要打開
參數:CAN句柄指針,&hcan1 或 &hcan2
返回值:返回值:HAL狀態

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

功能:配置CAN過濾器
參數:第一個,CAN句柄指針,&hcan1 或 &hcan2
第二個,CAN配置結構體的指針
返回值:返回值:HAL狀態

HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)

功能:使能中斷
參數:第一個,CAN句柄指針,&hcan1 或 &hcan2
第二個,使能哪個中斷,在stm32f4xx_HAL_Driver.h中,搜索Receive Interrupts可以查到各宏定義
返回值:返回值:HAL狀態

void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *hcan)(根據使用0可能替換成1

功能:接收回調函數,CAN回調後進行的操作。一般在此接收數據
參數:第一個,CAN句柄指針
返回值:void

HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, CAN_TxHeaderTypeDef *pHeader, uint8_t aData[], uint32_t *pTxMailbox)**

功能:增加一個消息到第一個空閒的 Tx 郵箱,並且激活對應的傳輸請求

參數:第一個,CAN句柄指針,&hcan1 或 &hcan2
第二個,發送報文定義結構體的指針
​ 第三個,數據幀數組的內容,長度不能超過定義的長度
​ 第四個,Tx郵箱,可填 (uint32_t*)CAN_TX_MAILBOX0 ,CAN_TX_MAILBOX1 , CAN_TX_MAILBOX3
返回值:HAL狀態

HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo, CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])

功能:從Rx FIFO收取一個 CAN 幀
參數:第一個,CAN句柄指針,&hcan1 或 &hcan2​
第二個,Rx FIFO,可填 CAN_RX_FIFO0, CAN_RX_FIFO1
​ 第三個,接收報文定義結構體的指針
​ 第四個,接受數據數組
返回值:HAL狀態

HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, CAN_FilterTypeDef *sFilterConfig)

功能:設置接收過濾器
參數:第一個,CAN句柄指針,&hcan1 或 &hcan2
第二個,過濾器類型定義結構體指針
返回值:HAL狀態

8.4.3 CAN編程步驟示例

  1. 定義接收過濾器類型定義結構體(CAN_FilterTypeDef)變量

  2. 配置CAN接收過濾器HAL_CAN_ConfigFilter

  3. 開啓CAN,HAL_CAN_Start

  4. 發送,HAL_CAN_AddTxMessage

  5. 接收,需要先開啓中斷HAL_CAN_ActivateNotification,第二個參數設置爲CAN_IT_RX_FIFO0_MSG_PENDING

    接收中斷回調函數HAL_CAN_RxFifo0MsgPendingCallback,裏面定義接收報文定義結構體(CAN_RxHeaderTypeDef)結構體變量。用接收函數HAL_CAN_GetRxMessage接收

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章