//************************************程序功能*************************************************** //節(jié)點1向CAN節(jié)點2發(fā)送數(shù)據(jù),數(shù)據(jù)的頭兩個字節(jié)分別是:節(jié)點1的ID和要求節(jié)點2回復的數(shù)據(jù)長度 //節(jié)點2收到節(jié)點1的信息后,立即按照節(jié)點1的要求回復數(shù)據(jù) //************************************************************************************************ #i nclude <AT89X51.H> #i nclude <SJA_nnyt.H> //SJA存儲器定義頭文件 #i nclude <SJA_nnyt.C> //SJA子程序文件 #i nclude <display_s.h> //顯示頭文件 #i nclude<string.h> //字符串函數(shù) //***************************頭文件***************************************************// void Init_Cpu(void); //初始化單片機 void Sja_1000_Init(void); //初始化SIA //************************************************************************************ bit s; //配置sja標志 bit flag_send; //發(fā)送命令標志 unsigned char data a[5]={0x05,0x05,0x05,0x05,0x05}; //顯示"5" unsigned char b[5]={0x12,0x12,0x12,0x12,0x12}; //顯示"p" unsigned char c[5]={0x01,0x01,0x01,0x01,0x01}; //顯示"1" unsigned char data send_data[10],rcv_data[10]; //發(fā)送和接收數(shù)組 unsigned char bdata flag_init; //保存中斷寄存器值 unsigned int count_k; //延時記數(shù)用 sbit rcv_flag=flag_init^0; //接收中斷標志 sbit err_flag=flag_init^2; //錯誤中斷標志 //***********************************************************************************// void main(void) {
s=0; //配置sja1000出現(xiàn)錯誤時,重新初始化 do{ Sja_1000_Init(); }while(s!=0); Init_Cpu(); //initialize mcu flag_init=0x00; //保存中斷寄存器值清零 while(1) { if(rcv_flag) //if there is receive interrupt { rcv_flag=0; //接收標志位清零 BCAN_DATA_RECEIVE(rcv_data); //接收數(shù)據(jù) BCAN_CMD_PRG(RRB_CMD); //釋放接收緩沖區(qū) flag_send=1; //發(fā)送命令置位 } if(flag_send) { flag_send=0; //發(fā)送位清零 send_data[0]=rcv_data[2]; //接收到的"發(fā)送方ID10~ID3" send_data[1]=rcv_data[3]; //接收到的"發(fā)送方ID2~ID0"和要求的數(shù)據(jù)長度 send_data[2]=0x88; send_data[3]=0x89; BCAN_DATA_WRITE(send_data); //發(fā)送數(shù)據(jù) BCAN_CMD_PRG(TR_CMD); //置位發(fā)送請求位 for(count_k=0;count_k<200;count_k++) display(a); //延時顯示"5" } if (err_flag) //錯誤中斷 { for(count_k=0;count_k<280;count_k++) display(c); //錯誤顯示"1" err_flag=0; //錯誤標志位清零 Sja_1000_Init(); //初始化SJA } display(b); //顯示"p" } }
void ex0_int(void) interrupt 0 using 1 //外部中斷0 { SJA_BCANAdr=REG_INTERRUPT; //指針指向中斷寄存器 flag_init=*SJA_BCANAdr; //保持中斷寄存器值 }
void Init_Cpu(void) //單片機初始化,開放外部中斷0 { PX0=1; EX0=1; EA=1; }
void Sja_1000_Init(void) { s=BCAN_CREATE_COMMUNATION(); //SJA自測 s=BCAN_ENTER_RETMODEL(); //進入復位 s=BCAN_SET_BANDRATE(0x04); //設(shè)置波特率100K/S s=BCAN_SET_OBJECT(0xaa,0x00); //設(shè)置地址ID:550 s=BCAN_SET_OUTCLK(0xaa,0x48); //設(shè)置輸出方式,禁止COLOCKOUT輸出 s=BCAN_QUIT_RETMODEL(); //退出復位模式 SJA_BCANAdr=REG_CONTROL; //地址指針指向控制寄存器 *SJA_BCANAdr|=0x1e; //開放錯誤\接收\發(fā)送中斷 } ******************以下為匯編程序*********************************************************************
系統(tǒng)can地址為550,用于can系統(tǒng)測試,應(yīng)用T0定時器每隔1s向can總線發(fā)送一組數(shù)據(jù):數(shù)據(jù)長度為8個字節(jié), 首字節(jié)為05H,第二個字節(jié)為累加變量,每秒鐘數(shù)值增加1, ********************************************************************************************************* CONTROLLER_BASE EQU 7E00H ;SJA1000的片選地址
RCV_GOOD BIT 0FH ;成功的接收一幀標志 SEC_FLAG BIT 010H ;一秒到標志 ERR_FLAG BIT 011H ;監(jiān)測到錯誤標志
SAVE_INT_INFO DATA 032H ;保存SJA1000中斷寄存器的內(nèi)容
SEND_DATA_BUF1 DATA 040H ;發(fā)送緩沖區(qū) SEND_DATA_BUF2 DATA 041H SEND_DATA_BUF3 DATA 042H SEND_DATA_BUF4 DATA 043H SEND_DATA_BUF5 DATA 044H SEND_DATA_BUF6 DATA 045H SEND_DATA_BUF7 DATA 046H SEND_DATA_BUF8 DATA 047H SEND_DATA_BUF9 DATA 048H SEND_DATA_BUF10 DATA 049H
RCV_DATA_BUF1 DATA 050H ;接收緩沖區(qū) RCV_DATA_BUF2 DATA 051H RCV_DATA_BUF3 DATA 052H RCV_DATA_BUF4 DATA 053H RCV_DATA_BUF5 DATA 054H RCV_DATA_BUF6 DATA 055H RCV_DATA_BUF7 DATA 056H RCV_DATA_BUF8 DATA 057H RCV_DATA_BUF9 DATA 058H RCV_DATA_BUF10 DATA 059H
ERROR_STATUS DATA 07CH ;錯誤狀態(tài)表示 TEST_DATA DATA 07FH ;測試發(fā)送數(shù)據(jù) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;程序開始 ORG 0000H LJMP MAIN ;運行主程序
ORG 0003H LJMP BCAN_INT0 ;中斷方式訪問SJA1000程序
ORG 000BH LJMP T0_INTERRUPT ;定時器0中斷
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG 0100H ;程序開始 MAIN: MOV R0,#07fH CLR A MOV @R0,A DJNZ R0,$-1 MOV @R0,A MOV SP,#60H ;設(shè)置SP CLR P2.0 ;SJA1000退出硬件復位模式 LCALL SJA1000_INT0 ;初始化SJA1000 LCALL T0_INIT CLR P3.4 ;點亮指示燈 SETB PX0 SETB IT0 SETB EX0 SETB ET0 SETB TR0 SETB EA
LOOPER: JNB RCV_GOOD,LOOPER2 ;sja1000成功接收一幀,通知CPU處理 CLR RCV_GOOD LCALL RCVDATA_PRG LOOPER2: JNB SEC_FLAG,LOOPER3 ;一秒時間到,每秒發(fā)送一次 CLR SEC_FLAG CLR P3.5 ;點亮指示燈 LCALL SENDDATA_PRG LOOPER3: JNB ERR_FLAG,LOOPER4 ;錯誤標志,錯誤處理 CLR ERR_FLAG LCALL ERR_PRG LOOPER4: AJMP LOOPER
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;初始化SJA1000;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; SJA1000_INT0: LCALL BCAN_CREATE_COMMUNATION ;調(diào)用SJA1000接口測試函數(shù) MOV R7, #04 LCALL BCAN_SET_BANDRATE ;設(shè)置波特率為100k MOV R7, #0A8H ;設(shè)置接收報文ID MOV R6, #0FFH LCALL BCAN_SET_OBJECT MOV R7, #0AAH ;設(shè)置輸出控制、時鐘分頻;正常輸出模式 MOV R6, #048H ;使能內(nèi)部比較器、禁止CLKOUT LCALL BCAN_SET_OUTCLK ; LCALL BCAN_QUIT_RETMODEL ;退出復位狀態(tài) MOV DPTR,#REG_CONTROL ;開放SJA1000內(nèi)部功能中斷 MOV A,#01EH ;中斷開放 MOVX @DPTR,A CLR F0 RET
;;;;;;;;;;;;;;;;;;;;;;錯誤信息處理;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ERR_PRG: LCALL BCAN_ENTER_RETMODEL ;進入復位模式 LCALL SJA1000_INT0 ; MOV ERROR_STATUS,#0FCH RET
;;;;;;;;;;;;;;;;;;;;;;;接收數(shù)據(jù)處理部分;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; RCVDATA_PRG: MOV R0,# RCV_DATA_BUF1 ;微處理器接收首地址 LCALL BCAN_DATA_RECEIVE ;調(diào)用接收數(shù)據(jù)子程序 MOV R7,#04H ;釋放接收緩沖區(qū) LCALL BCAN_CMD_PRG ; RET ;;;;;;;;;;;;;;;;;;控制SJA1000向CAN總線發(fā)送數(shù)據(jù)處理部分;;;;;;;;;;;;;;; SENDDATA_PRG: MOV R0, #SEND_DATA_BUF1 MOV @R0, #02H INC R0 MOV @R0, #08H INC R0 MOV @R0, #05H MOV A, TEST_DATA INC R0 MOV @R0, A MOV R0, #SEND_DATA_BUF1 LCALL BCAN_DATA_WRITE ;將要發(fā)送的數(shù)據(jù)送入發(fā)送緩沖區(qū) MOV R7, #01 LCALL BCAN_CMD_PRG RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定時器0初始化;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; T0_INIT: MOV A,TMOD ANL A,#0F0H ORL A,#01H MOV TMOD,A;T0工作在方式1 MOV TH0,#0FCH ;定時周期1MS MOV TL0,#066H MOV 3AH,#00H RET
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;外部中斷0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; BCAN_INT0: push DPH PUSH DPL PUSH PSW ;PSW,ACC入棧 PUSH ACC USING 3 ;應(yīng)用寄存器第3組 MOV DPTR,#REG_INTERRUPT ;讀中斷寄存器 MOVX A,@DPTR ; MOV SAVE_INT_INFO,A ;保存中斷寄存器的內(nèi)容 JNB ACC.0,BCAN_INT1 ;接收中斷 SETB RCV_GOOD ;置位接收標志
BCAN_INT1: MOV A,SAVE_INT_INFO JNB ACC.2,BCAN_INT2 ;錯誤中斷 SETB ERR_FLAG ;置位錯誤標志 BCAN_INT2: POP ACC POP PSW POP DPL POP DPH RETI ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;定時器0中斷;;;;;;;;;;;;;;;; T0_INTERRUPT: push DPH PUSH DPL PUSH PSW ;PSW、ACC入棧 PUSH ACC USING 2 MOV TH0,#80H ;設(shè)置定時周期0.3S MOV TL0,#26H INC 3AH MOV A,3AH CJNE A,#23H,T0_QUIT ;判斷1秒時間是否到 MOV 3AH,#00H INC TEST_DATA ;測試發(fā)送的數(shù)據(jù),每1秒加1 SETB SEC_FLAG ;置位1秒到標志 T0_QUIT: POP ACC POP PSW POP DPL POP DPH RETI
BCAN_ENTER_RETMODEL: MOV DPTR, #REG_CONTROL ;控制寄存器訪問 MOVX A, @DPTR ; ORL A, #01H ;置位復位請求 MOVX @DPTR, A ; CLR F0 MOVX A, @DPTR ;驗證復位是否寫入 JB ACC.0, BCAN_ER_QUIT SETB F0 ;復位不成功 BCAN_ER_QUIT: RET
BCAN_QUIT_RETMODEL: MOV DPTR, #REG_CONTROL ; 控制寄存器訪問 MOVX A, @DPTR ; ANL A, #0FEH ;清零復位請求,進入工作狀態(tài) MOVX @DPTR, A CLR F0 MOVX A, @DPTR JNB ACC.0, BCAN_QR_QUIT ;驗證是否退出復位狀態(tài) SETB F0 BCAN_QR_QUIT: RET
BCAN_DATA_WRITE: MOV DPTR, #REG_STATUS ;讀取狀態(tài)寄存器 MOVX A, @DPTR ;判斷上次發(fā)送是否完成 SETB F0 JNB ACC.3, BCAN_DW_QUIT ;正在發(fā)送退出 CLR F0 MOVX A, @DPTR ;判斷發(fā)送緩沖區(qū)是否鎖定, SETB F0 JNB ACC.2, BCAN_DW_QUIT ;鎖定則跳出 CLR F0 INC R0 ; MOV A, @R0 ;ID號的低3位 \RTR位 \數(shù)據(jù)長度DLC DEC R0 ;恢復指針指向發(fā)送數(shù)據(jù)的首地址 MOV DPTR, #REG_TxBuffer1;發(fā)送緩沖區(qū)首地址
JB ACC.4, BCAN_WYB ;遠程幀 ;數(shù)據(jù)幀 ANL A, #0FH ;計算發(fā)送數(shù)據(jù)的長度 ADD A, #02H MOV R7, A AJMP BCAN_WRTXBUF ;
BCAN_WYB: MOV R7, #02 ;寫入發(fā)送緩沖區(qū)數(shù)據(jù)長度為2
BCAN_WRTXBUF: MOV A, @R0 ;開始寫入 MOVX @DPTR, A SETB F0 MOVX A, @DPTR ;校驗寫入的是否正確 XRL A, @R0 JNZ BCAN_DW_QUIT ;寫入錯誤退出 CLR F0 ;正確寫入繼續(xù) INC R0 INC DPTR DJNZ R7, BCAN_WRTXBUF ;沒有寫完繼續(xù) BCAN_DW_QUIT: RET
BCAN_DATA_RECEIVE: MOV DPTR, #REG_STATUS MOVX A, @DPTR SETB F0 JNB ACC.0, BCAN_DR_QUIT ;判斷報文是否有效 CLR F0
MOV DPTR, #REG_RxBuffer2 ;接收報文的ID號的低3位 \RTR位 \數(shù)據(jù)長度DLC MOVX A, @DPTR MOV DPTR, #REG_RxBuffer1 ;接收緩沖區(qū)的首地址 JB ACC.4, BCAN_RCVYB ;接收到的是遠程幀 ;數(shù)據(jù)幀 ANL A, #0FH ;計算接收到的數(shù)據(jù)長度 ADD A, #02H ;計算報文的長度 MOV R6, A AJMP BCAN_RCVDATA
BCAN_RCVYB: MOV R6, #02 ;遠程幀
BCAN_RCVDATA: ;開始讀取數(shù)據(jù) MOVX A, @DPTR MOV @R0, A INC DPTR INC R0 DJNZ R6, BCAN_RCVDATA
BCAN_DR_QUIT: RET
BCAN_SET_BANDRATE: MOV A, R7 ;判斷波特率的值是否存在 CLR CY SUBB A, #13 ; SETB F0 JNC BCAN_SETBR_QUIT ;輸入的值大于12則不正確 CLR F0 MOV A, R7 RL A MOV DPTR, #BCAN_SETBR ;查表找出相應(yīng)的預設(shè)第一個值 MOVC A, @A+DPTR MOV R5, A ;將數(shù)據(jù)保存 MOV A, R7 ;找出第二個值 RL A INC A MOVC A, @A+DPTR MOV R6, A ;保存值
MOV DPTR, #REG_BTR0 ;裝入波特率預設(shè)值,同步跳轉(zhuǎn)寬度 ;位寬度 MOV A, R5 MOVX @DPTR, A SETB F0 MOVX A, @DPTR XRL A, R5 ;判斷寫入是否正確 JNZ BCAN_SETBR_QUIT ;不正確 CLR F0 INC DPTR MOV A, R6 MOVX @DPTR, A SETB F0 MOVX A, @DPTR XRL A, R6 ;判斷寫入是否正確 JNZ BCAN_SETBR_QUIT CLR F0 BCAN_SETBR_QUIT: RET
BCAN_SETBR: DB 053H, 02FH ;20KBPS的預設(shè)值 DB 087H, 0FFH ;40KBPS的預設(shè)值 DB 047H, 02FH ;50KBPS的預設(shè)值 DB 083H, 0FFH ;80KBPS的預設(shè)值 DB 043H, 02fH ;100KBPS的預設(shè)值 DB 03H, 01cH ;125KBPS的預設(shè)值 DB 081H, 0faH ;200KBPS的預設(shè)值 DB 01H, 01cH ;250KBPS的預設(shè)值 DB 080H, 0faH ;400KBPS的預設(shè)值 DB 00H, 01cH ;500KBPS的預設(shè)值 DB 080H, 0b6H ;666KBPS的預設(shè)值 DB 00H, 016H ;800KBPS的預設(shè)值 DB 00H, 014H ;1000KBPS的預設(shè)值
BCAN_SET_OBJECT: MOV DPTR, #REG_ACR ;寫ACR寄存器 MOV A, R7 MOVX @DPTR, A MOVX A, @DPTR SETB F0 XRL A, R7 ;檢驗寫入是否正確 JNZ BCAN_SETO_QUIT CLR F0 INC DPTR ;寫AMR寄存器 MOV A, R6 MOVX @DPTR, A MOVX A, @DPTR SETB F0 XRL A, R6 ;檢驗寫入是否正確 JNZ BCAN_SETO_QUIT CLR F0 BCAN_SETO_QUIT: RET
BCAN_SET_OUTCLK: MOV DPTR, #REG_OCR ;寫OCR寄存器 MOV A, R7 MOVX @DPTR, A MOVX A, @DPTR SETB F0 XRL A,R7 JNZ BCAN_OCR_QUIT ;檢驗寫入是否正確 CLR F0 MOV DPTR, |
|