Code:
Device 16F876A
Config HS_OSC, WDT_OFF, PWRTE_OFF
Xtal = 20
ON_INTERRUPT ipwm
' Assign some Interrupt associated aliases
SYMBOL T0IE = INTCON.5 ' TMR0 Overflow Interrupt Enable
SYMBOL T0IF = INTCON.2 ' TMR0 Overflow Interrupt Flag
SYMBOL GIE = INTCON.7 ' Global Interrupt Enable
SYMBOL PS0 = OPTION_REG.0 ' Prescaler ratio bit-0
SYMBOL PS1 = OPTION_REG.1 ' Prescaler ratio bit-1
SYMBOL PS2 = OPTION_REG.2 ' Prescaler ratio bit-2
SYMBOL PSA = OPTION_REG.3 ' Prescaler Assignment (1=assigned to WDT 0=assigned to oscillator)
SYMBOL T0CS = OPTION_REG.5 ' Timer0 Clock Source Select (0=Internal clock 1=External PORTA.4)
Declare ADIN_RES 10 ' Set number of bits in result
Declare ADIN_TAD FRC ' Set clock source (3=rc)
Declare ADIN_STIME 10 ' Set sampling time in uS (was 50)
Declare LCD_TYPE ALPHA
Declare LCD_DTPIN PORTC.0
Declare LCD_ENPIN PORTC.5
Declare LCD_RSPIN PORTC.4
Declare LCD_INTERFACE 4
Declare LCD_LINES 2
symbol GLED portb.5
symbol PWMCYLEN 60
symbol M1F portb.4
symbol M1B portb.6
symbol M2F portb.2
symbol M2B portc.7
dim i as dword
dim j as dword
dim h as dword
dim k as dword
dim asenscalib as word
dim asensor as dword
dim potval as word
dim angle as dword
dim oldangle as dword
dim arate as dword
dim speed as dword
dim oldspeed as dword
dim spdout as byte
dim torque as dword
dim ptime as word
dim aCon as word
dim arCon as dword
dim pwmm1spd as byte
dim pwmm2spd as byte
dim pwmcycle as word
dim incr as dword
dim cpause as byte
' PWM interrupt handler variables
dim intCount as byte
dim direction as byte
GOTO overInterrupt
EDATA word 500, word 701, word 696, word 10, word 10
' Interrupt routine starts here
ipwm:
asm
movfw pwmm1spd
subwf intCount, w
btfsc STATUS, C
goto PWMOFF
PWMON:
movlw 1
subwf direction, w
btfsc STATUS, Z
goto FORWARD
bcf M1B
bsf M1F
bcf M2F
bsf M2B
goto DONEPWM
FORWARD:
bcf M2B
bsf M2F
bcf M1F
bsf M1B
goto DONEPWM
PWMOFF:
; Turn everything off
bcf M1F ; Since this is the down part of the cycle
bcf M1B ; Easier to turn everything off than test
bcf M2F ; which motors to turn off...
bcf M2B
DONEPWM:
decfsz intCount, 1 ; Decrement intCount
goto intDoneStuff ; if NOT ZERO, then jump to intDoneStuff
movlw 255 ; otherwise (if 0)... 255 into w
movwf intCount ; reset counter
intDoneStuff:
bcf T0IF ; Clear the TMR0 overflow flag
endasm
CONTEXT RESTORE ' Restore the registers and exit the interrupt
overInterrupt:
TRISB = %10000011
TRISC = $00
TRISA = $FF
ADCON1 = %10000001
M1F = 0 ' Turn all motors off
M1B = 0
M2F = 0
M2B = 0
portb.2 = 0
delayms 25 ' Wait for display (is this necessary?)
print $FE, 1, " Hello" ' Clear display and show Hello
delayms 333
print $FE, 1 ' Clear display
pwmm1spd = 40
pwmm2spd = 40
intCount = 255
' Initiate the interrupt
GIE = 0 ' Turn off global interrupts
PSA = 1 ' Assign the prescaler to external oscillator
PS0 = 0 ' Set the prescaler
PS1 = 0 ' to increment TMR0
PS2 = 0 ' every 256th instruction cycle
T0CS = 0 ' Assign TMR0 clock to internal source
TMR0 = 0 ' Clear TMR0 initially
T0IE = 1 ' Enable TMR0 overflow interrupt
GIE = 1 ' Enable global interrupts
asenscalib = eread 0
ADIN 0, aCon
ADIN 2, arCon
aCon = aCon / 12
arCon = arCon * 35
oldspeed = 0
oldangle = 0
speed = 0
pwmcycle = 0
PORTB.5 = 0
incr = 1
i = 0
cpause = 0
delayms 10
loop:
while PORTB.7 = 1 ' Then we're in calibrate mode
''''''''''' test code
ADIN 0, potval
pwmm1spd = potval >> 2
'''''''''''''''''''''''''''''''''''''''
' M1F = 0 ' Turn all motors off
' M1B = 0
' M2F = 0
' M2B = 0
speed = 0 ' Reset values in case we've already been running...
arate = 0
oldangle = 0
ADIN 1, asensor
ADIN 0, aCon
ADIN 2, arCon
aCon = aCon / 12
arCon = arCon * 35
if arCon < 0 then
print at 1, 1, "aK:", #aCon, " arK:-", #arCon, "(/10k)"
else
print at 1, 1, "aK:", #aCon, " arK:", #arCon, "(/10k)"
endif
print 2, 1, "clb : ", #asensor, " (", #asenscalib, ")"
if PORTB.1 = 1 then
asenscalib = asensor
ewrite 0, [asenscalib]
endif
wend
' END OF CALIBRATION
' BALANCING ALGORITHM
direction = 1
ADIN 0, potval
pwmm1spd = potval >> 2
goto loop
end
Bookmarks