基于Can總線(xiàn)的嵌入式網(wǎng)絡(luò )控制節點(diǎn)的設計與實(shí)現
近年來(lái),基于各種總線(xiàn)標準的網(wǎng)絡(luò )化控制系統已經(jīng)在工業(yè)控制領(lǐng)域內得到廣泛應用。網(wǎng)絡(luò )化控制系統采用了完全分散化的控制節點(diǎn)結構,將控制的權力很大部分交給了處于控制現場(chǎng)的智能節點(diǎn),系統內各種交互信息通過(guò)現場(chǎng)總線(xiàn)傳送。
本文引用地址:http://dyxdggzs.com/article/201611/319045.htm當前已實(shí)用化的總線(xiàn)標準有許多種,如WorldFIP, Profibus, LONWORKS, CAN等。其中,CAN(Controller Area Network)是Bosch公司在現代汽車(chē)應用技術(shù)中領(lǐng)先推出的一種串行通信網(wǎng)絡(luò )。CAN主線(xiàn)采用多主站工作方式,根據優(yōu)先權進(jìn)行總線(xiàn)訪(fǎng)問(wèn)仲裁,能夠檢測出通信過(guò)程產(chǎn)生的任何錯誤。CAN總線(xiàn)還具有卓越的信號傳輸性能,當信號傳輸距離達到l0km時(shí),它仍可提供高達SOKbit/s的數據傳輸速率。另外,CAN協(xié)議廢除了站地址編碼,而采用對通信數據塊編碼的方式,這樣使得網(wǎng)絡(luò )內的節點(diǎn)個(gè)數在理論上不受限制。目前,CAN總線(xiàn)已經(jīng)在許多行業(yè)得到了廣泛的應用,尤其是工業(yè)控制領(lǐng)域,并常被認為是最有前途的現場(chǎng)總線(xiàn)之一。
常用的CAN總線(xiàn)節點(diǎn)一般采用的是“單片機+CAN控制器”的結構,這樣由于運算能力的限制,這類(lèi)節點(diǎn)的智能化程度較低,常是作為工控機節點(diǎn)的從節點(diǎn)。而近年來(lái),以ARM為代表的嵌入式32位微處理器技術(shù)得到了飛速發(fā)展,無(wú)論是在功耗、便攜性還是在硬件成本上,許多高性能的ARM芯片已經(jīng)與單片機相差無(wú)幾,因此在CAN節點(diǎn)設計中,使用ARM芯片取代傳統的8/16位單片機已經(jīng)是一個(gè)非常實(shí)用的選擇。這樣設計的CAN節點(diǎn),不僅保留了低功耗、低成本和小體積的優(yōu)點(diǎn),而且性能得到了大幅提高,若輔以大容量的存儲器,同時(shí)運行功能強大的嵌入式操作系統,它幾乎已可以取代原先的工控機節點(diǎn)。本文則從軟硬件兩方面詳細介紹了上述設計方案的具體實(shí)現過(guò)程。
1 節點(diǎn)的接口電路設計
本文設計的CAN總線(xiàn)節點(diǎn)是某工業(yè)控制系統的一個(gè)子模塊,同時(shí)綜合考慮其它相關(guān)需求和功能擴展,因此選用了AT91 RM9200處理器作為系統的核心處理單元。AT91 RM9200,是ATMEL公司生產(chǎn)的一款高性能的ARM9處理器,它是一款通用工業(yè)級ARM芯片,主頻為180MHz/200MIPS,已經(jīng)在工業(yè)控制、智能儀器儀表等領(lǐng)域內得到了大量的成功應用。
CAN控制器選用的是SJA 1000芯片,它是Philips公司生產(chǎn)的一款獨立CAN總線(xiàn)控制器芯片,專(zhuān)用于移動(dòng)目標和一般工業(yè)環(huán)境中控制器局域網(wǎng)絡(luò )((CAN)。SJA 1000本質(zhì)上是早期的PCA82C200的升級產(chǎn)品,與后者在管腳、電氣特性上完全兼容,而且除具有基本CAN工作模式((BasicCAN)外,還增加了一種新的增強工作模式(PeIiCAN),這種新模式支持具有許多新特性的CAN2.OB協(xié)議。
SJAlooo的總線(xiàn)接口采用的是地址總線(xiàn)和數據總線(xiàn)復用的方式,這種方式與s1類(lèi)似,也采用總線(xiàn)復用架構的處理器,接口很方便,并在讀寫(xiě)時(shí)序上也很好配合,但當與數據總線(xiàn)和地址總線(xiàn)分離的微處理器接口時(shí),則需要專(zhuān)門(mén)的讀寫(xiě)邏輯與之配合,并且還相對比較復雜,基于這個(gè)原因,目前許多設計都采用諸如SPI等專(zhuān)用接口的CAN總線(xiàn)控制器,但這種方式使應用受到了諸多限制,如要求微處理器必須有SPI接口,同時(shí)當系統需要多路CAN總線(xiàn)接口時(shí),會(huì )受到SPI端口數的限制等。
ARM架構的數據總線(xiàn)和地址總線(xiàn)是分離的,因此,必須引入專(zhuān)門(mén)的控制邏輯,才能實(shí)現對SJA1000的操作。
圖1和圖2分別為SJA 1000讀/寫(xiě)操作時(shí)序。分析其讀/寫(xiě)時(shí)序,可以看出,無(wú)論是讀操作還是寫(xiě)操作,首先必須送出操作寄存器的地址,然后讀/寫(xiě)數據。在寫(xiě)地址的過(guò)程中,片選信號(/CS )和讀(/RD )、寫(xiě)(/WR)均無(wú)效(高電平),僅ALE信號有效(高電平),而在讀/寫(xiě)數據的過(guò)程中,讀/寫(xiě)信號有效(低電平),ALE信號無(wú)效(低電平),同時(shí),在操作的過(guò)程中,還必須滿(mǎn)足信號電平的持續時(shí)間。
因此,可以采用如圖3所示的控制邏輯實(shí)現。
圖1 SJA1000的讀操作時(shí)序(Intel模式)
圖2 SJA1000的寫(xiě)操作時(shí)序(Intel模式)
圖3 SJA1000操作時(shí)序的實(shí)現
在圖3所示的SJA1000操作時(shí)序的實(shí)現中,左端的信號如/CS, /RD, /WR, A7分別為ARM微處理器的片選、讀、寫(xiě)控制信號,A7為地址信號(也可以是其它的地址),右端產(chǎn)生的ALE CAN,/CS CAN, /WR_CAN, /RD_ CAN分別與SJA1000對應的信號相連接,當微處理器對SJA100()對應的地址進(jìn)行讀寫(xiě)操作時(shí),即可產(chǎn)生正確的控制邏輯。
2 節點(diǎn)的驅動(dòng)程序開(kāi)發(fā)
在工業(yè)控制應用中,使用嵌入式操作系統已逐漸成為一個(gè)流行的選擇。目前,市場(chǎng)上的嵌入式操作系統超過(guò)100種,其中嵌入式Linux是一種非常理想、經(jīng)濟的選擇,因為它不僅具有功能強大、高性能、穩定性好等優(yōu)點(diǎn),還是免費并開(kāi)放源代碼的。同時(shí)Linux內核采用了模塊化設計,具有非常良好的移植性和可定制性?,F在,許多ARM生產(chǎn)廠(chǎng)商都已經(jīng)將Linux系統移植到其生產(chǎn)的ARM芯片上,并發(fā)布了相關(guān)源代碼供用戶(hù)免費使用。本系統中采用的操作系統就是ATMEL公司發(fā)布的支持其AT912RM9200處理器的ARM-Linux系統的版本,版本號為2.4.27。
CAN控制器SJA1000顯然屬于Linux系統中的字符設備類(lèi)型,其驅動(dòng)程序的實(shí)現架構類(lèi)似于系統中字符設備的通用實(shí)現結構,關(guān)于Linux設備驅動(dòng)開(kāi)發(fā)的詳細分析可參考文獻。本小節則以SJA1000的增強工作模式(PeIiCAN)為例,對Linux系統下CAN設備驅動(dòng)程序的主要實(shí)現部分進(jìn)行了詳細說(shuō)明,包括主要數據結構的定義、操作函數和中斷函數的實(shí)現三個(gè)部分。
2.1 CAN設備驅動(dòng)的主要數據結構
為方便驅動(dòng)程序的設計和編寫(xiě),驅動(dòng)中定義了兩個(gè)數據結構體,即協(xié)議幀數據結構和緩沖區結構體,下面給出每個(gè)結構體的定義及成員變量的解釋。
其中,協(xié)議幀結構體是用來(lái)對CAN網(wǎng)絡(luò )的報文數據幀進(jìn)行抽象,驅動(dòng)中使用該結構體來(lái)進(jìn)行用戶(hù)與內核空間的數據幀傳遞及發(fā)送/接收數據緩沖區的管理。
從緩沖區結構體的定義可以看出,CAN設備的數據緩沖區由兩個(gè)獨立緩沖區構成,一個(gè)用于設備讀操作,另一個(gè)用于寫(xiě)操作。讀緩沖區和寫(xiě)緩沖區都是一個(gè)先入先出的環(huán)形緩沖區,緩沖區的大小設為協(xié)議幀結構體的整數倍,如64倍。驅動(dòng)通過(guò)緩沖區的讀指針和寫(xiě)指針來(lái)進(jìn)行緩沖區管理。如對于接收緩沖區(讀緩沖區),它的讀指針指向了當驅動(dòng)程序從內核空間向用戶(hù)空間拷貝報文數據幀時(shí),緩沖區中第一個(gè)有效數據幀的位置;而緩沖區的寫(xiě)指針則代表了在控制器芯片執行接收數據時(shí),即將數據幀從SJA1000的寄存器讀到緩沖區,緩沖區的當前可寫(xiě)位置;這樣通過(guò)讀指針和寫(xiě)指針的相對位置及緩沖區的整體長(cháng)度就可以得到讀緩沖區中當前的數據幀個(gè)數。寫(xiě)緩沖區的管理與讀緩沖區基本相同,其詳細機制可參考后面給出的相關(guān)偽代碼。同時(shí)緩沖區中還定義了volatile int型變量tx_in_progress來(lái)表征當前是否有實(shí)際的數據發(fā)送操作已被啟動(dòng),“1”標識已啟動(dòng),否則為“0”。另外,結構體定義中使用到了Linux系統的等待隊列結構,關(guān)于它的詳細機制可參考文獻。
2.2 CAN設備的操作函數
字符設備驅動(dòng)的核心就是實(shí)現設備的操作函數結構,所謂的操作函數結構,本質(zhì)上是定義了應用程序在設備上的所有可能操作。但對于某一具體設備,驅動(dòng)中只需要實(shí)現設備工作所必須的操作。如對于CAN設備,本例中共實(shí)現了5種系統調用函數,即open, close, read, write和ioctl函數。
其中,open函數是在應用程序打開(kāi)CAN設備時(shí)被調用,函數主要實(shí)現兩部分功能,首先對驅動(dòng)中的變量和數據結構進(jìn)行初始化,并分配緩沖區空間。另一部分就是對CAN控制器SJA 1000初始化,即在復位時(shí)為芯片的各個(gè)寄存器設置正確的初始值。對于SJA1000芯片,需要設置的寄存器包括:1)模式和時(shí)鐘寄存器;2)輸出控制寄存器;3)驗收代碼寄存器和驗收屏蔽寄存器;4)總線(xiàn)定時(shí)寄存器;5)錯誤計數寄存器;6)中斷使能寄存器。需要注意的是,SJA1000的配置寄存器只能在復位模式下可寫(xiě),所以在設置寄存器之前,必須先進(jìn)入復位模式,所有設置完成后必須返回正常工作模式,關(guān)于SJA 1000芯片寄存器設置的更多內容可參見(jiàn)文獻。CAN設備的close調用的實(shí)現功能非常簡(jiǎn)單,即等待緩沖區中已有的數據幀被處理完,然后釋放緩沖區,最后關(guān)閉設備中斷。
驅動(dòng)程序的write就是對應于用戶(hù)寫(xiě)CAN設備時(shí)的系統調用。它的功能就是完成應用程序在用戶(hù)空間中的報文發(fā)送,即報文數據從用戶(hù)空間向內核空間的傳遞。下面給出了實(shí)現write函數的偽代碼:
ssize t can-write(......)
{
.....
判斷指定的數據長(cháng)度是否滿(mǎn)足數據幀格式,若不滿(mǎn)足,則提示并返回;
通過(guò)寫(xiě)指針和讀指針的相對位置及緩沖區的整體長(cháng)度計算輸出緩沖區中空閑空間的大小,
while空閑空間長(cháng)度<一個(gè)數據幀大小使用interruptible_sleep_on_timeout()函數將寫(xiě)進(jìn)程放入寫(xiě)操作等待隊列睡眠,該函數既說(shuō)明了睡眠可被信號中斷,還可以指定進(jìn)程的最長(cháng)睡眠時(shí)間;
睡眠結束后,再次計算空閑空間的大小。若空閑空間長(cháng)度已大于或等于一個(gè)數據幀大小,則可跳出循環(huán),否則繼續while循環(huán);
從用戶(hù)空間拷貝N字節數據到輸出緩沖區,其中:N = min(計算的空閑空間大小,數據長(cháng)度參數),然后更新輸出緩沖區的寫(xiě)指針位置;
if當前無(wú)實(shí)際的發(fā)送操作已被啟動(dòng),即tx_in_progress等于0
置位tx in_progress為1,同時(shí)調用發(fā)送初始化函數,即將輸出緩沖區中第一個(gè)有效數據幀寫(xiě)入到控制器芯片相應的發(fā)送寄存器中,同時(shí)使能發(fā)送操作,完成后,結束c} write()函數并返回數值N;
else
函數直接結束,返回N
}
需要說(shuō)明的是,上述偽碼中在對臨界區變量進(jìn)行操作和判斷時(shí),即計算空閑區長(cháng)度和判斷飲_in_progress變量時(shí),必須要在關(guān)閉設備中斷條件下進(jìn)行,操作完成后立即重新打開(kāi)中斷,下面描述的讀函數中與臨界區變量相關(guān)的操作也必須采用同樣的機制。
讀函數read的功能就是響應用戶(hù)對CAN設備的讀操作,如果接收緩沖區中已有了數據幀,則直接從緩沖區拷貝M字節的數據返回給用戶(hù),其中M為用戶(hù)要求字節數與緩沖區已有數據字節數之間的較小值,更新讀指針位置然后函數返回數值M,而如果當前緩沖區中無(wú)有效數據,則需要判斷設備文件的讀取模式,若為非阻塞模式,則直接返回,否則將讀進(jìn)程放入讀操作等待隊列睡眠,指定進(jìn)程的最大睡眠時(shí)間并設置為睡眠可被信號中斷模式,當任務(wù)被喚醒后,再對喚醒方式進(jìn)行判斷,若因睡眠時(shí)間結束而喚醒,則函數直接返回相應標識,否則說(shuō)明緩沖區中已有數據,則執行上述的拷貝動(dòng)作,并更新緩沖區的讀指針位置,函數結束并返回實(shí)際讀取字節數,具體實(shí)現略。
設備的iOCtl函數是用于設備控制的公共接口,可以根據設備的具體需求來(lái)實(shí)現相應的控制代碼,在本文中共實(shí)現了三種功能,即清除讀/寫(xiě)緩沖區、設置總線(xiàn)波特率、設置驗收代碼寄存器和驗收屏蔽寄存器。
2.3 CAN設備的中斷函數
如上所述,設備的讀函數和寫(xiě)函數只是完成用戶(hù)空間與設備的接收/發(fā)送緩沖區之間的數據幀傳遞,而真正的數據接收和發(fā)送工作,即芯片的寄存器與數據緩沖區之間的數據讀取和寫(xiě)入,是由設備中斷函數來(lái)完成。因此,實(shí)現中斷函數既是驅動(dòng)程序開(kāi)發(fā)的核心,也是難點(diǎn)。下面是本例中使用的中斷函數的偽代碼:
ssize_tcan_isr_handle(......)
{
......
讀Call芯片的中斷狀態(tài)寄存器,用來(lái)判斷中斷源類(lèi)型;
if CAN接收中斷
讀芯片的RX幀信息寄存器,然后根據接收的數據幀類(lèi)型,即標準幀或擴展幀,讀取相應的ID寄存器和RX數據寄存器,并將各數值寫(xiě)入一個(gè)數據幀結構體中,再把讀取的該數據幀拷貝到接收緩沖區中,緩沖區的寫(xiě)指針就是緩沖區的當前可寫(xiě)位置,拷貝完成后,更新寫(xiě)指針位置;
讀控制器的狀態(tài)寄存器,判斷RXFIFO是否還有可用信息,若還有信息,則重復執行上述的數據讀取操作,否則就判斷讀操作等待隊列上是否有睡眠任務(wù),有則喚醒它,中斷函數結束;
else if CAN發(fā)送中斷
判斷設備的發(fā)送緩沖區是否已為空,若為空,則置tx_in_progress變量為0,并判斷寫(xiě)操作等待隊列上是否有睡眠進(jìn)程,有則喚醒它,然后中斷函數結束,
否則繼續發(fā)送緩沖區中的數據幀,而緩沖區的讀指針代表了緩沖區中當前需要發(fā)送的數據幀位置,發(fā)送完成后,更新讀指針位置,并判斷寫(xiě)操作等待隊列上是否有睡眠進(jìn)程,有則喚醒它,中斷函數退出;
else即為其他中斷
判斷錯誤類(lèi)型,并置位相應錯誤標識,然后分別判斷寫(xiě)操作等待隊列和讀操作等待隊列上是否有睡眠進(jìn)程,有則喚醒它,中斷函數退出;
}
當CAN控制器發(fā)生除接收中斷和發(fā)送中斷外的其它類(lèi)型中斷時(shí),一般是根據具體的應用需求采取相應的處理措施。本例中采用了置位相應標識,由用戶(hù)程序進(jìn)行處理的方式。另外,驅動(dòng)程序除實(shí)現上述的操作函數和中斷函數,還應在模塊初始化函數中完成設備注冊、申請中斷并注冊中斷函數及其他初始化工作;在模塊清除函數中需要卸載設備并釋放中斷資源。
3 結束語(yǔ)
本文從軟硬件兩方面對基于A(yíng)RM9芯片的CAN節點(diǎn)的具體設計過(guò)程進(jìn)行了介紹,對硬件設計中的關(guān)鍵性問(wèn)題和驅動(dòng)模塊實(shí)現結構都作了詳細分析。目前,該CAN總線(xiàn)節點(diǎn)作為一個(gè)子系統已在某高速的網(wǎng)絡(luò )化數據采集系統中得到應用,運行結果表明設備在CAN總線(xiàn)2.0B協(xié)議標準(兼容2.0A)下,數據發(fā)送、接收完全正常,滿(mǎn)足了系統工作要求。本文給出的示例具有一定的普適性,對基于其他嵌入式設備上的CAN模塊開(kāi)發(fā)也有一定的參考價(jià)值。
評論