基于C8051F040單片機的CAN總線通信 硬件部分
硬件部分電路結(jié)構(gòu)如下:
CAN收發(fā)模塊原本采用的是ATA6660高速CAN收發(fā)芯片,電路連接如下:
設計電路為:當單片機發(fā)送數(shù)據(jù)時,D18閃爍,并將數(shù)據(jù)傳送給ATA6660芯片;當ATA6660芯片接受到總線上的數(shù)據(jù)時,D17閃爍,并將數(shù)據(jù)傳送給單片機。
實際調(diào)試時,發(fā)現(xiàn)C8051F040單片機既沒辦法發(fā)送數(shù)據(jù)到總線上,也沒辦法從總線上接收到數(shù)據(jù)。
用示波器對電路檢測發(fā)現(xiàn),當單片機需要發(fā)送數(shù)據(jù)時,ATA6660芯片的TXD引腳上能檢測到數(shù)據(jù),且D18閃爍。示波器檢測總線上的電壓,沒有變化。PC端顯示總線上的數(shù)據(jù)為FE。當PC端給總線發(fā)送數(shù)據(jù)時,總線上能檢測到電壓的變化,而ATA6660芯片的RXD引腳電壓為0。故懷疑為CAN收發(fā)部分硬件存在問題。
因此,將CAN收發(fā)模塊換為直接購買的TJA1050CAN收發(fā)模塊,電路如下圖所示。通過測試,CAN模塊工作正常。而單片機能夠成功發(fā)送數(shù)據(jù),接收數(shù)據(jù)失敗。
對比前后兩個電路可以發(fā)現(xiàn),區(qū)別在于CAN收發(fā)芯片的RS引腳。ATA6660芯片的RS引腳懸空,而TJA1050芯片的RS引腳接地。
查閱ATA6660芯片數(shù)據(jù)手冊,發(fā)現(xiàn)RS引腳的功能為Switch Standby Mode/Normal Mode。而Standy Mode的解釋為:
故使用ATA6660模塊時無法正常收發(fā)數(shù)據(jù)。而正確的電路應為:
軟件部分
程序參考自童長飛編著的《C8051F系列單片機開發(fā)與C語言編程》例程12-1。
1.基本設置
int n; //看門狗禁止 WDTCN = 0x07; WDTCN = 0xDE; WDTCN = 0xAD; SFRPAGE = 0x0F; //交叉開關(guān)使能,但沒有進行外圍設備配置 XBR0 = 0x00; XBR1 = 0x00; XBR2 = 0x40; XBR3 = 0x00; //管腳輸出配置,P0口為開漏輸出,其中P0.6接上拉電阻,P0為數(shù)字輸入口 SFRPAGE = 0x0F; P0MDOUT = 0x00; P1MDIN = 0xFF; //晶振配置 OSCXCN = 0x77;//選擇外部晶振22.1MHz。 //系統(tǒng)時鐘為外部時鐘二分頻:22.1 MHz / 2 = 11.05 MHz for (n = 0; n < 255; n++); while ((OSCXCN & 0x80) == 0); CLKSEL |= 0x01;2.CAN消息對象清零
void clear_msg_objects (void) //將所有消息清零 { uchar i; SFRPAGE = CAN0_PAGE; CAN0ADR = IF1CMDMSK; CAN0DATL = 0xFF; for (i=1;i<33;i++) { CAN0ADR = IF1CMDRQST; CAN0DATL = i; } }3.CAN發(fā)送初始化
void init_msg_object_TX (char MsgNum,uint id) { uint temp; SFRPAGE = CAN0_PAGE; CAN0ADR = IF1CMDMSK; //指向IF1 Command Mask Registers CAN0DAT = 0x00b3; /* IF1 Command Mask Registers =0x00b3 WR/RD=1,Mask=0,Arb=1,Control=1,ClrIntPnd=0,TxRqst=0,DataA=1,DataB=1,一次發(fā)送8字節(jié)數(shù)據(jù)*/ CAN0ADR = IF1ARB1; CAN0DAT = 0x0000; /*IF1 Arbitration Registers1 =0x0000,即ID15-0=0*/ temp=id<<2;//標準id為ID28-ID18,所以要左移2位 temp&=0x1fff; temp|=0xa000; CAN0DAT = temp; //地址自增,指向IF1 Arbitration Registers2 /*IF1 Arbitration Registers2=101(id)00b MsgVal=1,Xtd=0,為標準模式,擴展ID無效,Dir=1,為發(fā)送*/ CAN0DAT = 0x0088; /*IF1 Message Control Registers=0x0088 NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=0,RmtEn=0,TxRqst=0 EoB=1,DLC3-0=1000,即數(shù)據(jù)長度為8*/ CAN0ADR = IF1CMDRQST; CAN0DAT = MsgNum; /*IF1 Command Request Registers=MsgNum,將以上配置寫入MsgNum號消息*/ }4.CAN接收初始化
void init_msg_object_RX (char MsgNum,uchar id) { uint temp; SFRPAGE = CAN0_PAGE; CAN0ADR = IF2CMDMSK; CAN0DAT = 0x00fb; /* IF2 Command Mask Registers =0x00fb WR/RD=1,Mask=1,Arb=1,Control=1,ClrIntPnd=1,TxRqst=0,DataA=1,DataB=1,一次接收8字節(jié)數(shù)據(jù)*/ CAN0ADR = IF2MSK1; CAN0DAT = 0x0000; CAN0DAT = 0x0000; CAN0ADR = IF2ARB1; CAN0DAT = 0x0000; /*IF2 Arbitration Registers1 =0x0000,即ID15-0=0*/ temp=id<<2;//標準id為ID28-ID18,所以要左移2位 temp&=0x1fff; temp|=0x8000; CAN0DAT = temp; /*IF2 Arbitration Registers2=100(id)00b MsgVal=1,Xtd=0,為標準模式,擴展ID無效,Dir=0,為接收*/ CAN0DAT = 0x0488; /*IF2 Message Control Registers=0x0488 NewDat=0,MsgLst=0,IntPnd=0,UMask=0,TxIE=0,RxIE=1,接收中斷使能;RmtEn=0,TxRqst=0 EoB=1,DLC3-0=1000,即數(shù)據(jù)長度為8*/ CAN0ADR = IF2CMDRQST; CAN0DATL = MsgNum; /*IF2 Command Request Registers=MsgNum,將以上配置寫入MsgNum號消息*/ }5.CAN波特率設置
Calculation of the CAN bit timing :
System clock
f_sys = 22.1184 MHz/2 = 11.0592 MHz.
System clock period t_sys = 1/f_sys = 90.422454 ns.
CAN time quantum
tq = t_sys (at BRP = 0)
Desired bit rate is 1 MBit/s, desired bit time is 1000 ns.
Actual bit time = 11 tq = 996.65ns ~ 1000 ns
Actual bit rate is 1.005381818 MBit/s = Desired bit rate+0.5381%
CAN bus length = 10 m, with 5 ns/m signal delay time.
Propagation delay time : 2*(transceiver loop delay + bus line delay) = 400 ns
(maximum loop delay between CAN nodes)
Prop_Seg = 5 tq = 452 ns ( >= 400 ns).
Sync_Seg = 1 tq
Phase_seg1 + Phase_Seg2 = (11-6) tq = 5 tq
Phase_seg1 <= Phase_Seg2, => Phase_seg1 = 2 tq and Phase_Seg2 = 3 tq
SJW = (min(Phase_Seg1, 4) tq = 2 tq
TSEG1 = (Prop_Seg + Phase_Seg1 - 1) = 6
TSEG2 = (Phase_Seg2 - 1)
= 2
SJW_p = (SJW - 1)
= 1
Bit Timing Register = BRP + SJW_p*0x0040 = TSEG1*0x0100 + TSEG2*0x1000 = 2640
Clock tolerance df :
A: df < min(Phase_Seg1, Phase_Seg2) / (2 * (13*bit_time - Phase_Seg2))
B: df < SJW / (20 * bit_time)
A: df < 2/(2*(13*11-3)) = 1/(141-3) = 1/138 = 0.7246%
B: df < 2/(20*11)
= 1/110 = 0.9091%
Actual clock tolerance is 0.7246% - 0.5381% = 0.1865% (no problem for quartz)
SFRPAGE = CAN0_PAGE; CAN0CN=0X41; CAN0ADR=BITREG; CAN0DAT=0x2640;//調(diào)波特率6.發(fā)送函數(shù)
void transmit (char MsgNum) { uchar num; SFRPAGE = CAN0_PAGE; CAN0ADR = IF1CMDMSK; CAN0DAT = 0x0087; /* IF1 Command Mask Registers =0x0087 WR/RD=1,Mask=0,Arb=0,Control=0,ClrIntPnd=0,TxRqst=1,DataA=1,DataB=1,一次發(fā)送8字節(jié)數(shù)據(jù)*/ CAN0ADR = IF1DATA1; /*將8字節(jié)數(shù)據(jù)寫入IF1*/ for(num=0;num<4;num++) { CAN0DATH=sdata[2*num+1]; CAN0DATL=sdata[2*num]; } CAN0ADR = IF1CMDRQST; CAN0DATL = MsgNum; //將以上配置寫入MsgNum號CAN消息 }7.接收函數(shù)
void receive_data (uchar MsgNum) { uchar i; SFRPAGE = CAN0_PAGE; CAN0ADR = IF2CMDMSK; CAN0DATL = 0x0f; /* IF1 Command Mask Registers =0xxx0f WR/RD=0,Mask=0,Arb=0,Control=0,ClrIntPnd=1,NewDat=1,DataA=1,DataB=1,一次發(fā)送8字節(jié)數(shù)據(jù)*/ CAN0ADR = IF2CMDRQST; CAN0DATL = MsgNum; //指向MsgNum號消息 CAN0ADR = IF2DATA1; for(i=0;i<4;i++) rdata[i].tempval=CAN0DAT;//接收數(shù)據(jù) isnewdata=1; } 最后現(xiàn)象:單片機發(fā)送成功,PC端能成功接收發(fā)送的數(shù)據(jù)。而單片機接收CAN總線數(shù)據(jù)時異常。TJA1050芯片的RXD引腳能檢測到電壓變化,而單片機Status Register寄存器中RxOk位為‘1’,但沒有產(chǎn)生接收中斷,接收消息對象中的數(shù)據(jù)也未改變。
其中0x02為發(fā)送消息對象,0x04為接收消息對象。
CAN0STA為Status Register寄存器中低8位。RxOk為‘1’。
將單片機設置為測試模式,CAN Control Register寄存器中Test位置1。使用回路靜音模式時,將CAN Test Register寄存器LBack和Silent同時置1,使TX與RX自身形成回路,單片機自發(fā)自收。結(jié)果為單片機接收不到自己發(fā)送的數(shù)據(jù)。
使用測試模式中的基本模式時,將CAN Test Register寄存器Basic位置1。此模式下,控制器不使用消息內(nèi)存,即控制器不使用32個消息對象,而是將IF1寄存器作為發(fā)送緩存區(qū),將IF2寄存器作為接收緩存區(qū)。此模式下,單片機發(fā)送數(shù)據(jù)正常,接收數(shù)據(jù)時,IF2寄存器緩存區(qū)接收到的數(shù)據(jù)不正確。
最終,通信失敗原因尚未得知。。。
評論
查看更多