I can get the 1.0 to 3.0ms pulses I need at 50Hz rate very easily. To enter the low set, high set, and save modes I have 1 button which steps through the menu. I use the A-D to adjust the widths by setting the low pulse value and high pulse values,using 2 pots,which also works, fine just polling the Go/Done bit (no interrupt for A-D).
I was hoping to flash an LED at different speeds using TMR0 for set low mode (pulse 0 .1 to 1.4mS) set high mode (pulse 1.5 to 3.0mS) and save mode (LED off) selected by the button.
The snag is that whenever I set TMR0ON bit the output pulse width of the PWM is no longer predicatble. I suspect that the interrupt routine is the issue as CCP1IF will always enter the routine, and so will TMR0IF. I have tried changing priorites on the interrupts and various other things.
The code attached is a stripped down version in an attempt to trace the problem, and just generates 2 x 4 different pulse widths with slow LED flash for the first 4 and fast flash for the last 4. As soon as TMR0 is enabled the flash works but the pulse widths are anything. With TMRO disabled the pulses are fine. I have tried using TMR0 with higher counts and prescaler to reduce the interrupts and with lower counts, but the effect is stil the same. Short of triggering another small PIC or even a 555 (do you remember those?) for the LED, has anyone got any ideas?
Code: Select all
program SimplePWM
'IntOsc @64MHz gives 16MHz system clock
'T1 div by 8 (max prescale) gives 0.5us interupts, so 50Hz(20mS) requires 40000
'Counts, and gives a 0.5us resolution to PWM output.
'Using TMR1 The CCP module compares held value with TMR1 and on match resets
'TMR1 and causes a CCP interrupt. The selscted output pin is the toggled and CCPR
'is reloaded with the correcet value. No interupts are used for TMR1 as it never
'reaches 0xFFFF unless Current period = 0
' Declarations section
dim
CCPR,
current_period,
cmax
as word
count
as byte
POUT as sbit at LATC.0 'PWM for this applicatio but can be any pin
Const total_period = 40000 '20mS @ 64MHz clock
RTH = 0xFC '0x3C '1mS TMR0 Ticks
RTL = 0x17 '0xAF 'commented values for 50ms Ticks
'tried various prescale values as well
Sub procedure interrupt()
'PWM generator,
If CCP1IF then
if ((current_period > 0) AND (current_period < total_period)) then
If POUT = 1 then
POUT = 0 'Set pin low for off time
CCPR = total_period - current_period
else
POUT = 1 'Set pin high for on time
end if
else
if current_period = total_period then
POUT = 1
CCPR = current_period
else
if current_period = 0 then
POUT = 0
end if
end if
end if
CCPR1H = CCPR >>8 'Reload CCP values
CCPR1L = CCPR
CCP1IF_bit = 0 'clear flag
end if
If TMR0IF_bit then
latd.2 = not latd.2
TMR0H = RTH 'reload
TMR0L = RTL
inc(count)
if count > cmax then
count = 0
latd.0 = not latd.0 'Indicator to flash
end if
TMR0IF_bit = false
end if
GIE_bit = true
end sub
main:
OSCCON = 0x70
PLLEN_bit = true '64MHz
ANSELA = 0 'Set all digital
ANSELB = 0
ANSELC = 0
ANSELD = 0
LATA = 0
LATB = 0
LATC = 0
LATD = 1
TRISA = 0
TRISB = 0
TRISC = 0
TRISD = 0
T1CON = %00110000 'T1 off no interrupts used, PS div by 8 = 0.5uS ticks
TMR1H = 0
TMR1L = 0
T0CON = %00000011 'PS on DIV by 16, 16 Bit tmr off for now Bits 0-2 are PS value
TMR0H = RTH 'gives 1mS ticks
TMR0L = RTL
TMR0IF_Bit = 0
TMR0IE_bit = 1
'TMR0IP_Bit = 0 'lo priority 1mS interrupts
CCP1CON = 0x0b 'special trigger mode, compares to TMR1 and resets TMR1 on match
CCPR = 0 'CPP start value
CCP1IF_bit = 0
CCP1IE_bit = 1 'enable ints
'CCP1IP_bit = 1 'hi priority every 20/40000 ms = 10uS
'IPEN_bit = true 'enable priority
PEIE_bit = true
GIE_bit = true
TMR1ON_bit = true 'start timer1
TMR0ON_bit = true 'comment to stop TMR0
while (1) 'infinite loop.
' TEST CODE..drives 2 x 4 different pulse widths for 2 seconds each LATB shows position
LATB = 0x01
cmax = 200
current_period = 900 '0.9mS
delay_ms(2000)
latb = latb<<1 '// delay 2s.
current_period = 3000 '3mS
delay_ms(2000)
latb = latb<<1 '// delay 2s.
current_period = 1200 '1.2ms
delay_ms(2000)
latb = latb<<1 ' // delay 2s.
current_period = 2400 '2.4ms
delay_ms(2000)
cmax = 100
latb = latb<<1
current_period = 900
delay_ms(2000)
latb = latb<<1 '// delay 2s.
current_period = 3000
delay_ms(2000)
latb = latb<<1 '// delay 2s.
current_period = 1200
delay_ms(2000)
latb = latb<<1 ' // delay 2s.
current_period = 2400
delay_ms(2000)
'latb = latb<<1
wend
end.