STM32-CAN通訊

CAN協議簡介

CAN 是控制器局域網絡(Controller Area Network)的簡稱, 它是由研發和生產汽車電子產品著稱的德國 BOSCH 公司開發的,並最終成爲國際標準(ISO11519) , 是國際上應用最普遍的現場總線之一。編程

CAN 總線協議已經成爲汽車計算機控制系統和嵌入式工業控制局域網的標準總線,而且擁有以 CAN 爲底層協議專爲大型貨車和重工機械車輛設計的 J1939 協議。近年來, 它具備的高可靠性和良好的錯誤檢測能力受到重視,被普遍應用於汽車計算機控制系統和環境溫度惡劣、電磁輻射強及振動大的工業環境。緩存

CAN物理層

與 I2C、 SPI 等具備時鐘信號的同步通信方式不一樣, CAN 通信並非以時鐘信號來進行同步的,它是一種異步通信,只具備 CAN_High 和 CAN_Low 兩條信號線,共同構成一組差分信號線,以差分信號的形式進行通信。網絡

  1. 閉環總線網絡

CAN 物理層的形式主要有兩種, 圖 43-1 中的 CAN 通信網絡是一種遵循 ISO11898 標準的高速、短距離「閉環網絡」,它的總線最大長度爲 40m,通訊速度最高爲 1Mbps,總線的兩端各要求有一個「120 歐」的電阻。架構

  1. 開環總線網絡

圖 43-2 中的是遵循 ISO11519-2 標準的低速、遠距離「開環網絡」,它的最大傳輸距離爲 1km,最高通信速率爲 125kbps,兩根總線是獨立的、不造成閉環,要求每根總線上各串聯有一個「2.2 千歐」的電阻。異步

  1. 通信節點

從 CAN 通信網絡圖可瞭解到, CAN 總線上能夠掛載多個通信節點,節點之間的信號通過總線傳輸,實現節點間通信。因爲 CAN 通信協議不對節點進行地址編碼,而是對數據內容進行編碼的,因此網絡中的節點個數理論上不受限制,只要總線的負載足夠便可,能夠經過中繼器加強負載。函數

CAN 通信節點由一個 CAN 控制器及 CAN 收發器組成,控制器與收發器之間經過CAN_Tx 及 CAN_Rx 信號線相連,收發器與 CAN 總線之間使用 CAN_High 及 CAN_Low信號線相連。其中 CAN_Tx 及 CAN_Rx 使用普通的相似 TTL 邏輯信號,而 CAN_High 及CAN_Low 是一對差分信號線,使用比較特別的差分信號,下一小節再詳細說明。oop

當 CAN 節點須要發送數據時, 控制器把要發送的二進制編碼經過 CAN_Tx 線發送到收發器,而後由收發器把這個普通的邏輯電平信號轉化成差分信號,經過差分線CAN_High 和 CAN_Low 線輸出到 CAN 總線網絡。而經過收發器接收總線上的數據到控制器時,則是相反的過程,收發器把總線上收到的 CAN_High 及 CAN_Low 信號轉化成普通的邏輯電平信號,經過 CAN_Rx 輸出到控制器中。學習

例如, STM32 的 CAN 片上外設就是通信節點中的控制器,爲了構成完整的節點,還要給它外接一個收發器,在咱們實驗板中使用型號爲 TJA1050 的芯片做爲 CAN 收發器。CAN 控制器與 CAN 收發器的關係如同 TTL 串口與 MAX3232 電平轉換芯片的關係,MAX3232 芯片把 TTL 電平的串口信號轉換成 RS-232 電平的串口信號, CAN 收發器的做用則是把 CAN 控制器的 TTL 電平信號轉換成差分信號(或者相反)。測試

  1. 差分信號

差分信號又稱差模信號,與傳統使用單根信號線電壓表示邏輯的方式有區別,使用差分信號傳輸時,須要兩根信號線,這兩個信號線的振幅相等,相位相反,經過兩根信號線的電壓差值來表示邏輯 0 和邏輯 1。見圖 43-3,它使用了 V+與 V-信號的差值表達出了圖下方的信號。ui

相對於單信號線傳輸的方式,使用差分信號傳輸具備以下優勢:

 抗干擾能力強,當外界存在噪聲干擾時,幾乎會同時耦合到兩條信號線上,而接收端只關心兩個信號的差值,因此外界的共模噪聲能夠被徹底抵消。

 能有效抑制它對外部的電磁干擾,一樣的道理,因爲兩根信號的極性相反,他們對外輻射的電磁場能夠相互抵消,耦合的越緊密,泄放到外界的電磁能量越少。

 時序定位精確, 因爲差分信號的開關變化是位於兩個信號的交點,而不像普通單端信號依靠高低兩個閾值電壓判斷,於是受工藝,溫度的影響小,能下降時序上的偏差,同時也更適合於低幅度信號的電路。

因爲差分信號線具備這些優勢,因此在 USB 協議、 485 協議、以太網協議及 CAN 協議的物理層中,都使用了差分信號傳輸。

  1. CAN 協議中的差分信號

CAN 協議中對它使用的 CAN_High 及 CAN_Low 表示的差分信號作了規定,見表 43-1及圖 43-4。以高速 CAN 協議爲例,當表示邏輯 1 時(隱性電平), CAN_High 和 CAN_Low線上的電壓均爲 2.5v,即它們的電壓差 VH-VL=0V;而表示邏輯 0 時(顯性電平),CAN_High 的電平爲 3.5V, CAN_Low 線的電平爲 1.5V,即它們的電壓差爲 VH-VL=2V。例如,當 CAN 收發器從 CAN_Tx 線接收到來自 CAN 控制器的低電平信號時(邏輯 0),它會使 CAN_High 輸出 3.5V,同時 CAN_Low 輸出 1.5V,從而輸出顯性電平表示邏輯 0。

在 CAN 總線中,必須使它處於隱性電平(邏輯 1)或顯性電平(邏輯 0)中的其中一個狀態。假若有兩個 CAN 通信節點,在同一時間,一個輸出隱性電平,另外一個輸出顯性電平,相似 I2C 總線的「線與」特性將使它處於顯性電平狀態,顯性電平的名字就是這樣來的, 便可以認爲顯性具備優先的意味。

因爲 CAN 總線協議的物理層只有 1 對差分線,在一個時刻只能表示一個信號,因此對通信節點來講, CAN 通信是半雙工的,收發數據須要分時進行。在 CAN 的通信網絡中,由於共用總線,在整個網絡中同一時刻只能有一個通信節點發送信號,其他的節點在該時刻都只能接收。

協議層

以上是 CAN 的物理層標準,約定了電氣特性,如下介紹的協議層則規定了通信邏輯。

  1. CAN 的波特率及位同步

因爲 CAN 屬於異步通信,沒有時鐘信號線,鏈接在同一個總線網絡中的各個節點會像串口異步通信那樣,節點間使用約定好的波特率進行通信,特別地, CAN 還會使用「位同步」 的方式來抗干擾、吸取偏差,實現對總線電平信號進行正確的採樣,確保通信正常。

位時序分解

爲了實現位同步, CAN 協議把每個數據位的時序分解成如圖 43-5 所示的 SS 段、PTS 段、 PBS1 段、 PBS2 段,這四段的長度加起來即爲一個 CAN 數據位的長度。分解後最小的時間單位是 Tq,而一個完整的位由 8~25 個 Tq 組成。爲方便表示, 圖 43-5 中的高低電平直接表明信號邏輯 0 或邏輯 1(不是差分信號)。

該圖中表示的 CAN 通信信號每個數據位的長度爲 19Tq,其中 SS 段佔 1Tq, PTS 段佔 6Tq, PBS1 段佔 5Tq, PBS2 段佔 7Tq。信號的採樣點位於 PBS1 段與 PBS2 段之間,經過控制各段的長度,能夠對採樣點的位置進行偏移,以便準確地採樣。

各段的做用如介紹下:

 SS 段(SYNC SEG)

SS 譯爲同步段, 若通信節點檢測到總線上信號的跳變沿被包含在 SS 段的範圍以內,則表示節點與總線的時序是同步的,當節點與總線同步時,採樣點採集到的總線電平便可被肯定爲該位的電平。 SS 段的大小固定爲 1Tq。

 PTS 段(PROP SEG)

PTS 譯爲傳播時間段,這個時間段是用於補償網絡的物理延時時間。 是總線上輸入比較器延時和輸出驅動器延時總和的兩倍。 PTS 段的大小能夠爲 1~8Tq。

 PBS1 段(PHASE SEG1),PBS1 譯爲相位緩衝段,主要用來補償邊沿階段的偏差,它的時間長度在從新同步的時候能夠加長。 PBS1 段的初始大小能夠爲 1~8Tq。

 PBS2 段(PHASE SEG2)

PBS2 這是另外一個相位緩衝段,也是用來補償邊沿階段偏差的,它的時間長度在從新同步時能夠縮短。 PBS2 段的初始大小能夠爲 2~8Tq。

通信的波特率

總線上的各個通信節點只要約定好 1 個 Tq 的時間長度以及每個數據位佔據多少個Tq,就能夠肯定 CAN 通信的波特率。

例如,假設上圖中的 1Tq=1us,而每一個數據位由 19 個 Tq 組成,則傳輸一位數據須要時間 T1bit =19us,從而每秒能夠傳輸的數據位個數爲:

1x106/19 = 52631.6 (bps)

這個每秒可傳輸的數據位的個數即爲通信中的波特率。

同步過程分析

波特率只是約定了每一個數據位的長度,數據同步還涉及到相位的細節,這個時候就須要用到數據位內的 SS、 PTS、 PBS1 及 PBS2 段了。

根據對段的應用方式差別, CAN 的數據同步分爲硬同步和從新同步。其中硬同步只是當存在「幀起始信號」時起做用,沒法確保後續一連串的位時序都是同步的,而從新同步方式可解決該問題,這兩種方式具體介紹以下:

(1) 硬同步

若某個 CAN 節點經過總線發送數據時,它會發送一個表示通信起始的信號(即下一小節介紹的幀起始信號),該信號是一個由高變低的降低沿。而掛載到 CAN 總線上的通信節點在不發送數據時,會時刻檢測總線上的信號。

見圖 43-6,能夠看到當總線出現幀起始信號時,某節點檢測到總線的幀起始信號不在節點內部時序的 SS 段範圍,因此判斷它本身的內部時序與總線不一樣步,於是這個狀態的採樣點採集得的數據是不正確的。因此節點以硬同步的方式調整,把本身的位時序中的 SS段平移至總線出現降低沿的部分,得到同步,同步後採樣點就能夠採集得正確數據了。

(2) 從新同步

前面的硬同步只是當存在幀起始信號時才起做用,若是在一幀很長的數據內,節點信號與總線信號相位有偏移時,這種同步方式就無能爲力了。於是須要引入從新同步方式,它利用普通數據位的高至低電平的跳變沿來同步(幀起始信號是特殊的跳變沿)。從新同步與硬同步方式類似的地方是它們都使用 SS 段來進行檢測,同步的目的都是使節點內的 SS段把跳變沿包含起來。

從新同步的方式分爲超前和滯後兩種狀況,以總線跳變沿與 SS 段的相對位置進行區分。第一種相位超前的狀況如圖 43-7,節點從總線的邊沿跳變中,檢測到它內部的時序比總線的時序相對超前 2Tq,這時控制器在下一個位時序中的 PBS1 段增長 2Tq 的時間長度,使得節點與總線時序從新同步。

第二種相位滯後的狀況如圖 43-8,節點從總線的邊沿跳變中,檢測到它的時序比總線的時序相對滯後 2Tq,這時控制器在前一個位時序中的 PBS2 段減小 2Tq 的時間長度,得到同步。

在從新同步的時候, PBS1 和 PBS2 中增長或減小的這段時間長度被定義爲「從新同步補償寬度 SJW (reSynchronization Jump Width)」。通常來講 CAN 控制器會限定 SJW 的最大值,如限定了最大 SJW=3Tq 時,單次同步調整的時候不能增長或減小超過 3Tq 的時間長度,如有須要,控制器會經過屢次小幅度調整來實現同步。當控制器設置的 SJW 極限值較大時,能夠吸取的偏差加大,但通信的速度會降低。

  1. CAN 的報文種類及結構

在 SPI 通信中, 片選、時鐘信號、數據輸入及數據輸出這 4 個信號都有單獨的信號線,I2C 協議包含有時鐘信號及數據信號 2 條信號線,異步串口包含接收與發送 2 條信號線,這些協議包含的信號都比 CAN 協議要豐富,它們能輕易進行數據同步或區分數據傳輸方向。而 CAN 使用的是兩條差分信號線,只能表達一個信號,簡潔的物理層決定了 CAN 必然要配上一套更復雜的協議,如何用一個信號通道實現一樣、甚至更強大的功能呢? CAN協議給出的解決方案是對數據、操做命令(如讀/寫)以及同步信號進行打包,打包後的這些內容稱爲報文。

報文的種類

在原始數據段的前面加上傳輸起始標籤、片選(識別)標籤和控制標籤,在數據的尾段加上 CRC 校驗標籤、應答標籤和傳輸結束標籤,把這些內容按特定的格式打包好,就能夠用一個通道表達各類信號了, 各類各樣的標籤就如同 SPI 中各類通道上的信號,起到了協同傳輸的做用。當整個數據包被傳輸到其它設備時,只要這些設備按格式去解讀,就能還原出原始數據,這樣的報文就被稱爲 CAN 的「數據幀」 。

爲了更有效地控制通信, CAN 一共規定了 5 種類型的幀,它們的類型及用途說明如表43-2。

<table><colgroup><col><col></colgroup><tbody><tr><th><div class="table-cell-line"><span>幀</span></div></th><th><div class="table-cell-line"><span>幀用途</span></div></th></tr><tr><td><div class="table-cell-line"><span>數據幀</span></div></td><td><div class="table-cell-line"><span>用於節點向外傳送數據</span></div></td></tr><tr><td><div class="table-cell-line"><span>遙控幀</span></div></td><td><div class="table-cell-line"><span>用於向遠端節點請求數據</span></div></td></tr><tr><td><div class="table-cell-line"><span>錯誤幀</span></div></td><td><div class="table-cell-line"><span>用於向遠端節點通知校驗錯誤,請求從新發送上一個數據</span></div></td></tr><tr><td><div class="table-cell-line"><span>過載幀</span></div></td><td><div class="table-cell-line"><span>用於通知遠端節點:本節點還沒有作好接收準備</span></div></td></tr><tr><td><div class="table-cell-line"><span>幀間隔</span></div></td><td><div class="table-cell-line"><span>用於將數據幀及遙控幀與前面的幀分離開來</span></div></td></tr></tbody></table>

數據幀的結構

數據幀是在 CAN 通信中最主要、最複雜的報文,咱們來了解它的結構,見圖 43-9。

數據幀以一個顯性位(邏輯 0)開始,以 7 個連續的隱性位(邏輯 1)結束,在它們之間,分別有仲裁段、控制段、數據段、 CRC 段和 ACK 段

 幀起始

SOF 段(Start Of Frame),譯爲幀起始,幀起始信號只有一個數據位,是一個顯性電平,它用於通知各個節點將有數據傳輸,其它節點經過幀起始信號的電平跳變沿來進行硬同步。

 仲裁段

當同時有兩個報文被髮送時,總線會根據仲裁段的內容決定哪一個數據包能被傳輸,這也是它名稱的由來。

仲裁段的內容主要爲本數據幀的 ID 信息(標識符), 數據幀具備標準格式和擴展格式兩種,區別就在於 ID 信息的長度,標準格式的 ID 爲 11 位,擴展格式的 ID 爲 29 位,它在標準 ID 的基礎上多出 18 位。在 CAN 協議中, ID 起着重要的做用,它決定着數據幀發送的優先級,也決定着其它節點是否會接收這個數據幀。 CAN 協議不對掛載在它之上的節點分配優先級和地址,對總線的佔有權是由信息的重要性決定的,即對於重要的信息,咱們會給它打包上一個優先級高的 ID,使它可以及時地發送出去。也正由於它這樣的優先級分配原則,使得 CAN 的擴展性大大增強,在總線上增長或減小節點並不影響其它設備。報文的優先級,是經過對 ID 的仲裁來肯定的。根據前面對物理層的分析咱們知道若是總線上同時出現顯性電平和隱性電平,總線的狀態會被置爲顯性電平, CAN 正是利用這個特性進行仲裁。

若兩個節點同時競爭 CAN 總線的佔有權,當它們發送報文時, 若首先出現隱性電平,則會失去對總線的佔有權,進入接收狀態。見圖 43-10,在開始階段,兩個設備發送的電平同樣,因此它們一直繼續發送數據。到了圖中箭頭所指的時序處,節點單元 1 發送的爲隱性電平,而此時節點單元 2 發送的爲顯性電平,因爲總線的「線與」特性使它表達出顯示電平,所以單元 2 競爭總線成功,這個報文得以被繼續發送出去。

仲裁段 ID 的優先級也影響着接收設備對報文的反應。由於在 CAN 總線上數據是以廣播的形式發送的,全部鏈接在 CAN 總線的節點都會收到全部其它節點發出的有效數據,於是咱們的 CAN 控制器大多具備根據 ID 過濾報文的功能,它能夠控制本身只接收某些 ID的報文。

回看圖 43-9 中的數據幀格式,可看到仲裁段除了報文 ID 外,還有 RTR、 IDE 和 SRR位。

(1) RTR 位(Remote Transmission Request Bit),譯做遠程傳輸請求位,它是用於區分數據幀和遙控幀的,當它爲顯性電平時表示數據幀,隱性電平時表示遙控幀。

(2) IDE 位(Identifier Extension Bit),譯做標識符擴展位,它是用於區分標準格式與擴展格式,當它爲顯性電平時表示標準格式,隱性電平時表示擴展格式。

(3) SRR 位(Substitute Remote Request Bit),只存在於擴展格式,它用於替代標準格式中的RTR 位。因爲擴展幀中的 SRR 位爲隱性位, RTR 在數據幀爲顯性位,因此在兩個 ID相同的標準格式報文與擴展格式報文中,標準格式的優先級較高。

 控制段

在控制段中的 r1 和 r0 爲保留位,默認設置爲顯性位。它最主要的是 DLC 段(Data Length Code),譯爲數據長度碼,它由 4 個數據位組成,用於表示本報文中的數據段含有多少個字節, DLC 段表示的數字爲 0~8。

 數據段

數據段爲數據幀的核心內容,它是節點要發送的原始信息,由 0~8 個字節組成, MSB先行。

 CRC 段

爲了保證報文的正確傳輸, CAN 的報文包含了一段 15 位的 CRC 校驗碼,一旦接收節點算出的 CRC 碼跟接收到的 CRC 碼不一樣, 則它會向發送節點反饋出錯信息,利用錯誤幀請求它從新發送。 CRC 部分的計算通常由 CAN 控制器硬件完成,出錯時的處理則由軟件控制最大重發數。

在 CRC 校驗碼以後,有一個 CRC 界定符,它爲隱性位,主要做用是把 CRC 校驗碼與後面的 ACK 段間隔起來。

 ACK 段

ACK 段包括一個 ACK 槽位,和 ACK 界定符位。相似 I2C 總線,在 ACK 槽位中,發送節點發送的是隱性位,而接收節點則在這一位中發送顯性位以示應答。在 ACK 槽和幀結束之間由 ACK 界定符間隔開。

 幀結束

EOF 段(End Of Frame),譯爲幀結束,幀結束段由發送節點發送的 7 個隱性位表示結束。

其它報文的結構

關於其它的 CAN 報文結構,再也不展開講解,其主要內容見圖 43-11。

STM32的CAN外設簡介

STM32 的芯片中具備 bxCAN 控制器 (Basic Extended CAN), 它支持 CAN 協議 2.0A 和2.0B 標準。

該 CAN 控制器支持最高的通信速率爲 1Mb/s;能夠自動地接收和發送 CAN 報文,支持使用標準 ID 和擴展 ID 的報文;外設中具備 3 個發送郵箱,發送報文的優先級可使用軟件控制,還能夠記錄發送的時間;具備 2 個 3 級深度的接收 FIFO,可以使用過濾功能只接收或不接收某些 ID 號的報文;可配置成自動重發;不支持使用 DMA 進行數據收發。

STM32的CAN架構剖析

STM32 的有兩組 CAN 控制器,其中 CAN1 是主設備,框圖中的「存儲訪問控制器」是由 CAN1 控制的, CAN2 沒法直接訪問存儲區域,因此使用 CAN2 的時候必須使能CAN1 外設的時鐘。框圖中主要包含 CAN 控制內核、發送郵箱、接收 FIFO 以及驗收篩選器,下面對框圖中的各個部分進行介。

  1. CAN 控制內核

框圖中標號1處的 CAN 控制內核包含了各類控制寄存器及狀態寄存器,咱們主要講解其中的主控制寄存器 CAN_MCR 及位時序寄存器 CAN_BTR。

主控制寄存器 CAN_MCR

主控制寄存器 CAN_MCR 負責管理 CAN 的工做模式,它使用如下寄存器位實現控制。

(1) DBF 調試凍結功能

DBF(Debug freeze)調試凍結,使用它可設置 CAN 處於工做狀態或禁止收發的狀態,禁止收發時仍可訪問接收 FIFO 中的數據。這兩種狀態是當 STM32 芯片處於程序調試模式時才使用的,平時使用並不影響。

(2) TTCM 時間觸發模式

TTCM(Time triggered communication mode)時間觸發模式,它用於配置 CAN 的時間觸發通訊模式,在此模式下, CAN 使用它內部定時器產生時間戳, 並把它保存在CAN_RDTxR、CAN_TDTxR 寄存器中。內部定時器在每一個 CAN 位時間累加,在接收和發送的幀起始位被採樣,並生成時間戳。 利用它能夠實現 ISO 11898-4 CAN 標準的分時同步通訊功能。

(3) ABOM 自動離線管理

ABOM(Automatic bus-off management) 自動離線管理,它用於設置是否使用自動離線管理功能。 當節點檢測到它發送錯誤或接收錯誤超過必定值時,會自動進入離線狀態,在離線狀態中, CAN 不能接收或發送報文。 處於離線狀態的時候,能夠軟件控制恢復或者直接使用這個自動離線管理功能,它會在適當的時候自動恢復。

(4) AWUM 自動喚醒

AWUM(Automatic bus-off management), 自動喚醒功能, CAN 外設可使用軟件進入低功耗的睡眠模式,若是使能了這個自動喚醒功能,當 CAN 檢測到總線活動的時候,會自動喚醒。

(5) NART 自動重傳

NART(No automatic retransmission)報文自動重傳功能,設置這個功能後, 當報文發送失敗時會自動重傳至成功爲止。若不使用這個功能,不管發送結果如何,消息只發送一次。

(6) RFLM 鎖定模式

RFLM(Receive FIFO locked mode)FIFO 鎖定模式,該功能用於鎖定接收 FIFO。鎖定後,當接收 FIFO 溢出時,會丟棄下一個接收的報文。若不鎖定,則下一個接收到的報文會覆蓋原報文。

(7) TXFP 報文發送優先級的斷定方法

TXFP(Transmit FIFO priority)報文發送優先級的斷定方法,當 CAN 外設的發送郵箱中有多個待發送報文時,本功能能夠控制它是根據報文的 ID 優先級仍是報文存進郵箱的順序來發送。

位時序寄存器(CAN_BTR)及波特率

CAN 外設中的位時序寄存器 CAN_BTR 用於配置測試模式、波特率以及各類位內的段參數。

(1) 測試模式

爲方便調試, STM32 的 CAN 提供了測試模式,配置位時序寄存器 CAN_BTR 的 SILM及 LBKM 寄存器位能夠控制使用正常模式、靜默模式、迴環模式及靜默迴環模式,見圖43-13。

各個工做模式介紹以下:

 正常模式

正常模式下就是一個正常的 CAN 節點,能夠向總線發送數據和接收數據。

 靜默模式

靜默模式下,它本身的輸出端的邏輯 0 數據會直接傳輸到它本身的輸入端,邏輯1 能夠被髮送到總線,因此它不能向總線發送顯性位(邏輯 0),只能發送隱性位(邏輯 1)。輸入端能夠從總線接收內容。因爲它只可發送的隱性位不會強制影響總線的狀態,因此把它稱爲靜默模式。這種模式通常用於監測,它能夠用於分析總線上的流量,但又不會由於發送顯性位而影響總線。

 迴環模式

迴環模式下,它本身的輸出端的全部內容都直接傳輸到本身的輸入端,輸出端的內容同時也會被傳輸到總線上,即也可以使用總線監測它的發送內容。輸入端只接收本身發送端的內容,不接收來自總線上的內容。使用迴環模式能夠進行自檢。

 迴環靜默模式

迴環靜默模式是以上兩種模式的結合,本身的輸出端的全部內容都直接傳輸到本身的輸入端,而且不會向總線發送顯性位影響總線,不能經過總線監測它的發送內容。輸入端只接收本身發送端的內容,不接收來自總線上的內容。這種方式能夠在「熱自檢」時使用,即自我檢查的時候,不會干擾總線。

以上說的各個模式,是不須要修改硬件接線的,如當輸出直連輸入時,它是在 STM32芯片內部鏈接的,傳輸路徑不通過 STM32 的 CAN_Tx/Rx 引腳,更不通過外部鏈接的 CAN收發器,只有輸出數據到總線或從總線接收的狀況下才會通過 CAN_Tx/Rx 引腳和收發器。

(2) 位時序及波特率

STM32 外設定義的位時序與咱們前面解釋的 CAN 標準時序有一點區別,見圖 43-14。

STM32 的 CAN 外設位時序中只包含 3 段,分別是同步段 SYNC_SEG、位段 BS1 及位段 BS2,採樣點位於 BS1 及 BS2 段的交界處。其中 SYNC_SEG 段固定長度爲 1Tq,而BS1 及 BS2 段能夠在位時序寄存器 CAN_BTR 設置它們的時間長度,它們能夠在從新同步期間增加或縮短,該長度 SJW 也可在位時序寄存器中配置。

理解 STM32 的 CAN 外設的位時序時,能夠把它的 BS1 段理解爲是由前面介紹的CAN 標準協議中 PTS 段與 PBS1 段合在一塊兒的,而 BS2 段就至關於 PBS2 段。

瞭解位時序後,咱們就能夠配置波特率了。 經過配置位時序寄存器 CAN_BTR 的TS1[3:0]及 TS2[2:0]寄存器位設定 BS1 及 BS2 段的長度後,咱們就能夠肯定每一個 CAN 數據位的時間:

BS1 段時間:

TS1=Tq x (TS1[3:0] + 1),

BS2 段時間:

TS2= Tq x (TS2[2:0] + 1),

一個數據位的時間:

T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq

其中單個時間片的長度 Tq 與 CAN 外設的所掛載的時鐘總線及分頻器配置有關,CAN1 和 CAN2 外設都是掛載在 APB1 總線上的,而位時序寄存器 CAN_BTR 中的 BRP[9:0]寄存器位能夠設置 CAN 外設時鐘的分頻值 ,因此:

Tq = (BRP[9:0]+1) x TPCLK

其中的 PCLK 指 APB1 時鐘,默認值爲 45MHz。

最終能夠計算出 CAN 通信的波特率:

BaudRate = 1/N Tq

例如表 43-3 說明了一種把波特率配置爲 1Mbps 的方式。

  1. CAN 發送郵箱

回到圖 24-5 中的 CAN 外設框圖,在標號2處的是 CAN 外設的發送郵箱,它一共有 3個發送郵箱,即最多能夠緩存 3 個待發送的報文。每一個發送郵箱中包含有標識符寄存器 CAN_TIxR、數據長度控制寄存器 CAN_TDTxR及 2 個數據寄存器 CAN_TDLxR、 CAN_TDHxR,它們的功能見表 43-5。

當咱們要使用 CAN 外設發送報文時,把報文的各個段分解,按位置寫入到這些寄存器中,並對標識符寄存器 CAN_TIxR 中的發送請求寄存器位 TMIDxR_TXRQ 置 1,便可把數據發送出去。

其中標識符寄存器 CAN_TIxR 中的 STDID 寄存器位比較特別。咱們知道 CAN 的標準標識符的總位數爲 11 位,而擴展標識符的總位數爲 29 位的。當報文使用擴展標識符的時候,標識符寄存器 CAN_TIxR 中的 STDID[10:0]等效於 EXTID[18:28]位,它與 EXTID[17:0]共同組成完整的 29 位擴展標識符。

  1. CAN 接收 FIFO

圖 24-5 中的 CAN 外設框圖,在標號3處的是 CAN 外設的接收 FIFO,它一共有 2 個接收 FIFO,每一個 FIFO 中有 3 個郵箱,即最多能夠緩存 6 個接收到的報文。當接收到報文時, FIFO 的報文計數器會自增,而 STM32 內部讀取 FIFO 數據以後,報文計數器會自減,咱們經過狀態寄存器可獲知報文計數器的值,而經過前面主控制寄存器的 RFLM 位,可設置鎖定模式,鎖定模式下 FIFO 溢出時會丟棄新報文,非鎖定模式下 FIFO 溢出時新報文會覆蓋舊報文。

跟發送郵箱相似,每一個接收 FIFO 中包含有標識符寄存器 CAN_RIxR、數據長度控制寄存器CAN_RDTxR 及 2 個數據寄存器 CAN_RDLxR、 CAN_RDHxR,它們的功能見表43-5。

經過中斷或狀態寄存器知道接收 FIFO 有數據後,咱們再讀取這些寄存器的值便可把接收到的報文加載到 STM32 的內存中。

  1. 驗收篩選器

圖 24-5 中的 CAN 外設框圖,在標號4處的是 CAN 外設的驗收篩選器,一共有 28 個篩選器組,每一個篩選器組有 2 個寄存器, CAN1 和 CAN2 共用的篩選器的。

在 CAN 協議中,消息的標識符與節點地址無關,但與消息內容有關。所以,發送節點將報文廣播給全部接收器時,接收節點會根據報文標識符的值來肯定軟件是否須要該消息,爲了簡化軟件的工做, STM32 的 CAN 外設接收報文前會先使用驗收篩選器檢查,只接收須要的報文到 FIFO 中。

篩選器工做的時候,能夠調整篩選 ID 的長度及過濾模式。根據篩選 ID 長度來分類有

有如下兩種:

(1) 檢查 STDID[10:0]、 EXTID[17:0]、 IDE 和 RTR 位,一共 31 位。

(2) 檢查 STDID[10:0]、 RTR、 IDE 和 EXTID[17:15],一共 16 位。

經過配置篩選尺度寄存器 CAN_FS1R 的 FSCx 位能夠設置篩選器工做在哪一個尺度。

而根據過濾的方法分爲如下兩種模式:

(1) 標識符列表模式,它把要接收報文的 ID 列成一個表,要求報文 ID 與列表中的某一個標識符徹底相同才能夠接收,能夠理解爲白名單管理。

(2) 掩碼模式,它把可接收報文 ID 的某幾位做爲列表,這幾位被稱爲掩碼,能夠把它理解成關鍵字搜索,只要掩碼(關鍵字)相同,就符合要求,報文就會被保存到接收 FIFO。

經過配置篩選模式寄存器 CAN_FM1R 的 FBMx 位能夠設置篩選器工做在哪一個模式。

不一樣的尺度和不一樣的過濾方法可以使篩選器工做在圖 43-15 的 4 種狀態。

每組篩選器包含 2 個 32 位的寄存器,分別爲 CAN_FxR1 和 CAN_FxR2,它們用來存儲要篩選的 ID 或掩碼,各個寄存器位表明的意義與圖中兩個寄存器下面「映射」的一欄一致,各個模式的說明見表 43-6。

例以下面的表格所示,在掩碼模式時,第一個寄存器存儲要篩選的 ID,第二個寄存器存儲掩碼,掩碼爲 1 的部分表示該位必須與 ID 中的內容一致,篩選的結果爲表中第三行的ID 值,它是一組包含多個的 ID 值,其中 x 表示該位能夠爲 1 能夠爲 0。

而工做在標識符模式時, 2 個寄存器存儲的都是要篩選的 ID,它只包含 2 個要篩選的ID 值(32 位模式時)。

若是使能了篩選器,且報文的 ID 與全部篩選器的配置都不匹配, CAN 外設會丟棄該報文,不存入接收 FIFO。

  1. 總體控制邏輯

回到圖 24-5 結構框圖,圖中的標號5處表示的是 CAN2 外設的結構,它與 CAN1 外設是同樣的,他們共用篩選器且因爲存儲訪問控制器由 CAN1 控制,因此要使用 CAN2 的時候必需要使能 CAN1 的時鐘。

CAN初始化結構體

從 STM32 的 CAN 外設咱們瞭解到它的功能很是多,控制涉及的寄存器也很是豐富,而使用STM32 標準庫提供的各類結構體及庫函數能夠簡化這些控制過程。跟其它外設同樣,STM32 標準庫提供了 CAN 初始化結構體及初始化函數來控制 CAN 的工做方式,提供了收發報文使用的結構體及收發函數,還有配置控制篩選器模式及 ID 的結構體。這些內容都定義在庫文件「stm32f4xx_can.h」及「stm32f4xx_can.c」中,編程時咱們能夠結合這兩個文件內的註釋使用或參考庫幫助文檔。

首先咱們來學習初始化結構體的內容,見代碼清單 24-1。

代碼清單 43-1 CAN 初始化結構體

/**

* @brief CAN 初始化結構體

*/

typedef struct {

    uint16_t CAN_Prescaler; /*配置 CAN 外設的時鐘分頻,可設置爲 1-1024*/

    uint8_t CAN_Mode; /*配置 CAN 的工做模式,迴環或正常模式*/

    uint8_t CAN_SJW; /*配置 SJW 極限值 */

    uint8_t CAN_BS1; /*配置 BS1 段長度*/

    uint8_t CAN_BS2; /*配置 BS2 段長度 */

    FunctionalState CAN_TTCM; /*是否使能 TTCM 時間觸發功能*/

    FunctionalState CAN_ABOM; /*是否使能 ABOM 自動離線管理功能*/

    FunctionalState CAN_AWUM; /*是否使能 AWUM 自動喚醒功能 */

    FunctionalState CAN_NART; /*是否使能 NART 自動重傳功能*/

    FunctionalState CAN_RFLM; /*是否使能 RFLM 鎖定 FIFO 功能*/

    FunctionalState CAN_TXFP; /*配置 TXFP 報文優先級的斷定方法*/

} CAN_InitTypeDef;

這些結構體成員說明以下,其中括號內的文字是對應參數在 STM32 標準庫中定義的宏,這些結構體成員都是「43.2.1 1CAN 控制內核」小節介紹的內容,可對比閱讀:

(1) CAN_Prescaler

本成員設置 CAN 外設的時鐘分頻,它可控制時間片 Tq 的時間長度,這裏設置的值最終會減 1 後再寫入 BRP 寄存器位,即前面介紹的 Tq 計算公式:

Tq = (BRP[9:0]+1) x TPCLK

等效於: Tq = CAN_Prescaler x TPCLK

(2) CAN_Mode

本成員設置 CAN 的工做模式,可設置爲正常模式(CAN_Mode_Normal)、迴環模式(CAN_Mode_LoopBack)、靜默模式(CAN_Mode_Silent)以及迴環靜默模式(CAN_Mode_Silent_LoopBack)。

(3) CAN_SJW

本成員能夠配置 SJW 的極限長度,即 CAN 從新同步時單次可增長或縮短的最大長度,它能夠被配置爲 1-4Tq(CAN_SJW_1/2/3/4tq)。

(4) CAN_BS1

本成員用於設置 CAN 位時序中的 BS1 段的長度,它能夠被配置爲 1-16 個 Tq 長度(CAN_BS1_1/2/3…16tq)。

(5) CAN_BS2

本成員用於設置 CAN 位時序中的 BS2 段的長度,它能夠被配置爲 1-8 個 Tq 長度(CAN_BS2_1/2/3…8tq)。SYNC_SEG、 BS1 段及 BS2 段的長度加起來即一個數據位的長度,即前面介紹的原來

計算公式:

T1bit =1Tq+TS1+TS2 =1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)

等效於: T1bit = 1Tq+CAN_BS1+CAN_BS2

(6) CAN_TTCM

本成員用於設置是否使用時間觸發功能(ENABLE/DISABLE),時間觸發功能在某些CAN 標準中會使用到。

(7) CAN_ABOM

本成員用於設置是否使用自動離線管理(ENABLE/DISABLE),使用自動離線管理能夠在節點出錯離線後適時自動恢復,不須要軟件干預。

(8) CAN_ AWUM

本成員用於設置是否使用自動喚醒功能(ENABLE/DISABLE),使能自動喚醒功能後它會在監測到總線活動後自動喚醒。

(9) CAN_ABOM

本成員用於設置是否使用自動離線管理功能(ENABLE/DISABLE),使用自動離線管理能夠在出錯時離線後適時自動恢復,不須要軟件干預。

(10) CAN_NART

本成員用於設置是否使用自動重傳功能(ENABLE/DISABLE),使用自動重傳功能時,會一直髮送報文直到成功爲止。

(11) CAN_RFLM

本成員用於設置是否使用鎖定接收 FIFO(ENABLE/DISABLE),鎖定接收 FIFO 後,若FIFO 溢出時會丟棄新數據,不然在 FIFO 溢出時以新數據覆蓋舊數據。

(12) CAN_TXFP

本成員用於設置發送報文的優先級斷定方法(ENABLE/DISABLE),使能時,以報文存入發送郵箱的前後順序來發送,不然按照報文 ID 的優先級來發送。

配置完這些結構體成員後,咱們調用庫函數 CAN_Init 便可把這些參數寫入到 CAN 控制寄存器中,實現 CAN 的初始化。

CAN發送及接收結構體

在發送或接收報文時,須要往發送郵箱中寫入報文信息或從接收 FIFO 中讀取報文信息,利用 STM32 標準庫的發送及接收結構體能夠方便地完成這樣的工做,它們的定義見代碼清單 43-2。

代碼清單 43-2 CAN 發送及接收結構體

/**

* @brief CAN Tx message structure definition

* 發送結構體

*/

typedef struct {

    uint32_t StdId; /*存儲報文的標準標識符 11 位, 0-0x7FF. */

    uint32_t ExtId; /*存儲報文的擴展標識符 29 位, 0-0x1FFFFFFF. */

    uint8_t IDE; /*存儲 IDE 擴展標誌 */

    uint8_t RTR; /*存儲 RTR 遠程幀標誌*/

   uint8_t DLC; /*存儲報文數據段的長度, 0-8 */

   uint8_t Data[8]; /*存儲報文數據段的內容 */

} CanTxMsg;



/**

* @brief CAN Rx message structure definition

* 接收結構體

*/

typedef struct {

    uint32_t StdId; /*存儲了報文的標準標識符 11 位, 0-0x7FF. */

    uint32_t ExtId; /*存儲了報文的擴展標識符 29 位, 0-0x1FFFFFFF. */

    uint8_t IDE; /*存儲了 IDE 擴展標誌 */

    uint8_t RTR; /*存儲了 RTR 遠程幀標誌*/

    uint8_t DLC; /*存儲了報文數據段的長度, 0-8 */

    uint8_t Data[8]; /*存儲了報文數據段的內容 */

    uint8_t FMI; /*存儲了 本報文是由通過篩選器存儲進 FIFO 的, 0-0xFF */

} CanRxMsg;

這些結構體成員都是「43.2.1 2CAN 發送郵箱及 CAN 接收 FIFO」小節介紹的內容,可對比閱讀,發送結構體與接收結構體是相似的,只是接收結構體多了一個 FMI 成員,說明以下:

(1) StdId

本成員存儲的是報文的 11 位標準標識符,範圍是 0-0x7FF。

(2) ExtId

本成員存儲的是報文的 29 位擴展標識符,範圍是 0-0x1FFFFFFF。 ExtId 與 StdId 這兩個成員根據下面的 IDE 位配置,只有一個是有效的。

(3) IDE

本成員存儲的是擴展標誌 IDE 位,當它的值爲宏 CAN_ID_STD 時表示本報文是標準幀,使用 StdId 成員存儲報文 ID;當它的值爲宏 CAN_ID_EXT 時表示本報文是擴展幀,使用 ExtId 成員存儲報文 ID。

(4) RTR

本成員存儲的是報文類型標誌 RTR 位,當它的值爲宏 CAN_RTR_Data 時表示本報文是數據幀;當它的值爲宏 CAN_RTR_Remote 時表示本報文是遙控幀,因爲遙控幀沒有數據段,因此當報文是遙控幀時,下面的 Data[8]成員的內容是無效的。

(5) DLC

本成員存儲的是數據幀數據段的長度,它的值的範圍是 0-8,當報文是遙控幀時 DLC值爲 0。

(6) Data[8]

本成員存儲的就是數據幀中數據段的數據。

(7) FMI

本成員只存在於接收結構體,它存儲了篩選器的編號,表示本報文是通過哪一個篩選器存儲進接收 FIFO 的,能夠用它簡化軟件處理。

CAN篩選器結構體

CAN 的篩選器有多種工做模式,利用篩選器結構體可方便配置,它的定義見代碼清單43-3。

代碼清單 43-3 CAN 篩選器結構體

/**

* @brief CAN filter init structure definition

* CAN 篩選器結構體

*/

typedef struct {

    uint16_t CAN_FilterIdHigh; /*CAN_FxR1 寄存器的高 16 位 */

    uint16_t CAN_FilterIdLow; /*CAN_FxR1 寄存器的低 16 位*/

    uint16_t CAN_FilterMaskIdHigh; /*CAN_FxR2 寄存器的高 16 位*/

    uint16_t CAN_FilterMaskIdLow; /*CAN_FxR2 寄存器的低 16 位 */

    uint16_t CAN_FilterFIFOAssignment; /*設置通過篩選後數據存儲到哪一個接收 FIFO

    */

    uint8_t CAN_FilterNumber; /*篩選器編號,範圍 0-27*/

    uint8_t CAN_FilterMode; /*篩選器模式 */

    uint8_t CAN_FilterScale; /*設置篩選器的尺度 */

    FunctionalState CAN_FilterActivation; /*是否使能本篩選器*/

} CAN_FilterInitTypeDef;

這些結構體成員都是「43.2.1 4 驗收篩選器」小節介紹的內容,可對比閱讀,各個結構體成員的介紹以下:

(1) CAN_FilterIdHigh

CAN_FilterIdHigh 成員用於存儲要篩選的 ID,若篩選器工做在 32 位模式,它存儲的是所篩選 ID 的高 16 位;若篩選器工做在 16 位模式,它存儲的就是一個完整的要篩選的 ID。

(2) CAN_FilterIdLow

相似地, CAN_FilterIdLow 成員也是用於存儲要篩選的 ID,若篩選器工做在 32 位模式,它存儲的是所篩選 ID 的低 16 位;若篩選器工做在 16 位模式,它存儲的就是一個完整的要篩選的 ID。

(3) CAN_FilterMaskIdHigh

CAN_FilterMaskIdHigh 存儲的內容分兩種狀況,當篩選器工做在標識符列表模式時,它的功能與 CAN_FilterIdHigh 相同,都是存儲要篩選的 ID; 而當篩選器工做在掩碼模式時,它存儲的是 CAN_FilterIdHigh 成員對應的掩碼,與 CAN_FilterIdLow 組成一組篩選器。

(4) CAN_FilterMaskIdLow

相似地, CAN_FilterMaskIdLow 存儲的內容也分兩種狀況,當篩選器工做在標識符列表模式時,它的功能與 CAN_FilterIdLow 相同,都是存儲要篩選的 ID; 而當篩選器工做在掩碼模式時,它存儲的是 CAN_FilterIdLow 成員對應的掩碼,與CAN_FilterIdLow 組成一組篩選器。

上面四個結構體的存儲的內容很容易讓人糊塗,請結合前面的圖 43-14 和下面的表43-7 理解,若是還搞不清楚,再結合庫函數 CAN_FilterInit 的源碼來分析。

對這些結構體成員賦值的時候,還要注意寄存器位的映射,即注意哪部分表明 STID,哪部分表明 EXID 以及 IDE、 RTR 位。

(5) CAN_FilterFIFOAssignment

本成員用於設置當報文經過篩選器的匹配後,該報文會被存儲到哪個接收 FIFO,它的可選值爲 FIFO0 或 FIFO1(宏 CAN_Filter_FIFO0/1)。

(6) CAN_FilterNumber

本成員用於設置篩選器的編號,即本過濾器結構體配置的是哪一組篩選器, CAN 一共有 28 個篩選器,因此它的可輸入參數範圍爲 0-27。

(7) CAN_FilterMode

本成員用於設置篩選器的工做模式,能夠設置爲列表模式(宏 CAN_FilterMode_IdList)及掩碼模式(宏 CAN_FilterMode_IdMask)。

(8) CAN_FilterScale

本成員用於設置篩選器的尺度,能夠設置爲 32 位長(宏 CAN_FilterScale_32bit)及 16 位長(宏 CAN_FilterScale_16bit)。

(9) CAN_FilterActivation

本成員用於設置是否激活這個篩選器(宏 ENABLE/DISABLE)。

配置完這些結構體成員後,咱們調用庫函數 CAN_FilterInit 便可把這些參數寫入到篩選控制寄存器中, 從而使用篩選器。咱們前面說若是不理解那幾個 ID 結構體成員存儲的內容時,能夠直接閱讀庫函數 CAN_FilterInit 的源代碼理解,就是由於它直接對寄存器寫入內容,代碼的邏輯是很是清晰的。

參考引用:

  1. 野火---《零死角玩轉STM32-F429挑戰者》
  2. 《STM32F4xx中文參考手冊》
  3. 《Cortex-M4內核編程手冊》
相關文章
相關標籤/搜索