📄 can_ref.asm
字号:
;*******************************************************************
; Microchip CAN Reference Design
;
; Mike Richitelli
; Diversified Engineering
; 283 Indian River Road
; Orange, CT 06477
; (203)799-7875 fax(203)799-7892
; WWW.DIVERSIFIEDENGINEERING.NET
;
;*******************************************************************
;*******************************************************************
TITLE " CAN_Ref Design "
;*******************************************************************
dVersion equ 1
dRelease equ 5
;======================================================================
; Transmits CAN message every 131 mSec. Message contains two data bytes
; that represent a 12 bit value with least significant byte
; sent first.
; Cycles between three outputs:
; Pot: Value goes from 0 to 0xFF0 as Pot is turned clockwise.
; ID is selected from DIP switches #3 and #4 as follows:
; #3 #4 ID
; 0 0 transmission disabled
; 0 1 0x100
; 1 0 0x200
; 1 1 0x300
;
; Push button switch: Switch open => 0, Switch closed => 0xFFF
; ID is Pot ID + 0x010
;
; CdS: Value goes from 0 to 0xFF0 as Pot is turned clockwise.
; ID is Pot ID + 0x020
;
; CAN messages received are assumed to be 12 bit data sent as two bytes,
; least significant byte first.
;
; The base ID for receiving CAN messages is specified by DIP
; switches #1 and #2:
; #1 #2 ID
; 0 0 0x000
; 0 1 0x100
; 1 0 0x200
; 1 1 0x300
;
; Lamp: If the message ID matches the ID selected by the DIP
; switches the 12 bit data is used to generate a PWM output
; where a 0 value gives a zero duty cycle and 0xFFF generates
; a 100% duty cycle. The lamp output is proportional to
; the duty cycle.
; ID is Base ID
;
; LED: On if value received is >= 0x800 and off if < 0x800.
; ID is Base ID + 0x010
;
;======================================================================
;----- PIC16F876 Micro -----;
LIST P=16F876
LIST r=dec,x=on,t=off
#include "P16F876.INC"
__CONFIG _BODEN_ON&_CP_OFF&_WRT_ENABLE_ON&_PWRTE_ON&_WDT_OFF&_HS_OSC&_DEBUG_OFF&_CPD_OFF&_LVP_OFF
__IDLOCS (dVersion<<8)|dRelease ; version: vvrr , vv- version, rr - release
;---------------------------;
#include "MACROS16.INC"
#include "MCP2510.INC"
; errorlevel 0,-306,-302,-305
;******** constants
;Crystal freq 4.00 MHz, Fosc/4 = 1 uS
;
; Timer 1: Uses no prescale => Tic is 1 uSec
; 8 bit rollover 256 uSec
; 16 bit rollover 65.536 mSec
; 8 bit timers
; TMR1L: 1 uSec tics with maximum of 1/2 rollover = 128 uSec maximum
; TMR1H: 256 uSec tics with maximum of 1/2 rollover = 32.768 msec maximum
;======================================================================
;************************
; A/D selection ( value of ADCON0 )
#define dA2DRA0 B'01000000' ; fosc/8 clk, RA0, A/D off
#define dA2DRA3 B'01011000' ; fosc/8 clk, RA3, A/D off
;************************
; special function defines
#define _SSPEN SSPCON,SSPEN ; SPI enable
;************************
;; General control flags definitions
#define tbWork bGenFlags1,0 ; working bit
#define tbReset bGenFlags1,1 ; must reset
#define tbNewSPI bGenFlags1,2 ; new SPI data available
#define tbRxMsgPend bGenFlags1,3 ; new CAN message received
#define tbTxMsg bGenFlags1,4 ; xmit next CAN message
#define tbRC2NowHigh bGenFlags1,5 ; Robot PWM signal high
;***************** PIN DEFINITIONS **************************
#define tp2510_CS_ PORTA,1 ; CS_ for 2510 chip
;; I/O
#define tpSwitch_ PORTB,1 ; Push button switch, Open => high
#define tpLED PORTB,2 ; LED
;; Analog In
#define tpA2D_CS_ PORTB,1 ; CS_ for 3201 A2D chip
#define tpEE_CS_ PORTB,2 ; CS_ for 25040 E2
;***************** LOCAL REGISTER STORAGE **************************
;
;
;============ BANK 0 =================
cblock 0x20
;; interrupt variables
bIntSaveSt ; save Status
bIntSaveFSR ; save FSR
bIntSavPCLATH ; interrupt storage for PCLATH
bIntWork ; working
iIntWork:2 ; working
;; general work space
bGenFlags1 ; general control flags 1
bGenFlags2 ; general control flags 2
bWork ; work byte
bWork1 ; work byte
iWork:2 ; work integer
bCnt ; work byte counter
;; Arithmetic
iA:2 ; 2 byte integer
iB:2 ; 2 byte integer
;; Timer1
iTimer1:2 ; counts Timer1 rollover
bGenClk ; general clock
bXmitClk ; Countdown to xmit next message
;; In/Out variables
iA2DValue:2 ; 12 bit or 8 bit A2D value
bPWMValue ; 8 bit PWM value
iRecValue:2 ; 12 bit received value
;; general control
bSwXmitID ; ID for transmission from DIP switch
bBaseRecID ; ID for reception from DIP switch
bRecIDNext ; Rec Base ID + 1
bXmitID ; ID for transmission of next msg
bNextMsgType ; Select next msg
;; Received CAN message
iRecID_L ; ID of received message (3 bits left justified)
iRecID_H ; ID of received message (8 bits left justified)
bRecCount ; number of bytes received
pRecDataBase:8 ; received data
;; Low level SPI interface
b2510RegAdr ; Register address
b2510RegData ; Data sent/received
b2510RegMask ; Bit Mask
; following used in interrupt
bSPICnt ; # bytes remaining to receive
pSPIBuf ; Pointer into buffer
pSPIBufBase:12 ; Base of SPI receive/xmit buffer
endc
; storage for interrupt service routine
; W saved in one of these locations depending on the page selected
; at the time the interrupt occured
bIntSaveW0 equ 0x7F ; interrupt storage for W
;============ BANK 1 =================
bIntSaveW1 equ 0xFF ; interrupt storage for W
;*******************************************************************
;********** LOCAL MACROS *******************************************
;*******************************************************************
;
; Shift left 2 byte integer once.
iShiftL macro iVar
bcf _C ; clear carry bit
rlf iVar,F
rlf iVar+1,F
endm
; Shift right 2 byte integer once.
iShiftR macro iVar
bcf _C ; clear carry bit
rrf iVar+1,F
rrf iVar,F
endm
; Increment 2 byte integer
intInc macro iVar
incf iVar,F
skipNZ
incf iVar+1,F
endm
;
;; --------------------------------------------------------
;; Set TRM1H 8 bit clock
; TMR1H: 256 uSec tics with maximum of 1/2 rollover = 32.768 msec maximum
;; --------------------------------------------------------
Set1HClock macro bClk,Value
movfw TMR1H
addlw Value
movwf bClk
endm
;; --------------------------------------------------------
;; Jump to jLabel if TMR1H (low byte) < bClk
;; --------------------------------------------------------
jmp1HNotYet macro bClk,jLabel
movfw TMR1H
subwf bClk,W
andlw 0x80
jmpZ jLabel
endm
;; --------------------------------------------------------
;; Jump to jLabel if TMR1H (low byte) < bClk
;; --------------------------------------------------------
jmp1HDone macro bClk,jLabel
movfw TMR1H
subwf bClk,W
andlw 0x80
jmpNZ jLabel
endm
;********************************************************************
; Begin Program Code
;********************************************************************
ORG 0x0 ;memory @ 0x0
nop ;nop ICD!!
goto HardStart
ORG 04h ;Interrupt Vector @ 0x4
;**********************************************************
; Interrupt service routine - must be at location 4 if page 1 is used
; Context save & restore takes ~20 instr
;**********************************************************
;; Global int bit, GIE, has been reset.
;; W saved in bIntSaveW0 or bIntSaveW1 depending on the bank selected at
;; the time the interrupt occured.
movwf bIntSaveW0 ; save W in either of two locations
; depending on bank currently selected
;; only way to preserve Status bits (since movf sets Z) is with a
;; swapf command now
swapf STATUS,W ; Status to W with nibbles swapped
BANK0
movwf bIntSaveSt
movfw FSR
movwf bIntSaveFSR ; save FSR
movf PCLATH,W
movwf bIntSavPCLATH ; interrupt storage for PCLATH
clrf PCLATH ; set to page 0
;; Must determine source of interrupt
;; SPI interrupt
btfsc _SSPIF ; SPI interrupt
goto IntSPI
jmpSet _TMR1IF,jIntTimer1 ; Timer1 overflow interrupt flag
;; unknown
;; restore registers and return
IntReturn
BANK0
movf bIntSavPCLATH,W ; interrupt storage for PCLATH
movwf PCLATH
movf bIntSaveFSR,W ; restore FSR
movwf FSR
swapf bIntSaveSt,W ; get swapped Status (now unswapped)
movwf STATUS ; W to Status ( bank select restored )
swapf bIntSaveW0,F ; swap original W in place
swapf bIntSaveW0,W ; now load and unswap ( no status change)
retfie ; return from interrupt
;***************** ID TABLE ****************************
; Look up ID associated with bits 0,1 in W
RxIDTable addwf PCL,F ;Jump to char pointed to in W reg
;( adds 5bits from PCLATH )
retlw 0x00 ; 0
retlw 0x20 ; 1
retlw 0x10 ; 2
retlw 0x30 ; 3
RxIDTable_End
#if ( (RxIDTable & 0xF00) != (RxIDTable_End & 0xF00) )
MESSG "Warning - Table crosses page boundry in computed jump"
#endif
; Look up ID associated with bits 0,1 in W
TxIDTable addwf PCL,F ;Jump to char pointed to in W reg
;( adds 5bits from PCLATH )
retlw 0xFF ; 0
retlw 0x20 ; 1
retlw 0x10 ; 2
retlw 0x30 ; 3
TxIDTable_End
#if ( (TxIDTable & 0xF00) != (TxIDTable_End & 0xF00) )
MESSG "Warning - Table crosses page boundry in computed jump"
#endif
;***************** LIBRARY STORAGE & FUNCTIONS ****************************
#include "CanLib.asm" ; basic 2510 interface routines
#include "a2d3201.asm" ; MCP3201 AD routines
;***************** Local Interrupt Handlers ****************************
;**********************************************************
;jIntTimer1
; Timer1 rollover interrupt.
;
;**********************************************************
jIntTimer1 ; Timer1 overflow interrupt flag
bcf _TMR1IF ; timer1 rollover interrupt flag
intInc iTimer1
jmpFeqZ bXmitClk,IntReturn
decfsz bXmitClk,F ; Countdown to xmit next message
goto IntReturn
; Countdown to xmit next message
bsf tbTxMsg ; xmit next CAN msg
goto IntReturn
;**********************************************************
;IntSPI
;
; A single buffer, at pSPIBufBase, is used for both SPI receive and
; transmit. When a byte is removed from the buffer to transmit it is
; replaced by the byte received.
;
; When here the buffer pointer, pSPIBuf, points to the last byte loaded
; for transmission. This is the location that the received byte will be stored.
;
; When here the count, bSPICnt, contains the number of bytes remaining
; to be received. This is one less then the number remaining to be
; transmitted. When bSPICnt reaches zero the transaction is complete.
;
;
;**********************************************************
IntSPI
bcf _SSPIF ; clear interrupt flag
;; Transfer received byte to the next location in the buffer
bV2bV pSPIBuf,FSR
incf pSPIBuf,F
movfw SSPBUF ; get data & clear buffer flag
movwf INDF ; put it into SPI buffer
decfsz bSPICnt,F
goto jIntSPI1 ; More bytes to send
;; Last transaction completed
bsf tp2510_CS_ ; CS_ for 2510 chip
goto IntReturn
jIntSPI1
;; Fetch next byte from buffer and load it for transmission
incf FSR,F
movfw INDF ; get byte from buffer
movwf SSPBUF ; send it
goto IntReturn
;**********************************************************
;**********************************************************
;**********************************************************
HardStart
call Init
;; Make sure no chips are selected
bsf tp2510_CS_ ; CS_ for 2510 chip
;; Read DIP switch and create bBaseRecID and bSwXmitID
;; Rec ID bits are at pins 0,1 of PORTC and are logic high = 1
movfw PORTC
andlw 0x03
call RxIDTable
movwf bBaseRecID
;; Xmit ID bits are at pins 6,7 of PORTC and are logic low = 1
swapf PORTC,W
movwf bSwXmitID
rrf bSwXmitID,F
rrf bSwXmitID,W
andlw 0x03
call TxIDTable
movwf bSwXmitID
;; ----------------- One time calculations ----------------
;; Setup SPI port
call InitSPIPort
;; Wait 28 mS for 2510 to initialize ( there is no significance to 28 mS -
;; we just selected a large time since time is not critical)
Set1HClock bGenClk,100 ; 277.77 uSec tics
jInit5
jmp1HNotYet bGenClk,jInit5
;; Setup all 2510 registers
call Init2510
bsf tbTxMsg ; xmit flag
;; --------------------------------------------------------
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -