STM32 CAN通信詳解
?首先是自己項(xiàng)目工程中自己的東西分享給大家,后面CAN詳解內(nèi)容是轉(zhuǎn)載他人的優(yōu)秀文檔。
?????? 由于STM32F4中我使用的擴(kuò)展標(biāo)識符(ID)是29位(28~0),STM32的過濾器和掩碼是32位分別映射到{10~0、28~0、IDE、RTR、0}上;那么我們就可以根據(jù)這些內(nèi)容建立自己的過濾和掩碼。其中不建議使用CAN接收中斷中的EXtID進(jìn)行多個(gè)節(jié)點(diǎn)ID區(qū)分,因?yàn)檠诖a中為零的是不定的也即不判斷,X可能是0或1。比如下圖中1,ID 、掩碼、映射,之間的關(guān)系。
我們代碼初始化中有提示比如標(biāo)識符ID,ExtId范圍0~0x1FFFFFFF。CAN_FilterIdLow低三位其實(shí)是IDE、RTR、0;過濾ID不要用最低三位。

?如下圖展示的是不用最低3位的CAN_init函數(shù)

另外一種方法是規(guī)定好本機(jī)地址以及目標(biāo)發(fā)送地址,比如我們程序中使用29位擴(kuò)展標(biāo)識符
uint32_t?StdId;?/*存儲(chǔ)報(bào)文的標(biāo)準(zhǔn)標(biāo)識符11位,0-0x7FF. */
uint32_t?ExtId;?/*存儲(chǔ)報(bào)文的擴(kuò)展標(biāo)識符29位,0-0x1FFFFFFF. */
29位ExtId中,28-21位目標(biāo)地址 7-14位本機(jī)地址,那么在CAN發(fā)送中,ExtId表示為

?目標(biāo)地址左移21位,本機(jī)地址左移7位,組成ExtId。另外在過濾中,過濾28-21位,因?yàn)檫@個(gè)是其他設(shè)備發(fā)送過來的,這個(gè)時(shí)候其他設(shè)備28-21位對應(yīng)的本機(jī)地址。如圖

本章參考資料:《STM32F4xx?中文參考手冊2》、《STM32F4xx規(guī)格書》、庫幫助文檔《stm32f4xx_dsp_stdperiph_lib_um.chm》。
若對CAN通訊協(xié)議不了解,可先閱讀《CAN總線入門》、《CAN-bus規(guī)范》文檔內(nèi)容學(xué)習(xí)。
關(guān)于實(shí)驗(yàn)板上的CAN收發(fā)器可查閱《TJA1050》文檔了解。
40.1 CAN協(xié)議簡介
CAN是控制器局域網(wǎng)絡(luò)(Controller Area Network)的簡稱,它是由研發(fā)和生產(chǎn)汽車電子產(chǎn)品著稱的德國BOSCH公司開發(fā)的,并最終成為國際標(biāo)準(zhǔn)(ISO11519),是國際上應(yīng)用最廣泛的現(xiàn)場總線之一。
CAN總線協(xié)議已經(jīng)成為汽車計(jì)算機(jī)控制系統(tǒng)和嵌入式工業(yè)控制局域網(wǎng)的標(biāo)準(zhǔn)總線,并且擁有以CAN為底層協(xié)議專為大型貨車和重工機(jī)械車輛設(shè)計(jì)的J1939協(xié)議。近年來,它具有的高可靠性和良好的錯(cuò)誤檢測能力受到重視,被廣泛應(yīng)用于汽車計(jì)算機(jī)控制系統(tǒng)和環(huán)境溫度惡劣、電磁輻射強(qiáng)及振動(dòng)大的工業(yè)環(huán)境。
40.1.1?CAN物理層
與I2C、SPI等具有時(shí)鐘信號的同步通訊方式不同,CAN通訊并不是以時(shí)鐘信號來進(jìn)行同步的,它是一種異步通訊,只具有CAN_High和CAN_Low兩條信號線,共同構(gòu)成一組差分信號線,以差分信號的形式進(jìn)行通訊。
1.????閉環(huán)總線網(wǎng)絡(luò)
CAN物理層的形式主要有兩種,圖?401中的CAN通訊網(wǎng)絡(luò)是一種遵循ISO11898標(biāo)準(zhǔn)的高速、短距離”閉環(huán)網(wǎng)絡(luò)”,它的總線最大長度為40m,通信速度最高為1Mbps,總線的兩端各要求有一個(gè)”120歐”的電阻。

圖?401 CAN閉環(huán)總線通訊網(wǎng)絡(luò)
2.????開環(huán)總線網(wǎng)絡(luò)
圖?402中的是遵循ISO11519-2標(biāo)準(zhǔn)的低速、遠(yuǎn)距離”開環(huán)網(wǎng)絡(luò)”,它的最大傳輸距離為1km,最高通訊速率為125kbps,兩根總線是獨(dú)立的、不形成閉環(huán),要求每根總線上各串聯(lián)有一個(gè)”2.2千歐”的電阻。

圖?402 CAN開環(huán)總線通訊網(wǎng)絡(luò)
3.????通訊節(jié)點(diǎn)????
從CAN通訊網(wǎng)絡(luò)圖可了解到,CAN總線上可以掛載多個(gè)通訊節(jié)點(diǎn),節(jié)點(diǎn)之間的信號經(jīng)過總線傳輸,實(shí)現(xiàn)節(jié)點(diǎn)間通訊。由于CAN通訊協(xié)議不對節(jié)點(diǎn)進(jìn)行地址編碼,而是對數(shù)據(jù)內(nèi)容進(jìn)行編碼的,所以網(wǎng)絡(luò)中的節(jié)點(diǎn)個(gè)數(shù)理論上不受限制,只要總線的負(fù)載足夠即可,可以通過中繼器增強(qiáng)負(fù)載。
CAN通訊節(jié)點(diǎn)由一個(gè)CAN控制器及CAN收發(fā)器組成,控制器與收發(fā)器之間通過CAN_Tx及CAN_Rx信號線相連,收發(fā)器與CAN總線之間使用CAN_High及CAN_Low信號線相連。其中CAN_Tx及CAN_Rx使用普通的類似TTL邏輯信號,而CAN_High及CAN_Low是一對差分信號線,使用比較特別的差分信號,下一小節(jié)再詳細(xì)說明。
當(dāng)CAN節(jié)點(diǎn)需要發(fā)送數(shù)據(jù)時(shí),控制器把要發(fā)送的二進(jìn)制編碼通過CAN_Tx線發(fā)送到收發(fā)器,然后由收發(fā)器把這個(gè)普通的邏輯電平信號轉(zhuǎn)化成差分信號,通過差分線CAN_High和CAN_Low線輸出到CAN總線網(wǎng)絡(luò)。而通過收發(fā)器接收總線上的數(shù)據(jù)到控制器時(shí),則是相反的過程,收發(fā)器把總線上收到的CAN_High及CAN_Low信號轉(zhuǎn)化成普通的邏輯電平信號,通過CAN_Rx輸出到控制器中。
例如,STM32的CAN片上外設(shè)就是通訊節(jié)點(diǎn)中的控制器,為了構(gòu)成完整的節(jié)點(diǎn),還要給它外接一個(gè)收發(fā)器,在我們實(shí)驗(yàn)板中使用型號為TJA1050的芯片作為CAN收發(fā)器。CAN控制器與CAN收發(fā)器的關(guān)系如同TTL串口與MAX3232電平轉(zhuǎn)換芯片的關(guān)系,MAX3232芯片把TTL電平的串口信號轉(zhuǎn)換成RS-232電平的串口信號,CAN收發(fā)器的作用則是把CAN控制器的TTL電平信號轉(zhuǎn)換成差分信號(或者相反)。
4.????差分信號
差分信號又稱差模信號,與傳統(tǒng)使用單根信號線電壓表示邏輯的方式有區(qū)別,使用差分信號傳輸時(shí),需要兩根信號線,這兩個(gè)信號線的振幅相等,相位相反,通過兩根信號線的電壓差值來表示邏輯0和邏輯1。見圖?403,它使用了V+與V-信號的差值表達(dá)出了圖下方的信號。

圖?403?差分信號
相對于單信號線傳輸?shù)姆绞?,使用差分信號傳輸具有如下?yōu)點(diǎn):
?????抗干擾能力強(qiáng),當(dāng)外界存在噪聲干擾時(shí),幾乎會(huì)同時(shí)耦合到兩條信號線上,而接收端只關(guān)心兩個(gè)信號的差值,所以外界的共模噪聲可以被完全抵消。
?????能有效抑制它對外部的電磁干擾,同樣的道理,由于兩根信號的極性相反,他們對外輻射的電磁場可以相互抵消,耦合的越緊密,泄放到外界的電磁能量越少。
?????時(shí)序定位精確,由于差分信號的開關(guān)變化是位于兩個(gè)信號的交點(diǎn),而不像普通單端信號依靠高低兩個(gè)閾值電壓判斷,因而受工藝,溫度的影響小,能降低時(shí)序上的誤差,同時(shí)也更適合于低幅度信號的電路。
由于差分信號線具有這些優(yōu)點(diǎn),所以在USB協(xié)議、485協(xié)議、以太網(wǎng)協(xié)議及CAN協(xié)議的物理層中,都使用了差分信號傳輸。
5.????CAN協(xié)議中的差分信號
CAN協(xié)議中對它使用的CAN_High及CAN_Low表示的差分信號做了規(guī)定,見表?401及圖?404。以高速CAN協(xié)議為例,當(dāng)表示邏輯1時(shí)(隱性電平),CAN_High和CAN_Low線上的電壓均為2.5v,即它們的電壓差VH-VL=0V;而表示邏輯0時(shí)(顯性電平),CAN_High的電平為3.5V,CAN_Low線的電平為1.5V,即它們的電壓差為VH-VL=2V。例如,當(dāng)CAN收發(fā)器從CAN_Tx線接收到來自CAN控制器的低電平信號時(shí)(邏輯0),它會(huì)使CAN_High輸出3.5V,同時(shí)CAN_Low輸出1.5V,從而輸出顯性電平表示邏輯0。
表?401 CAN協(xié)議標(biāo)準(zhǔn)表示的信號邏輯
信號
ISO11898(高速)
ISO11519-2(低速)
隱性(邏輯1)
顯性(邏輯0)
隱性(邏輯1)
顯性(邏輯0)
最小值
典型值
最大值
最小值
典型值
最大值
最小值
典型值
最大值
最小值
典型值
最大值
CAN_High(V)
2.0
2.5
3.0
2.75
3.5
4.5
1.6
1.75
1.9
3.85
4.0
5.0
CAN_Low(V)
2.0
2.5
3.0
0.5
1.5
2.25
3.10
3.25
3.4
0
1.0
1.15
High-Low電位差?(V)
-0.5
0
0.05
1.5
2.0
3.0
-0.3
-1.5
-
0.3
3.0
-

圖?404 CAN的差分信號(高速)
在CAN總線中,必須使它處于隱性電平(邏輯1)或顯性電平(邏輯0)中的其中一個(gè)狀態(tài)。假如有兩個(gè)CAN通訊節(jié)點(diǎn),在同一時(shí)間,一個(gè)輸出隱性電平,另一個(gè)輸出顯性電平,類似I2C總線的”線與”特性將使它處于顯性電平狀態(tài),顯性電平的名字就是這樣來的,即可以認(rèn)為顯性具有優(yōu)先的意味。
由于CAN總線協(xié)議的物理層只有1對差分線,在一個(gè)時(shí)刻只能表示一個(gè)信號,所以對通訊節(jié)點(diǎn)來說,CAN通訊是半雙工的,收發(fā)數(shù)據(jù)需要分時(shí)進(jìn)行。在CAN的通訊網(wǎng)絡(luò)中,因?yàn)楣灿每偩€,在整個(gè)網(wǎng)絡(luò)中同一時(shí)刻只能有一個(gè)通訊節(jié)點(diǎn)發(fā)送信號,其余的節(jié)點(diǎn)在該時(shí)刻都只能接收。
40.1.2?協(xié)議層
以上是CAN的物理層標(biāo)準(zhǔn),約定了電氣特性,以下介紹的協(xié)議層則規(guī)定了通訊邏輯。
1.????CAN的波特率及位同步
由于CAN屬于異步通訊,沒有時(shí)鐘信號線,連接在同一個(gè)總線網(wǎng)絡(luò)中的各個(gè)節(jié)點(diǎn)會(huì)像串口異步通訊那樣,節(jié)點(diǎn)間使用約定好的波特率進(jìn)行通訊,特別地,CAN還會(huì)使用”位同步”的方式來抗干擾、吸收誤差,實(shí)現(xiàn)對總線電平信號進(jìn)行正確的采樣,確保通訊正常。
位時(shí)序分解
為了實(shí)現(xiàn)位同步,CAN協(xié)議把每一個(gè)數(shù)據(jù)位的時(shí)序分解成如圖?405所示的SS段、PTS段、PBS1段、PBS2段,這四段的長度加起來即為一個(gè)CAN數(shù)據(jù)位的長度。分解后最小的時(shí)間單位是Tq,而一個(gè)完整的位由8~25個(gè)Tq組成。為方便表示,圖?405中的高低電平直接代表信號邏輯0或邏輯1(不是差分信號)。

圖?405 CAN位時(shí)序分解圖
該圖中表示的CAN通訊信號每一個(gè)數(shù)據(jù)位的長度為19Tq,其中SS段占1Tq,PTS段占6Tq,PBS1段占5Tq,PBS2段占7Tq。信號的采樣點(diǎn)位于PBS1段與PBS2段之間,通過控制各段的長度,可以對采樣點(diǎn)的位置進(jìn)行偏移,以便準(zhǔn)確地采樣。
各段的作用如介紹下:
?????SS段(SYNC SEG)
SS譯為同步段,若通訊節(jié)點(diǎn)檢測到總線上信號的跳變沿被包含在SS段的范圍之內(nèi),則表示節(jié)點(diǎn)與總線的時(shí)序是同步的,當(dāng)節(jié)點(diǎn)與總線同步時(shí),采樣點(diǎn)采集到的總線電平即可被確定為該位的電平。SS段的大小固定為1Tq。
?????PTS段(PROP SEG)
PTS譯為傳播時(shí)間段,這個(gè)時(shí)間段是用于補(bǔ)償網(wǎng)絡(luò)的物理延時(shí)時(shí)間。是總線上輸入比較器延時(shí)和輸出驅(qū)動(dòng)器延時(shí)總和的兩倍。PTS段的大小可以為1~8Tq。
?????PBS1段(PHASE SEG1),
PBS1譯為相位緩沖段,主要用來補(bǔ)償邊沿階段的誤差,它的時(shí)間長度在重新同步的時(shí)候可以加長。PBS1段的初始大小可以為1~8Tq。
?????PBS2段(PHASE SEG2)
PBS2這是另一個(gè)相位緩沖段,也是用來補(bǔ)償邊沿階段誤差的,它的時(shí)間長度在重新同步時(shí)可以縮短。PBS2段的初始大小可以為2~8Tq。
通訊的波特率
總線上的各個(gè)通訊節(jié)點(diǎn)只要約定好1個(gè)Tq的時(shí)間長度以及每一個(gè)數(shù)據(jù)位占據(jù)多少個(gè)Tq,就可以確定CAN通訊的波特率。
例如,假設(shè)上圖中的1Tq=1us,而每個(gè)數(shù)據(jù)位由19個(gè)Tq組成,則傳輸一位數(shù)據(jù)需要時(shí)間T1bit?=19us,從而每秒可以傳輸?shù)臄?shù)據(jù)位個(gè)數(shù)為:
1x106/19 = 52631.6 (bps)
這個(gè)每秒可傳輸?shù)臄?shù)據(jù)位的個(gè)數(shù)即為通訊中的波特率。
同步過程分析
????波特率只是約定了每個(gè)數(shù)據(jù)位的長度,數(shù)據(jù)同步還涉及到相位的細(xì)節(jié),這個(gè)時(shí)候就需要用到數(shù)據(jù)位內(nèi)的SS、PTS、PBS1及PBS2段了。
根據(jù)對段的應(yīng)用方式差異,CAN的數(shù)據(jù)同步分為硬同步和重新同步。其中硬同步只是當(dāng)存在”幀起始信號”時(shí)起作用,無法確保后續(xù)一連串的位時(shí)序都是同步的,而重新同步方式可解決該問題,這兩種方式具體介紹如下:
(1)????硬同步
若某個(gè)CAN節(jié)點(diǎn)通過總線發(fā)送數(shù)據(jù)時(shí),它會(huì)發(fā)送一個(gè)表示通訊起始的信號(即下一小節(jié)介紹的幀起始信號),該信號是一個(gè)由高變低的下降沿。而掛載到CAN總線上的通訊節(jié)點(diǎn)在不發(fā)送數(shù)據(jù)時(shí),會(huì)時(shí)刻檢測總線上的信號。
見圖?406,可以看到當(dāng)總線出現(xiàn)幀起始信號時(shí),某節(jié)點(diǎn)檢測到總線的幀起始信號不在節(jié)點(diǎn)內(nèi)部時(shí)序的SS段范圍,所以判斷它自己的內(nèi)部時(shí)序與總線不同步,因而這個(gè)狀態(tài)的采樣點(diǎn)采集得的數(shù)據(jù)是不正確的。所以節(jié)點(diǎn)以硬同步的方式調(diào)整,把自己的位時(shí)序中的SS段平移至總線出現(xiàn)下降沿的部分,獲得同步,同步后采樣點(diǎn)就可以采集得正確數(shù)據(jù)了。

圖?406?硬同步過程圖
(2)????重新同步
前面的硬同步只是當(dāng)存在幀起始信號時(shí)才起作用,如果在一幀很長的數(shù)據(jù)內(nèi),節(jié)點(diǎn)信號與總線信號相位有偏移時(shí),這種同步方式就無能為力了。因而需要引入重新同步方式,它利用普通數(shù)據(jù)位的高至低電平的跳變沿來同步(幀起始信號是特殊的跳變沿)。重新同步與硬同步方式相似的地方是它們都使用SS段來進(jìn)行檢測,同步的目的都是使節(jié)點(diǎn)內(nèi)的SS段把跳變沿包含起來。
重新同步的方式分為超前和滯后兩種情況,以總線跳變沿與SS段的相對位置進(jìn)行區(qū)分。第一種相位超前的情況如圖?407,節(jié)點(diǎn)從總線的邊沿跳變中,檢測到它內(nèi)部的時(shí)序比總線的時(shí)序相對超前2Tq,這時(shí)控制器在下一個(gè)位時(shí)序中的PBS1段增加2Tq的時(shí)間長度,使得節(jié)點(diǎn)與總線時(shí)序重新同步。

圖?407?相位超前時(shí)的重新同步
第二種相位滯后的情況如圖?408,節(jié)點(diǎn)從總線的邊沿跳變中,檢測到它的時(shí)序比總線的時(shí)序相對滯后2Tq,這時(shí)控制器在前一個(gè)位時(shí)序中的PBS2段減少2Tq的時(shí)間長度,獲得同步。

圖?408?相位滯后時(shí)的重新同步
在重新同步的時(shí)候,PBS1和PBS2中增加或減少的這段時(shí)間長度被定義為”重新同步補(bǔ)償寬度SJW (reSynchronization Jump Width)“。一般來說CAN控制器會(huì)限定SJW的最大值,如限定了最大SJW=3Tq時(shí),單次同步調(diào)整的時(shí)候不能增加或減少超過3Tq的時(shí)間長度,若有需要,控制器會(huì)通過多次小幅度調(diào)整來實(shí)現(xiàn)同步。當(dāng)控制器設(shè)置的SJW極限值較大時(shí),可以吸收的誤差加大,但通訊的速度會(huì)下降。
2.????CAN的報(bào)文種類及結(jié)構(gòu)
在SPI通訊中,片選、時(shí)鐘信號、數(shù)據(jù)輸入及數(shù)據(jù)輸出這4個(gè)信號都有單獨(dú)的信號線,I2C協(xié)議包含有時(shí)鐘信號及數(shù)據(jù)信號2條信號線,異步串口包含接收與發(fā)送2條信號線,這些協(xié)議包含的信號都比CAN協(xié)議要豐富,它們能輕易進(jìn)行數(shù)據(jù)同步或區(qū)分?jǐn)?shù)據(jù)傳輸方向。而CAN使用的是兩條差分信號線,只能表達(dá)一個(gè)信號,簡潔的物理層決定了CAN必然要配上一套更復(fù)雜的協(xié)議,如何用一個(gè)信號通道實(shí)現(xiàn)同樣、甚至更強(qiáng)大的功能呢?CAN協(xié)議給出的解決方案是對數(shù)據(jù)、操作命令(如讀/寫)以及同步信號進(jìn)行打包,打包后的這些內(nèi)容稱為報(bào)文。
報(bào)文的種類
在原始數(shù)據(jù)段的前面加上傳輸起始標(biāo)簽、片選(識別)標(biāo)簽和控制標(biāo)簽,在數(shù)據(jù)的尾段加上CRC校驗(yàn)標(biāo)簽、應(yīng)答標(biāo)簽和傳輸結(jié)束標(biāo)簽,把這些內(nèi)容按特定的格式打包好,就可以用一個(gè)通道表達(dá)各種信號了,各種各樣的標(biāo)簽就如同SPI中各種通道上的信號,起到了協(xié)同傳輸?shù)淖饔?。?dāng)整個(gè)數(shù)據(jù)包被傳輸?shù)狡渌O(shè)備時(shí),只要這些設(shè)備按格式去解讀,就能還原出原始數(shù)據(jù),這樣的報(bào)文就被稱為CAN的”數(shù)據(jù)幀”。
為了更有效地控制通訊,CAN一共規(guī)定了5種類型的幀,它們的類型及用途說明如表?402。
表?402?幀的種類及其用途
幀
幀用途
數(shù)據(jù)幀
用于節(jié)點(diǎn)向外傳送數(shù)據(jù)
遙控幀
用于向遠(yuǎn)端節(jié)點(diǎn)請求數(shù)據(jù)
錯(cuò)誤幀
用于向遠(yuǎn)端節(jié)點(diǎn)通知校驗(yàn)錯(cuò)誤,請求重新發(fā)送上一個(gè)數(shù)據(jù)
過載幀
用于通知遠(yuǎn)端節(jié)點(diǎn):本節(jié)點(diǎn)尚未做好接收準(zhǔn)備
幀間隔
用于將數(shù)據(jù)幀及遙控幀與前面的幀分離開來
數(shù)據(jù)幀的結(jié)構(gòu)
數(shù)據(jù)幀是在CAN通訊中最主要、最復(fù)雜的報(bào)文,我們來了解它的結(jié)構(gòu),見圖?409。

圖?409?數(shù)據(jù)幀的結(jié)構(gòu)
數(shù)據(jù)幀以一個(gè)顯性位(邏輯0)開始,以7個(gè)連續(xù)的隱性位(邏輯1)結(jié)束,在它們之間,分別有仲裁段、控制段、數(shù)據(jù)段、CRC段和ACK段。
?????幀起始
SOF段(Start Of Frame),譯為幀起始,幀起始信號只有一個(gè)數(shù)據(jù)位,是一個(gè)顯性電平,它用于通知各個(gè)節(jié)點(diǎn)將有數(shù)據(jù)傳輸,其它節(jié)點(diǎn)通過幀起始信號的電平跳變沿來進(jìn)行硬同步。
?????仲裁段
當(dāng)同時(shí)有兩個(gè)報(bào)文被發(fā)送時(shí),總線會(huì)根據(jù)仲裁段的內(nèi)容決定哪個(gè)數(shù)據(jù)包能被傳輸,這也是它名稱的由來。
仲裁段的內(nèi)容主要為本數(shù)據(jù)幀的ID信息(標(biāo)識符),數(shù)據(jù)幀具有標(biāo)準(zhǔn)格式和擴(kuò)展格式兩種,區(qū)別就在于ID信息的長度,標(biāo)準(zhǔn)格式的ID為11位,擴(kuò)展格式的ID為29位,它在標(biāo)準(zhǔn)ID的基礎(chǔ)上多出18位。在CAN協(xié)議中,ID起著重要的作用,它決定著數(shù)據(jù)幀發(fā)送的優(yōu)先級,也決定著其它節(jié)點(diǎn)是否會(huì)接收這個(gè)數(shù)據(jù)幀。CAN協(xié)議不對掛載在它之上的節(jié)點(diǎn)分配優(yōu)先級和地址,對總線的占有權(quán)是由信息的重要性決定的,即對于重要的信息,我們會(huì)給它打包上一個(gè)優(yōu)先級高的ID,使它能夠及時(shí)地發(fā)送出去。也正因?yàn)樗@樣的優(yōu)先級分配原則,使得CAN的擴(kuò)展性大大加強(qiáng),在總線上增加或減少節(jié)點(diǎn)并不影響其它設(shè)備。
報(bào)文的優(yōu)先級,是通過對ID的仲裁來確定的。根據(jù)前面對物理層的分析我們知道如果總線上同時(shí)出現(xiàn)顯性電平和隱性電平,總線的狀態(tài)會(huì)被置為顯性電平,CAN正是利用這個(gè)特性進(jìn)行仲裁。
若兩個(gè)節(jié)點(diǎn)同時(shí)競爭CAN總線的占有權(quán),當(dāng)它們發(fā)送報(bào)文時(shí),若首先出現(xiàn)隱性電平,則會(huì)失去對總線的占有權(quán),進(jìn)入接收狀態(tài)。見圖?4010,在開始階段,兩個(gè)設(shè)備發(fā)送的電平一樣,所以它們一直繼續(xù)發(fā)送數(shù)據(jù)。到了圖中箭頭所指的時(shí)序處,節(jié)點(diǎn)單元1發(fā)送的為隱性電平,而此時(shí)節(jié)點(diǎn)單元2發(fā)送的為顯性電平,由于總線的”線與”特性使它表達(dá)出顯示電平,因此單元2競爭總線成功,這個(gè)報(bào)文得以被繼續(xù)發(fā)送出去。

圖?4010?仲裁過程
仲裁段ID的優(yōu)先級也影響著接收設(shè)備對報(bào)文的反應(yīng)。因?yàn)樵贑AN總線上數(shù)據(jù)是以廣播的形式發(fā)送的,所有連接在CAN總線的節(jié)點(diǎn)都會(huì)收到所有其它節(jié)點(diǎn)發(fā)出的有效數(shù)據(jù),因而我們的CAN控制器大多具有根據(jù)ID過濾報(bào)文的功能,它可以控制自己只接收某些ID的報(bào)文。
回看圖?409中的數(shù)據(jù)幀格式,可看到仲裁段除了報(bào)文ID外,還有RTR、IDE和SRR位。
(1)????RTR位(Remote Transmission Request Bit),譯作遠(yuǎn)程傳輸請求位,它是用于區(qū)分?jǐn)?shù)據(jù)幀和遙控幀的,當(dāng)它為顯性電平時(shí)表示數(shù)據(jù)幀,隱性電平時(shí)表示遙控幀。
(2)????IDE位(Identifier Extension Bit),譯作標(biāo)識符擴(kuò)展位,它是用于區(qū)分標(biāo)準(zhǔn)格式與擴(kuò)展格式,當(dāng)它為顯性電平時(shí)表示標(biāo)準(zhǔn)格式,隱性電平時(shí)表示擴(kuò)展格式。
(3)????SRR位(Substitute Remote Request Bit),只存在于擴(kuò)展格式,它用于替代標(biāo)準(zhǔn)格式中的RTR位。由于擴(kuò)展幀中的SRR位為隱性位,RTR在數(shù)據(jù)幀為顯性位,所以在兩個(gè)ID相同的標(biāo)準(zhǔn)格式報(bào)文與擴(kuò)展格式報(bào)文中,標(biāo)準(zhǔn)格式的優(yōu)先級較高。
?????控制段
在控制段中的r1和r0為保留位,默認(rèn)設(shè)置為顯性位。它最主要的是DLC段(Data Length Code),譯為數(shù)據(jù)長度碼,它由4個(gè)數(shù)據(jù)位組成,用于表示本報(bào)文中的數(shù)據(jù)段含有多少個(gè)字節(jié),DLC段表示的數(shù)字為0~8。
?????數(shù)據(jù)段
數(shù)據(jù)段為數(shù)據(jù)幀的核心內(nèi)容,它是節(jié)點(diǎn)要發(fā)送的原始信息,由0~8個(gè)字節(jié)組成,MSB先行。
?????CRC段
為了保證報(bào)文的正確傳輸,CAN的報(bào)文包含了一段15位的CRC校驗(yàn)碼,一旦接收節(jié)點(diǎn)算出的CRC碼跟接收到的CRC碼不同,則它會(huì)向發(fā)送節(jié)點(diǎn)反饋出錯(cuò)信息,利用錯(cuò)誤幀請求它重新發(fā)送。CRC部分的計(jì)算一般由CAN控制器硬件完成,出錯(cuò)時(shí)的處理則由軟件控制最大重發(fā)數(shù)。
在CRC校驗(yàn)碼之后,有一個(gè)CRC界定符,它為隱性位,主要作用是把CRC校驗(yàn)碼與后面的ACK段間隔起來。
?????ACK段
ACK段包括一個(gè)ACK槽位,和ACK界定符位。類似I2C總線,在ACK槽位中,發(fā)送節(jié)點(diǎn)發(fā)送的是隱性位,而接收節(jié)點(diǎn)則在這一位中發(fā)送顯性位以示應(yīng)答。在ACK槽和幀結(jié)束之間由ACK界定符間隔開。
?????幀結(jié)束
EOF段(End Of Frame),譯為幀結(jié)束,幀結(jié)束段由發(fā)送節(jié)點(diǎn)發(fā)送的7個(gè)隱性位表示結(jié)束。
其它報(bào)文的結(jié)構(gòu)
關(guān)于其它的CAN報(bào)文結(jié)構(gòu),不再展開講解,其主要內(nèi)容見圖?4011。

圖?4011?各種CAN報(bào)文的結(jié)構(gòu)
40.2 STM32的CAN外設(shè)簡介
STM32的芯片中具有bxCAN控制器?(Basic Extended CAN),它支持CAN協(xié)議2.0A和2.0B標(biāo)準(zhǔn)。
該CAN控制器支持最高的通訊速率為1Mb/s;可以自動(dòng)地接收和發(fā)送CAN報(bào)文,支持使用標(biāo)準(zhǔn)ID和擴(kuò)展ID的報(bào)文;外設(shè)中具有3個(gè)發(fā)送郵箱,發(fā)送報(bào)文的優(yōu)先級可以使用軟件控制,還可以記錄發(fā)送的時(shí)間;具有2個(gè)3級深度的接收FIFO,可使用過濾功能只接收或不接收某些ID號的報(bào)文;可配置成自動(dòng)重發(fā);不支持使用DMA進(jìn)行數(shù)據(jù)收發(fā)。
40.2.1?STM32的CAN架構(gòu)剖析

圖?4012 STM32的CAN外設(shè)架構(gòu)圖
STM32的有兩組CAN控制器,其中CAN1是主設(shè)備,框圖中的”存儲(chǔ)訪問控制器”是由CAN1控制的,CAN2無法直接訪問存儲(chǔ)區(qū)域,所以使用CAN2的時(shí)候必須使能CAN1外設(shè)的時(shí)鐘??驁D中主要包含CAN控制內(nèi)核、發(fā)送郵箱、接收FIFO以及驗(yàn)收篩選器,下面對框圖中的各個(gè)部分進(jìn)行介紹。
1.????CAN控制內(nèi)核
框圖中標(biāo)號處的CAN控制內(nèi)核包含了各種控制寄存器及狀態(tài)寄存器,我們主要講解其中的主控制寄存器CAN_MCR及位時(shí)序寄存器CAN_BTR。
主控制寄存器CAN_MCR
主控制寄存器CAN_MCR負(fù)責(zé)管理CAN的工作模式,它使用以下寄存器位實(shí)現(xiàn)控制。
(1)????DBF調(diào)試凍結(jié)功能
DBF(Debug freeze)調(diào)試凍結(jié),使用它可設(shè)置CAN處于工作狀態(tài)或禁止收發(fā)的狀態(tài),禁止收發(fā)時(shí)仍可訪問接收FIFO中的數(shù)據(jù)。這兩種狀態(tài)是當(dāng)STM32芯片處于程序調(diào)試模式時(shí)才使用的,平時(shí)使用并不影響。
(2)????TTCM時(shí)間觸發(fā)模式
TTCM(Time triggered communication mode)時(shí)間觸發(fā)模式,它用于配置CAN的時(shí)間觸發(fā)通信模式,在此模式下,CAN使用它內(nèi)部定時(shí)器產(chǎn)生時(shí)間戳,并把它保存在CAN_RDTxR、CAN_TDTxR寄存器中。內(nèi)部定時(shí)器在每個(gè)CAN位時(shí)間累加,在接收和發(fā)送的幀起始位被采樣,并生成時(shí)間戳。利用它可以實(shí)現(xiàn)ISO 11898-4 CAN標(biāo)準(zhǔn)的分時(shí)同步通信功能。
(3)????ABOM自動(dòng)離線管理
ABOM(Automatic bus-off management)?自動(dòng)離線管理,它用于設(shè)置是否使用自動(dòng)離線管理功能。當(dāng)節(jié)點(diǎn)檢測到它發(fā)送錯(cuò)誤或接收錯(cuò)誤超過一定值時(shí),會(huì)自動(dòng)進(jìn)入離線狀態(tài),在離線狀態(tài)中,CAN不能接收或發(fā)送報(bào)文。處于離線狀態(tài)的時(shí)候,可以軟件控制恢復(fù)或者直接使用這個(gè)自動(dòng)離線管理功能,它會(huì)在適當(dāng)?shù)臅r(shí)候自動(dòng)恢復(fù)。
(4)????AWUM自動(dòng)喚醒
AWUM(Automatic bus-off management),自動(dòng)喚醒功能,CAN外設(shè)可以使用軟件進(jìn)入低功耗的睡眠模式,如果使能了這個(gè)自動(dòng)喚醒功能,當(dāng)CAN檢測到總線活動(dòng)的時(shí)候,會(huì)自動(dòng)喚醒。
(5)????NART自動(dòng)重傳
NART(No automatic retransmission)報(bào)文自動(dòng)重傳功能,設(shè)置這個(gè)功能后,當(dāng)報(bào)文發(fā)送失敗時(shí)會(huì)自動(dòng)重傳至成功為止。若不使用這個(gè)功能,無論發(fā)送結(jié)果如何,消息只發(fā)送一次。
(6)????RFLM鎖定模式
RFLM(Receive FIFO locked mode)FIFO鎖定模式,該功能用于鎖定接收FIFO。鎖定后,當(dāng)接收FIFO溢出時(shí),會(huì)丟棄下一個(gè)接收的報(bào)文。若不鎖定,則下一個(gè)接收到的報(bào)文會(huì)覆蓋原報(bào)文。
(7)????TXFP報(bào)文發(fā)送優(yōu)先級的判定方法
TXFP(Transmit FIFO priority)報(bào)文發(fā)送優(yōu)先級的判定方法,當(dāng)CAN外設(shè)的發(fā)送郵箱中有多個(gè)待發(fā)送報(bào)文時(shí),本功能可以控制它是根據(jù)報(bào)文的ID優(yōu)先級還是報(bào)文存進(jìn)郵箱的順序來發(fā)送。
位時(shí)序寄存器(CAN_BTR)及波特率
CAN外設(shè)中的位時(shí)序寄存器CAN_BTR用于配置測試模式、波特率以及各種位內(nèi)的段參數(shù)。
(1)????測試模式
為方便調(diào)試,STM32的CAN提供了測試模式,配置位時(shí)序寄存器CAN_BTR的SILM及LBKM寄存器位可以控制使用正常模式、靜默模式、回環(huán)模式及靜默回環(huán)模式,見圖?4013。

圖?4013?四種工作模式
各個(gè)工作模式介紹如下:
?????正常模式
正常模式下就是一個(gè)正常的CAN節(jié)點(diǎn),可以向總線發(fā)送數(shù)據(jù)和接收數(shù)據(jù)。
?????靜默模式
靜默模式下,它自己的輸出端的邏輯0數(shù)據(jù)會(huì)直接傳輸?shù)剿约旱妮斎攵?,邏?可以被發(fā)送到總線,所以它不能向總線發(fā)送顯性位(邏輯0),只能發(fā)送隱性位(邏輯1)。輸入端可以從總線接收內(nèi)容。由于它只可發(fā)送的隱性位不會(huì)強(qiáng)制影響總線的狀態(tài),所以把它稱為靜默模式。這種模式一般用于監(jiān)測,它可以用于分析總線上的流量,但又不會(huì)因?yàn)榘l(fā)送顯性位而影響總線。
?????回環(huán)模式
回環(huán)模式下,它自己的輸出端的所有內(nèi)容都直接傳輸?shù)阶约旱妮斎攵耍敵龆说膬?nèi)容同時(shí)也會(huì)被傳輸?shù)娇偩€上,即也可使用總線監(jiān)測它的發(fā)送內(nèi)容。輸入端只接收自己發(fā)送端的內(nèi)容,不接收來自總線上的內(nèi)容。使用回環(huán)模式可以進(jìn)行自檢。
?????回環(huán)靜默模式
回環(huán)靜默模式是以上兩種模式的結(jié)合,自己的輸出端的所有內(nèi)容都直接傳輸?shù)阶约旱妮斎攵?,并且不?huì)向總線發(fā)送顯性位影響總線,不能通過總線監(jiān)測它的發(fā)送內(nèi)容。輸入端只接收自己發(fā)送端的內(nèi)容,不接收來自總線上的內(nèi)容。這種方式可以在”熱自檢”時(shí)使用,即自我檢查的時(shí)候,不會(huì)干擾總線。
以上說的各個(gè)模式,是不需要修改硬件接線的,如當(dāng)輸出直連輸入時(shí),它是在STM32芯片內(nèi)部連接的,傳輸路徑不經(jīng)過STM32的CAN_Tx/Rx引腳,更不經(jīng)過外部連接的CAN收發(fā)器,只有輸出數(shù)據(jù)到總線或從總線接收的情況下才會(huì)經(jīng)過CAN_Tx/Rx引腳和收發(fā)器。
(2)????位時(shí)序及波特率
STM32外設(shè)定義的位時(shí)序與我們前面解釋的CAN標(biāo)準(zhǔn)時(shí)序有一點(diǎn)區(qū)別,見圖?4014。

圖?4014 STM32中CAN的位時(shí)序
STM32的CAN外設(shè)位時(shí)序中只包含3段,分別是同步段SYNC_SEG、位段BS1及位段BS2,采樣點(diǎn)位于BS1及BS2段的交界處。其中SYNC_SEG段固定長度為1Tq,而BS1及BS2段可以在位時(shí)序寄存器CAN_BTR設(shè)置它們的時(shí)間長度,它們可以在重新同步期間增長或縮短,該長度SJW也可在位時(shí)序寄存器中配置。
理解STM32的CAN外設(shè)的位時(shí)序時(shí),可以把它的BS1段理解為是由前面介紹的CAN標(biāo)準(zhǔn)協(xié)議中PTS段與PBS1段合在一起的,而BS2段就相當(dāng)于PBS2段。
了解位時(shí)序后,我們就可以配置波特率了。通過配置位時(shí)序寄存器CAN_BTR的TS1[3:0]及TS2[2:0]寄存器位設(shè)定BS1及BS2段的長度后,我們就可以確定每個(gè)CAN數(shù)據(jù)位的時(shí)間:
BS1段時(shí)間:
TS1=Tq x (TS1[3:0] + 1),
BS2段時(shí)間:
TS2= Tq x (TS2[2:0] + 1),
一個(gè)數(shù)據(jù)位的時(shí)間:
T1bit?=1Tq+TS1+TS2?=1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)= N Tq
其中單個(gè)時(shí)間片的長度Tq與CAN外設(shè)的所掛載的時(shí)鐘總線及分頻器配置有關(guān),CAN1和CAN2外設(shè)都是掛載在APB1總線上的,而位時(shí)序寄存器CAN_BTR中的BRP[9:0]寄存器位可以設(shè)置CAN外設(shè)時(shí)鐘的分頻值,所以:
Tq = (BRP[9:0]+1) x TPCLK
其中的PCLK指APB1時(shí)鐘,默認(rèn)值為45MHz。
最終可以計(jì)算出CAN通訊的波特率:
BaudRate = 1/N Tq
例如表?403說明了一種把波特率配置為1Mbps的方式。
表?403?一種配置波特率為1Mbps的方式
參數(shù)
說明
SYNC_SE段
固定為1Tq
BS1段
設(shè)置為5Tq (實(shí)際寫入TS1[3:0]的值為4)
BS2段
設(shè)置為3Tq (實(shí)際寫入TS2[2:0]的值為2)
TPCLK
APB1按默認(rèn)配置為F=45MHz,TPCLK=1/45M
CAN外設(shè)時(shí)鐘分頻
設(shè)置為5分頻(實(shí)際寫入BRP[9:0]的值為4)
1Tq時(shí)間長度
Tq = (BRP[9:0]+1) x TPCLK?????= ????5 x 1/45M=1/9M
1位的時(shí)間長度
T1bit?=1Tq+TS1+TS2 ????????????= ????1+5+3 = 9Tq
波特率
BaudRate = 1/N Tq????????????=????1/(1/9M x 9)=1Mbps
2.????CAN發(fā)送郵箱
回到圖?245中的CAN外設(shè)框圖,在標(biāo)號?處的是CAN外設(shè)的發(fā)送郵箱,它一共有3個(gè)發(fā)送郵箱,即最多可以緩存3個(gè)待發(fā)送的報(bào)文。
每個(gè)發(fā)送郵箱中包含有標(biāo)識符寄存器CAN_TIxR、數(shù)據(jù)長度控制寄存器CAN_TDTxR及2個(gè)數(shù)據(jù)寄存器CAN_TDLxR、CAN_TDHxR,它們的功能見表?405。
表?404?發(fā)送郵箱的寄存器
寄存器名
功能
標(biāo)識符寄存器CAN_TIxR
存儲(chǔ)待發(fā)送報(bào)文的ID、擴(kuò)展ID、IDE位及RTR位
數(shù)據(jù)長度控制寄存器CAN_TDTxR
存儲(chǔ)待發(fā)送報(bào)文的DLC段
低位數(shù)據(jù)寄存器CAN_TDLxR
存儲(chǔ)待發(fā)送報(bào)文數(shù)據(jù)段的Data0-Data3這四個(gè)字節(jié)的內(nèi)容
高位數(shù)據(jù)寄存器CAN_TDHxR
存儲(chǔ)待發(fā)送報(bào)文數(shù)據(jù)段的Data4-Data7這四個(gè)字節(jié)的內(nèi)容
當(dāng)我們要使用CAN外設(shè)發(fā)送報(bào)文時(shí),把報(bào)文的各個(gè)段分解,按位置寫入到這些寄存器中,并對標(biāo)識符寄存器CAN_TIxR中的發(fā)送請求寄存器位TMIDxR_TXRQ置1,即可把數(shù)據(jù)發(fā)送出去。
其中標(biāo)識符寄存器CAN_TIxR中的STDID寄存器位比較特別。我們知道CAN的標(biāo)準(zhǔn)標(biāo)識符的總位數(shù)為11位,而擴(kuò)展標(biāo)識符的總位數(shù)為29位的。當(dāng)報(bào)文使用擴(kuò)展標(biāo)識符的時(shí)候,標(biāo)識符寄存器CAN_TIxR中的STDID[10:0]等效于EXTID[18:28]位,它與EXTID[17:0]共同組成完整的29位擴(kuò)展標(biāo)識符。
3.????CAN接收FIFO
圖?245中的CAN外設(shè)框圖,在標(biāo)號?處的是CAN外設(shè)的接收FIFO,它一共有2個(gè)接收FIFO,每個(gè)FIFO中有3個(gè)郵箱,即最多可以緩存6個(gè)接收到的報(bào)文。當(dāng)接收到報(bào)文時(shí),F(xiàn)IFO的報(bào)文計(jì)數(shù)器會(huì)自增,而STM32內(nèi)部讀取FIFO數(shù)據(jù)之后,報(bào)文計(jì)數(shù)器會(huì)自減,我們通過狀態(tài)寄存器可獲知報(bào)文計(jì)數(shù)器的值,而通過前面主控制寄存器的RFLM位,可設(shè)置鎖定模式,鎖定模式下FIFO溢出時(shí)會(huì)丟棄新報(bào)文,非鎖定模式下FIFO溢出時(shí)新報(bào)文會(huì)覆蓋舊報(bào)文。
跟發(fā)送郵箱類似,每個(gè)接收FIFO中包含有標(biāo)識符寄存器CAN_RIxR、數(shù)據(jù)長度控制寄存器CAN_RDTxR及2個(gè)數(shù)據(jù)寄存器CAN_RDLxR、CAN_RDHxR,它們的功能見表?405。
表?405?發(fā)送郵箱的寄存器
寄存器名
功能
標(biāo)識符寄存器CAN_RIxR
存儲(chǔ)收到報(bào)文的ID、擴(kuò)展ID、IDE位及RTR位
數(shù)據(jù)長度控制寄存器CAN_RDTxR
存儲(chǔ)收到報(bào)文的DLC段
低位數(shù)據(jù)寄存器CAN_RDLxR
存儲(chǔ)收到報(bào)文數(shù)據(jù)段的Data0-Data3這四個(gè)字節(jié)的內(nèi)容
高位數(shù)據(jù)寄存器CAN_RDHxR
存儲(chǔ)收到報(bào)文數(shù)據(jù)段的Data4-Data7這四個(gè)字節(jié)的內(nèi)容
通過中斷或狀態(tài)寄存器知道接收FIFO有數(shù)據(jù)后,我們再讀取這些寄存器的值即可把接收到的報(bào)文加載到STM32的內(nèi)存中。
4.????驗(yàn)收篩選器
圖?245中的CAN外設(shè)框圖,在標(biāo)號?處的是CAN外設(shè)的驗(yàn)收篩選器,一共有28個(gè)篩選器組,每個(gè)篩選器組有2個(gè)寄存器,CAN1和CAN2共用的篩選器的。
在CAN?協(xié)議中,消息的標(biāo)識符與節(jié)點(diǎn)地址無關(guān),但與消息內(nèi)容有關(guān)。因此,發(fā)送節(jié)點(diǎn)將報(bào)文廣播給所有接收器時(shí),接收節(jié)點(diǎn)會(huì)根據(jù)報(bào)文標(biāo)識符的值來確定軟件是否需要該消息,為了簡化軟件的工作,STM32的CAN外設(shè)接收報(bào)文前會(huì)先使用驗(yàn)收篩選器檢查,只接收需要的報(bào)文到FIFO中。
篩選器工作的時(shí)候,可以調(diào)整篩選ID的長度及過濾模式。根據(jù)篩選ID長度來分類有有以下兩種:
(1)????檢查STDID[10:0]、EXTID[17:0]、IDE?和RTR?位,一共31位。
(2)????檢查STDID[10:0]、RTR、IDE?和EXTID[17:15],一共16位。
通過配置篩選尺度寄存器CAN_FS1R的FSCx位可以設(shè)置篩選器工作在哪個(gè)尺度。
而根據(jù)過濾的方法分為以下兩種模式:
(1)????標(biāo)識符列表模式,它把要接收報(bào)文的ID列成一個(gè)表,要求報(bào)文ID與列表中的某一個(gè)標(biāo)識符完全相同才可以接收,可以理解為白名單管理。
(2)????掩碼模式,它把可接收報(bào)文ID的某幾位作為列表,這幾位被稱為掩碼,可以把它理解成關(guān)鍵字搜索,只要掩碼(關(guān)鍵字)相同,就符合要求,報(bào)文就會(huì)被保存到接收FIFO。
通過配置篩選模式寄存器CAN_FM1R的FBMx位可以設(shè)置篩選器工作在哪個(gè)模式。
不同的尺度和不同的過濾方法可使篩選器工作在圖?4015的4種狀態(tài)。

圖?4015?篩選器的4種工作狀態(tài)
每組篩選器包含2個(gè)32位的寄存器,分別為CAN_FxR1和CAN_FxR2,它們用來存儲(chǔ)要篩選的ID或掩碼,各個(gè)寄存器位代表的意義與圖中兩個(gè)寄存器下面”映射”的一欄一致,各個(gè)模式的說明見表?406。
表?406?篩選器的工作狀態(tài)說明
模式
說明
32位掩碼模式
CAN_FxR1存儲(chǔ)ID,CAN_FxR2存儲(chǔ)哪個(gè)位必須要與CAN_FxR1中的ID一致,2個(gè)寄存器表示1組掩碼。
32位標(biāo)識符模式
CAN_FxR1和CAN_FxR2各存儲(chǔ)1個(gè)ID,2個(gè)寄存器表示2個(gè)篩選的ID
16位掩碼模式
CAN_FxR1高16位存儲(chǔ)ID,低16位存儲(chǔ)哪個(gè)位必須要與高16位的ID一致;
CAN_FxR2高16位存儲(chǔ)ID,低16位存儲(chǔ)哪個(gè)位必須要與高16位的ID一致
2個(gè)寄存器表示2組掩碼。
16位標(biāo)識符模式
CAN_FxR1和CAN_FxR2各存儲(chǔ)2個(gè)ID,2個(gè)寄存器表示4個(gè)篩選的ID
例如下面的表格所示,在掩碼模式時(shí),第一個(gè)寄存器存儲(chǔ)要篩選的ID,第二個(gè)寄存器存儲(chǔ)掩碼,掩碼為1的部分表示該位必須與ID中的內(nèi)容一致,篩選的結(jié)果為表中第三行的ID值,它是一組包含多個(gè)的ID值,其中x表示該位可以為1可以為0。
ID
1
0
1
1
1
0
1
…
掩碼
1
1
1
0
0
1
0
…
篩選的ID
1
0
1
x
x
0
x
…
而工作在標(biāo)識符模式時(shí),2個(gè)寄存器存儲(chǔ)的都是要篩選的ID,它只包含2個(gè)要篩選的ID值(32位模式時(shí))。
如果使能了篩選器,且報(bào)文的ID與所有篩選器的配置都不匹配,CAN外設(shè)會(huì)丟棄該報(bào)文,不存入接收FIFO。
5.????整體控制邏輯
回到圖?245結(jié)構(gòu)框圖,圖中的標(biāo)號…處表示的是CAN2外設(shè)的結(jié)構(gòu),它與CAN1外設(shè)是一樣的,他們共用篩選器且由于存儲(chǔ)訪問控制器由CAN1控制,所以要使用CAN2的時(shí)候必須要使能CAN1的時(shí)鐘。
40.3 CAN初始化結(jié)構(gòu)體
從STM32的CAN外設(shè)我們了解到它的功能非常多,控制涉及的寄存器也非常豐富,而使用STM32標(biāo)準(zhǔn)庫提供的各種結(jié)構(gòu)體及庫函數(shù)可以簡化這些控制過程。跟其它外設(shè)一樣,STM32標(biāo)準(zhǔn)庫提供了CAN初始化結(jié)構(gòu)體及初始化函數(shù)來控制CAN的工作方式,提供了收發(fā)報(bào)文使用的結(jié)構(gòu)體及收發(fā)函數(shù),還有配置控制篩選器模式及ID的結(jié)構(gòu)體。這些內(nèi)容都定義在庫文件”stm32f4xx_can.h“及”stm32f4xx_can.c“中,編程時(shí)我們可以結(jié)合這兩個(gè)文件內(nèi)的注釋使用或參考庫幫助文檔。
首先我們來學(xué)習(xí)初始化結(jié)構(gòu)體的內(nèi)容,見代碼清單?241。
代碼清單?401 CAN初始化結(jié)構(gòu)體
1?/**
2?* @brief CAN?初始化結(jié)構(gòu)體
3?*/
4 typedef?struct?{
5?uint16_t?CAN_Prescaler;?/*配置CAN外設(shè)的時(shí)鐘分頻,可設(shè)置為1-1024*/
6?uint8_t?CAN_Mode;?/*配置CAN的工作模式,回環(huán)或正常模式*/
7?uint8_t?CAN_SJW;?/*配置SJW極限值?*/
8?uint8_t?CAN_BS1;?/*配置BS1段長度*/
9?uint8_t?CAN_BS2;?/*配置BS2段長度?*/
10?FunctionalState CAN_TTCM;?/*是否使能TTCM時(shí)間觸發(fā)功能*/
11?FunctionalState CAN_ABOM;?/*是否使能ABOM自動(dòng)離線管理功能*/
12?FunctionalState CAN_AWUM;?/*是否使能AWUM自動(dòng)喚醒功能?*/
13?FunctionalState CAN_NART;?/*是否使能NART自動(dòng)重傳功能*/
14?FunctionalState CAN_RFLM;?/*是否使能RFLM鎖定FIFO功能*/
15?FunctionalState CAN_TXFP;?/*配置TXFP報(bào)文優(yōu)先級的判定方法*/
16?} CAN_InitTypeDef;
這些結(jié)構(gòu)體成員說明如下,其中括號內(nèi)的文字是對應(yīng)參數(shù)在STM32標(biāo)準(zhǔn)庫中定義的宏,這些結(jié)構(gòu)體成員都是”40.2.1 1CAN控制內(nèi)核”小節(jié)介紹的內(nèi)容,可對比閱讀:
(1)????CAN_Prescaler
本成員設(shè)置CAN外設(shè)的時(shí)鐘分頻,它可控制時(shí)間片Tq的時(shí)間長度,這里設(shè)置的值最終會(huì)減1后再寫入BRP寄存器位,即前面介紹的Tq計(jì)算公式:
Tq = (BRP[9:0]+1) x TPCLK
等效于:Tq = CAN_Prescaler x TPCLK
(2)????CAN_Mode
本成員設(shè)置CAN的工作模式,可設(shè)置為正常模式(CAN_Mode_Normal)、回環(huán)模式(CAN_Mode_LoopBack)、靜默模式(CAN_Mode_Silent)以及回環(huán)靜默模式(CAN_Mode_Silent_LoopBack)。
(3)????CAN_SJW
本成員可以配置SJW的極限長度,即CAN重新同步時(shí)單次可增加或縮短的最大長度,它可以被配置為1-4Tq(CAN_SJW_1/2/3/4tq)。
(4)????CAN_BS1
本成員用于設(shè)置CAN位時(shí)序中的BS1段的長度,它可以被配置為1-16個(gè)Tq長度(CAN_BS1_1/2/3…16tq)。
(5)????CAN_BS2
本成員用于設(shè)置CAN位時(shí)序中的BS2段的長度,它可以被配置為1-8個(gè)Tq長度(CAN_BS2_1/2/3…8tq)。
SYNC_SEG、BS1段及BS2段的長度加起來即一個(gè)數(shù)據(jù)位的長度,即前面介紹的原來計(jì)算公式:
T1bit?=1Tq+TS1+TS2?=1+ (TS1[3:0] + 1)+ (TS2[2:0] + 1)
等效于:T1bit?= 1Tq+CAN_BS1+CAN_BS2
(6)????CAN_TTCM
本成員用于設(shè)置是否使用時(shí)間觸發(fā)功能(ENABLE/DISABLE),時(shí)間觸發(fā)功能在某些CAN標(biāo)準(zhǔn)中會(huì)使用到。
(7)????CAN_ABOM
本成員用于設(shè)置是否使用自動(dòng)離線管理(ENABLE/DISABLE),使用自動(dòng)離線管理可以在節(jié)點(diǎn)出錯(cuò)離線后適時(shí)自動(dòng)恢復(fù),不需要軟件干預(yù)。
(8)????CAN_ AWUM
本成員用于設(shè)置是否使用自動(dòng)喚醒功能(ENABLE/DISABLE),使能自動(dòng)喚醒功能后它會(huì)在監(jiān)測到總線活動(dòng)后自動(dòng)喚醒。
(9)????CAN_ABOM
本成員用于設(shè)置是否使用自動(dòng)離線管理功能(ENABLE/DISABLE),使用自動(dòng)離線管理可以在出錯(cuò)時(shí)離線后適時(shí)自動(dòng)恢復(fù),不需要軟件干預(yù)。
(10)????CAN_NART
本成員用于設(shè)置是否使用自動(dòng)重傳功能(ENABLE/DISABLE),使用自動(dòng)重傳功能時(shí),會(huì)一直發(fā)送報(bào)文直到成功為止。
(11)????CAN_RFLM
本成員用于設(shè)置是否使用鎖定接收FIFO(ENABLE/DISABLE),鎖定接收FIFO后,若FIFO溢出時(shí)會(huì)丟棄新數(shù)據(jù),否則在FIFO溢出時(shí)以新數(shù)據(jù)覆蓋舊數(shù)據(jù)。
(12)????CAN_TXFP
本成員用于設(shè)置發(fā)送報(bào)文的優(yōu)先級判定方法(ENABLE/DISABLE),使能時(shí),以報(bào)文存入發(fā)送郵箱的先后順序來發(fā)送,否則按照報(bào)文ID的優(yōu)先級來發(fā)送。
配置完這些結(jié)構(gòu)體成員后,我們調(diào)用庫函數(shù)CAN_Init即可把這些參數(shù)寫入到CAN控制寄存器中,實(shí)現(xiàn)CAN的初始化。
40.4 CAN發(fā)送及接收結(jié)構(gòu)體
在發(fā)送或接收報(bào)文時(shí),需要往發(fā)送郵箱中寫入報(bào)文信息或從接收FIFO中讀取報(bào)文信息,利用STM32標(biāo)準(zhǔn)庫的發(fā)送及接收結(jié)構(gòu)體可以方便地完成這樣的工作,它們的定義見代碼清單?402。
代碼清單?402 CAN發(fā)送及接收結(jié)構(gòu)體
1?/**
2?* @brief CAN Tx message structure definition
3?*?發(fā)送結(jié)構(gòu)體
4?*/
5 typedef?struct?{
6?uint32_t?StdId;?/*存儲(chǔ)報(bào)文的標(biāo)準(zhǔn)標(biāo)識符11位,0-0x7FF. */
7?uint32_t?ExtId;?/*存儲(chǔ)報(bào)文的擴(kuò)展標(biāo)識符29位,0-0x1FFFFFFF. */
8?uint8_t?IDE;?/*存儲(chǔ)IDE擴(kuò)展標(biāo)志?*/
9?uint8_t?RTR;?/*存儲(chǔ)RTR遠(yuǎn)程幀標(biāo)志*/
10?uint8_t?DLC;?/*存儲(chǔ)報(bào)文數(shù)據(jù)段的長度,0-8 */
11?uint8_t?Data[8];?/*存儲(chǔ)報(bào)文數(shù)據(jù)段的內(nèi)容?*/
12?} CanTxMsg;
13
14?/**
15?* @brief CAN Rx message structure definition
16?*?接收結(jié)構(gòu)體
17?*/
18 typedef?struct?{
19?uint32_t?StdId;?/*存儲(chǔ)了報(bào)文的標(biāo)準(zhǔn)標(biāo)識符11位,0-0x7FF. */
20?uint32_t?ExtId;?/*存儲(chǔ)了報(bào)文的擴(kuò)展標(biāo)識符29位,0-0x1FFFFFFF. */
21?uint8_t?IDE;?/*存儲(chǔ)了IDE擴(kuò)展標(biāo)志?*/
22?uint8_t?RTR;?/*存儲(chǔ)了RTR遠(yuǎn)程幀標(biāo)志*/
23?uint8_t?DLC;?/*存儲(chǔ)了報(bào)文數(shù)據(jù)段的長度,0-8 */
24?uint8_t?Data[8];?/*存儲(chǔ)了報(bào)文數(shù)據(jù)段的內(nèi)容?*/
25?uint8_t?FMI;?/*存儲(chǔ)了本報(bào)文是由經(jīng)過篩選器存儲(chǔ)進(jìn)FIFO的,0-0xFF */
26?} CanRxMsg;
這些結(jié)構(gòu)體成員都是”40.2.1 2CAN發(fā)送郵箱及CAN接收FIFO“小節(jié)介紹的內(nèi)容,可對比閱讀,發(fā)送結(jié)構(gòu)體與接收結(jié)構(gòu)體是類似的,只是接收結(jié)構(gòu)體多了一個(gè)FMI成員,說明如下:
(1)????StdId
本成員存儲(chǔ)的是報(bào)文的11位標(biāo)準(zhǔn)標(biāo)識符,范圍是0-0x7FF。
(2)????ExtId
本成員存儲(chǔ)的是報(bào)文的29位擴(kuò)展標(biāo)識符,范圍是0-0x1FFFFFFF。ExtId與StdId這兩個(gè)成員根據(jù)下面的IDE位配置,只有一個(gè)是有效的。
(3)????IDE
本成員存儲(chǔ)的是擴(kuò)展標(biāo)志IDE位,當(dāng)它的值為宏CAN_ID_STD時(shí)表示本報(bào)文是標(biāo)準(zhǔn)幀,使用StdId成員存儲(chǔ)報(bào)文ID;當(dāng)它的值為宏CAN_ID_EXT時(shí)表示本報(bào)文是擴(kuò)展幀,使用ExtId成員存儲(chǔ)報(bào)文ID。
(4)????RTR
本成員存儲(chǔ)的是報(bào)文類型標(biāo)志RTR位,當(dāng)它的值為宏CAN_RTR_Data時(shí)表示本報(bào)文是數(shù)據(jù)幀;當(dāng)它的值為宏CAN_RTR_Remote時(shí)表示本報(bào)文是遙控幀,由于遙控幀沒有數(shù)據(jù)段,所以當(dāng)報(bào)文是遙控幀時(shí),下面的Data[8]成員的內(nèi)容是無效的。
(5)????DLC
本成員存儲(chǔ)的是數(shù)據(jù)幀數(shù)據(jù)段的長度,它的值的范圍是0-8,當(dāng)報(bào)文是遙控幀時(shí)DLC值為0。
(6)????Data[8]
本成員存儲(chǔ)的就是數(shù)據(jù)幀中數(shù)據(jù)段的數(shù)據(jù)。
(7)????FMI
本成員只存在于接收結(jié)構(gòu)體,它存儲(chǔ)了篩選器的編號,表示本報(bào)文是經(jīng)過哪個(gè)篩選器存儲(chǔ)進(jìn)接收FIFO的,可以用它簡化軟件處理。
當(dāng)需要使用CAN發(fā)送報(bào)文時(shí),先定義一個(gè)上面發(fā)送類型的結(jié)構(gòu)體,然后把報(bào)文的內(nèi)容按成員賦值到該結(jié)構(gòu)體中,最后調(diào)用庫函數(shù)CAN_Transmit把這些內(nèi)容寫入到發(fā)送郵箱即可把報(bào)文發(fā)送出去。
接收報(bào)文時(shí),通過檢測標(biāo)志位獲知接收FIFO的狀態(tài),若收到報(bào)文,可調(diào)用庫函數(shù)CAN_Receive把接收FIFO中的內(nèi)容讀取到預(yù)先定義的接收類型結(jié)構(gòu)體中,然后再訪問該結(jié)構(gòu)體即可利用報(bào)文了。
40.5 CAN篩選器結(jié)構(gòu)體
CAN的篩選器有多種工作模式,利用篩選器結(jié)構(gòu)體可方便配置,它的定義見代碼清單?403。
代碼清單?403 CAN篩選器結(jié)構(gòu)體
1?/**
2?* @brief CAN filter init structure definition
3?* CAN篩選器結(jié)構(gòu)體
4?*/
5 typedef?struct?{
6?uint16_t?CAN_FilterIdHigh;?/*CAN_FxR1寄存器的高16位?*/
7?uint16_t?CAN_FilterIdLow;?/*CAN_FxR1寄存器的低16位*/
8?uint16_t?CAN_FilterMaskIdHigh;?/*CAN_FxR2寄存器的高16位*/
9?uint16_t?CAN_FilterMaskIdLow;?/*CAN_FxR2寄存器的低16位?*/
10?uint16_t?CAN_FilterFIFOAssignment;?/*設(shè)置經(jīng)過篩選后數(shù)據(jù)存儲(chǔ)到哪個(gè)接收FIFO */
11?uint8_t?CAN_FilterNumber;?/*篩選器編號,范圍0-27*/
12?uint8_t?CAN_FilterMode;?/*篩選器模式?*/
13?uint8_t?CAN_FilterScale;?/*設(shè)置篩選器的尺度?*/
14?FunctionalState CAN_FilterActivation;?/*是否使能本篩選器*/
15?} CAN_FilterInitTypeDef;
這些結(jié)構(gòu)體成員都是”40.2.1 4驗(yàn)收篩選器”小節(jié)介紹的內(nèi)容,可對比閱讀,各個(gè)結(jié)構(gòu)體成員的介紹如下:
(1)????CAN_FilterIdHigh
CAN_FilterIdHigh成員用于存儲(chǔ)要篩選的ID,若篩選器工作在32位模式,它存儲(chǔ)的是所篩選ID的高16位;若篩選器工作在16位模式,它存儲(chǔ)的就是一個(gè)完整的要篩選的ID。
(2)????CAN_FilterIdLow
類似地,CAN_FilterIdLow成員也是用于存儲(chǔ)要篩選的ID,若篩選器工作在32位模式,它存儲(chǔ)的是所篩選ID的低16位;若篩選器工作在16位模式,它存儲(chǔ)的就是一個(gè)完整的要篩選的ID。
(3)????CAN_FilterMaskIdHigh
CAN_FilterMaskIdHigh存儲(chǔ)的內(nèi)容分兩種情況,當(dāng)篩選器工作在標(biāo)識符列表模式時(shí),它的功能與CAN_FilterIdHigh相同,都是存儲(chǔ)要篩選的ID;而當(dāng)篩選器工作在掩碼模式時(shí),它存儲(chǔ)的是CAN_FilterIdHigh成員對應(yīng)的掩碼,與CAN_FilterIdLow組成一組篩選器。
(4)????CAN_FilterMaskIdLow
類似地,CAN_FilterMaskIdLow存儲(chǔ)的內(nèi)容也分兩種情況,當(dāng)篩選器工作在標(biāo)識符列表模式時(shí),它的功能與CAN_FilterIdLow相同,都是存儲(chǔ)要篩選的ID;而當(dāng)篩選器工作在掩碼模式時(shí),它存儲(chǔ)的是CAN_FilterIdLow成員對應(yīng)的掩碼,與CAN_FilterIdLow組成一組篩選器。
上面四個(gè)結(jié)構(gòu)體的存儲(chǔ)的內(nèi)容很容易讓人糊涂,請結(jié)合前面的圖?4014和下面的表?407理解,如果還搞不清楚,再結(jié)合庫函數(shù)CAN_FilterInit的源碼來分析。
表?407?不同模式下各結(jié)構(gòu)體成員的內(nèi)容
模式
CAN_FilterIdHigh
CAN_FilterIdLow
CAN_FilterMaskIdHigh
CAN_FilterMaskIdLow
32位列表模式
ID1的高16位
ID1的低16位
ID2的高16位
ID2的低16位
16位列表模式
ID1的完整數(shù)值
ID2的完整數(shù)值
ID3的完整數(shù)值
ID4的完整數(shù)值
32位掩碼模式
ID1的高16位
ID1的低16位
ID1掩碼的高16位
ID1掩碼的低16位
16位掩碼模式
ID1的完整數(shù)值
ID2的完整數(shù)值
ID1掩碼的完整數(shù)值
ID2掩碼完整數(shù)值
對這些結(jié)構(gòu)體成員賦值的時(shí)候,還要注意寄存器位的映射,即注意哪部分代表STID,哪部分代表EXID以及IDE、RTR位。
(5)????CAN_FilterFIFOAssignment
本成員用于設(shè)置當(dāng)報(bào)文通過篩選器的匹配后,該報(bào)文會(huì)被存儲(chǔ)到哪一個(gè)接收FIFO,它的可選值為FIFO0或FIFO1(宏CAN_Filter_FIFO0/1)。
(6)????CAN_FilterNumber
本成員用于設(shè)置篩選器的編號,即本過濾器結(jié)構(gòu)體配置的是哪一組篩選器,CAN一共有28個(gè)篩選器,所以它的可輸入?yún)?shù)范圍為0-27。
(7)????CAN_FilterMode
本成員用于設(shè)置篩選器的工作模式,可以設(shè)置為列表模式(宏CAN_FilterMode_IdList)及掩碼模式(宏CAN_FilterMode_IdMask)。
(8)????CAN_FilterScale
本成員用于設(shè)置篩選器的尺度,可以設(shè)置為32位長(宏CAN_FilterScale_32bit)及16位長(宏CAN_FilterScale_16bit)。
(9)????CAN_FilterActivation
本成員用于設(shè)置是否激活這個(gè)篩選器(宏ENABLE/DISABLE)。
配置完這些結(jié)構(gòu)體成員后,我們調(diào)用庫函數(shù)CAN_FilterInit即可把這些參數(shù)寫入到篩選控制寄存器中,從而使用篩選器。我們前面說如果不理解那幾個(gè)ID結(jié)構(gòu)體成員存儲(chǔ)的內(nèi)容時(shí),可以直接閱讀庫函數(shù)CAN_FilterInit的源代碼理解,就是因?yàn)樗苯訉拇嫫鲗懭雰?nèi)容,代碼的邏輯是非常清晰的。
40.6 CAN—雙機(jī)通訊實(shí)驗(yàn)
本小節(jié)演示如何使用STM32的CAN外設(shè)實(shí)現(xiàn)兩個(gè)設(shè)備之間的通訊,該實(shí)驗(yàn)中使用了兩個(gè)實(shí)驗(yàn)板,如果您只有一個(gè)實(shí)驗(yàn)板,也可以使用CAN的回環(huán)模式進(jìn)行測試,不影響學(xué)習(xí)的。為此,我們提供了”CAN—雙機(jī)通訊”及”CAN—回環(huán)測試”兩個(gè)工程,可根據(jù)自己的實(shí)驗(yàn)環(huán)境選擇相應(yīng)的工程來學(xué)習(xí)。這兩個(gè)工程的主體都是一樣的,本教程主要以”CAN—雙機(jī)通訊”工程進(jìn)行講解。
40.6.1?硬件設(shè)計(jì)

圖?4016?雙CAN通訊實(shí)驗(yàn)硬件連接圖
圖?4016中的是兩個(gè)實(shí)驗(yàn)板的硬件連接。在單個(gè)實(shí)驗(yàn)板中,作為CAN控制器的STM32引出CAN_Tx和CAN_Rx兩個(gè)引腳與CAN收發(fā)器TJA1050相連,收發(fā)器使用CANH及CANL引腳連接到CAN總線網(wǎng)絡(luò)中。為了方便使用,我們每個(gè)實(shí)驗(yàn)板引出的CANH及CANL都連接了1個(gè)120歐的電阻作為CAN總線的端電阻,所以要注意如果您要把實(shí)驗(yàn)板作為一個(gè)普通節(jié)點(diǎn)連接到現(xiàn)有的CAN總線時(shí),是不應(yīng)添加該電阻的!
要實(shí)現(xiàn)通訊,我們還要使用導(dǎo)線把實(shí)驗(yàn)板引出的CANH及CANL兩條總線連接起來,才能構(gòu)成完整的網(wǎng)絡(luò)。實(shí)驗(yàn)板之間CANH1與CANH2連接,CANL1與CANL2連接即可。
要注意的是,由于我們的實(shí)驗(yàn)板CAN使用的信號線與液晶屏共用了,為防止干擾,平時(shí)我們默認(rèn)是不給CAN收發(fā)器供電的,使用CAN的時(shí)候一定要把CAN接線端子旁邊的”C/4-5V“排針使用跳線帽與”5V“排針連接起來進(jìn)行供電,并且把液晶屏從板子上拔下來。
如果您使用的是單機(jī)回環(huán)測試的工程實(shí)驗(yàn),就不需要使用導(dǎo)線連接板子了,而且也不需要給收發(fā)器供電,因?yàn)榛丨h(huán)模式的信號是不經(jīng)過收發(fā)器的,不過,它還是不能和液晶屏同時(shí)使用的。
40.6.2?軟件設(shè)計(jì)
為了使工程更加有條理,我們把CAN控制器相關(guān)的代碼獨(dú)立分開存儲(chǔ),方便以后移植。在”串口實(shí)驗(yàn)”之上新建”bsp_can.c“及”bsp_can.h“文件,這些文件也可根據(jù)您的喜好命名,它們不屬于STM32標(biāo)準(zhǔn)庫的內(nèi)容,是由我們自己根據(jù)應(yīng)用需要編寫的。
1.????編程要點(diǎn)
(1)????初始化CAN通訊使用的目標(biāo)引腳及端口時(shí)鐘;
(2)????使能CAN外設(shè)的時(shí)鐘;
(3)????配置CAN外設(shè)的工作模式、位時(shí)序以及波特率;
(4)????配置篩選器的工作方式;
(5)????編寫測試程序,收發(fā)報(bào)文并校驗(yàn)。
2.????代碼分析
CAN硬件相關(guān)宏定義
我們把CAN硬件相關(guān)的配置都以宏的形式定義到”bsp_can.h“文件中,見代碼清單?242。
代碼清單?404 CAN硬件配置相關(guān)的宏(bsp_can.h文件)
1
2?/*CAN硬件相關(guān)的定義*/
3?#define CANx CAN1
4?#define CAN_CLK RCC_APB1Periph_CAN1
5?/*接收中斷號*/
6?#define CAN_RX_IRQ CAN1_RX0_IRQn
7?/*接收中斷服務(wù)函數(shù)*/
8?#define CAN_RX_IRQHandler CAN1_RX0_IRQHandler
9
10?/*引腳*/
11?#define CAN_RX_PIN GPIO_Pin_8
12?#define CAN_TX_PIN GPIO_Pin_9
13?#define CAN_TX_GPIO_PORT GPIOB
14?#define CAN_RX_GPIO_PORT GPIOB
15?#define CAN_TX_GPIO_CLK RCC_AHB1Periph_GPIOB
16?#define CAN_RX_GPIO_CLK RCC_AHB1Periph_GPIOB
17?#define CAN_AF_PORT GPIO_AF_CAN1
18?#define CAN_RX_SOURCE GPIO_PinSource8
19?#define CAN_TX_SOURCE GPIO_PinSource9
以上代碼根據(jù)硬件連接,把與CAN通訊使用的CAN號、引腳號、引腳源以及復(fù)用功能映射都以宏封裝起來,并且定義了接收中斷的中斷向量和中斷服務(wù)函數(shù),我們通過中斷來獲知接收FIFO的信息。
初始化CAN的 GPIO
利用上面的宏,編寫CAN的初始化函數(shù),見代碼清單?243。
代碼清單?405 CAN的GPIO初始化函數(shù)(bsp_can.c文件)
1 /*
1
2?*?函數(shù)名:CAN_GPIO_Config
3?*?描述:CAN的GPIO?配置
4?*?輸入:無
5?*?輸出?:?無
6?*?調(diào)用:內(nèi)部調(diào)用
7?*/
8?static void?CAN_GPIO_Config(void)
9?{
10?GPIO_InitTypeDef GPIO_InitStructure;
11
12?/*?使能GPIO時(shí)鐘*/
13?RCC_AHB1PeriphClockCmd(CAN_TX_GPIO_CLK|CAN_RX_GPIO_CLK, ENABLE);
14
15?/*?引腳源*/
16?GPIO_PinAFConfig(CAN_TX_GPIO_PORT, CAN_RX_SOURCE, CAN_AF_PORT);
17?GPIO_PinAFConfig(CAN_RX_GPIO_PORT, CAN_TX_SOURCE, CAN_AF_PORT);
18
19?/*?配置?CAN TX?引腳?*/
20?GPIO_InitStructure.GPIO_Pin = CAN_TX_PIN;
21?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
22?GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
23?GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
24?GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
25?GPIO_Init(CAN_TX_GPIO_PORT, &GPIO_InitStructure);
26
27?/*?配置?CAN RX?引腳?*/
28?GPIO_InitStructure.GPIO_Pin = CAN_RX_PIN ;
29?GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
30?GPIO_Init(CAN_RX_GPIO_PORT, &GPIO_InitStructure);
31?}
與所有使用到GPIO的外設(shè)一樣,都要先把使用到的GPIO引腳模式初始化,配置好復(fù)用功能。CAN的兩個(gè)引腳都配置成通用推挽輸出模式即可。
配置CAN的工作模式
接下來我們配置CAN的工作模式,由于我們是自己用的兩個(gè)板子之間進(jìn)行通訊,波特率之類的配置只要兩個(gè)板子一致即可。如果您要使實(shí)驗(yàn)板與某個(gè)CAN總線網(wǎng)絡(luò)的通訊的節(jié)點(diǎn)通訊,那么實(shí)驗(yàn)板的CAN配置必須要與該總線一致。我們實(shí)驗(yàn)中使用的配置見代碼清單?244。
代碼清單?406?配置CAN的工作模式(bsp_can.c文件)
1?/*
2?*?函數(shù)名:CAN_Mode_Config
3?*?描述:CAN的模式配置
4?*?輸入:無
5?*?輸出?:?無
6?*?調(diào)用:內(nèi)部調(diào)用
7?*/
8?static void?CAN_Mode_Config(void)
9?{
10?CAN_InitTypeDef CAN_InitStructure;
11?/************************CAN通信參數(shù)設(shè)置************************/
12?/* Enable CAN clock */
13?RCC_APB1PeriphClockCmd(CAN_CLK, ENABLE);
14
15?/*CAN寄存器初始化*/
16?CAN_DeInit(CAN1);
17?CAN_StructInit(&CAN_InitStructure);
18
19?/*CAN單元初始化*/
20?CAN_InitStructure.CAN_TTCM=DISABLE;?//MCR-TTCM?關(guān)閉時(shí)間觸發(fā)通信模式使能
21?CAN_InitStructure.CAN_ABOM=ENABLE;?//MCR-ABOM?使能自動(dòng)離線管理
22?CAN_InitStructure.CAN_AWUM=ENABLE;?//MCR-AWUM?使用自動(dòng)喚醒模式
23?CAN_InitStructure.CAN_NART=DISABLE;?//MCR-NART?禁止報(bào)文自動(dòng)重傳
24?CAN_InitStructure.CAN_RFLM=DISABLE;?//MCR-RFLM?接收FIFO?不鎖定
25?????????????????????????//?溢出時(shí)新報(bào)文會(huì)覆蓋原有報(bào)文
26?CAN_InitStructure.CAN_TXFP=DISABLE;?//MCR-TXFP?發(fā)送FIFO優(yōu)先級取決于報(bào)文標(biāo)示符
27?CAN_InitStructure.CAN_Mode = CAN_Mode_Normal;?//正常工作模式
28?CAN_InitStructure.CAN_SJW=CAN_SJW_2tq;?//BTR-SJW?重新同步跳躍寬度?2個(gè)時(shí)間單元
29
30?/* ss=1 bs1=5 bs2=3?位時(shí)間寬度為(1+5+3)?波特率即為時(shí)鐘周期tq*(1+3+5) */
31?CAN_InitStructure.CAN_BS1=CAN_BS1_5tq;?//BTR-TS1?時(shí)間段1?占用了5個(gè)時(shí)間單元
32?CAN_InitStructure.CAN_BS2=CAN_BS2_3tq;?//BTR-TS1?時(shí)間段2?占用了3個(gè)時(shí)間單元
33
34?/* CAN Baudrate = 1 MBps (1MBps已為stm32的CAN最高速率) (CAN?時(shí)鐘頻率為?APB 1 = 45 MHz) */
35?BTR-BRP?波特率分頻器定義了時(shí)間單元的時(shí)間長度?45/(1+5+3)/5=1 Mbps
36?CAN_InitStructure.CAN_Prescaler =5;
37?CAN_Init(CANx, &CAN_InitStructure);
38?}
這段代碼主要是把CAN的模式設(shè)置成了正常工作模式,如果您閱讀的是”CAN—回環(huán)測試”的工程,這里是被配置成回環(huán)模式的,除此之外,兩個(gè)工程就沒有其它差別了。
代碼中還把位時(shí)序中的BS1和BS2段分別設(shè)置成了5Tq和3Tq,再加上SYNC_SEG段,一個(gè)CAN數(shù)據(jù)位就是9Tq了,加上CAN外設(shè)的分頻配置為5分頻,CAN所使用的總線時(shí)鐘fAPB1?= 45MHz,于是我們可計(jì)算出它的波特率:
1Tq = 1/(45M/5)=1/9 us
T1bit=(5+3+1) x Tq =1us
波特率=1/T1bit?=1Mbps
配置篩選器
以上是配置CAN的工作模式,為了方便管理接收報(bào)文,我們還要把篩選器用起來,見代碼清單?245。
代碼清單?407?配置CAN的篩選器(bsp_can.c文件)
1
2?/*IDE位的標(biāo)志*/
3?#define CAN_ID_STD ((uint32_t)0x00000000)?/*標(biāo)準(zhǔn)ID */
4?#define CAN_ID_EXT ((uint32_t)0x00000004)?/*擴(kuò)展ID */
5
6?/*RTR位的標(biāo)志*/
7?#define CAN_RTR_Data ((uint32_t)0x00000000)?/*數(shù)據(jù)幀?*/
8?#define CAN_RTR_Remote ((uint32_t)0x00000002)?/*遠(yuǎn)程幀*/
9
10?/************************************************************************/
11?/*
12?*?函數(shù)名:CAN_Filter_Config
13?*?描述:CAN的篩選器配置
14?*?輸入:無
15?*?輸出?:?無
16?*?調(diào)用:內(nèi)部調(diào)用
17?*/
18?static void?CAN_Filter_Config(void)
19?{
20?CAN_FilterInitTypeDef CAN_FilterInitStructure;
21
22?/*CAN篩選器初始化*/
23?CAN_FilterInitStructure.CAN_FilterNumber=0;?//篩選器組0
24?//工作在掩碼模式
25?CAN_FilterInitStructure.CAN_FilterMode=CAN_FilterMode_IdMask;
26?//篩選器位寬為單個(gè)32位。
27?CAN_FilterInitStructure.CAN_FilterScale=CAN_FilterScale_32bit;
28
29?/*?使能篩選器,按照標(biāo)志符的內(nèi)容進(jìn)行比對篩選,
30?擴(kuò)展ID不是如下的就拋棄掉,是的話,會(huì)存入FIFO0。?*/
31//要篩選的ID高位,第0位保留,第1位為RTR標(biāo)志,第2位為IDE標(biāo)志,從第3位開始是EXID
32CAN_FilterInitStructure.CAN_FilterIdHigh= ((((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF0000)>>16;
33?//要篩選的ID低位
34?CAN_FilterInitStructure.CAN_FilterIdLow= (((u32)0x1314<<3)|CAN_ID_EXT|CAN_RTR_DATA)&0xFFFF;
35?//篩選器高16位每位必須匹配
36?CAN_FilterInitStructure.CAN_FilterMaskIdHigh= 0xFFFF;
37?//篩選器低16位每位必須匹配
38?CAN_FilterInitStructure.CAN_FilterMaskIdLow= 0xFFFF;
39?//篩選器被關(guān)聯(lián)到FIFO0
40?CAN_FilterInitStructure.CAN_FilterFIFOAssignment=CAN_Filter_FIFO0 ;
41?//使能篩選器
42?CAN_FilterInitStructure.CAN_FilterActivation=ENABLE;
43
44?CAN_FilterInit(&CAN_FilterInitStructure);
45?/*CAN通信中斷使能*/
46?CAN_ITConfig(CANx, CAN_IT_FMP0, ENABLE);
47?}
這段代碼把篩選器第0組配置成了32位的掩碼模式,并且把它的輸出連接到接收FIFO0,若通過了篩選器的匹配,報(bào)文會(huì)被存儲(chǔ)到接收FIFO0。
篩選器配置的重點(diǎn)是配置ID和掩碼,根據(jù)我們的配置,這個(gè)篩選器工作在圖?4017中的模式。
圖?4017?一個(gè)32位的掩碼模式篩選器
在該配置中,結(jié)構(gòu)體成員CAN_FilterIdHigh和CAN_FilterIdLow存儲(chǔ)的是要篩選的ID,而CAN_FilterMaskIdHigh和CAN_FilterMaskIdLow存儲(chǔ)的是相應(yīng)的掩碼。在賦值時(shí),要注意寄存器位的映射,在32位的ID中,第0位是保留位,第1位是RTR標(biāo)志,第2位是IDE標(biāo)志,從第3位起才是報(bào)文的ID(擴(kuò)展ID)。
因此在上述代碼中我們先把擴(kuò)展ID”0x1314“、IDE位標(biāo)志”宏CAN_ID_EXT“以及RTR位標(biāo)志”宏CAN_RTR_DATA“根據(jù)寄存器位映射組成一個(gè)32位的數(shù)據(jù),然后再把它的高16位和低16位分別賦值給結(jié)構(gòu)體成員CAN_FilterIdHigh和CAN_FilterIdLow。
而在掩碼部分,為簡單起見我們直接對所有位賦值為1,表示上述所有標(biāo)志都完全一樣的報(bào)文才能經(jīng)過篩選,所以我們這個(gè)配置相當(dāng)于單個(gè)ID列表的模式,只篩選了一個(gè)ID號,而不是篩選一組ID號。這里只是為了演示方便,實(shí)際使用中一般會(huì)對不要求相等的數(shù)據(jù)位賦值為0,從而過濾一組ID,如果有需要,還可以繼續(xù)配置多個(gè)篩選器組,最多可以配置28個(gè),代碼中只是配置了篩選器組0。
對結(jié)構(gòu)體賦值完畢后調(diào)用庫函數(shù)CAN_FilterInit把個(gè)篩選器組的參數(shù)寫入到寄存器中。
配置接收中斷
在配置篩選器代碼的最后部分我們還調(diào)用庫函數(shù)CAN_ITConfig使能了CAN的中斷,該函數(shù)使用的輸入?yún)?shù)宏CAN_IT_FMP0表示當(dāng)FIFO0接收到數(shù)據(jù)時(shí)會(huì)引起中斷,該接收中斷的優(yōu)先級配置如下,見代碼清單?246。
代碼清單?408?配置CAN接收中斷的優(yōu)先級(bsp_can.c文件)
1?/*接收中斷號*/
2?#define CAN_RX_IRQ CAN1_RX0_IRQn
3?/*
4?*?函數(shù)名:CAN_NVIC_Config
5?*?描述:CAN的NVIC?配置,第1優(yōu)先級組,0,0優(yōu)先級
6?*?輸入:無
7?*?輸出?:?無
8?*?調(diào)用:內(nèi)部調(diào)用
9?*/
10?static void?CAN_NVIC_Config(void)
11?{
12?NVIC_InitTypeDef NVIC_InitStructure;
13?/* Configure one bit for preemption priority */
14?NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);
15?/*中斷設(shè)置*/
16?NVIC_InitStructure.NVIC_IRQChannel = CAN_RX_IRQ;?//CAN RX中斷
17?NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
18?NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
19?NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
20?NVIC_Init(&NVIC_InitStructure);
21?}
這部分與我們配置其它中斷的優(yōu)先級無異,都是配置NVIC結(jié)構(gòu)體,優(yōu)先級可根據(jù)自己的需要配置,最主要的是中斷向量,上述代碼中把中斷向量配置成了CAN的接收中斷。
設(shè)置發(fā)送報(bào)文
要使用CAN發(fā)送報(bào)文時(shí),我們需要先定義一個(gè)發(fā)送報(bào)文結(jié)構(gòu)體并向它賦值,見代碼清單?247。
代碼清單?409?設(shè)置要發(fā)送的報(bào)文(bsp_can.c文件)
1?/*IDE位的標(biāo)志*/
2?#define CAN_ID_STD ((uint32_t)0x00000000)?/*標(biāo)準(zhǔn)ID */
3?#define CAN_ID_EXT ((uint32_t)0x00000004)?/*擴(kuò)展ID */
4
5?/*RTR位的標(biāo)志*/
6?#define CAN_RTR_Data ((uint32_t)0x00000000)?/*數(shù)據(jù)幀?*/
7?#define CAN_RTR_Remote ((uint32_t)0x00000002)?/*遠(yuǎn)程幀*/
8
9?/*
10?*?函數(shù)名:CAN_SetMsg
11?*?描述:CAN通信報(bào)文內(nèi)容設(shè)置,設(shè)置一個(gè)數(shù)據(jù)內(nèi)容為0-7的數(shù)據(jù)包
12?*?輸入:無
13?*?輸出?:?無
14?*?調(diào)用:外部調(diào)用
15?*/
16?void?CAN_SetMsg(CanTxMsg *TxMessage)
17?{
18?uint8_t?ubCounter = 0;
19
20?//TxMessage.StdId=0x00;
21?TxMessage->ExtId=0x1314;?//使用的擴(kuò)展ID
22?TxMessage->IDE=CAN_ID_EXT;?//擴(kuò)展模式
23?TxMessage->RTR=CAN_RTR_DATA;?//發(fā)送的是數(shù)據(jù)
24?TxMessage->DLC=8;?//數(shù)據(jù)長度為8字節(jié)
25
26?/*設(shè)置要發(fā)送的數(shù)據(jù)0-7*/
27?for?(ubCounter = 0; ubCounter < 8; ubCounter++)
28?{
29?TxMessage->Data[ubCounter] = ubCounter;
30?}
31?}
這段代碼是我們?yōu)榱朔奖阊菔径约憾x的設(shè)置報(bào)文內(nèi)容的函數(shù),它把報(bào)文設(shè)置成了擴(kuò)展模式的數(shù)據(jù)幀,擴(kuò)展ID為0x1314,數(shù)據(jù)段的長度為8,且數(shù)據(jù)內(nèi)容分別為0-7,實(shí)際應(yīng)用中您可根據(jù)自己的需求發(fā)設(shè)置報(bào)文內(nèi)容。當(dāng)我們設(shè)置好報(bào)文內(nèi)容后,調(diào)用庫函數(shù)CAN_Transmit即可把該報(bào)文存儲(chǔ)到發(fā)送郵箱,然后CAN外設(shè)會(huì)把它發(fā)送出去:
CAN_Transmit(CANx, &TxMessage);
接收報(bào)文
由于我們設(shè)置了接收中斷,所以接收報(bào)文的操作是在中斷的服務(wù)函數(shù)中完成的,見代碼清單?248。
代碼清單?4010?接收報(bào)文(stm32f4xx_it.c)
1
2?/*接收中斷服務(wù)函數(shù)*/
3?#define CAN_RX_IRQHandler CAN1_RX0_IRQHandler
4
5 extern?__IO?uint32_t?flag ;?//用于標(biāo)志是否接收到數(shù)據(jù),在中斷函數(shù)中賦值
6 extern?CanRxMsg RxMessage;?//接收緩沖區(qū)
7?/********************************************************************/
8?void?CAN_RX_IRQHandler(void)
9?{
10?/*從郵箱中讀出報(bào)文*/
11?CAN_Receive(CANx, CAN_FIFO0, &RxMessage);
12
13?/*?比較ID是否為0x1314 */
14?if?((RxMessage.ExtId==0x1314) && (RxMessage.IDE==CAN_ID_EXT) && (RxMessage.DLC==8) )
15?{
16?flag = 1;?//接收成功
17?}
18?else
19?{
20?flag = 0;?//接收失敗
21?}
22?}
根據(jù)我們前面的配置,若CAN接收的報(bào)文經(jīng)過篩選器匹配后會(huì)被存儲(chǔ)到FIFO0中,并引起中斷進(jìn)入到這個(gè)中斷服務(wù)函數(shù)中,在這個(gè)函數(shù)里我們調(diào)用了庫函數(shù)CAN_Receive把報(bào)文從FIFO復(fù)制到自定義的接收報(bào)文結(jié)構(gòu)體RxMessage中,并且比較了接收到的報(bào)文ID是否與我們希望接收的一致,若一致就設(shè)置標(biāo)志flag=1,否則為0,通過flag標(biāo)志通知主程序流程獲知是否接收到數(shù)據(jù)。
要注意如果設(shè)置了接收報(bào)文中斷,必須要在中斷內(nèi)調(diào)用CAN_Receive函數(shù)讀取接收FIFO的內(nèi)容,因?yàn)橹挥羞@樣才能清除該FIFO的接收中斷標(biāo)志,如果不在中斷內(nèi)調(diào)用它清除標(biāo)志的話,一旦接收到報(bào)文,STM32會(huì)不斷進(jìn)入中斷服務(wù)函數(shù),導(dǎo)致程序卡死。
3.????main函數(shù)
最后我們來閱讀main函數(shù),了解整個(gè)通訊流程,見代碼清單?2414。
代碼清單?4011 main函數(shù)
1
2?_IO?uint32_t?flag = 0;?//用于標(biāo)志是否接收到數(shù)據(jù),在中斷函數(shù)中賦值
3?CanTxMsg TxMessage;?//發(fā)送緩沖區(qū)
4?CanRxMsg RxMessage;?//接收緩沖區(qū)
5
6?/**
7?* @brief?主函數(shù)
8?* @param?無
9?* @retval?無
10?*/
11?int?main(void)
12?{
13?LED_GPIO_Config();
14
15?/*初始化USART1*/
16?Debug_USART_Config();
17
18?/*初始化按鍵*/
19?Key_GPIO_Config();
20
21?/*初始化can,在中斷接收CAN數(shù)據(jù)包*/
22?CAN_Config();
23
24?printf(”\r\n歡迎使用秉火?STM32 F429?開發(fā)板。\r\n”);
25?printf(”\r\n秉火F429 CAN通訊實(shí)驗(yàn)例程\r\n”);
26
27?printf(”\r\n實(shí)驗(yàn)步驟:\r\n”);
28
29?printf(”\r\n?1.使用導(dǎo)線連接好兩個(gè)CAN訊設(shè)備\r\n”);
30?printf(”\r\n?2.使用跳線帽連接好:5v — C/4-5V?\r\n”);
31?printf(”\r\n?3.按下開發(fā)板的KEY1鍵,會(huì)使用CAN向外發(fā)送0-7的數(shù)據(jù)包,包的擴(kuò)展ID為0x1314?\r\n”);
32?printf(”\r\n?4.若開發(fā)板的CAN接收到擴(kuò)展ID為0x1314的數(shù)據(jù)包,會(huì)把數(shù)據(jù)以打印到串口。?\r\n”);
33?printf(”\r\n?5.本例中的can波特率為1MBps,為stm32的can最高速率。?\r\n”);
34
35?while?(1)
36?{
37?/*按一次按鍵發(fā)送一次數(shù)據(jù)*/
38?if?( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON)
39?{
40?LED_BLUE;
41?/*設(shè)置要發(fā)送的報(bào)文*/
42?CAN_SetMsg(&TxMessage);
43?/*把報(bào)文存儲(chǔ)到發(fā)送郵箱,發(fā)送*/
44?CAN_Transmit(CANx, &TxMessage);
45
46?can_delay(10000);//等待發(fā)送完畢,可使用CAN_TransmitStatus查看狀態(tài)
47
48?LED_GREEN;
49
50?printf(”\r\n已使用CAN發(fā)送數(shù)據(jù)包!\r\n”);
51?printf(”\r\n發(fā)送的報(bào)文內(nèi)容為:\r\n”);
52?printf(”\r\n擴(kuò)展ID號ExtId:0x%x?\r\n”,TxMessage.ExtId);
53?CAN_DEBUG_ARRAY(TxMessage.Data,8);
54?}
55?if?(flag==1)
56?{
57?LED_GREEN;
58?printf(”\r\nCAN接收到數(shù)據(jù):\r\n”);
59
60?CAN_DEBUG_ARRAY(RxMessage.Data,8);
61
62?flag=0;
63?}
64?}
65?}
在main函數(shù)里,我們調(diào)用了CAN_Config函數(shù)初始化CAN外設(shè),它包含我們前面解說的GPIO初始化函數(shù)CAN_GPIO_Config、中斷優(yōu)先級設(shè)置函數(shù)CAN_NVIC_Config、工作模式設(shè)置函數(shù)CAN_Mode_Config以及篩選器配置函數(shù)CAN_Filter_Config。
初始化完成后,我們在while循環(huán)里檢測按鍵,當(dāng)按下實(shí)驗(yàn)板的按鍵1時(shí),它就調(diào)用CAN_SetMsg函數(shù)設(shè)置要發(fā)送的報(bào)文,然后調(diào)用CAN_Transmit函數(shù)把該報(bào)文存儲(chǔ)到發(fā)送郵箱,等待CAN外設(shè)把它發(fā)送出去。代碼中并沒有檢測發(fā)送狀態(tài),如果需要,您可以調(diào)用庫函數(shù)CAN_TransmitStatus檢查發(fā)送狀態(tài)。
while循環(huán)中在其它時(shí)間一直檢查flag標(biāo)志,當(dāng)接收到報(bào)文時(shí),我們的中斷服務(wù)函數(shù)會(huì)把它置1,所以我們可以通過它獲知接收狀態(tài),當(dāng)接收到報(bào)文時(shí),我們把它使用宏CAN_DEBUG_ARRAY輸出到串口。
40.6.3?下載驗(yàn)證
下載驗(yàn)證這個(gè)CAN實(shí)驗(yàn)時(shí),我們建議您先使用”CAN—回環(huán)測試”的工程進(jìn)行測試,它的環(huán)境配置比較簡單,只需要一個(gè)實(shí)驗(yàn)板,用USB線使實(shí)驗(yàn)板”USB TO UART“接口跟電腦連接起來,在電腦端打開串口調(diào)試助手,并且把編譯好的該工程下載到實(shí)驗(yàn)板,然后復(fù)位。這時(shí)在串口調(diào)試助手可看到CAN測試的調(diào)試信息,按一下實(shí)驗(yàn)板上的KEY1按鍵,實(shí)驗(yàn)板會(huì)使用回環(huán)模式向自己發(fā)送報(bào)文,在串口調(diào)試助手可以看到相應(yīng)的發(fā)送和接收的信息。
使用回環(huán)測試成功后,如果您有兩個(gè)實(shí)驗(yàn)板,需要按照”硬件設(shè)計(jì)”小節(jié)中的圖例連接兩個(gè)板子的CAN總線,并且一定要接上跳線帽給CAN收發(fā)器供電、把液晶屏拔掉防止干擾。用USB線使實(shí)驗(yàn)板”USB TO UART“接口跟電腦連接起來,在電腦端打開串口調(diào)試助手,然后使用”CAN—雙機(jī)通訊”工程編譯,并給兩個(gè)板子都下載該程序,然后復(fù)位。這時(shí)在串口調(diào)試助手可看到CAN測試的調(diào)試信息,按一下其中一個(gè)實(shí)驗(yàn)板上的KEY1按鍵,另一個(gè)實(shí)驗(yàn)板會(huì)接收到報(bào)文,在串口調(diào)試助手可以看到相應(yīng)的發(fā)送和接收的信息。
40.7 每課一問
8.????在工程中嘗試修改發(fā)送報(bào)文的ID,試驗(yàn)它能不能經(jīng)過篩選器被接收到。
9.????修改篩選器的掩碼配置,使得它能接收ID為”0x 13xx”的報(bào)文。