手把手教你實現穩定的CAN通信(一)

這篇先摁下具體的實現方法不談,先講一些概念。如果感覺概念的具體闡述有些累牘,就直接看加粗的結論。

最佳/最大用戶併發數

我們從例子,引發出具體的概念。
理髮店共有3名理髮師(處理器同時處理事務數)處理到店理髮的用戶,理髮師給每個用戶理髮的時間爲1小時(處理時間),店裏有三個等待的理髮的椅子(請求緩存),客人在理髮店呆的時間超過3個小時就會無法忍受離開(超時時間)。
在這個場景裏,隨着用戶增大(負載),1.資源利用率逐漸增加,到3名客戶後維持不變。2.系統吞吐量逐漸增加,到達3個客戶後增加的速度變小,到了9個客戶左右開始下降。3.響應時間在0~3個客戶之間保持穩定,超過3個客戶之後逐漸增加,增長速度也逐漸增加,超過9個客戶之後接近無窮大。
最佳/最大用戶併發數
資源利用率和相應時間隨着負載的變化曲線比較好理解,吞吐量在這裏表示系統成功執行的請求數,吞吐量在超過9個客戶下降的主要原因是因爲系統超負荷運算,多餘的上線文切換,低速IO的訪問,或如STM32的CAN超負荷報文下,多餘的中斷響應,ARM模式的切換,客觀上將處理時間(1小時)拉長了,所以會導致吞吐量下降。因爲用“併發用戶數”這個詞容易引起誤會,尤其是在現在多核的處理器以及普及。我將併發改爲單位時間的請求數。
對一個確定的被測系統來說,在某個具體的軟硬件環境下,他的"最佳單位時間請求數"以及“最大單位時間請求數”都是客觀存在的,我們做的系統,應該確保系統的“最大單位時間請求數”大於系統需要承受的峯值負載,並且在系統的日常使用過程中,負載處在“最佳單位時間請求數”左右。
STM32版本,總線系統上實測出來的最佳單位時間請求數是1/100ms左右,凳子數量受RAM(幾k放到這去做緩存,協議長度100)限制,再加上重發等機制引起的數據量震盪,最大單位時間請求數當時我已經喪失了測的興趣

CAN總線佈線長度限制

CAN總線上任意兩個節點之間的最大傳輸距離,決定因素有兩個方面,一個是互連總線節點的迴路延時(由CAN總線控制器和驅動器等引入)+總線線路延時。另一個是由於總線電纜串聯等效電阻和總線節點的輸入電阻而導致的信號幅度下降。

CAN總線循環延時

《ISO 11898-1》把一個位時間分爲四段。
Bit Time
Sync_Seg(同步段)、Phase_Seg1(相位緩衝段1)、Phase_Seg2(相位緩衝段2):CAN控制器在每一個CAN幀的幀起始做硬同步,將總線的跳變沿定位到這個段內,在傳輸過程中,因爲CAN幀使用位填充的方式進行編碼,總線上不會連續出現6個相同的位電平,CAN控制通過預設的SJW調整位寬長度進行軟同步,如果節點出現正相位差,則增加Phase_Seg1段長度,當節點產生負的相位差,則減少Phase_Seg2段長度,確保總線上的跳變沿處在同步段。

Prop_Seg(傳輸段):一般的CAN控制器都將傳輸段和相位緩衝段1合併爲一個時間段供用戶配置(諸如STM32的bxCAN)。傳輸段用於抵消數據由CAN控制器發出,到總線上另一個CAN控制器的時間延時。

Sample Point(採樣點):CAN控制器在這個時間點判斷總線當前位是顯性的還是隱性的。

CAN系統之所以對信號傳輸延時非常敏感,主要來源於節點之間競爭訪問網絡時的非破壞性仲裁以及幀內應答。也就是說,一個節點A控制總線由顯性轉換爲隱性時(ACK應答間隙),另一個節點B在採樣到總線爲隱性的時候,需要控制總線爲顯性,而節點A能夠正常採樣到總線爲顯性。設tprop(a,b)爲由A節點的CAN控制到B節點控制器的通信延時。
節點延時
以收發器選擇TJA1044(循環延時爲210ns),波特率爲500K,採樣點爲位時間的80%的爲例,我們先將電信號在線纜上的傳輸速度暫定爲0.23m/ns。可以計算出總線的長度爲(((1 * 109/5 * 105)* 80% - 2 * 210)*0.23)/2= 135.7m。
135.7m是在線纜的傳輸速度爲0.23m/ns計算出來的,在實際情況中,有不同的因素影響着這個參數。
1.使用線徑更粗,或者鍍金鍍銀的線纜,能夠有效地提高速度。
2.總線每接入一個設備都會給總線引入分佈電容,影響信號傳輸特性,使傳輸速度降低。實驗室實測在1M波特率的情況下,上了10個上節點就很難達到總線的理論距離了。
3.總線節點不同的連接拓撲,會在很大程度上影響傳輸速度和信號質量

當然,沒有說的這麼玄乎,我看網上還有專門測總線傳輸延時和節點的容抗和阻抗的。其實把握了基本原理底線,再測試一些自己開發設備在幾種典型應用的性能,就能得針對現場的實際情況得出一個性價比較高的方案。

差分電壓

CAN總線降低了通信頻率之後,限制總線長度的就不是線上的延時了,而是輸入差動電壓。因爲我做的應用對速率有硬性要求,這部分這篇文章就點到計算公式上。
公式一:Vdiff.in.req=Vth+Ksm*(Vdiff.out-Vth)
其中Vdiff.in.req爲收發器顯性電平採樣需要的壓差,Vth爲接收差分閾值如下圖>0.9v,KSM爲決定安全電壓的差分系數,Vdiff.out爲收發器輸出的差動電壓。
差分電壓

公式二:Vdiff.in=Vdiff.out/(2RW(1/RT+(n-1)/Rdiff)+1)
其中Vdiff.in爲差分輸入電壓,Vdiff.out爲差分輸出電壓,RW爲總線電纜電阻,RT爲終端電阻,Rdiff爲CAN節點差分電阻。n爲總線終端數。
公式三:RWmax=Pmax*Lmax
其中RWmax爲最大線阻。Pmax最大電阻率,Lmax總線最大長度。
將公式三和公式二代入公式一,即可得到總線最大長度。
可以看出,在差分電壓在總線上壓降爲決定因素的情況下(速率低,通信距離長),總線最大長度與節點數和終點電阻以及導線的電阻率成反比。

CAN總線節點數量。

單純談CAN總線的節點數量是由收發器的可驅動最小負載阻抗決定。
最大節點數量節點數量計算公式(假設總線電阻RW爲0,此時爲最壞情況):n < 1+Riff_min*(1/Rl_min-2/Rt_min)
下面舉一個例子來計算一下最大的帶節點數量:
收發器選型TJA1044:
Riff_min(差動輸入阻抗最小值):19K歐姆
Rl_min(可驅動最小負載阻抗):45歐姆
終端匹配電阻阻值:
Rt_min(特徵阻抗):120歐姆
最終得值:107個終端。
107個終端的計算值可能比在實際環境下的帶機量要小一些,如果注意can節點之間的距離,線纜的質量,支線長度等因素,可以做到120個左右的穩定使用。

振鈴效應/終端電阻

因爲這塊是CAN通信出現問題的多發原因,我儘量的多說一些,但是我會避開地彈、眼圖這些概念。我們都知道CAN通信是差分信號,但是我先從單端的信號講起,什麼是振鈴(過沖)。我們從一個測試電路入手,A點爲電壓輸出端口,B點是爲了接入電阻切的口,C點爲同軸電壓測試點。
測試用板
在B點處用導線相連,C點引同軸線到示波器(內阻1M),A點接入電源,能夠看到示波器上升沿有過沖現象。
振鈴波形
如果信號在傳輸過程中感受到阻抗的變化,就會發生信號的反射。根據反射係數公式,當信號感受到阻抗變小之後,就會發生負反射,反射的負電壓就會使信號產生下衝,反之像剛纔的例子,信號遇到了開路,阻抗突然變成了無窮大,就會發生過沖。
過沖/下衝
而信號在驅動端和遠端負載之間多次反射,其結果就是信號振鈴。信號振鈴的過程可以用反彈圖來直觀解釋。假設驅動端的輸出阻抗是10歐姆,PCB的特性阻抗是50歐姆(可以通過改變PCB走線走線寬度,走線方式,以及內層參考平面間介質厚度來調整),遠端開路(遠端阻抗無窮大),驅動端產生傳輸信號3.3v,我們忽略寄生電容電感的影響,只考慮阻性負載,我們跟着信號在這條傳輸線上跑一次,看看到底發生了什麼。
第一反射:信號從驅動端芯片出發,經過10歐姆的輸出阻抗和PCB走線50歐姆的特性阻抗分壓,實際加到PCB走線源端A點的電壓爲2.75V。信號傳輸到遠端B點,由於遇到開路,阻抗無窮大,反射係數爲1,信號全部反射,反射信號也爲2.75v,則此時B點的電壓是2.75+2.75=5.5v。
第二次反射:傳輸線上擡高的2.75v反射電壓傳輸回A點,阻抗由50歐姆變爲10歐姆,發生負反射,根據阻抗變化的關係,A點反射的電壓爲-1.83v,該電壓再次到達B點,再次發生反射,反射電壓爲-1.83v。則此時B點測量的電壓值爲5.5v-1.83-1.83=1.84V。
第三次反射…第四次反射。反射電壓在A點與B電來回回彈,直至消失。如下圖,線上的電壓標值爲信號(壓差)值。
振鈴效應
觀察B點測量的電壓,我們期望的是一個穩定的3.3輸出,但是得到的卻是5.5v----1.84v----4.28v。在示波器上顯示的信號傳輸波形就如振鈴一樣。
解決這種單端信號過沖的一般方法叫做匹配,或者叫做端接(termination).端接可以總結爲兩種形式:第一種是源端串聯電阻,與傳輸線做阻抗匹配,消除第二次反射。
串聯阻抗匹配
第二種是終端並聯匹配消除第一次反射。
並聯負載
在實際的電路中,我們要根據電路不同的特點來選擇合適的端接方式,具體可以可以從驅動DDR的電路入手,參考高速PCB理論。
單端的信號就介紹這麼多,說差分信號。
差分信號的干擾從兩個方面理解:1.共模干擾(Common-mode):兩導線上振幅相等,而方向相同稱爲共模干擾,它串入的迴路是信號線和地線之間。2.差模干擾(Differential-mode):兩導線上干擾電流,振幅相等,方向相反。他串入的迴路是兩個差分信號線之間。
差模信號採用跨接電阻來分別匹配,消除信號的反射影響,CAN線如果不接終端電阻,振鈴的現象會非常明顯的用示波器量出,CAN總線的通信質量下降。具體的信號反彈圖如上邊的單端信號。如果加了終端電阻,信號的CANH和CANL的信號反彈會相互抵消,差模信號的振鈴效應會消失。實際的電壓如下圖。

終端電阻
但是,這種端接方式對共模信號產生問題。CANH與CANL的地同時向上擡1v會產生振鈴效應直至衰減完畢,不過信號共模信號的干擾產生的是同相同幅的的干擾,對我們差分信號的數據識別影響不大,而且CAN線上走的也不是有周期的時鐘信號。但是共模信號帶來的振鈴效應電壓幅值過大,還有有機率帶來can位數據丟失同步,導致CAN錯誤計數累加的問題。
有些文章介紹過can信號下降沿因爲總線間電容斜率變大,終端電阻有幫助放電,提高斜率的作用,我做的測試沒有測出來,就不贅述了。
對以前搞過485通信的同學,可能有總線長短,帶機數小,就不用接終端匹配的概念。這裏強調一下不管是跨接終端電阻做匹配,還是分別並聯匹配。只要是CAN總線,無論總線長短,帶機數量,都要做這個匹配。

粘包/半包與拆包

講了這麼多跟軟件沒有關係的概念,這個一級標題的內容我要告訴你怎麼簡單處理CAN總線上的拆包問題。
CAN協議的幀格式規定了一幀CAN協議中包含8字節64位數據。如果你的系統應用層的協議的數據量小於一個CAN幀中的數據量,那麼恭喜你,可以不用看這部分了。最近CIA的網站介紹了一種CAN FD的實現,波特率最高支持到5Mbit/s,一幀包含的有效數據能達到64字節512位的數據。
粘包和半包的產生原因,是因爲鏈路層(MAC芯片,CAN控制器)將應用層的下發的業務數據做分片處理(CAN分割成每8字節一個數據幀),那麼勢必會引起數據傳輸到對端的基本數據單位是分片的長度,那麼就會出現收到的數據不是一整包的數據(半包),這個比較好理解。粘包是因爲數據傳輸延時等原因,兩整包的數據一起收到。

發送部分的邏輯:將發送的整包數據的源地址和目標地址以及這個數據在目標設備的緩存起始地址(這個地址表示的寬度是8字節數據)寫入要發送幀的標識符(使用擴展幀)。將分片的數據寫入幀的數據區,然後發送。因爲這裏我們先將拆包,所以這部分邏輯我先點到這個局部,下一個文章我再細講發送部分如何將並行轉成串行,以及總線時間片的測量及實現。

接收部分邏輯:先說數據結構A,因爲數據的緩存是隨機存儲,且單位數據長度是固定的,這裏就選擇最單純的char類型的二維數組S,列數指定爲8字節,行數根據實際的平臺的限制,選擇合適的幀緩存數據最大值(256)。數據結構A還包括兩個char類型指針,一個指向待處理數據頭,一個指向待處理數據尾。然後根據根據實際的需要以及處理器的RAM剩餘情況,選擇合適的支持節點數(64個終端),數據結構B是我們拆包使用的數據結構,由支持節點數個數的數據結構A,和一個表示數據結構A有待處理項的Int值。
數據結構
CAN接收中斷函數先判斷從標識符中取出目標地址,判斷合法之後將CAN數據放到源地址對應的數據結構B.A[源地址].S[行地址]中,,並移動待處理數據爲尾指針。這塊處理需要注意兩點。
1.放數據的時候根據幀中實際數據長度,結合尾指針位置以及標識符中指定行地址綜合判斷,決定放到內存8字節單位空間的那個字節位置,保證針對每個終端的內存地址空間從字節流的角度上看是連續的。
2.遇到不連續的寫入(尾指針在行地址2,寫入數據的行地址卻是10),要根據包長度來判斷合法性。
至此,我們有了總線上不同源地址對這個目標地址的發送數據的緩存,下面就是拆包了。
拆包流程圖
說回我這邊的實際情況,爲了處理終端之間同時發送CAN報文(競爭),而導致來自不同終端分幀錯位,又因爲緩解各個地方通信壓力,已經用了大量的RAM。
STM32版本就對總線的最大帶機量在軟件上做了默認處理,爲64臺,如果在實際應用中,終端不會發生競爭的,可以忽略這個限制

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