Registered Member #49
Joined: Thu Feb 09 2006, 04:05AM
Location: Bigass Pile of Penguins
Posts: 362
|
Anyone up for a thread of useful PIC code, or the code you find yourself writing over and over?
I'll start.
This .asm file is one I use often for projects that need hobby servo (PWM) output. If you're running a 20MHz clock on a pic the 20ms timing for a servo is a bit awkward since its larger than the maximum PIC interrupt timer interval.
This code solves that by resetting the interrupts automatically as required to give the proper PWM spacing. Simply move a value from 0 to 255 into the Thtl1 and Thtl2 registers and PORTB 0 and 1 will have proper PWM output.
Your code can be inserted into the main loop and will run in between pulses (i.e. around 20ms of every 22ms).
LIST P=16F777 ; Use the PIC16F628 and decimal system
#include "P16F777.INC" ; Include header file
;memory addresses start with 20h/32 (dec)
T1 equ 0x22
T2 equ 0x23
Int_Flag equ 0x2E
PWM1 equ 0x2F
PWM2 equ 0x30
PWM3 equ 0x31
Thtl1 equ 0x32
Thtl2 equ 0x33
W_TEMP equ 0x7E
STATUS_TEMP equ 0x7F
ORG 0x000
goto Main_Start
ORG 0x004
goto Interrupt_Start
Main_Start
;***********************
;***********************
;Initialization
;***********************
;***********************
;*** Configure PORTB
BSF STATUS, RP0
bcf PORTB, 0 ;Throttle 1 output
bcf PORTB, 1 ;Throttle 2 output
bcf STATUS, RP0
;*** Enable TMR0
clrf TMR0
bsf STATUS, RP0
movlw b'11000111'
movwf OPTION_REG
bcf STATUS, RP0
clrf INTCON
bsf INTCON, GIE
bsf INTCON, TMR0IE
movlw D'2'
movwf Int_Flag
;***********************
;***********************
;Main Program
;***********************
;***********************
;*** Main loop
mainloop
;***********************
;***********************
;YOUR CODE HERE!!
;***********************
;***********************
goto mainloop
;***********************
;***********************
;Utility Functions
;***********************
;***********************
;*** Adjustable delay
Pause movwf T2
Pstart movlw d'255'
movwf T1
Ploop decf T1
btfss STATUS, Z
goto Ploop
decf T2
btfss STATUS, Z
goto Pstart
return
;*** TMR 0 Interrupt
Interrupt_Start
MOVWF W_TEMP ;Copy W to TEMP register
SWAPF STATUS, W ;Swap status to be saved into W
CLRF STATUS ;bank 0, regardless of current bank, Clears IRP,RP1,RP0
MOVWF STATUS_TEMP ;Save status to bank zero STATUS_TEMP register
bcf INTCON, TMR0IF ;clear interrupt
decf Int_Flag ;dec flag
btfsc STATUS, Z
goto Flag0
Flag1 bsf STATUS, RP0 ;Change Prescaler
movlw b'11000110' ;128
movwf OPTION_REG
bcf STATUS, RP0
clrf INTCON
bsf INTCON, GIE
bsf INTCON, TMR0IE
goto ExitInt
Flag0 movlw D'2'
movwf Int_Flag
bsf STATUS, RP0 ;Change Prescaler
movlw b'11000111' ;256
movwf OPTION_REG
bcf STATUS, RP0
clrf INTCON
bsf INTCON, GIE
bsf INTCON, TMR0IE
;do high pulse loop (5000inst/ms)
movlw D'255'
movwf PWM1
movlw D'6'
movwf PWM2
bsf PORTB, 0
bsf PORTB, 1
Pulse0 decfsz PWM1 ;1 --- 3 * 255 = 765 * 6 = .916ms
goto Pulse0 ;2
decfsz PWM2
goto Pulse0
;remainder loops (6000 inst/255 thtl)
movfw Thtl1
movwf PWM1
movfw Thtl2
movwf PWM2
Pulse1 decf PWM1 ;1
btfsc STATUS, Z ;2
bcf PORTB, 0
decf PWM2 ;1
btfsc STATUS, Z ;2
bcf PORTB, 1
movlw D'6'
movwf PWM3
Pulse2 decfsz PWM3 ;1
goto Pulse2 ;2
btfsc PORTB, 0
goto Pulse1
btfsc PORTB, 1
goto Pulse1
ExitInt
SWAPF STATUS_TEMP, W ;Swap STATUS_TEMP register into W
;(sets bank to original state)
MOVWF STATUS ;Move W into STATUS register
SWAPF W_TEMP, F ;Swap W_TEMP
SWAPF W_TEMP, W ;Swap W_TEMP into W
RETFIE
END
|