CAN Bus Diagnostic Translator

CAN Bus Diagnostic Translator MANUAL Kenneth Heck John Murphy USE AND CARE I. USE First, decide in what manner you wish to use the device: Are you ...
Author: Milton Walton
7 downloads 1 Views 40KB Size
CAN Bus Diagnostic Translator MANUAL

Kenneth Heck John Murphy

USE AND CARE I. USE First, decide in what manner you wish to use the device: Are you using it as a straightthrough from the car to the PC? Are you going to record from the car going around the track? Or are you going to play back a pre-recorded session from a Compact Flash card? STRAIGHT-THROUGH MODE Connect the device to the PC via the DB-9 connector, making sure to tighten the screws to reduce vibration. On the other side, connect the device to the CAN bus, locking the connector firmly for a good connection. Load the CAN translator software on the PC, and connect the device to power. The power LED will come on and the software will let you know when it is ready to proceed. Run the car's systems normally, being careful not to pull on the device's cables. When you are finished, disconnect the power and detach the device's cables, making sure not to get grease or motor oil in the connectors. If possible, wash your hands before handling the device, or use a clean cloth. RECORD MODE Open the device's case and insert a Compact Flash card into its connector, with its label side facing away from the circuit board. Close the case carefully. Connect the device to the CAN bus, locking its connector, and connect it to power. Secure the device carefully to avoid damaging it while the car is in motion. When you have finished, disconnect the device from power and from the CAN bus. Retrieve the card by opening the case again. DO NOT open the case with dirty hands. The Compact Flash card can remain in the device indefinitely, but on each new run the device begins writing from the beginning of the card, obliterating any data that may have been stored previously. Back up all data and keep logs, in possible, of whether a given card is safe to re-use. PLAYBACK MODE Open the device's case and insert the Compact Flash card into its socket. Connect the device to your PC via the DB-9 connector. Load the CAN translator software on your PC, then connect the device to power. When the program indicates that it is ready, push the playback button on the device.

Cards written to with the device are readable multiple times, provided that they are not written to by this device or any other in the meantime. See the manufacturer's information for your card to determine how long it will hold data.

I. CARE So long as the device is kept clean and dry, it should continue to operate normally. After use, the user should inspect all connectors to ensure that no dirt or oil has gotten in. Check internal cables periodically for cracks, especially around the headers. In choosing a location in the car to mount the device, consider the following things: ? Vibration – If the device is mounted to a moving part, or loosely mounted to a stable part, vibration can cause cables to come loose or disconnect competely. ? Heat – While the device itself is designed for average ambient temperatures inside an operating car, it is not designed to be placed directly on or near a heated element, such as the radiator or air conditioner. If possible, it is best to mount the device in the passenger space. ? Water and Oil – Do not mount the device in such a way that water or oil will fall on it during operation. Take special care when using the device in wet weather to avoid putting it in the path of water or steam.

TROUBLESHOOTING Power LED does not come on ? Check power connection. Make sure that the connector fits securely into the device and that the cable is free of defects such as cracks. Make sure that the cable is connected to either the car's power supply or a wall outlet. ? Examine the circuit board for damage or defects. Make sure that each chip is secure in its space and that none of the resistors or jumpers show scorch marks. Examine the LED itself to make sure that it has not been damaged. Check its connection to the board by gently probing it to see if has come loose. ? With a voltmeter, test pin 40 on the PIC chip when the device is powered to see if it is a logical high. If not, the problem may be the PIC itself, and it may need to be reprogrammed or replaced. CAN LEDs do not come on ? The CAN bus may not be active at all times. If possible, do something with the car that would ordinarily cause a message to be transferred. Starting the car, pumping the brakes, turning on the headlights or windshield wipers would all do this. ? Ensure that the device is connected to the CAN bus and locked securely to the connector. ? In playback mode, the LEDs may not come on, even though the device may be correctly attached to a working CAN bus. This is normal for playback mode. Disconnect it from power and reconnect it. Translator Software does not detect device, even though power LED is on ? Disconnect the device from power and reconnect it after checking to be sure that it is correctly attached to your computer. ? Make sure that the COM port on your computer is working properly. Unresolved IRQ conflicts will cause the serial communications on your computer to not work properly. ? Go to the Windows Control Panel, under System. Go to your COM port settings under Device Manager, and select the tab labelled Port Settings. Set the following values if they are not already set: Bits per second: 9600 Data bits: 8 Parity: None Stop Bits: 1 Flow control: None

APPENDIX B: SCHEMATIC

APPENDIX C: SOURCE CODE FOR PIC 16F877

;+===========================+ ;|John Murphy | ;|Kenneth Heck | ;| | ;|CAN bus adaptor | ;|28 November, 2001 | ;| | ;+===========================+ list p=16f877 ; Include file, change directory if needed include "p16f877.inc" __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_OFF & _HS_OSC & _WRT_ENABLE_OFF & _LVP_ON & _DEBUG_OFF & _CPD_OFF #define debug ;#define echo ;+===========================+ ;| Variables | ;+===========================+ ;For the Interrupt Service Routines: W_TEMP equ STATUS_TEMP equ PCLATH_TEMP equ FSR_TEMP equ 0x74

0x71 0x72 0x73

;*************************************** ; DEVMODE ;Device's Mode/STATUS Byte ; Bit 0-2 MODE SELECT ; Bit 3 PC_buff overflow error ; Bit 4 CAN_buff overflow error ; Bit 5 CompactFlash full error ; Bit 6 PC_buff contains data ;*************************************** DEVMODE equ 0x75 #define PC_BUFF_OVERFLOW DEVMODE, #define CAN_BUFF_OVERFLOW DEVMODE, #define CF_INSERTED #define PC_BUFF_NOTEMPTY DEVMODE, #define CAN_BUFF_NOTEMPTY DEVMODE, DEVFLAG #define #define

equ CAN_RX0_READY CAN_RX1_READY

3 4 DEVMODE, 5 6 7

0x76 DEVFLAG, 0 DEVFLAG, 1

#define #define #define

SPI_IN_PROGRESS USART_IN_PROGRESS CF_IN_PROGRESS

DEVFLAG, 2 DEVFLAG, 3 DEVFLAG, 4

delay equ 0x21 rcv equ 0x22 loopctr0 equ 0x23 ;Whenever we write to the 2510, we write two bytes at a time. Load ;them into these first, then call SPI_Write ; And yes, these are all in the same bank as SSBUF. Makes life much easier later on. SPI1 SPI2 SPI3 SPIOUT

equ equ equ equ

0x26 0x27 0x28 0x29

CF_DATA_HIGH CD_DATA_LO equ

equ 0x2B

0x2A

POWER_ON_MSG INIT_MSG equ

equ 0x42

0x55

equ equ equ

0xE5 0xE6 0xE7

0x33 equ equ 0x36

0x34 0x35

;Here are our buffers: CAN_buff_in CAN_buff_out CAN_buff_ctr PC_buff_in equ PC_buff_out PC_buff_ctr outcounter equ

PC_buff equ 0x40 ;This ends at 0x50, for 16 bytes -- two CAN packets' worth PC_buff_end equ 0x51 CAN_buff equ 0xA0 ;This stretches out to 0xE0h -- 64 bytes CAN_buff_end equ 0xE1

;+===========================+ ;| Constants | ;+===========================+ #define #define #define

CAN_CS TXB0_TX TXB1_TX

;Compact Flash control lines #define CF_RESET #define CF_CD1 #define CF_OE #define CF_WE #define CF_RDY #define CF_CE1

PORTB, 2 PORTB, 6 PORTB, 5

PORTA, 5

;Output PORTA, 1 PORTA, 2 PORTA, 3 PORTA, 4 PORTA, 0

;Output ;Output ;Output ;Input ;Output

;+============================+ ; CANSTAT bits 3-1 ; Interrupt flag code ; 000 = No Interrupt ; 001 = Error Interrupt ; 010 = Wake Up Interrupt ; 011 = TXB0 Interrupt ; 100 = TXB1 Interrupt ; 101 = TXB2 Interrupt ; 110 = RXB0 Interrupt ; 111 = RXB1 Interrupt ;+============================+ CANCTRL CANSTAT CANINTE CANINTF CNF1 CNF2 CNF3

equ equ equ equ equ equ equ

SPI_RESET equ

B'11000000'

RXB0DLC RXBUF0 RXM0SIDH RXM0SIDL RXB1DLC RXBUF1 RXM1SIDH RXM1SIDL

equ equ 0x20 0x21 equ equ 0x24 0x25

equ equ

equ equ

TXBUF0 equ TXBUF1 equ Only one used by current code TXB1CTRL equ 0x40 TXBUF2 equ

0x0F 0x0E 0x2B 0x2C 0x2A 0x29 0x28 ;2510's RESET command

0x65 B'01100110'

;Start of RXB0

0x75 B'01110110'

;Start of RXB1

B'00100110' B'01000110'

;Start of TXB0 ;Start of TXB1 300

ns)

;No?

;Is there a card inserted? Go set up the 2510

;We have card! bsf CF_INSERTED banksel PORTA bsf CF_RESET nop nop bcf CF_RESET nop nop call wait call wait call wait call wait call wait call wait call wait call wait ;LONG wait. This may not be long enough, but it's probably OK

;+==========================+ ;| MCP2510 Config | ;+==========================+ CAN_INIT ;Initiate MCP2510 reset banksel PORTB bcf CAN_CS

;

movlw movwf

SPI_RESET SSPBUF

banksel movlw movwf call

TXREG 0x31 TXREG txwait

banksel movfw

SSPBUF SSPBUF

banksel bsf

PORTB CAN_CS

banksel

TXREG

;Hit the Chip Select

; ;

movfw movwf

0x43 TXREG

;And now -- we wait! call wait call wait call wait call wait ;This is probably excessive, but time is not ;critical at this point... ; Technically, this should be 128 Osc cycles from the 2510's point of view. ; It's running on the same clock that the PIC is, divided by four ; ; ; ;

banksel movlw movwf call

TXREG 0x32 TXREG txwait

; We need to set up the acceptance masks and filters here. ; For the demo, we're using RXBUF0, so let's set its mask to all 0's banksel movlw movwf movlw movwf call

SPI1 RXM0SIDH SPI1 0x00 SPI2 SPI_WRITE

banksel movlw movwf movlw movwf call

SPI1 RXM0SIDL SPI1 0x00 SPI2 SPI_WRITE

; For that matter, let's turn off RXBUF1 by setting its mask to all 1's, ; ensuring that nothing will match it. banksel movlw movwf movlw movwf call

SPI1 RXM1SIDH SPI1 0xFF SPI2 SPI_WRITE

banksel movlw movwf movlw movwf call

SPI1 RXM1SIDL SPI1 0xFF SPI2 SPI_WRITE

;The following settings I got from the sample code that

Microchip made available. banksel movlw movwf movlw movwf call

SPI1 CNF1 SPI1 0x03 SPI2 SPI_WRITE

banksel movlw movwf movlw movwf call

SPI1 CNF2 SPI1 0x90 SPI2 SPI_WRITE

banksel movlw movwf movlw movwf call ; Lastly, receipt in RXB0 banksel movlw movwf movlw movwf call

SPI1 CNF3 SPI1 0x02 SPI2 SPI_WRITE let's tell the 2510 to interrupt us upon message

SPI1 CANINTE SPI1 0x01 SPI2 SPI_WRITE

;******************************************************************** *******; ;+ Now that that's all done, let's set it up in loopback mode ;+ ;+ banksel SPI1 ;+ movlw CANCTRL ;+ movwf SPI1 ;+ movlw B'01000000' ; Loopback Mode ;+ movwf SPI2 ;+ call SPI_WRITE ;******************************************************************** ******** banksel SPI1 movlw CANCTRL movwf SPI1 movlw B'01110000' abort all pending transmissions movwf SPI2 call SPI_WRITE ; ; ; ;

banksel movlw movwf call

TXREG 0x33 TXREG txwait

; Listen-only mode, and

;+========================+ ;| Main Sequence | ;+========================+ banksel PORTB bsf PORTB, 7

;Hit the power indicator

clrf clrf

PIR1 PIR2

banksel movlw movwf call

TXREG INIT_MSG TXREG txwait

banksel bsf bsf

INTCON INTCON, 6 ;Enable peripheral interrupts INTCON, 7 ;Enable global interrupts

mainloop ; Okay, now let's take all those buffers we filled up and direct their data to where it ; needs to go btfsc call

CAN_RX0_READY READ_RXB0

;Is there anything in the transmit buffer? ;(I should really be using a flag for this instead!) banksel CAN_buff_ctr movf CAN_buff_ctr, F bz checkPCbuffer banksel movfw movwf banksel movfw movwf

CAN_buff_out CAN_buff_out FSR TXREG INDF TXREG

banksel CAN_buff_out movfw CAN_buff_out alloted space? addlw 0x1F we've overflowed bnc CANdecnormally movlw CAN_buff movwf CAN_buff_out decf CAN_buff_ctr goto endservice CANdecnormally incf CAN_buff_out decf CAN_buff_ctr underflow, since we already checked

;Data

;Have we read beyond our ; This will overflow if ;branch-no-carry

; I'm not checking for

checkPCbuffer ;Is there banksel movf bz banksel movfw movwf banksel movfw movwf

anything in the transmit buffer? PC_buff_ctr PC_buff_ctr, F endservice PC_buff_out PC_buff_out FSR TXREG INDF TXREG

movfw PC_buff_out alloted space? addlw 0xB0 we've overflowed bnc PCnormaldec movlw PC_buff movwf PC_buff_out decf PC_buff_ctr goto endservice PCnormaldec incf PC_buff_out decf PC_buff_ctr underflow, since we already checked

;Data

;Have we read beyond our ; This will overflow if ;branch-no-carry

; I'm not checking for

endservice ;Include any necessary clean-up here goto

mainloop

;+=========================+ ;| Function Calls | ;+=========================+ wait

del

banksel movlw movwf decf skpz goto return

delay B'11100000' delay delay

banksel btfss goto bcf return

PIR1 PIR1, TXIF txloop PIR1, TXIF

del

txwait txloop

SPI_WRITE ;Do NOT call until SPI has been configured!!! banksel PORTB bcf CAN_CS ;MCP2510's chip select line

#ifdef

debug movlw movwf

0x57 TXREG

;Debugging message

movlw

B'00000010'

;MCP2510 Write command

banksel movwf

SSPBUF SSPBUF

movf

SSPBUF, W

movfw banksel movwf

SPI1 SSPBUF SSPBUF

movf

SSPBUF, W

movfw banksel movwf

SPI2 SSPBUF SSPBUF

movf

SSPBUF, W

#endif

;We've moved our three bytes, now let's go home banksel PORTB bsf CAN_CS return BIT_MODIFY ;Do NOT call until SPI has been configured!!! banksel PORTB bcf CAN_CS ;MCP2510's chip select line

#ifdef

debug movlw movwf

0x42 TXREG

movlw banksel movwf

B'00000101' SSPBUF SSPBUF

movfw banksel movwf

SPI1 SSPBUF SSPBUF

movfw banksel movwf

SPI2 SSPBUF SSPBUF

movfw banksel movfw

SPI3 SSPBUF SSPBUF

;Debugging message

#endif

;We've edited the register, let's go back

;MCP2510 Bitwise Modify

banksel bsf return

PORTB CAN_CS

banksel bcf

PORTB CAN_CS

debug movlw movwf

0x52 TXREG

movlw banksel movwf

B'00000011' SSPBUF SSPBUF

movwf banksel movwf

SPI1 SSPBUF SSPBUF

SPI_READ

#ifdef

;Debugging message

#endif ;MCP2510 Read command

;The next thing that comes in is the contents of that register. ; At this stage, nothing that comes from the 2510 is used by the PIC -; it's just a straight pass-through

rgo2

banksel btfss goto

SSPSTAT SSPSTAT, BF rgo2

banksel movfw banksel movwf

SSPBUF SSPBUF SPIOUT SPIOUT

banksel bsf

PORTB CAN_CS

return

READ_RXB0 ;This function "calls up" the 2510, reads out the Data Length register, and loops that many ; times, feeding into the CAN_buff ring buffer. ;Right now, interrupts are turned OFF during the entire operation. This is ridiculous. ; I bet that turning interrupts back on during any wait periods, or just briefly in between ; cycles would help a lot. ; The CLEVER way to do this would be to externally load an offset, since adding 0x10 to each of ; these address bytes would select RXB1, instead. ; However, there is some doubt as to whether we will actually ever need RXB1. banksel

INTCON

bcf

INTCON, 7 ;OK, it's dumb, but it's temporary.

banksel bcf

PORTB CAN_CS

movlw banksel movwf

B'00000011' SSPBUF SSPBUF

;MCP2510 Read command

RXB0DLC

;Address of RX Buffer 0's

movwf Data Length Code movwf

;Poke the 2510

SSPBUF

;The next thing that comes in is the contents of that register. banksel btfss goto

SSPSTAT SSPSTAT, BF rxb01

banksel movfw andlw bottom four bits

SSPBUF SSPBUF B'00001111'

rxb01

;Mask out all but the ; creating a nice loop

timer banksel movwf bz don't waste time

loopctr0 loopctr0 rxb0done

; It may be empty, in which case,

banksel movlw movwf

SSPBUF B'00000011' SSPBUF

movlw movwf

RXBUF0 SSPBUF

banksel movfw movwf

PC_buff_in PC_buff_in FSR

;Address of start bit

rxb0loop

banksel rxb0loopinner btfss goto

SSPSTAT SSPSTAT, BF rxb0loopinner

banksel movfw

SSPBUF SSPBUF

banksel movwf incf movlw xorwf

CAN_buff INDF CAN_buff_in CAN_buff_end CAN_buff_in, W

skpz goto

rb0_rest

;Is the new address out of

bounds? ;If it is, loop around

movlw movwf

CAN_buff CAN_buff_in

;Loop around

rb0_rest incf movlw xorwf skpnz set the error bit bsf

CAN_buff_ctr 0x40 CAN_buff_ctr, W

banksel we're done. decf bnz

loopctr0

bsf

;64 bytes

-- HUGE counter

;If the counter overflows, CAN_BUFF_OVERFLOW ;Decrement our counter, and see if

loopctr0 rxb0loop CAN_BUFF_NOTEMPTY

rxb0done banksel PORTB bsf CAN_CS interrupts, to prevent overflows banksel bsf

;Do this before re-enabling

INTCON INTCON, 7

return CF_READY BTFSS goto return

CF_RDY CF_READY

CF_READ call CF_READY ;Input from data lines banksel TRISD movlw 0xFF movwf TRISD banksel PORTD clrf PORTD bsf

CF_OE

; ******************************** ; Handle incoming communications from the PC PC_SERVICE banksel movfw movwf

PC_buff_in PC_buff_in FSR

banksel movfw

RCREG RCREG

; The following code grabs that byte from RCREG and puts it into the PC_buff buffer ; When that buffer's counter is an integer multiple of eight, it gets flushed out

; onto the CAN bus. movwf incf movlw xorwf

INDF PC_buff_in PC_buff_end PC_buff_in, W

skpz goto movlw movwf

;If it is, loop around pc_rest PC_buff PC_buff_in ;Loop around

;Is the new address out of

bounds?

pc_rest incf movlw xorwf skpnz set the error bit bsf

PC_buff_ctr 0x10 PC_buff_ctr, W

;16 bytes ;If the counter overflows,

PC_BUFF_OVERFLOW

; At this point, we've loaded the new byte into the buffer, incremented the position ; and checked for overflow. We now indicate that the PC buffer contains data ; and head back to IntService bsf

PC_BUFF_NOTEMPTY

goto

CheckCAN

CAN_SERVICE ;Since the MCP2510 generates various things, ; This routine needs to read interrupt) ; Then poll the 2510 for the then a flag ; should be set for the MAIN Don't do it here

an external interrupt for off portb (To clear the error.

If it IS a message,

LOOP to read the buffer.

banksel movf bcf

PORTB PORTB, F CAN_CS

movlw banksel movwf

B'00000011' SSPBUF SSPBUF

;MCP2510 Read command

movwf banksel movwf

CANSTAT SSPBUF SSPBUF

;the 2510's status register

;Clear that interrupt

;The next thing that comes in is the contents of that register. ; We don't care about errors. They aren't processed in listen mode, anyhow. banksel

SSPSTAT

CS2

btfss goto

SSPSTAT, BF CS2

banksel movfw andlw

SSPBUF SSPBUF B'00001110'

banksel bsf

PORTB CAN_CS

xorlw bnz

B'00001100' NextISR

bsf

CAN_RX0_READY

goto

NextISR

;RXB0 Interrupt ;If anything else, then

forget it.

;+==========================+ ;| Interrupt Routines | ;+==========================+ IntService movwf

W_TEMP

swapf movwf movfw movwf movfw movwf

STATUS, W STATUS_TEMP FSR FSR_TEMP PCLATH PCLATH_TEMP

;save W, STATUS, PCLATH,

and FSR

banksel PIR1 ;Perform interrupt routines CheckPC btfsc goto

PIR1, RCIF PC_SERVICE

btfsc goto

PIR1, INTE CAN_SERVICE

CheckCAN

NextISR ;Clear Receive errors bcf RCREG, CREN bsf RCREG, CREN bcf PIR1, RCIF ;All done! Now let's put everything back where it was movfw PCLATH_TEMP movwf PCLATH movfw FSR_TEMP movwf FSR swapf STATUS_TEMP, W movwf STATUS swapf W_TEMP, F swapf W_TEMP, W retfie

end