list P=PIC16F690 #include "P16F690.inc" __config (_CP_OFF & _WDT_OFF & _PWRTE_ON & _HS_OSC) #define RFIDdebug ; constants and mask definitions ; variable definitions RFIDMachineState equ 0x20 RFIDByteCounter equ 0x21 RFIDNibbleIndicator equ 0x22 RFID_Read equ 0x23 RFIDNewData equ 0x24 TimeoutCounter equ 0x26 #define SPI_Header 0xB9 #define SPI_End 0x9B SPI_Index equ 0x25 #define SPI_RequestPort PORTC #define SPI_RequestBit 3 ASCII_Byte equ 0x2E Hex_Nibble equ 0x2F RFIDChecksum equ 0x30 ;MSB to LSB from RFID reader RFID_ByteArray equ 0x31 #define DebugPort PORTC DebugBit equ 0 DebugLED equ 2 ; bit definitions ; program start org 0 goto Main org 5 ;RFID State switch RFIDStateSwitch: addwf PCL,f goto RFIDState_Message ;case 0 goto RFIDState_Data ;case 1 goto RFIDState_End ;case 2 ;-----------------------------------------------------------; ; Main - initialization of ports and configuration ; ;-----------------------------------------------------------; Main: ;General Initialization ;Clear ANSEL registers banksel ANSEL clrf ANSEL clrf ANSELH ;Set Outputs before initialization banksel PORTA clrf PORTA clrf PORTB clrf PORTC banksel DebugPort bsf DebugPort,DebugLED ;Set TRIS registers banksel TRISA bsf TRISB,5 ;RX input bcf TRISB,7 ;TX output bsf TRISC,DebugBit bcf TRISC,DebugLED bcf SPI_RequestPort,SPI_RequestBit bcf TRISC,SPI_RequestBit ;SPI Request Line bsf TRISB,6 ;SCK input bsf TRISB,4 ;SDI input bcf TRISC,7 ;SDO output bsf TRISC,6 ;SS input ;secret master mode ; bcf TRISB,6 ;SCK output//input ; bsf TRISB,4 ;SDI input ; bcf TRISC,7 ;SDO output ; bcf TRISC,6 ;SS output //input ;;Initialize SPI banksel SPI_Index movlw 0x04 movwf SPI_Index banksel SSPBUF movlw 0xA5 movwf SSPBUF banksel SSPCON movlw b'00110100' ; xx1xxxxx Enables SPI ; xxx1xxxx CKP - clock idles high ; xxxx0100 SPI slave with SS enabled movwf SSPCON banksel SSPSTAT clrf SSPSTAT ; 0xxxxxxx Required for slave mode ; x0xxxxxx CKE - Data transmitted on rising edge of SCK ;Initialize EUSART ;set baud rate to 9600: 20MHz/16/(129+1) banksel SPBRG movlw d'129' movwf SPBRG banksel TXSTA bsf TXSTA,BRGH ;asynch: banksel TXSTA bcf TXSTA,SYNC banksel RCSTA bsf RCSTA,SPEN ;transmission and reception enable banksel TXSTA bsf TXSTA,TXEN banksel RCSTA bsf RCSTA,CREN ;Initialize Timer banksel PIR1 bcf PIR1,TMR2IF banksel PR2 movlw d'255' movwf PR2 call TimerReset banksel T2CON movlw b'01111111' ;1:16 pre and post scaler, timer on movwf T2CON ;State machine initialization pagesel RFIDReset call RFIDReset ;Call UARTReset Function ;Event Checker Loop: LoopStart: LoopContinue: ;check for received message on EUSART banksel PIR1 btfsc PIR1,RCIF ;check if new UART message call RFIDReceive ;call UART Received function if so ;check for new serial transmission banksel SSPSTAT btfsc SSPSTAT,BF ;check for new serial transmission call SPIUpdate ;call update function to load next byte ;update timer, check for timeout banksel PIR1 btfss PIR1,TMR2IF ;check to see if timer 2 rolled over goto LoopContinue ;update timer banksel PIR1 bcf PIR1,TMR2IF ;clear timer overflow flag banksel TimeoutCounter decfsz TimeoutCounter ;decrease counter by 1 tick goto LoopContinue ; TIMEOUT: call TimerReset ;reset state timer call RFIDReset ;reset state machine on timeout goto LoopContinue ; Reset Timeout Counter TimerReset: banksel TimeoutCounter movlw 0x76 ;one second timer movwf TimeoutCounter ;reset counter return ; Update SPI transmission SPIUpdate: call TimerReset ;reset timeout counter ;Clear flag banksel PIR1 movf PIR1,W banksel SSPBUF movf SSPBUF,W banksel SPI_Index decfsz SPI_Index,f ;decrement index goto SPINewByte ;load next byte ;if index hit 0, end SPI transmission banksel SPI_RequestPort bcf SPI_RequestPort,SPI_RequestBit ;clear ready to send bit movlw SPI_End movwf SSPBUF ;store end byte in register, just to clear it ;reset index movlw 0x05 banksel SPI_Index movwf SPI_Index return ; Load next byte for SPI transmission SPINewByte: movlw RFID_ByteArray ;access array of rfid bytes banksel SPI_Index addwf SPI_Index,W ;index array on counter movwf FSR ;store target index banksel SSPBUF movf INDF,W movwf SSPBUF ;load next byte return ;UART Reset Function RFIDReset: ;Set UARTMachineState to WaitingForMessage state banksel RFIDMachineState clrf RFIDMachineState ;Initialize Byte Counter to 6 banksel RFIDByteCounter movlw d'6' movwf RFIDByteCounter ;Initialize RFIDNibbleIndicator to High banksel RFIDNibbleIndicator movlw 0xFF movwf RFIDNibbleIndicator ;clear checksum banksel RFIDChecksum clrf RFIDChecksum return ;UART Receive function: RFIDReceive: call TimerReset ;reset timeout counter ;Read byte from receive register, store as RFID_Read banksel RCREG movf RCREG,W banksel RFID_Read movwf RFID_Read ;Switch on UARTMachineState banksel RFIDMachineState pageselw RFIDStateSwitch movf RFIDMachineState,W goto RFIDStateSwitch ;State: WaitingForMessage RFIDState_Message: banksel RFID_Read movf RFID_Read,W ;if RFID_Read is 0x02 xorlw 0x02 btfss STATUS,Z goto RFIDReset ;if not 02, reset and exit call RFIDReset ;if 02, reset and continue ;clear new rfid flag banksel RFIDNewData bcf RFIDNewData,0 banksel RFIDMachineState incf RFIDMachineState,f ;set state to waiting for data return ;return to loop ;State: WaitingForData RFIDState_Data banksel RFID_Read movf RFID_Read,W call ASCIItoHex ;Call ASCIItoHex function on RFID_READ banksel RFIDNibbleIndicator btfsc RFIDNibbleIndicator,0 ;If NibbleIndicator is High swapf Hex_Nibble,f ;make nibble MSB. Using SWAPF, whatup!? ;Add Nibble to RFID_Byte(RFIDByteCounter) movlw RFID_ByteArray ;access array of rfid bytes banksel RFIDByteCounter addwf RFIDByteCounter,W ;index array on byte counter movwf FSR ;store target index banksel RFIDNibbleIndicator btfsc RFIDNibbleIndicator,0 ;If NibbleIndicator is high, new byte clrf INDF ;clear indexed byte banksel Hex_Nibble movf Hex_Nibble,W ;load nibble to add to indexed byte addwf INDF,f ;add nibble to byte ;Swap RFIDNibbleIndicator banksel RFIDNibbleIndicator comf RFIDNibbleIndicator,f ;If RFIDNibbleIndicator is high, prepare for new byte btfss RFIDNibbleIndicator,0 return ;return to loop otherwise #ifdef RFIDdebug ;output to UART if byte index is 2, 3, or 4 for checkoff movf RFIDByteCounter,W sublw 0x02 btfsc STATUS,Z goto Output movf RFIDByteCounter,W sublw 0x03 btfsc STATUS,Z goto Output movf RFIDByteCounter,W sublw 0x04 btfsc STATUS,Z goto Output goto Continue Output: banksel RFIDChecksum movf INDF,w ;load recent completed byte to w btfsc PIR1,TXIF movwf TXREG #endif Continue: banksel RFIDChecksum movf INDF,w ;load recent completed byte to w xorwf RFIDChecksum,f ;bitwise add byte to checksum banksel RFIDByteCounter decfsz RFIDByteCounter,f ;decrement byte counter return ;return to loop if not 0 ;if byte counter reached 0, we finished with checksum ;check checksum: banksel RFIDChecksum movf RFIDChecksum,f ;if checksum is 0, then Z=1 btfss STATUS,Z goto RFIDReset ;if bad checksum, bail on transfer, return to loop banksel RFIDMachineState incf RFIDMachineState,f ;set state to waiting for end byte return ;return to loop ;State:: Waiting for End RFIDState_End: ;check if RFID_Read is 0x03 banksel RFID_Read movf RFID_Read,W xorlw 03 btfss STATUS,Z ;if not goto RFIDReset ;exit loop, reset state to waiting for message ;otherwise banksel RFIDNewData bsf RFIDNewData,0 ;set new data flag banksel SSPBUF movlw SPI_Header movwf SSPBUF ;put header in buffer banksel SPI_Index movlw 0x05 movwf SPI_Index ;start counter at 3 banksel SPI_RequestPort bsf SPI_RequestPort,SPI_RequestBit ;indicate ready to send ;turn on debug led banksel DebugPort bsf DebugPort,DebugLED goto RFIDReset ;exit loop, reset state to waiting for message ; Convert ASCII byte to Hex nibble ASCIItoHex: banksel ASCII_Byte movwf ASCII_Byte ;if ascii byte > 40, add 9 sublw 0x40 movlw 0 btfss STATUS,C movlw 9 addwf ASCII_Byte,W ;get lower nibble andlw 0x0F banksel Hex_Nibble movwf Hex_Nibble return end