title "asmMotor 2 - DC Motor Control using a TMR0 Timebase"
;
; This Program Monitors a Pot at RA3 (RA3) and moves a
; DC Motor Accordingly. Values less than 0x80 move the
; motor in reverse while Values greater than 0x80 move
; the motor forwards. When the Pot is at an extreme, the
; Software PWM moves at full speed.
;
; Hardware Notes:
; PIC16F684 running at 4 MHz Using the Internal Clock
; RA4 - Pot Command
; RC5/P1A - Motor Forwards High
; RC4/P1B - Motor Reverse PWM (on Low)
; RC3/P1C - Motor Reverse High
; RC2/P1D - Motor Forwards PWM (on Low)
;
;
; Myke Predko
; 05.01.10
;
#INCLUDE <P16F88.INC>
__CONFIG _CONFIG1, _CP_OFF & _CCP1_RB0 & _DEBUG_OFF & _WRT_PROTECT_OFF & _CPD_OFF & _LVP_OFF & _BODEN_OFF & _MCLR_ON & _PWRTE_OFF & _WDT_OFF & _INTRC_IO
__CONFIG _CONFIG2, _IESO_OFF & _FCMEN_OFF
; Variables
CBLOCK 0x20
Direction
ADCState, ADCValue
PWMDuty, PWMCycle
ENDC
PAGE
; Mainline
org 0
nop ; For ICD Debug
movlw b'010111' ; Set PORTB According to
movwf PORTB ; Operating Parameters
movlw 7 ; Turn off Comparators
movwf CMCON
movlw b'00001101' ; Enable ADC on RA4
movwf ADCON0
clrf TMR0 ; Using TMR0 as a PWM Base
bsf STATUS, RP0
movlw b'11010001' ; 1:4 Prescaler to TMR0
movwf OPTION_REG ^ 0x80;
movlw 1 << 3 ; RA4 (AN3) ADC Input
movwf ANSEL ^ 0x80
movlw b'00010000' ; Select ADC Clock as Fosc/8
movwf ADCON1 ^ 0x80
bcf STATUS, RP0
bcf INTCON, TMR0IF ; Wait for TMR0 to Overflow
clrf ADCState
clrf PWMDuty ; Not Moving at First
clrf PWMCycle ; Start at the Beginning
clrf Direction ; Moving Forwards
Loop:
btfss INTCON, TMR0IF ; Wait for Timer Overflow
goto $ - 1
bcf INTCON, TMR0IF ; Reset and Wait for Next
btfsc ADCState, 0 ; Start or Read ADC?
goto ADCRead
bsf ADCON0, GO ; Start ADC Read
bsf ADCState, 0 ; Next State
goto ADCDone
ADCRead: ; Read the ADC Value
movf ADRESH, w
movwf ADCValue
clrf ADCState ; Original State
ADCDone: ; Process ADC Value
movlw 0x80 ; Forwards or Reverse?
subwf ADCValue, w
btfss STATUS, C ; Less than 0x80 go in Reverse
goto MotorReverse
MotorForwards:
movwf PWMDuty
bcf STATUS, C ; Convert the Value from 7 Bits
rrf PWMDuty, f ; to 5
bcf STATUS, C
rrf PWMDuty, f
clrf Direction ; Move Forwards
goto MotorUpdate
MotorReverse:
movlw 0x7F ; Cheesy 7 Bit Negation of the
xorwf ADCValue, w ; Reverse CCPR1L Value
movwf PWMDuty
bcf STATUS, C ; Convert the Value from 7 Bits
rrf PWMDuty, f ; to 5
bcf STATUS, C
rrf PWMDuty, f
movlw 1
movwf Direction ; Move Backwards
MotorUpdate: ; Check to Update the Motor
movf PWMDuty, w ; If Duty > Cycle, then Off
subwf PWMCycle, w
movlw b'011011' ; TRISB Forwards
btfsc Direction, 0 ; Forwards or Reverse?
movlw b'100111' ; TRISB Reverse
btfsc STATUS, C
movlw b'111111' ; Turn off Motors?
bsf STATUS, RP0
movwf TRISB ^ 0x80
bcf STATUS, RP0
incf PWMCycle, f ; Increment the PWM Cycle Count
bcf PWMCycle, 5 ; Maximum of 32 States
goto Loop ; Finished, Loop Around Again
end