;******************************************************************* ;dbt_speed_meas ;Derbot wheel speed is measured by frequency counting. This is a demo ;program. The frequency measurement concept can be embedded into larger ;programs, eg for speed control. ;TJW 7.7.05 Tested 11.7.05 ;******************************************************************* ;Clock is 4MHz ;Timer 0 counts left motor, Timer 1 right. ;CCP2 drives left motor, CCP1 drives right. ; list p=16F873A #include p16f873A.inc ; ;Set Configuration Word: crystal oscillator HS, WDT off, ; power-up timer on, code protect off, LV Program off. __CONFIG _HS_OSC & _WDT_OFF & _PWRTE_ON & _LVP_OFF ; ;Specify RAM delcntr1 equ 20 ;used in delay5 & delayADC SRs delcntr2 equ 21 int_cntr equ 22 tmr0_temp equ 23 ;used to develop left PWM op value tmr1_temp equ 24 ;used to develop right PWM op value flags equ 29 ;0 is L motor has completed, 1 for rt motor ;Specify some port bits ;For Port A mot_en_rt equ 2 mot_en_left equ 5 ;For Port B sounder equ 1 ;piezo electric sounder us_rt equ 6 ;right microswitch us_left equ 7 ;left microswitch ;For PortC mot_left equ 1 ;left motor direction bit, 1=forward mot_rt equ 2 ;right motor direction bit led_rt equ 5 ;diagnostic led led_left equ 6 ;diagnostic led mode equ 7 ;mode switch org 00 goto main org 04 goto Timer2_Int ;Initialise ;set up SFRs in Bank 1 main bcf status,rp1 bsf status,rp0 ;select memory bank 1 movlw B'00011011' ;set port A bits, bit 4 ip for opto movwf trisa movlw B'11001000' movwf trisb ;also port B bits movlw B'10000001' movwf trisc ;and port C bits, bit 0 ip for opto movlw B'01000100' movwf adcon1 ;select port A bits 0,1,3 for analog input, others digital movlw B'11101000' ;set up Timer 0: external input, low to high transition, ;no prescale movwf option_reg movlw D'250' ;set PWM prd movwf pr2 bsf pie1,tmr2ie ;enable Timer 2 interrupt ;set up SFRs in Bank 0 bcf status,rp0 ;select bank 0 movlw B'00000011' ;set up Timer 1: no prescale, oscillator disabled, movwf t1con ;external sync input movlw B'01111100' ;switch on Timer2, no prescale, /16 postscale movwf t2con movlw B'00001100' ;enable PWM movwf ccp1con movwf ccp2con ; ;Switch all outputs off clrf porta clrf portb clrf portc ;diagnostic, flash leds bsf portc,6 bsf portc,5 call delay500 bcf portc,6 bcf portc,5 ; ;clear timers clrf tmr0 clrf tmr1l clrf tmr1h ;set interrupts movlw D'250' ;load interrupt counter movwf int_cntr bcf pir1,tmr2if ;clear pending interrupt bsf intcon,peie ;enable peripheral interrupt bsf intcon,gie ;enable global interrupt ; ;start running, and wait for Timer interrupt movlw D'200' ;set PWM rate for reasonable forward speed. movwf ccpr1l movwf ccpr2l bsf portb,2 ;switch on optos bsf porta,mot_en_left ;enable motors bsf porta,mot_en_rt wait goto wait ; ;********************************************************************* ;ISR is here. Interrupts occur every 4ms. Count 250 (i.e.1.0s), then ;measure pulse count on each wheel. ;********************************************************************* Timer2_Int bsf portc,5 ;diagnostic decfsz int_cntr goto int_end ;here if making a measurement movf tmr0,0 ;save counter values movwf tmr0_temp movf tmr1l,0 movwf tmr1_temp clrf tmr0 ;clear counters clrf tmr1l movlw D'250' ;reload interrupt counter movwf int_cntr int_end bcf pir1,tmr2if bcf portc,5 ;diagnostic retfie ;********************************************************* ;SUBROUTINES ;********************************************************* ; ;introduces delay of 1ms approx delay1 movlw D'250' ;250 cycles called, ;each taking 4us movwf delcntr1 del1 nop ;4 inst cycles in this loop, ie 4us decfsz delcntr1,1 goto del1 return ;500ms delay (approx) - 500 calls to delay1 delay500 movlw D'250' movwf delcntr2 del5 call delay1 call delay1 decfsz delcntr2,1 goto del5 return ; end