以MCP2510爲控制器的CAN總綫使用後心得
經過對由MCP2510爲控制器的CAN匯流排的應用,大致得出了以下結論。
一〃首先是對晶片的電路接法,MCP2510的4、5、6、10、11可以空置,第3腳(CLK輸出脚)可以接到
CPU的OSC腳,以取代CPU的震蕩體,但最好不用。如果對實時要求不高的話,第12脚(中斷脚)也可以空置。
還有因爲MCP2551性能不好,易損壞。連到TXCAN、RXCAN的LED和5V間的電阻阻值不宜過小,取5K以上,最好不接。
MCP2551的8脚决定了晶片的工作功耗,接地是高速模式(功耗大),接5V就會進入低功耗模式,和地之間接47K電阻是斜率模式(經常是用這種方式)。第5脚的功能是輸出VDD/2的電壓,供別的晶片使用,這裏不用接。
最好用PCA82C250/251取代,管脚的接法和用法和MCP2551相容。
二〃這部分主要是對SPI和晶片的操作碼作一分析。下面的例子都是以PIC16F877爲平臺,用組合語言來編
寫。
對SPI介面的讀寫方法如下:
初始化SPI:
InitSSP
BANKSEL SSPSTAT
bsf SSPSTAT,6 ; SSPSTAT = 0x94 CKE=0 for mode 00 Operation
bcf SSPSTAT,7
BANKSEL PORT_CS2510
bsf CS2510
BANKSEL SSPCON
movlw b'00100000'
movwf SSPCON
return ; The PORT of CS2510 pin's location ; SSPCON = 0x20 ; CKP=0 , Master Mode with Fosc/4 clock
SPI介面的讀和寫。寫:先把數傳入W,再調用Write_SPI_Byte。讀:先調用Write_SPI_Byte,讀出的資料存放在W。每次讀寫時要使CS脚爲0,讀寫完畢CS置1,下面是副程式:
Write_SPI_Byte
BANKSEL SSPBUF
movwf SSPBUF
BANKSEL SSPSTAT
Wait_BF
btfss SSPSTAT,BF
goto Wait_BF
BANKSEL SSPBUF
movf SSPBUF,W
return ; Switch to SSPSTAT in order to test the BF Flag ; Read from SSPBUF will update BF Flag Automately !!
控制MCP2510晶片方法:
先說一下MCP2510晶片的操作,共有6個操作碼,重定,位元修改,讀數據,寫資料,讀晶片的各發送器和接收器的狀態,請求發送開始。下面使各操作的副程式:
重定,不需要參數,沒有返還變數:
RESET_2510 MACRO
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_RESET
call Write_SPI_Byte
BANKSEL PORT_CS2510
bsf CS2510
ENDM
位修改,有3個參數,M_DATA:要修改的內容 M_ADD:要修改寄存器的地址 M_MASK:對修改內容的遮罩寄存器,沒有返還變數:
MODIFY_2510 MACRO M_ADD,M_MASK,M_DATA BANKSEL PORT_CS2510 bcf CS2510 movlw CMD_MODIFY call Write_SPI_Byte movlw M_ADD call Write_SPI_Byte movlw M_MASK call Write_SPI_Byte movlw M_DATA call Write_SPI_Byte BANKSEL PORT_CS2510 bsf CS2510 ENDM
STATUS_2510 MACRO
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_STATUS 讀晶片的各發送器和接收器的狀態,狀態字返還到變數STATUS_byte中:
call Write_SPI_Byte movlw 0xff call Write_SPI_Byte movwf STATUS_byte call Write_SPI_Byte subwf STATUS_byte,W btfss STATUS,Z clrf STATUS_byte BANKSEL PORT_CS2510 bsf CS2510 ENDM
請求發送開始,這個副程式是發送發送器0裏面的資料,如要發送1把CMD_RTS0改成CMD_RTS1,發送2把CMD_RTS0改成CMD_RTS2,沒有返還值:
SEND_TXB0 MACRO BANKSEL PORT_CS2510 bcf CS2510 movlw CMD_RTS0 call Write_SPI_Byte BANKSEL PORT_CS2510 bsf CS2510 ENDM
READ_2510 MACRO R_ADD
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_READ
call Write_SPI_Byte
movlw R_ADD
call Write_SPI_Byte
movlw 0xff
call Write_SPI_Byte
BANKSEL PORT_CS2510
bsf CS2510
ENDM
WRITE_2510 MACRO W_ADD,W_DATA
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_WRITE
call Write_SPI_Byte
movlw W_ADD
call Write_SPI_Byte
movlw W_DATA
call Write_SPI_Byte
BANKSEL PORT_CS2510
bsf CS2510
ENDM ; TRansmit Buffer 0 讀數據,1個參數,R_ADD:指定寄存器地址,返還的寄存器內容存入W中: 寫資料,2個參數,W_DATA:寫入內容 W_ADD:寫入地址,W_DATA是常量。沒有返還值:
除了這些,爲了編程方便,還擴展了幾種操作方式,寫資料(W_DATA爲變數),多位元組讀數據,多位元組寫資料。
寫資料,這個副程式功能和WRITE_2510一樣,區別在于WRITE_2510的W_DATA是個常量,調用這個宏的時候W_DATA是固定不變的,WRITE_2510_DATA的W_DATA是個變數,寄存器裏的值可變化:
WRITE_2510_DATA MACRO BANKSEL PORT_CS2510 bcf CS2510 movlw CMD_WRITE W_ADD,W_DATA
call Write_SPI_Byte movlw W_ADD call Write_SPI_Byte movf W_DATA,W call Write_SPI_Byte BANKSEL PORT_CS2510 bsf CS2510 ENDM
多位元組讀數據,有3個參數,FSR:讀出資料緩衝區的指標,這是個間接定址寄存器,存放指標位址,讀出來的資料就存放在 FSR指定的寄存器內 Addr_2510:MCP2510的讀出首地址 Dlen_2510:讀出資料長度:
WRITE_2510S
movlw Buf_2510
movwf FSR
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_WRITE
call Write_SPI_Byte
BANKSEL Addr_2510
movf Addr_2510,W
call Write_SPI_Byte
WRITE_2510S_Loop
movf INDF,W
call Write_SPI_Byte
incf FSR,F
BANKSEL Dlen_2510
Decfsz Dlen_2510,F
goto WRITE_2510S_Loop
BANKSEL PORT_CS2510
bsf CS2510
return ; Write command of MCP2510 ; Starting Address !! ; Move data from @FSR to W ; Write to MCP2510 ; Point to next address ; Check the condition of "end of data"
多位元組寫資料
READ_2510S,有3個參數,FSR:寫入資料緩衝區的指標,這是個間接定址寄存器,存放指標地址, Addr_2510:MCP2510的寫入首地址 Dlen_2510:寫入資料長度:
READ_2510S
movlw Buf_REC
movwf FSR
BANKSEL PORT_CS2510
bcf CS2510
movlw CMD_READ
call Write_SPI_Byte
BANKSEL Addr_2510
movf Addr_2510,W
call Write_SPI_Byte
READ_2510S_Loop
movlw 0x00
call Write_SPI_Byte
movwf INDF
incf FSR
; Write command of MCP2510 ; Starting Address !! ; Write to @FSR
BANKSEL Dlen_2510 Decfsz Dlen_2510,F goto READ_2510S_Loop BANKSEL PORT_CS2510 bsf CS2510 return ; Check the total data read
三〃接下來是如何來進行CAN匯流排資料的發送和接收。
首先是對MCP2510的初始化:
1〃 重定,緊接著延時一下,以確保進入配置模式
RESET_2510
call Delay_MCP2510 ;一個延時副程式,不用太長時間
2〃 進入配置模式,其實在重定時已進入配置模式,可以去掉
MODIFY_2510 CANCTRL,b'11100000',b'10000000' ; Set to Configure Mode
3〃 設置震蕩脚是否輸出,幷且可以設置頻率,上電重定時是晶片震蕩體的八分之一頻率
MODIFY_2510 CANCTRL,b'00000111',b'00000100' ; Set Clock Out Freq
4〃 設置CAN匯流排的串列傳輸速率,下面設置是125K/S
WRITE_2510
WRITE_2510
WRITE_2510 CNF1,b'00000111' CNF2,b'10010000' CNF3,b'00000010' ; Set CNF1 , TQ = 2*8*1/16M = 1us 125k/bps ; Set CNF2 , PHASE1:3TQ,PRSEG:1TQ ; Set CNF3 , PHASE2:3TQ
5〃 設置中斷,下面設置是二個接收器中斷打開
WRITE_2510 CANINTE,b'00000011'
6〃 設置三個發送器和二個接收器的控制寄存器
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510 TXB0CTRL,b'00000011' TXB1CTRL,b'00000010' TXB2CTRL,b'00000001' RXB0CTRL,b'00000100' RXB1CTRL,b'00000000' ; TXB0CTRL , Supreme PRI ; TXB1CTRL , ; TXB2CTRL , The lowest PRI ; RXB0CTRL , 接收滾存 ; RXB1CTRL ,
7〃 配置各接收器的濾波驗收寄存器和遮罩寄存器,下面的配置是接收和RXF0SIDH寄存器相等的
資料,就是和常數MESSAGE相等
WRITE_2510 RXF0SIDH, MESSAGE ; MESSAGE is filter address
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510 RXF0SIDL,0x8 RXF1SIDH,0xff RXF1SIDL,0x8 RXF2SIDH,0xff RXF2SIDL,0x8 RXF3SIDH,0xff RXF3SIDL,0x8 RXF4SIDH,0xff RXF4SIDL,0x8 RXF5SIDH,0xff RXF5SIDL,0x8 RXM0SIDH,0xff RXM0SIDL,0x00 RXM0EID8,0x00 RXM0EID0,0x00
WRITE_2510
WRITE_2510
WRITE_2510
WRITE_2510 RXM1SIDH,0xff RXM1SIDL,0x00 RXM1EID8,0x00 RXM1EID0,0x00
8〃進入正常模式 MODIFY_2510 CANCTRL,b'11100000',b'00000000' ; Set to Normal Mode !!
發送副程式: 有5個參數,MESSAGE_NO1:接收方地址 Dlen_2510:發送的資料長度
SERIAL_NUMBER_TYPE, SERIAL_NUMBER_IDH, SERIAL_NUMBER_IDL:産品編號,這是代表自身的地址,要接收的那台設備如果在濾波驗收寄存器裏設置了和這三個參數相等的數就會收到發過去的資料:
TxMsg
STATUS_2510 ;先讀狀態字,確定發送器是否已準備好,沒有正在發的任務
BANKSEL STATUS_byte
btfsc STATUS_byte,2
goto TxMsg
WRITE_2510_DATA TXB0SIDH,SERIAL_NUMBER_TYPE ;寫發送地址
WRITE_2510 TXB0SIDL,(((MESSAGE_NO1 << 5) & b'11100000') | b'00001000')
WRITE_2510_DATA TXB0EID8,SERIAL_NUMBER_IDH
WRITE_2510_DATA TXB0EID0,SERIAL_NUMBER_IDL
WRITE_2510_DATA TXB0DLC,Dlen_2510 ;寫入發送長度
movlw TXB0D0 ;寫資料
movwf Addr_2510
call WRITE_2510S
SEND_TXB0 ;開始發送
Return
接收副程式:
只給出一個接收後存放資料的緩衝區首位址即可,Buf_REC。返還的長度也可以判斷有無接收到資料,如果是0表示沒收到資料,不為0累加器W的資料就是接收到的資料的長度。
RxMsg
STATUS_2510 ;先讀狀態字,判斷接收器0是否有接到資料
BANKSEL STATUS_byte
btfss STATUS_byte,0
retlw 0
READ_2510 RXB0SIDL ;讀取RXB0SIDL
READ_2510 RXB0DLC ;讀取接收的資料長度
Andlw 0x0f
movwf Dlen_2510
movwf TempVar1
movlw RXB0D0 ;讀取資料
movwf Addr_2510
call READ_2510S
MODIFY_2510 CANINTF,b'00000001',b'00000000' ;這裏很重要,接收完畢後一定要清中斷
movf TempVar1,W ;把長度存入W
return
四〃以上內容基本上概括了如何用MCP2510作CAN匯流排控制器的方法,附程式一份。