This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Problem in Timer

Hi,

I am using lpc1768. By using Timer, i have generated a square wave with time period of 16ms. The ON period should be 1ms and OFF period should be 15ms. I used two match registers MR0 and MR1. I done with MR0 for OFF period and MR1 for ON period. But am getting the signal as 15ms as ON period and 1ms as OFF period. Plz suggest some solutions.

Thank You

Parents
  • I am posting ma Code here.

    
    #include "lpc17xx.h"
    #include "type.h"
    #include "timer.h"
    
    extern uint32_t timer0_m0_counter, timer1_m0_counter;
    extern uint32_t timer0_m1_counter, timer1_m1_counter;
    
    int main (void)
    {
      uint32_t i;
    
       SystemInit();
    
       LPC_PINCON->PINSEL1&=~(3<<10);
    
    
       LPC_GPIO0->FIODIR|=(1<<21);
       LPC_GPIO0->FIOCLR|=(1<<21);
    
    
       LPC_GPIO1->FIODIR   |=  1<<29;                              // P1.29 = Outputs
       LPC_GPIO1->FIOCLR          =  1<<29;                                // Turn-OFF LED
    
    
      for ( i = 0; i < 2; i++ )
      {
            init_timer( i , TIME_INTERVAL );
            enable_timer( i );
    
      }
    
      /*Timer pgm*/
    
    
    void TIMER0_IRQHandler (void)
    {
      if ( LPC_TIM0->IR & (0x1<<0) )
      {
    
        LPC_TIM0->IR = 0x1<<0;             /* clear interrupt flag */
        timer0_m0_counter++;
    
    
            if  (LPC_GPIO0->FIOPIN & (1<<21))
            {
    
              LPC_GPIO0->FIOCLR|=(1<<21);
              LPC_GPIO1->FIOCLR   =  1<<29;                                // Turn-OFF LED
              LPC_TIM0->MCR = (0x3<<3);//|(0x3<<3);  /* Interrupt and Reset on MR1 */
    
            }
      }
    
    
      if ( LPC_TIM0->IR & (0x1<<1) )
      {
        LPC_TIM0->IR = 0x1<<1;             /* clear interrupt flag */
        timer0_m1_counter++;
    
            LPC_GPIO0->FIOSET|=(1<<21);
            LPC_GPIO1->FIOSET     =  1<<29;                                // Turn-ON LED
            LPC_TIM0->MCR = (0x3<<0);//|(0x3<<3);    /* Interrupt and Reset on MR0 */
    
      }
      if ( LPC_TIM0->IR & (0x1<<4) )
      {
            LPC_TIM0->IR = 0x1<<4;         /* clear interrupt flag */
            timer0_capture0++;
      }
      if ( LPC_TIM0->IR & (0x1<<5) )
      {
            LPC_TIM0->IR = 0x1<<5;         /* clear interrupt flag */
            timer0_capture1++;
      }
      return;
    }
    
    
    
    uint32_t init_timer ( uint8_t timer_num, uint32_t TimerInterval )
    {
      uint32_t pclkdiv, pclk;
    
      if ( timer_num == 0 )
      {
            timer0_m0_counter = 0;
            timer0_m1_counter = 0;
            timer0_capture0 = 0;
            timer0_capture1 = 0;
            LPC_SC->PCONP |= (0x01<<1);
    #if TIMER_MATCH
            LPC_PINCON->PINSEL3 &= ~((0x3<<24)|(0x3<<26));
            LPC_PINCON->PINSEL3 |= ((0x3<<24)|(0x3<<26));
    #else
            LPC_PINCON->PINSEL3 &= ~((0x3<<20)|(0x3<<22));
            LPC_PINCON->PINSEL3 |= ((0x3<<20)|(0x3<<22));
    #endif
            LPC_TIM0->IR = 0x0F;          /* Clear MATx interrupt include DMA request */
    
            /* By default, the PCLKSELx value is zero, thus, the PCLK for
            all the peripherals is 1/4 of the SystemFrequency. */
            /* Bit 2~3 is for TIMER0 */
            pclkdiv = (LPC_SC->PCLKSEL0 >> 2) & 0x03;
            switch ( pclkdiv )
            {
              case 0x00:
              default:
                    pclk = SystemFrequency/4;
                    break;
              case 0x01:
                    pclk = SystemFrequency;
                    break;
              case 0x02:
                    pclk = SystemFrequency/2;
                    break;
              case 0x03:
                    pclk = SystemFrequency/8;
                    break;
            }
            //LPC_TIM0->PR  = pclk/1000000; /* set prescaler to get 1 M counts/sec */
    
            LPC_TIM0->MR0 = TIME_INTERVALmS * 15 * 18; /* Set up 10 mS interval */
            LPC_TIM0->MR1 = TIME_INTERVALmS * 1 * 18; /* Set up 10 mS interval */
    #if TIMER_MATCH
            LPC_TIM0->EMR &= ~(0xFF<<4);
            LPC_TIM0->EMR |= ((0x3<<4)|(0x3<<6));
    #else
            /* Capture 0 and 1 on rising edge, interrupt enable. */
            LPC_TIM0->CCR = (0x1<<0)|(0x1<<2)|(0x1<<3)|(0x1<<5);
    #endif
            LPC_TIM0->MCR = (0x3<<0)|(0x3<<3);       /* Interrupt and Reset on MR0 and MR1 */
            NVIC_EnableIRQ(TIMER0_IRQn);
            return (TRUE);
      }
      else if ( timer_num == 1 )
      {
            timer1_m0_counter = 0;
            timer1_m1_counter = 0;
            timer1_capture0 = 0;
            timer1_capture1 = 0;
            LPC_SC->PCONP |= (0x1<<2);
    #if TIMER_MATCH
            LPC_PINCON->PINSEL3 &= ~((0x3<<12)|(0x3<<18));
            LPC_PINCON->PINSEL3 |= ((0x3<<12)|(0x3<<18));
    #else
            LPC_PINCON->PINSEL3 &= ~((0x3<<4)|(0x3<<6));
            LPC_PINCON->PINSEL3 |= ((0x3<<4)|(0x3<<6));
    #endif
            LPC_TIM1->IR = 0x0F;          /* Clear MATx interrupt include DMA request */
            /* By default, the PCLKSELx value is zero, thus, the PCLK for
            all the peripherals is 1/4 of the SystemFrequency. */
            /* Bit 4~5 is for TIMER0 */
            pclkdiv = (LPC_SC->PCLKSEL0 >> 4) & 0x03;
            switch ( pclkdiv )
            {
              case 0x00:
              default:
                    pclk = SystemFrequency/4;
                    break;
              case 0x01:
                    pclk = SystemFrequency;
                    break;
              case 0x02:
                    pclk = SystemFrequency/2;
                    break;
              case 0x03:
                    pclk = SystemFrequency/8;
                    break;
            }
            LPC_TIM1->PR  = pclk/1000000; /* set prescaler to get 1 M counts/sec */
            LPC_TIM1->MR0 = TIME_INTERVALmS * 10; /* Set up 10 mS interval */
            LPC_TIM1->MR1 = TIME_INTERVALmS * 10; /* Set up 10 mS interval */
    #if TIMER_MATCH
            LPC_TIM1->EMR &= ~(0xFF<<4);
            LPC_TIM1->EMR |= ((0x3<<4)|(0x3<<6));
    #else
            /* Capture 0/1 on rising edge, interrupt enable. */
            LPC_TIM1->CCR = (0x1<<0)|(0x1<<2)|(0x1<<3)|(0x1<<5);
    #endif
            LPC_TIM1->MCR = (0x3<<0)|(0x3<<3);       /* Interrupt and Reset on MR0 and MR1 */
            NVIC_EnableIRQ(TIMER1_IRQn);
            return (TRUE);
      }
      return (FALSE);
    }
    
    
    
    
    

Reply
  • I am posting ma Code here.

    
    #include "lpc17xx.h"
    #include "type.h"
    #include "timer.h"
    
    extern uint32_t timer0_m0_counter, timer1_m0_counter;
    extern uint32_t timer0_m1_counter, timer1_m1_counter;
    
    int main (void)
    {
      uint32_t i;
    
       SystemInit();
    
       LPC_PINCON->PINSEL1&=~(3<<10);
    
    
       LPC_GPIO0->FIODIR|=(1<<21);
       LPC_GPIO0->FIOCLR|=(1<<21);
    
    
       LPC_GPIO1->FIODIR   |=  1<<29;                              // P1.29 = Outputs
       LPC_GPIO1->FIOCLR          =  1<<29;                                // Turn-OFF LED
    
    
      for ( i = 0; i < 2; i++ )
      {
            init_timer( i , TIME_INTERVAL );
            enable_timer( i );
    
      }
    
      /*Timer pgm*/
    
    
    void TIMER0_IRQHandler (void)
    {
      if ( LPC_TIM0->IR & (0x1<<0) )
      {
    
        LPC_TIM0->IR = 0x1<<0;             /* clear interrupt flag */
        timer0_m0_counter++;
    
    
            if  (LPC_GPIO0->FIOPIN & (1<<21))
            {
    
              LPC_GPIO0->FIOCLR|=(1<<21);
              LPC_GPIO1->FIOCLR   =  1<<29;                                // Turn-OFF LED
              LPC_TIM0->MCR = (0x3<<3);//|(0x3<<3);  /* Interrupt and Reset on MR1 */
    
            }
      }
    
    
      if ( LPC_TIM0->IR & (0x1<<1) )
      {
        LPC_TIM0->IR = 0x1<<1;             /* clear interrupt flag */
        timer0_m1_counter++;
    
            LPC_GPIO0->FIOSET|=(1<<21);
            LPC_GPIO1->FIOSET     =  1<<29;                                // Turn-ON LED
            LPC_TIM0->MCR = (0x3<<0);//|(0x3<<3);    /* Interrupt and Reset on MR0 */
    
      }
      if ( LPC_TIM0->IR & (0x1<<4) )
      {
            LPC_TIM0->IR = 0x1<<4;         /* clear interrupt flag */
            timer0_capture0++;
      }
      if ( LPC_TIM0->IR & (0x1<<5) )
      {
            LPC_TIM0->IR = 0x1<<5;         /* clear interrupt flag */
            timer0_capture1++;
      }
      return;
    }
    
    
    
    uint32_t init_timer ( uint8_t timer_num, uint32_t TimerInterval )
    {
      uint32_t pclkdiv, pclk;
    
      if ( timer_num == 0 )
      {
            timer0_m0_counter = 0;
            timer0_m1_counter = 0;
            timer0_capture0 = 0;
            timer0_capture1 = 0;
            LPC_SC->PCONP |= (0x01<<1);
    #if TIMER_MATCH
            LPC_PINCON->PINSEL3 &= ~((0x3<<24)|(0x3<<26));
            LPC_PINCON->PINSEL3 |= ((0x3<<24)|(0x3<<26));
    #else
            LPC_PINCON->PINSEL3 &= ~((0x3<<20)|(0x3<<22));
            LPC_PINCON->PINSEL3 |= ((0x3<<20)|(0x3<<22));
    #endif
            LPC_TIM0->IR = 0x0F;          /* Clear MATx interrupt include DMA request */
    
            /* By default, the PCLKSELx value is zero, thus, the PCLK for
            all the peripherals is 1/4 of the SystemFrequency. */
            /* Bit 2~3 is for TIMER0 */
            pclkdiv = (LPC_SC->PCLKSEL0 >> 2) & 0x03;
            switch ( pclkdiv )
            {
              case 0x00:
              default:
                    pclk = SystemFrequency/4;
                    break;
              case 0x01:
                    pclk = SystemFrequency;
                    break;
              case 0x02:
                    pclk = SystemFrequency/2;
                    break;
              case 0x03:
                    pclk = SystemFrequency/8;
                    break;
            }
            //LPC_TIM0->PR  = pclk/1000000; /* set prescaler to get 1 M counts/sec */
    
            LPC_TIM0->MR0 = TIME_INTERVALmS * 15 * 18; /* Set up 10 mS interval */
            LPC_TIM0->MR1 = TIME_INTERVALmS * 1 * 18; /* Set up 10 mS interval */
    #if TIMER_MATCH
            LPC_TIM0->EMR &= ~(0xFF<<4);
            LPC_TIM0->EMR |= ((0x3<<4)|(0x3<<6));
    #else
            /* Capture 0 and 1 on rising edge, interrupt enable. */
            LPC_TIM0->CCR = (0x1<<0)|(0x1<<2)|(0x1<<3)|(0x1<<5);
    #endif
            LPC_TIM0->MCR = (0x3<<0)|(0x3<<3);       /* Interrupt and Reset on MR0 and MR1 */
            NVIC_EnableIRQ(TIMER0_IRQn);
            return (TRUE);
      }
      else if ( timer_num == 1 )
      {
            timer1_m0_counter = 0;
            timer1_m1_counter = 0;
            timer1_capture0 = 0;
            timer1_capture1 = 0;
            LPC_SC->PCONP |= (0x1<<2);
    #if TIMER_MATCH
            LPC_PINCON->PINSEL3 &= ~((0x3<<12)|(0x3<<18));
            LPC_PINCON->PINSEL3 |= ((0x3<<12)|(0x3<<18));
    #else
            LPC_PINCON->PINSEL3 &= ~((0x3<<4)|(0x3<<6));
            LPC_PINCON->PINSEL3 |= ((0x3<<4)|(0x3<<6));
    #endif
            LPC_TIM1->IR = 0x0F;          /* Clear MATx interrupt include DMA request */
            /* By default, the PCLKSELx value is zero, thus, the PCLK for
            all the peripherals is 1/4 of the SystemFrequency. */
            /* Bit 4~5 is for TIMER0 */
            pclkdiv = (LPC_SC->PCLKSEL0 >> 4) & 0x03;
            switch ( pclkdiv )
            {
              case 0x00:
              default:
                    pclk = SystemFrequency/4;
                    break;
              case 0x01:
                    pclk = SystemFrequency;
                    break;
              case 0x02:
                    pclk = SystemFrequency/2;
                    break;
              case 0x03:
                    pclk = SystemFrequency/8;
                    break;
            }
            LPC_TIM1->PR  = pclk/1000000; /* set prescaler to get 1 M counts/sec */
            LPC_TIM1->MR0 = TIME_INTERVALmS * 10; /* Set up 10 mS interval */
            LPC_TIM1->MR1 = TIME_INTERVALmS * 10; /* Set up 10 mS interval */
    #if TIMER_MATCH
            LPC_TIM1->EMR &= ~(0xFF<<4);
            LPC_TIM1->EMR |= ((0x3<<4)|(0x3<<6));
    #else
            /* Capture 0/1 on rising edge, interrupt enable. */
            LPC_TIM1->CCR = (0x1<<0)|(0x1<<2)|(0x1<<3)|(0x1<<5);
    #endif
            LPC_TIM1->MCR = (0x3<<0)|(0x3<<3);       /* Interrupt and Reset on MR0 and MR1 */
            NVIC_EnableIRQ(TIMER1_IRQn);
            return (TRUE);
      }
      return (FALSE);
    }
    
    
    
    
    

Children
  • Why are you using two match registers but only managing to have your ISR behave as if the timer had just a single match register?

    Don't you recognize that there can be multiple matches (and multiple match interrupts) without any reset in between? Why else would there be an option to configure the chip to reset (or to not reset) the timer on each of the individual match values?

    By the way - driving processor pins from the interrupt means there will always be latencies and jitter involved. The ISR isn't always trigged at exact time when you get a match. And then you spend a number of instructions just to figure out what to do. Match pins can toggle with zero ISR intervention. Match pins can produce that 15ms + 1ms cycle completely without ISR intervention - so the ISR would only be needed if you want your counters incremented.

    Have you actually spent time reading the timer chapter? And look at available sample code? And then returned back and read the timer chapter of the processor users manual a second time?

  • First i have done without reset. But its not working...

    Thank You

  • Well, you would normally have one match register produce a interrupt+reset while the other only produces an interrupt.

    And you make MR0 = 15ms and MR1 = 16ms. Or MR0 = 1ms and MR1 = 16ms.

    Then you get a 16ms cycle that either have 1+15 or 15+1 - both alternatives can give the correct output - the only difference is with of the periods it starts with directly when you initialize the timer.

    But in the end, it is important to note that things often doesn't work on first try. The task then isn't to rewrite the code randomly and see what happens. You instead take one step back and try to compare what you think you instructed the processor to do, with that the processor manual describes the processor to do. And the debugger can be used to look at state and compare with the state you assumed you would have.

    Random "work around" changes are seldom producing good solutions.

  • Why dont you use keil simulator? Or Connect a debugger and check whats actually happening?

    Is posting a thread and waiting for the reply the fastest method to solve the problem [given the nature of the problem. It can be solved by studying the example codes also]??

  • Actually in the MCR register i have given reset and interrupt in both MR) and MR1 register. Thats why i didnt get. Now am getting the expected signal.

    Thank You

  • And that was why I explicitly wondered why you played with two match registers while still configuring the timer to reset on every match making it impossible to reach any second match value.

    So next thing - are you aware that if you use the match output pins, then you can have the timer drive these pins with zero ISR involved? And zero jitter from interrupt response time or varying code paths of any code sequences?