徐志山
(宣城職業(yè)技術(shù)學(xué)院 機(jī)械與汽車(chē)工程系,安徽 宣城 242000)
CAN(Controller Area Network)為控制器局域網(wǎng)之意,是基于工業(yè)控制的現(xiàn)場(chǎng)總線(Field bus)的一種形式[1],稱(chēng)為CAN總線.CAN總線最早由德國(guó)Bosch公司開(kāi)發(fā)用于汽車(chē)上多個(gè)電子控制模塊間的通信,目的是提高通信可靠性,實(shí)現(xiàn)了汽車(chē)電控系統(tǒng)由分散控制向網(wǎng)絡(luò)控制的轉(zhuǎn)變,形成了車(chē)載網(wǎng)絡(luò)通信系統(tǒng)[2].早在1993年國(guó)際標(biāo)準(zhǔn)化組織(ISO)就通過(guò)了CAN總線通信協(xié)議.CAN總線通信協(xié)議包括兩部分,即CAN2.0A和CAN2.0B,它們的主要區(qū)別在于信息報(bào)文的格式不同,CAN2.0A提供11位的報(bào)文地址,而CAN2.0B提供29位的報(bào)文地址,所以,CAN2.0A被稱(chēng)為BasicCAN,而CAN2.0B被稱(chēng)為PeliCAN[3].
實(shí)際的CAN總線通信是發(fā)生在單片機(jī)之間的串行通信,但不是單片機(jī)之間的直接通信,而是發(fā)生在以單片機(jī)為核心的通信設(shè)備物理層和數(shù)據(jù)鏈路層之間的信息傳輸,其中,物理層是CAN總線的硬件層,主要實(shí)現(xiàn)物理信號(hào)傳輸、譯碼、位定時(shí)、位同步和位驅(qū)動(dòng),而數(shù)據(jù)鏈路層能夠?qū)崿F(xiàn)數(shù)據(jù)的總線仲裁、信息分段以及數(shù)據(jù)拆封、數(shù)據(jù)應(yīng)答、錯(cuò)誤檢測(cè)、超載通知等功能[4].要實(shí)現(xiàn)CAN總線通信,關(guān)鍵是CAN總線通信的硬件設(shè)計(jì)和軟件設(shè)計(jì),在硬件設(shè)備上有的采用8位單片機(jī),如PIC16F877[5],有的采用16位單片機(jī),如MC9S12X128[6],而SJA1000和TJA1050一直是作為CAN總線通信的控制器和收發(fā)器.江蘇啟東計(jì)算機(jī)廠生產(chǎn)的DVCC-51NET單片機(jī)開(kāi)發(fā)板裝有SJA1000和TJA1050芯片,在開(kāi)發(fā)板上插入STC89C52芯片作為主控芯片,將TJA1050的端子CAN-H(端子7)和CAN-L(端子6)用雙絞線與其他有同樣裝置的開(kāi)發(fā)板連接起來(lái),就可以進(jìn)行CAN總線開(kāi)關(guān)控制設(shè)計(jì).
按照CAN總線通信物理層協(xié)議要求,CAN總線通信就是通過(guò)專(zhuān)用的通信線(一般是屏蔽雙絞線)將若干個(gè)通信模塊并聯(lián)起來(lái),每個(gè)通信模塊叫做CAN節(jié)點(diǎn).對(duì)于非集成式CAN節(jié)點(diǎn)至少包括3部分,即:節(jié)點(diǎn)主控單元(單片機(jī))、CAN控制器、CAN收發(fā)器.節(jié)點(diǎn)主控單元負(fù)責(zé)與CAN控制器聯(lián)絡(luò),并不斷地采集和處理外圍信息;CAN控制器類(lèi)似于節(jié)點(diǎn)主控單元的外部RAM設(shè)備,它不僅具有存儲(chǔ)功能,而且還具有控制功能,主要負(fù)責(zé)信息成幀與解幀,再通過(guò)串行傳輸方式與CAN收發(fā)器聯(lián)系,將信息發(fā)送或接收;CAN收發(fā)器是CAN控制器的“端口”,負(fù)責(zé)轉(zhuǎn)換和傳輸信息.
圖1 CAN總線通信節(jié)點(diǎn)控制電路局部示意圖
3.1.1 數(shù)據(jù)信息規(guī)則
CAN總線通信信息在節(jié)點(diǎn)內(nèi)是0、1代碼組成的數(shù)據(jù),通過(guò)TJA1050向總線發(fā)送時(shí)轉(zhuǎn)變成電壓信號(hào).TJA1050具有傳輸速度高(最高可達(dá)1兆波特)、電磁輻射低、電磁干擾小和輸入范圍寬的特性.在發(fā)送端,對(duì)于高速CAN(如500千波特),當(dāng)節(jié)點(diǎn)向總線發(fā)送“0”位時(shí),CAN-H線電壓為3.5 V,CAN-L線電壓為1.5 V,稱(chēng)“顯性”狀態(tài);當(dāng)發(fā)送“1”位時(shí),CAN-H線與CAN-L線電壓近乎相等,約為2.5 V,稱(chēng)“隱性”狀態(tài).對(duì)于低速CAN(如100千波特),當(dāng)節(jié)點(diǎn)向總線發(fā)送顯性位“0”時(shí),CAN-H線電壓為3.6 V左右,CAN-L線為1.4 V左右;發(fā)送隱性位“1”時(shí),CAN-H線電壓為0 V,而CAN-L線為5 V.在接收端,TJA1050將CAN總線上的電壓信號(hào)還原成0、1數(shù)據(jù)位.
3.1.2 數(shù)據(jù)發(fā)送規(guī)則
CAN總線上的節(jié)點(diǎn)可主動(dòng)向網(wǎng)絡(luò)上其他節(jié)點(diǎn)發(fā)送數(shù)據(jù),為了防止總線上多節(jié)點(diǎn)間發(fā)送數(shù)據(jù)產(chǎn)生沖突,CAN總線通信協(xié)議規(guī)定:數(shù)據(jù)成幀發(fā)送,稱(chēng)為數(shù)據(jù)幀,每個(gè)數(shù)據(jù)幀包括7個(gè)域(起始域、仲裁域、控制域、數(shù)據(jù)域、校驗(yàn)域、應(yīng)答域和結(jié)束域),節(jié)點(diǎn)發(fā)送數(shù)據(jù)幀時(shí),先發(fā)送起始域,再發(fā)送仲裁域.當(dāng)節(jié)點(diǎn)發(fā)送數(shù)據(jù)出現(xiàn)競(jìng)爭(zhēng)時(shí),只有獲得仲裁權(quán)的節(jié)點(diǎn)才可以發(fā)送控制域、數(shù)據(jù)域、校驗(yàn)域,直至一幀數(shù)據(jù)發(fā)送完畢.仲裁權(quán)是根據(jù)仲裁域數(shù)值的大小來(lái)確定的,其數(shù)值越小優(yōu)先級(jí)越高.實(shí)際上,總線上的節(jié)點(diǎn)都有自己的仲裁域,根據(jù)需要可以將各個(gè)節(jié)點(diǎn)設(shè)定為不同的值,這樣避免了數(shù)據(jù)發(fā)送時(shí)出現(xiàn)的競(jìng)爭(zhēng)現(xiàn)象.一幀數(shù)據(jù)被發(fā)送完畢,發(fā)送節(jié)點(diǎn)CAN控制器的狀態(tài)寄存器自動(dòng)產(chǎn)生“發(fā)送中斷”信號(hào),有利于節(jié)點(diǎn)主控單元的中斷或查詢(xún)處理.
3.1.3 數(shù)據(jù)接收規(guī)則
TJA1050采用“差分式”接收數(shù)據(jù),按“位”以串行的方式送到SJA1000,在SJA1000內(nèi)經(jīng)物理同步后被解除填充位,自動(dòng)進(jìn)行錯(cuò)誤檢測(cè),以“并行”方式通過(guò)驗(yàn)收濾波器,驗(yàn)收過(guò)的數(shù)據(jù)移入SJA1000的RXFIFO(接收緩沖區(qū))區(qū).這時(shí),在STC89C52指令的作用下可將RXFIFO中有用數(shù)據(jù)讀出,同時(shí)執(zhí)行輸出指令,將接收到的有用數(shù)據(jù)對(duì)外輸出,并釋放SJA1000內(nèi)接收緩沖區(qū),為下一次接收新的數(shù)據(jù)做準(zhǔn)備.
CAN總線通信系統(tǒng)軟件設(shè)計(jì)包括:SJA1000初始化、SJA1000中斷處理、數(shù)據(jù)發(fā)送、數(shù)據(jù)接收及輸出、數(shù)據(jù)輸入和主程序.
3.2.1 SJA1000初始化
SJA1000的初始化可按下列步驟進(jìn)行.
第一步,復(fù)位.STC89C52對(duì)SJA1000片外尋址,賦予SJA1000控制寄存器(CR)的初值為01H,這時(shí)SJA1000控制寄存器“復(fù)位請(qǐng)求”位(CR.0)置1,即可使SJA1000進(jìn)入復(fù)位狀態(tài).
第二步,CAN總線波特率的設(shè)置.波特率的大小反映了位傳輸速率,CAN總線波特率的設(shè)置要考慮CAN通信驅(qū)動(dòng)設(shè)備的能力.SJA1000有兩個(gè)定時(shí)寄存器:BTR0和BTR1,BTR0用于確定位傳輸速率的預(yù)設(shè)值,而B(niǎo)TR1用于確定位定時(shí),由BTR0和BTR1就可以確定位傳輸速率及其允許的變化范圍.
第三步,設(shè)置接收?qǐng)?bào)文標(biāo)識(shí)符.CAN通信協(xié)議沒(méi)有明確規(guī)定標(biāo)識(shí)符的分配,任何一個(gè)節(jié)點(diǎn)發(fā)送的數(shù)據(jù)都是有用的,總有其他節(jié)點(diǎn)接收.為了明確表示數(shù)據(jù)的傳輸方向,對(duì)于采用11位標(biāo)識(shí)符的通信節(jié)點(diǎn)來(lái)說(shuō),將接收數(shù)據(jù)節(jié)點(diǎn)的標(biāo)識(shí)符數(shù)據(jù)高8位存放在發(fā)送節(jié)點(diǎn)驗(yàn)收代碼寄存器(ACR)中,同時(shí)在發(fā)送數(shù)據(jù)緩沖區(qū)起始的兩個(gè)字節(jié)空間中存放接收節(jié)點(diǎn)的標(biāo)識(shí)符和控制域,以確定接收節(jié)點(diǎn)及其應(yīng)該接收的數(shù)據(jù)字節(jié)的個(gè)數(shù).
第四步,輸出控制寄存器的設(shè)置.輸出控制寄存器的設(shè)置取決于SJA1000和TJA1050的連接情況,由于SJA1000的TX0、RX0分別通過(guò)一個(gè)定值電阻(390 Ω)連接到TJA1050的TXD和RXD端,為此采用正常輸出模式,推挽輸出,數(shù)據(jù)位為“0”時(shí)輸出極性為“高”,數(shù)據(jù)位為“1”時(shí)輸出極性為“低”.
第五步,時(shí)鐘分頻寄存器的設(shè)置.將時(shí)鐘分頻寄存器的最高位賦0值,在此采用CAN2.0A模式;將該寄存器的次高位置1,只需激活SJA1000的RX0端子,RX1端子接地;時(shí)鐘分頻寄存器BIT5位為0,無(wú)需用TX1端子中斷輸出;“關(guān)閉時(shí)鐘”位(BIT3)置位,禁用SJA1000的時(shí)鐘引腳CLKOUT,頻率選擇位CD2~CD0取值不受限制.
第六步,進(jìn)入工作模式.回到SJA1000的控制寄存器(CR),將CR.0位賦0值,即可進(jìn)入工作模式.由于采用單字節(jié)的輸入輸出信號(hào),不會(huì)產(chǎn)生溢出和錯(cuò)誤中斷,所以只需允許SJA1000的接收中斷和發(fā)送中斷,賦予控制寄存器的值為06H符合要求.
3.2.2 SJA1000中斷處理子程序
SJA1000中斷寄存器對(duì)于STC89C52來(lái)說(shuō)是只讀寄存器,可產(chǎn)生中斷標(biāo)志.STC89C52把SJA1000的中斷信號(hào)作為外部中斷來(lái)處理,當(dāng)SJA1000有接收中斷或發(fā)送中斷發(fā)生時(shí),中斷寄存器中相應(yīng)的位被置“1”,使STC89C52產(chǎn)生中斷,STC89C52隨即去執(zhí)行中斷服務(wù)——處理中斷子程序.若發(fā)生SJA1000接收中斷,STC89C52立即從SJA1000接收緩沖區(qū)接收數(shù)據(jù);若發(fā)生SJA1000發(fā)送中斷,STC89C52會(huì)從輸入設(shè)備接收新的數(shù)據(jù),為下一次發(fā)送做準(zhǔn)備.接收中斷和發(fā)送中斷不會(huì)同時(shí)發(fā)生,但有先后順序.
3.2.3 數(shù)據(jù)發(fā)送子程序
數(shù)據(jù)采用定時(shí)發(fā)送,利用STC89C52定時(shí)器的定時(shí)功能,每隔一定時(shí)間向SJA1000啟動(dòng)一次數(shù)據(jù)發(fā)送指令.若選擇LED燈做輸出設(shè)備,應(yīng)選擇不高于40 ms的時(shí)間間隔,可以避免LED燈的閃爍現(xiàn)象,但是發(fā)送數(shù)據(jù)的間隔時(shí)間應(yīng)高于發(fā)送數(shù)據(jù)的時(shí)間.發(fā)送數(shù)據(jù)時(shí),應(yīng)將存放在STC89C52發(fā)送緩沖區(qū)的數(shù)據(jù)傳送到SJA1000的發(fā)送緩沖區(qū),先發(fā)送接收節(jié)點(diǎn)仲裁域的高8位,緊接著發(fā)送其低3位、控制域和數(shù)據(jù)域,直至數(shù)據(jù)發(fā)送完畢,再向SJA1000啟動(dòng)數(shù)據(jù)發(fā)送指令,一旦SJA1000出現(xiàn)“發(fā)送中斷”信號(hào),表示一幀數(shù)據(jù)發(fā)送完畢.
3.2.4 數(shù)據(jù)接收及輸出子程序
CAN節(jié)點(diǎn)接收數(shù)據(jù)有兩種方法:中斷接收和查詢(xún)接收,在此啟用中斷接收方式.由于CAN總線數(shù)據(jù)采用“廣播式”發(fā)送,按照仲裁規(guī)則,只有獲得仲裁權(quán)的節(jié)點(diǎn)方可接收數(shù)據(jù),獲得仲裁的節(jié)點(diǎn)將數(shù)據(jù)的仲裁域、控制域和數(shù)據(jù)域依次有序接收到SJA1000的接收緩沖區(qū),并向接收節(jié)點(diǎn)STC89C52產(chǎn)生接收中斷信號(hào).接收節(jié)點(diǎn)STC89C52收到中斷信號(hào)后,就可以采用片外尋址的方式將接收節(jié)點(diǎn)SJA1000接收緩沖區(qū)中有用數(shù)據(jù)(對(duì)方8255A輸入數(shù)據(jù))存儲(chǔ)下來(lái),并送到接收節(jié)點(diǎn)STC89C52的接收緩沖區(qū)保存,同時(shí)接收節(jié)點(diǎn)STC89C52向己方8255A輸出,在LED上顯示從總線接收的有用信號(hào).
8255A輸出數(shù)據(jù)子程序如下.
8255A_OUT:
MOV DPTR, #9003H ;向8255A寫(xiě)指令
MOV A, #90H
MOVX @DPTR, A
MOV R0, #RCV_BUFF3 ;有用數(shù)據(jù)存放位置
MOV A, @R0
MOV DPTR, #9001H ;指向8255A的PB口
MOVX @DPTR, A ;向8255A的PB口輸出
RET
3.2.5 數(shù)據(jù)輸入子程序
輸入數(shù)據(jù)來(lái)自于撥碼開(kāi)關(guān)的位置信息,首先將接收方的狀態(tài)域和控制域存入STC89C52的發(fā)送緩沖區(qū),緊接著向8255A寫(xiě)入命令字,設(shè)置8255A各個(gè)端口的狀態(tài),將PA口作為輸入端口,PB口作為輸出端口.讀入雙擲開(kāi)關(guān)狀態(tài)(高電平、低電平)的位置信息,存入控制域之后的發(fā)送緩沖區(qū)內(nèi).
8255A數(shù)據(jù)輸入子程序如下.
8255A_IN:
MOV R0, #SEND_BUFF1 ;R0指向發(fā)送緩沖區(qū)
MOV @R0, #02H ;接收節(jié)點(diǎn)仲裁域高8位
INC R0
MOV A, #01H ;發(fā)送數(shù)據(jù)個(gè)數(shù)
MOV @R0, A ;將A的值送到SEND_BUFF2
MOV DPTR, #9003H ;指向8255A控制口
MOV A, #90H
MOVX @DPTR, A ;發(fā)送指令
MOV DPTR, #9000H ;指向8255A的PA口
MOVX A, @DPTR
MOV SEND_BUFF3, A ;輸入數(shù)據(jù)送到指定的存儲(chǔ)區(qū)
RET
3.2.6 主程序
主程序執(zhí)行時(shí),節(jié)點(diǎn)向總線定時(shí)發(fā)送數(shù)據(jù).為了節(jié)省CPU資源,采用STC89C52的定時(shí)器T0,設(shè)置為工作方式1、定時(shí)40 ms,開(kāi)放定時(shí)器T0中斷、外部中斷0中斷及總中斷,對(duì)SJA1000初始化,當(dāng)SJA1000進(jìn)入工作模式后,總線上節(jié)點(diǎn)靜聽(tīng)CAN總線數(shù)據(jù)變化.如果某個(gè)節(jié)點(diǎn)符合接收條件,將總線數(shù)據(jù)立即保存到節(jié)點(diǎn)的SJA1000的RXFIFO,并產(chǎn)生“接收中斷”,隨后將接收到的對(duì)方雙擲開(kāi)關(guān)信號(hào)通過(guò)8255A的PB口輸出到LED燈動(dòng)態(tài)顯示;當(dāng)定時(shí)器產(chǎn)生中斷信號(hào)時(shí),STC89C52啟動(dòng)向SJA1000傳輸數(shù)據(jù),并啟動(dòng)發(fā)送命令,將數(shù)據(jù)發(fā)送到總線上.數(shù)據(jù)發(fā)送完畢,SJA1000發(fā)送緩沖區(qū)被釋放,STC89C52可以重新接收雙擲開(kāi)關(guān)的輸入信號(hào),等待下一次數(shù)據(jù)發(fā)送.
為了實(shí)現(xiàn)CAN總線通信,現(xiàn)以?xún)蓚€(gè)DVCC-51NET開(kāi)發(fā)板為例,分別稱(chēng)為1號(hào)節(jié)點(diǎn)和2號(hào)節(jié)點(diǎn),每個(gè)節(jié)點(diǎn)按照?qǐng)D1所示的示意圖連接線路.雙擲開(kāi)關(guān)K0,K1,…,K7作為輸入設(shè)備,LED燈L0,L1,…,L7作為輸出設(shè)備,STC89C52、SJA1000和TJA1050分別為節(jié)點(diǎn)主控單元、節(jié)點(diǎn)CAN控制器、節(jié)點(diǎn)CAN收發(fā)器.初始狀態(tài)1號(hào)節(jié)點(diǎn)和2號(hào)節(jié)點(diǎn)的雙擲開(kāi)關(guān)全置于高電平(輸入值為FFH),程序運(yùn)行時(shí),兩個(gè)開(kāi)發(fā)板的LED燈均點(diǎn)亮.當(dāng)將1號(hào)節(jié)點(diǎn)的某一雙擲開(kāi)關(guān)(如K0)撥到低電平狀態(tài)(輸入為0),此時(shí)1號(hào)節(jié)點(diǎn)接收到輸入數(shù)據(jù)為FEH,1號(hào)節(jié)點(diǎn)將數(shù)據(jù)發(fā)送到總線上,總線上的2號(hào)節(jié)點(diǎn)處于接收狀態(tài),將接收到的數(shù)據(jù)送到2號(hào)節(jié)點(diǎn)8255A的PB口輸出,輸出端口PB的數(shù)據(jù)為FEH,經(jīng)反向驅(qū)動(dòng)器74LS240后,驅(qū)動(dòng)器使L0的控制端為高電平,這時(shí)2號(hào)節(jié)點(diǎn)L0燈熄滅,這樣實(shí)現(xiàn)了1號(hào)節(jié)點(diǎn)的開(kāi)關(guān)控制了2號(hào)節(jié)點(diǎn)相應(yīng)燈的亮滅,反過(guò)來(lái)也能實(shí)現(xiàn).
由于STC89C52單片機(jī)具有通信速度快、可靠性強(qiáng)的特點(diǎn),采用STC89C52單片機(jī)開(kāi)發(fā)CAN總線通信,可實(shí)現(xiàn)總線式控制,并可實(shí)現(xiàn)多個(gè)節(jié)點(diǎn)實(shí)時(shí)控制.在CAN總線通信系統(tǒng)中,CAN控制器是至關(guān)重要的芯片,但不能脫離單片機(jī)而獨(dú)立工作,如果說(shuō)單片機(jī)是通信的控制器,則CAN控制器是通信的執(zhí)行器.CAN總線通信的關(guān)鍵就是單片機(jī)對(duì)CAN控制器的訪問(wèn)和信息傳輸,主要是CAN控制器寄存器的設(shè)置及其狀態(tài)查詢(xún),只有把握各個(gè)寄存器的功能及對(duì)寄存器的編程方法,才能有效實(shí)現(xiàn)CAN總線通信.CAN收發(fā)器是總線的驅(qū)動(dòng)設(shè)備,總線并聯(lián)的節(jié)點(diǎn)越多,對(duì)收發(fā)器的驅(qū)動(dòng)能力要求也越高,收發(fā)器還決定了總線的電平狀態(tài).8255A在此用作單片機(jī)端口的擴(kuò)展芯片,僅能接收和輸出數(shù)字信號(hào),雙擲開(kāi)關(guān)和LED燈只作為簡(jiǎn)易的輸入和輸出設(shè)備,如果是模擬輸入和大功率輸出,還需增加其他電子設(shè)備(如模數(shù)轉(zhuǎn)換、功率放大電路),同時(shí)還要考慮電源的承載能力.
[1] 唐繼英.現(xiàn)場(chǎng)總線技術(shù)[M].天津:天津大學(xué)出版社,2008:161-188.
[2] 劉春暉,劉寶君.汽車(chē)車(chē)載網(wǎng)絡(luò)技術(shù)詳解[M].北京:機(jī)械工業(yè)出版社,2016:1-5.
[3] 牛躍聽(tīng),周立功,穆希輝,等.CAN總線應(yīng)用層協(xié)議實(shí)例解析[M].北京:北京航空航天大學(xué)出版社,2014:33-48.
[4] 李勇.汽車(chē)單片機(jī)及車(chē)載網(wǎng)絡(luò)技術(shù)[M].北京:電子工業(yè)出版社,2012:176-180.
[5] 孫鵬,沈顯慶,周杰.基于PIC單片機(jī)和SJA1000的CAN通信實(shí)現(xiàn)[J].機(jī)電一體化,2010(4):70-74.
[6] 宋春寧,童廣浙,林小峰.磷酸鐵鋰儲(chǔ)能電池管理系統(tǒng)設(shè)計(jì)[J].電源技術(shù),2015(10):2096-2098.