Interaction between interrupts

General discussion on mikroBasic PRO for PIC.
Post Reply
Author
Message
dangerous
Posts: 748
Joined: 08 Mar 2005 16:06
Location: Nottinghamshire, UK

Interaction between interrupts

#1 Post by dangerous » 27 Jul 2023 09:50

Hi, I am using a PIC18F45K22 running at 64MHz int osc to generate a 50Hz PWM for a servo, and it works fine using the capture/compare in special events mode to compare the CCPH & L with Timer 1.
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.

corneasushi@gmail.com
Posts: 2
Joined: 10 Jan 2024 09:20

Re: Interaction between interrupts

#2 Post by corneasushi@gmail.com » 26 Jan 2024 09:06

Implement critical sections in your code, especially when updating shared variables or registers in both the main loop and interrupt service routines. Disable interrupts temporarily when critical sections are being executed to avoid unexpected behavior.

Post Reply

Return to “mikroBasic PRO for PIC General”