;******************************************************************
; *
; Filename: 16F1823 Servo Steering.asm *
; Author: Mike McLaren, K8LH *
; (C)2012: Micro Application Consultants *
; : All Rights Reserved *
; Date: 29-Jan-12 *
; *
; 16F1823 four channel PWM "Servo Steering" experiment *
; *
; *
; MPLab: 8.80 (tabs=8) *
; MPAsm: 5.43 *
; *
;******************************************************************
#include <P16F1823.INC>
radix dec
errorlevel -302
list st=off
__CONFIG _CONFIG1, _FOSC_INTOSC & _WDTE_OFF & _MCLRE_OFF
__CONFIG _CONFIG2, _BORV_LO & _LVP_OFF & _PLLEN_OFF
;
; _PWRTE_OFF default
; _CP_OFF default
; _CPD_OFF default
; _BOREN_ON default
; _CLKOUTEN_OFF default
; _IESO_ON default
; _FCMEN_ON default
;
; _WRT_OFF default
; _STVREN_ON default
;
;--< variables >---------------------------------------------------
cblock 0x020 ; bank 0 ram
servo:8 ; 500..2500 (usecs)
width:2 ; isr work variable
frame ; frame counter, 0..20
steer ; steering bit mask
index ; servo channel index, 0..3
endc
;
; servo[0] -> RC5 (pin 5)
; servo[1] -> RC4 (pin 6)
; servo[2] -> RC3 (pin 7)
; servo[3] -> RC2 (pin 8)
;
;******************************************************************
; reset vector *
;******************************************************************
org 0x0000
v_reset
banksel ANSELA ; bank 3 |B3
clrf ANSELA ; set digital I/O |B3
bra init ; |B3
;******************************************************************
; interrupt vector *
;******************************************************************
org 0x0004
;
; void interrupt() // 250-uS (1000 cycle) interrupts
; { pir1.TMR2IF = 0; //
; if(width >= 250) //
; ccpr1l = 250; //
; else //
; ccpr1l = width; //
; width -= ccpr1l; //
;
; pstr1con = steer | (1<<STR1SYNC);
;
v_int
bcf PIR1,TMR2IF ; clear TMR2 interrupt flag |B0
movlw low(250) ; |B0
subwf width+0,W ; |B0
movlw high(250) ; |B0
subwfb width+1,W ; |B0
movf width+0,W ; |B0
skpnc ; borrow? yes, skip, else |B0
movlw 250 ; |B0
banksel CCPR1L ; bank 5 |B5
movwf CCPR1L ; duty cycle for next frame |B5
movlb 0 ; bank 0 |B0
subwf width+0,F ; |B0
movlw 0 ; |B0
subwfb width+1,F ; |B0
movf steer,W ; |B0
iorlw 1<<STR1SYNC ; |B0
banksel PSTR1CON ; |B5
movwf PSTR1CON ; steering for next frame |B5
movlb 0 ; bank 0 |B0
;
; if(--frame == 0) // if end of 5 ms period
; { frame = 20; // reset 5 ms counter and
; if(!(steer >>= 1)) // if last channel
; steer = 8; // reset for channel 0
; width = servo[index]; // new servo 'width'
; index++; index.2 = 0; // next channel index, 0..3
; }
; }
;
decfsz frame,F ; next servo? yes, skip, else |B0
retfie ; |B0
movlw 20 ; twenty 250 us periods |B0
movwf frame ; reset 5-msec counter |B0
lsrf steer,F ; last channel? |B0
skpnc ; no, skip, else |B0
bsf steer,3 ; reset to '00001000' |B0
lslf index,W ; index 0..3 -> 0..6 |B0
addlw servo ; add 'servo' array address |B0
movwf FSR0L ; |B0
clrf FSR0H ; |B0
moviw FSR0++ ; width = servo[index] |B0
movwf width+0 ; |B0
moviw FSR0++ ; |B0
movwf width+1 ; |B0
incf index,F ; bump index, 1..4 |B0
bcf index,2 ; 0..3 inclusive |B0
retfie ; |B0
;******************************************************************
; main.init *
;******************************************************************
;
; void main() //
; { ansela = 0; // digital I/O
; osccon = 0b01111010; // intosc = 16 MHz
; while(!oscstat.HFIOFS); // wait for osc stable
;
init
banksel OSCCON ; bank 1 |B1
movlw b'01111010' ; 16-MHz (no pll) |B1
movwf OSCCON ; setup 16-MHz INTOSC |B1
waitfs btfss OSCSTAT,HFIOFS ; stable? yes, skip, else |B1
bra waitfs ; branch and wait |B1
;
; // configure ports
;
; trisa = 0b00001000; // RA3 input
; trisc = 0b00000000; // RC5-RC0 all outputs
; lata = 0; //
; latc = 0; //
;
movlw b'00001000' ; |B1
movwf TRISA ; RA3/RX input, others outputs |B1
clrf TRISC ; RC5..RC0 outputs |B1
banksel LATA ; bank 2 |B2
clrf LATA ; |B2
clrf LATC ; |B2
;
; // initialize program variables
;
; unsigned char steer = 1; //
; unsigned char index = 0; //
; unsigned char frame = 1; //
; unsigned int width = 0; //
;
; unsigned int servo[] = { 1500, 1500, 1500, 1500 };
;
movlb 0 ; bank 0 |B0
movlw b'00000001' ; |B0
movwf steer ; steer = 0b00000001 |B0
clrf index ; |B0
clrf width+0 ; width = 0 |B0
clrf width+1 ; |B0
movlw 1 ; |B0
movwf frame ; frame = 1 |B0
movlw 1500%256 ; |B0
movwf servo+0 ; servo[0] = 1500 |B0
movwf servo+2 ; servo[1] = 1500 |B0
movwf servo+4 ; servo[2] = 1500 |B0
; movwf servo+6 ; servo[3] = 1500 |B0
movlw 1500/256 ; |B0
movwf servo+1 ; |B0
movwf servo+3 ; |B0
movwf servo+5 ; |B0
; movwf servo+7 ; |B0
movlw 500 ; servo[3] = 500 |B0
movwf servo+6 ; |B0
clrf servo+7 ; |B0
;
; // setup PWM for a 250 us (1000 cycle) period (16 MHz clock)
;
; ccp1con = 0b00001100; // active hi PWM mode
; pstr1con = 1<<STR1SYNC; // synchronous steering
; ccpr1l = 0; // 0% duty cycle initially
; tmr2 = 0; // clear TMR2
; t2con = 0b00000101; // -0000--- TOUTPS post 1:1
; // -----1-- TMR2ON -> "on"
; // ------01 T2CKPS prescale 4
; // for 1 usec 'ticks'
; pr2 = 250-1; // 250 us interrupts
; pie1.TMR2IE = 1; // enable TMR2 interrupts
; pir1 = 0; // clear peripheral int flags
; intcon = 1<<GIE|1<<PEIE; // enable interrupts
;
banksel CCP1CON ; bank 5 |B5
movlw b'00001100' ; 00------ P1M |B5
; --00---- DC1B duty cycle lsb's |B5
; ----1100 CCP1M active hi PWM |B5
movwf CCP1CON ; setup module for active hi PWM |B5
movlw 1<<STR1SYNC ; |B5
movwf PSTR1CON ; use synchronous steering |B5
clrf CCPR1L ; 0% duty cycle |B5
banksel TMR2 ; bank 0 |B0
clrf TMR2 ; |B0
movlw b'00000101' ; -0000--- TOUTPS post 1:1 |B0
; -----1-- TMR2ON timer 2 "on" |B0
; ------01 T2CKPS prescale 4 |B0
movwf T2CON ; for 1 usec (4 cycle) ticks |B0
movlw 250-1 ; |B0
movwf PR2 ; for 250 us period |B0
banksel PIE1 ; bank 1 |B1
bsf PIE1,TMR2IE ; enable TMR2 interrupts |B1
banksel PIR1 ; bank 0 |B0
clrf PIR1 ; clear all interrupt flags |B0
movlw 1<<GIE|1<<PEIE ; |B0
movwf INTCON ; global & peripheral ints on |B0
;******************************************************************
; main.loop *
;******************************************************************
;
; while(1); //
; }
;
loop
bra loop ; |B0
;******************************************************************
end