CAN通信稳定性开发分析
本篇文章從嵌入式工程師的角度,借鑒了一些成熟的通信概念與架構,從包括硬件,軟件各個角度分析嵌入式程序如何實現穩定CAN通信的難點以及方案,將相關的難點分別進行梳理,讀者在完整讀完這篇文章之后能夠對實現一個穩定CAN通信做到胸有成竹。
文章目錄
- CAN總線布線長度限制
- CAN總線循環延時
- 差分電壓
- CAN總線節點最大數量。
- 振鈴效應/終端電阻
- 最佳/最大用戶并發數
- 粘包/半包與拆包
CAN總線布線長度限制
CAN總線上任意兩個節點之間的最大傳輸距離,決定因素有兩個方面,一個是互連總線節點的回路延時(由CAN總線控制器和驅動器等引入)+總線線路延時。另一個是由于總線電纜串聯等效電阻和總線節點的輸入電阻而導致的信號幅度下降。
CAN總線循環延時
《ISO 11898-1》把一個位時間分為四段。
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。
計算的原理是(硬同步到采樣點所持續的時間-2倍的循環延時時間)/2倍的信號在總線上傳輸的速度。這里電信號在線纜的傳輸的速度,是跟實際選擇的線纜有關,當然,線纜以及節點數的接入,產生的容抗和感抗都會在不同的側面影響這個“速度”,從而對長度產生影響
我看網上還有專門測總線傳輸延時和節點的容抗和阻抗的。其實把握了基本原理底線,再測試一些自己開發設備在幾種典型應用的性能,就能得針對現場的實際情況得出一個性價比較高的方案。
差分電壓
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信號下降沿因為總線間電容斜率變大,終端電阻有幫助放電,提高斜率的作用,我做的測試沒有測出來,就不贅述了。
這里強調一下不管是跨接終端電阻做匹配,還是分別并聯匹配。只要是CAN總線,無論總線長短,帶機數量,都要做這個匹配,CAN總線對接收器的定義與其余的現場總線不同。
最佳/最大用戶并發數
我們從例子,引發出具體的概念。
理發店共有3名理發師(處理器同時處理事務數)處理到店理發的用戶,理發師給每個用戶理發的時間為1小時(處理時間),店里有三個等待的理發的椅子(請求緩存),客人在理發店呆的時間超過3個小時就會無法忍受離開(超時時間)。
在這個場景里,隨著用戶增大(負載),1.資源利用率逐漸增加,到3名客戶后維持不變。2.系統吞吐量逐漸增加,到達3個客戶后增加的速度變小,到了9個客戶左右開始下降。3.響應時間在0~3個客戶之間保持穩定,超過3個客戶之后逐漸增加,增長速度也逐漸增加,超過9個客戶之后接近無窮大。
資源利用率和相應時間隨著負載的變化曲線比較好理解,吞吐量在這里表示系統成功執行的請求數,吞吐量在超過9個客戶下降的主要原因是因為系統超負荷運算,多余的上線文切換,低速IO的訪問,或如STM32的CAN超負荷報文下,多余的中斷響應,ARM模式的切換,客觀上將處理時間(1小時)拉長了,所以會導致吞吐量下降。因為用“并發用戶數”這個詞容易引起誤會,尤其是在現在多核的處理器已經普及。我將并發改為單位時間的請求數。
對一個確定的被測系統(無論是從整體,業務軟件+硬件來說,還是硬件本身)來說,在一個特定的環境中,他的"最佳單位時間請求數"以及“最大單位時間請求數”都是客觀存在的,我們做的系統,應該確保系統的“最大單位時間請求數”大于系統需要承受的峰值負載,并且在系統的日常使用過程中,負載處在“最佳單位時間請求數”左右。
粘包/半包與拆包
講了這么多跟軟件沒有關系的概念,這個一級標題的內容我要告訴你怎么簡單處理CAN總線上的拆包問題。
CAN協議的幀格式規定了一幀CAN協議中包含8字節64位數據。如果你的系統應用層的協議的數據量小于一個CAN幀中的數據量,那么恭喜你,可以不用看這部分了。最近CIA的網站介紹了一種CAN FD的實現,波特率最高支持到5Mbit/s,一幀包含的有效數據能達到64字節512位的數據。
粘包和半包的產生原因,是因為鏈路層(MAC芯片,CAN控制器)將應用層的下發的業務數據做分片處理(CAN分割成每8字節一個數據幀),那么勢必會引起數據傳輸到對端的基本數據單位是分片的長度,那么就會出現收到的數據不是一整包的數據(半包),這個比較好理解。粘包是因為數據傳輸延時等原因,兩整包的數據一起收到。
發送部分的邏輯:將發送的整包數據的源地址和目標地址以及這個數據在目標設備的緩存起始地址(這個地址表示的寬度是8字節數據)寫入要發送幀的標識符(使用擴展幀)。將分片的數據寫入幀的數據區,然后發送。因為這里我們先將拆包,所以這部分邏輯我先點到這個局部,下一個文章我再細講發送部分如何將并行轉成串行,以及總線時間片的測量及實現。
接收部分邏輯:先說存儲數據的核心的數據結構,因為數據的緩存是隨機存儲,且單位數據長度是固定的,這里就選擇最單純的char類型的二維數組S,列數指定為8字節,行數根據實際的平臺的限制,選擇合適的幀緩存數據最大值(256)。數據結構A不僅包含S,還包括兩個char類型指針,一個指向待處理數據頭,一個指向待處理數據尾。然后根據根據實際的需要以及處理器的RAM剩余情況,選擇合適的支持節點數(64個終端),數據結構B是我們拆包使用的數據結構,由支持節點數個數的數據結構A,和一個表示數據結構A有待處理項的Int值。
CAN接收中斷函數先判斷從標識符中取出目標地址,判斷合法之后將CAN數據放到源地址對應的數據結構B.A[源地址].S[行地址]中,,并移動待處理數據為尾指針。這塊處理需要注意兩點。
1.放數據的時候根據幀中實際數據長度,結合尾指針位置以及標識符中指定行地址綜合判斷,決定放到內存8字節單位空間的那個字節位置,保證針對每個終端的內存地址空間從字節流的角度上看是連續的。
2.遇到不連續的寫入(尾指針在行地址2,寫入數據的行地址卻是10),要根據包長度來判斷合法性。
至此,我們有了總線上不同源地址對這個目標地址的發送數據的緩存,下面就是拆包了。
拆包因協議的特征而定拆包的邏輯,Netty 中就有針對不同特點的拆包器,比如固定長度的拆包器 FixedLengthFrameDecoder,分隔符拆包器 DelimiterBasedFrameDecoder以及基于數據包長度的拆包器 LengthFieldBasedFrameDecoder。
因為我使用的協議是有版本號和包長度的,跟 LengthFieldBasedFrameDecoder有點像,但是CAN通信要面對的是百分之百的分包,數據幀的亂序,以及一定概率的誤碼,且處理器性能以及資源有限。所以就復雜一些。拿兩個點來具體說明一下:
1.如果有數據就直接進行拆包的處理驗證,會引起沖突/MCU空轉的問題,甚至有一定概率引起RAM混亂的問題,這時就需要測量一下總線一個完整協議傳輸的時間,我這邊最長的協議時間為3ms,所以這邊就在自接收到第一幀數據之后3ms,再進行分包處理。
2.因為是百分之百的分包,所以數據幀的亂序概率我測試下來比實際想象的要高,所以就需要一個兜底的PlanB去將雜訊中的有效數據進行拆包,將會在這樣不會因為總線在出現誤碼/亂序的情況下,影響后續拆包的操作。(當然,這部分可以采用定期清緩存來保證,但是,我們要的是即刻的“恢復“,即PlanB能保證不丟有效幀,定期清緩存只是一種維護手段)。
具體的邏輯我如下圖流程圖
?十六宿舍 原創作品,轉載必須標注原文鏈接。
?2023 Yang Li. All rights reserved.
歡迎關注『十六宿舍』,大家喜歡的話,給個👍,更多關于嵌入式相關技術的內容持續更新中。
?
總結
以上是生活随笔為你收集整理的CAN通信稳定性开发分析的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 腾讯开源Spring Cloud Ten
- 下一篇: c语言出错英语显示怎么看,C语言程序设计