Code:
DEFINE OSC 20
Phase VAR BYTE[3] ' Array used as pointers into lookuptable.
DutyCycle VAR WORD[3] ' Array storing the dutycycles retreived from the table
Temp VAR WORD ' Temporary variable to avoid hard to understand array indexing
i VAR BYTE ' General purpose counter
led VAR PORTC.4
TRISC.2 = 0 ' Set PORTC.2 (CCP1) to output
TRISC.1 = 0
CCP1CON = %00001100 ' Set CCP1 to PWM
CCP2CON = %00001100
T2CON = %00000101 ' Turn on Timer2, Prescale=4
PR2 = 249 ' Set PR2 to get 5KHz out
TRISB.0 = 1 'set port bo to input
' The lookup table has 45 entries long, to get 120° phase shift we need to
' "start" the second phase at 1/3 of the cycle and the third phase at 2/3
' of the table. 45/3=15 so first phase starts at 0, second phase at 15
' and third phase at 30.
' Initilise pointers.
Phase[0] = 0 : Phase[1] = 15
High PORTC.3 'Set the initial state for portc.3
Low PORTC.0 'Same
High PORTC.6 'Same
Low PORTC.5 'Same
High PORTC.4
ON INTERRUPT GoTo faultsignal
INTCON = %10010000 'Enable RB0 INTERRUPT
OPTION_REG.6 = 0 'Interrupt on rising edge of RB0/INT pin
Main:
IF PORTB.0 = 1 Then 'Turn on LED only when signal is high.
Low LED
GoSub GetDuty ' Retrieve the dutycycle values for all three phases
GoSub SetDutyCycle ' Set the three PWM modules accordingly
EndIF
' Now increment the individual table pointers and make sure they wrap
' around to zero when they reach the end of the table. That way they
' will always stay 62 "steps" (120°) from each other.
For i = 0 TO 1
Phase[i] = Phase[i] + 1
IF Phase[i] > 44 Then
Phase[i] = 0 'When pointer is > 44 we need to wrap around to 0.
GoSub ChangeBridgeDrive 'One phase is starting over, go change the outputs.
EndIF
Next
PauseUs 200
GoTo Main
SetDutyCycle:
' Get value from the array of dutycycles and put it in the dutycycle
' registers of the 3 PWM modules. We could have used the array directly
' but this way (using a Temp variable) is easier to understand.
Temp = DutyCycle[0] ' Get dutycyle for phase 1 from the array and store in temp.
CCP1CON.4 = Temp.0 ' Set the LSB's
CCP1CON.5 = Temp.1
CCPR1L = Temp >> 2 ' Set the 8 high bits
Temp = DutyCycle[1] ' Same procedure.
CCP2CON.4 = Temp.0
CCP2CON.5 = Temp.1
CCPR2L = Temp >> 2
Return
' ------------------------------------------------------------------------------
' ---- Subroutine to retreive the three dutycycle values from the table.
' ---- Values will be stored in the DutyCycle array.
' ------------------------------------------------------------------------------
GetDuty:
' This For-Next loop runs three times. Each time it gets the value from the lookuptable
' that Phase[i] is pointing at. The Phase array pointers are incremented in the main loop
' and are always 15 "steps" appart so that a 120° phase shift is preserved.
For i = 0 TO 1
LookUp2 Phase[i], [0,70,137,208,275,341,408,470,529,588,643,694,745,788,827,866,898,925,_
953,968,984,996,1000,996,984,968,953,925,898,866,827,788,745,_
694,643,588,529,470,408,341,275,208,137,70,0],Temp
' Lookup2 can't handle an array as the designator so we need to
' put the value in a temporary variable first and then move
' it to the array of dutycycles.
DutyCycle[i] = Temp
Next
Return
ChangeBridgeDrive:
' When we come here the value i contains the phase counter that just got reset so we
' can use that to determine for which phase we should switch the outputs.
Select Case i
Case 0 ' It was Phase 1 that rolled over
Toggle PORTC.3 ' Invert the state of the pin
Toggle PORTC.0 ' Invert the state of the pin
Case 1 ' It was Phase 2 that rolled over
Toggle PORTC.5 ' Invert the state of the pin
Toggle PORTC.6 ' Invert the state of the pin
End Select
Return
Disable 'Disable interrupts in handler
faultsignal:
High led
CCP1CON = %00000000
INTCON.1 = 0 'Clear INTERRUPT flag
Resume 'Return TO main program
Enable 'Enable interrupts after handler
End
seem like it wont go back to main program.
Bookmarks