Beginners: please read this post and this post before posting to the forum.
0 Members and 1 Guest are viewing this topic.
;; Author: Barnaby Walters; Created: 27th March 2011; ; For PIC: 16F886; Default Radix: Hex;; Description: Contains the IR enable/detect loop. Lights different LEDs to indicate which direction an object is seen in; Runs at 4MHz ; ; Currently: The interrupt handler gets called, but not all of the logic works properly;; * * * * * * * * * * * * * * * *list p=16f886include p16f886.inc ; Set up 16F886 Config Registers __CONFIG _CONFIG1, _MCLRE_OFF & _WDT_OFF & _INTRC_OSC_NOCLKOUT & _BOR_ON & _CP_OFF & _DEBUG_OFF & _LVP_OFF & _FCMEN_OFF & _IESO_OFF & _CPD_OFF ; For Config Bank 1: No MCLR Reset, no WDT, int. Osc no clkout, BOR On, Code protection, Low voltage protection, essentially, very few features. __CONFIG _CONFIG2, _BOR40V & _WRT_OFF ; Set the BOR voltage to 4v, and we don't want any write protection ; Reserve Variablestmr1 equ 20h ; Debugtmr2 equ tmr1 + 1temp equ tmr2 + 1 IRData equ temp + 1w_temp equ IRData + 1status_temp equ w_temp + 1#define ls 0#define rs 1#define ll 2#define rl 3 ; IRData structure: 7:4 = N/A; 3 = Right Lit; 2 = Left Lit; 1 = Right Signal; 0 = Left Signal;firstAvailableRegister equ 0x20 org 0h nop ; Allows ICD2 Debugger to work - not that I'm using that. goto main ; Start main program org 4h goto isrRoutineinclude "/Users/barnabywalters/Documents/Electronics/PIC Programs/16F886/Weave.inc" ; Port/Useful Definitions; Interrupt Service Routine isrRoutine movwf w_temp movf STATUS,w movwf status_temp ; Save context; Actual ISR btfsc IRData,ll ; Is left emittor lit? bsf IRData,ls ; If yes, store a signal received to the left btfsc IRData,rl ; Is right emittor lit? bsf IRData,rs ; If yes, store a signal received to the right bsf portc,hb ; Light HB LED bcf INTCON,INTF ; Clear interrupt flag movf status_temp,w ; Restore context movwf STATUS swapf w_temp,f swapf w_temp,w retfie ; Return ; * * * * * * * * * * * SUBROUTINES * * * * * * * * * * * * * * *; Initalisation Routineinit clrf PORTA clrf PORTB clrf PORTC banksel OSCCON ; switches to bank 1. We need to be here to mess about with TRIS registers movlw b'01100001' ; movwf OSCCON ; Osc Config: 0 (un) , 110 (4Mhz) , 000 (Rd Only) , 1 (Use internal Clk) movlw b'00000000' ; movwf TRISA ; PORTA = all outputs. A0 = Right indicator A1 = Left Indicator movlw b'00000001' ; movwf TRISB ; PORTB 0:3 used. B1 = Right Enable B2 = Left Enable B0 = Sensor Input movwf WPUB ; Weak pull-up on RB0 movlw b'00000000' ; movwf TRISC ; PORTC = outputs. C3 = HB LED. Motors not used in this app (yet) movlw b'1000' movwf TRISE ; PORTE 3 (MCLR) = Input banksel ANSELH bcf ANSELH,4 banksel OPTION_REG bcf OPTION_REG,NOT_RBPU ; Enable RB Pull Ups bcf OPTION_REG,INTEDG ; Interrupt triggered on falling edge @ RB0 movlw b'10010000' movwf INTCON ; Enable unmasked interrupts, Enable interrupt on RB0 banksel PORTA ; Switch to bank 0 so we can move on with the program return ; Return to the program; Delay Routines:D30IRCycles ; Delays program flow for 30 cycles @ 38kHz — 'On' time for IREDs movlw d'2' movwf tmr2 movlw d'130' ; 30 IR Cycles = 780 instruction cycles. GOTO = 2 instruction cycles movwf tmr1 ; This timer will have to be completely decremented two times for the full 780 cyclesD30IR_Delay decfsz tmr1,F goto D30IR_Delay ; Cycle 195 times movwf tmr1 decfsz tmr2,F goto D30IR_Delay ; Go back and cycle twice return D15IRCycles ; Delays program flow for 15 cycles @ 38kHz — 'Off' time for IREDs movlw d'195' ; GOTO = 2 cycles. 2 * 195 = 390 instructions = 15 IR Cycles movwf tmr1D15IR_Delay decfsz tmr1,f goto D15IR_Delay return ; Look-Up Tables:motorControlLUT movf IRData,w andlw b'11' ; Mask off the bits we're interested in (1:0) movwf temp ; Store offset movlw high tableStart ; Get the high order part of address of tableStart movwf PCLATH ; movlw low tableStart ; Get low order address of tableStart addwf temp, w ; Add the offset btfsc STATUS, C ; Did it overflow? incf PCLATH,f ; If yes, add one to PCLATH movwf PCL ; Modify PCL and use the table…tableStart goto forwards goto softbackright goto softbackleft goto hardleft; * * * * * * * * * * Main Program * * * * * * * * * *main call init ; Set up ports, etc ; Program structure: Constantly alternate between IR LEDs. Each one on for 30 cycles, the off for 15 cycles as per datasheet sensorPollLoop bcf portc,hb ; Turn of HB LED call D15IRCycles ; — — — — — — — Hold LEDs off for the required time — — — — — — — bsf PORTB,2 ; Turn on the left IRED (Robot perspective) bsf IRData,ll ; Left IRED currently emitting. call D30IRCycles ; Hold it on for a certain amount of time bcf IRData,ll ; Left IRED not currently emitting bcf PORTB,2 ; Turn off the left IRED call D15IRCycles ; — — — — — — — Hold LEDs off for the required time — — — — — — — bsf PORTB,1 ; Turn on the right IRED (Robot perspective) bsf IRData,rl ; Right IRED currently emitting call D30IRCycles ; Hold it on for a certain amount of time bcf IRData,rl ; Right IRED not currently emitting bcf PORTB,1 ; Turn off the right IRED ; — — — — — — — One complete sensor poll finished — — — — — — — ; Now: See what data we have. For the moment, that means copying the data in IRData 3:2 to PORTA 3:2. How convenient… movf IRData,w ; Pop value of IRData into the W. Reg… movwf PORTA ; …and copy it into PORTA. Sorted! That's indicated the direction the signal was found in. bcf INTCON,GIE ; Disable interrupts while sorting out motor control call motorControlLUT ; Get the motor control signal required from the LUT movwf PORTC ; Move the signal into PORTC bsf INTCON,GIE ; Enable interrupts again clrf IRData ; Clear data from last sensor poll loop execution goto sensorPollLoop end
Thanks for posting to code. It looks rather nicely done with lots of comments. I saved myself a copying.
Just a suggestion:I now like to put a list on the PIC pins with the function they are being used for in the code. I started doing that when I went to use code I wrote a year before and wanted to build a new board. Took me a couple of hours to go through the code to determine what each pin was used for.
LIST ; Weave Include File (Weave.inc); – Contains port/pin names to make programming Weave easier, as well as abstract subroutines for motor operations NOLISTportc equ PORTC#define t1i 0 ; TMR1 Clock Input#define m1e 1 ; Motor 1 = Left Motor#define m2e 2 ; Motor 2 = Right Motor#define hb 3 ; Heart Beat LED#define m2f 4#define m2b 5#define m1f 6#define m1b 7portb equ PORTB#define int 0 ; External Interrupt Pinforwards movlw b'01010110' movwf portc returnbackwards movlw b'10100110' movwf portc returnbrake movlw b'11110110' movwf portc returncoast movlw b'11110000' movwf portc returnsoftleft movlw b'00010100' movwf portc returnsoftright movlw b'01000010' movwf portc returnsoftbackleft movlw b'01100100' movwf portc returnsoftbackright movlw b'10010010' movwf portc returnhardleft movlw b'10010110' movwf portc returnhardright movlw b'01100110' movwf portc return LIST