EmbeddedRelated.com
Forums
The 2024 Embedded Online Conference

LPC2138 Timer

Started by tah2k February 6, 2006
Hi Everyone-

I'm having a very strange problem with my timers and I suspect its 
just a bit-twiddling setup issue. I've implemented the MODBUS RTU 
serial protocol which terminates a message when an idle time 3.5 
character times is detected. So, I initialize my match register at 
0x5573 (3.5 character times at my clock speed) and interrupt upon 
match. While receiving characters, I simply try and reset the timer 
to prevent it expiring if the character came in within the 3.5 
character time. If the character comes in after the 3.5 character 
time, an interrupt is triggered and the message is terminated. I am 
finding, however, that immediately after starting the timer the TC 
register is equal to the match register and the interrupt is 
generated.

I call teh following code every time I receive a character:

    // Disable the counter clock.
    //m_regPtr->regTCR = REG_TMR_TCR_INIT;

    // Disable the match interrupt.
    m_regPtr->regMCR &= ~REG_TMR_MCR_INT_MR0_MASK;

    // Stop the timer.
    m_regPtr->regTCR &= ~REG_TMR_TCR_ENABLE_MASK;
    
    // Clear any pending interrupts.
    m_regPtr->regIR = REG_TMR_IR_INIT;        
    
    // Reset the timer.
    m_regPtr->regTCR |= REG_TMR_TCR_RESET_MASK;
    m_regPtr->regTCR &= ~REG_TMR_TCR_RESET_MASK;
    
    // Enable the match interrupt.
    m_regPtr->regMCR |= REG_TMR_MCR_INT_MR0_MASK;
    
    // Start the timer.
    m_regPtr->regTCR |= REG_TMR_TCR_ENABLE_MASK;

-Tim
	

An Engineer's Guide to the LPC2100 Series

--- In lpc2000@lpc2..., "tah2k" <tah2k@...> wrote:
>
> Hi Everyone-
> 
> I'm having a very strange problem with my timers and I suspect its 
> just a bit-twiddling setup issue. I've implemented the MODBUS RTU 
> serial protocol which terminates a message when an idle time 3.5 
> character times is detected. So, I initialize my match register at 
> 0x5573 (3.5 character times at my clock speed) and interrupt upon 
> match. While receiving characters, I simply try and reset the timer 
> to prevent it expiring if the character came in within the 3.5 
> character time. If the character comes in after the 3.5 character 
> time, an interrupt is triggered and the message is terminated. I am 
> finding, however, that immediately after starting the timer the TC 
> register is equal to the match register and the interrupt is 
> generated.
> 
> I call teh following code every time I receive a character:
> 
>     // Disable the counter clock.
>     //m_regPtr->regTCR = REG_TMR_TCR_INIT;
> 
>     // Disable the match interrupt.
>     m_regPtr->regMCR &= ~REG_TMR_MCR_INT_MR0_MASK;
> 
>     // Stop the timer.
>     m_regPtr->regTCR &= ~REG_TMR_TCR_ENABLE_MASK;
>     
>     // Clear any pending interrupts.
>     m_regPtr->regIR = REG_TMR_IR_INIT;        
>     
>     // Reset the timer.
>     m_regPtr->regTCR |= REG_TMR_TCR_RESET_MASK;
>     m_regPtr->regTCR &= ~REG_TMR_TCR_RESET_MASK;
>     
>     // Enable the match interrupt.
>     m_regPtr->regMCR |= REG_TMR_MCR_INT_MR0_MASK;
>     
>     // Start the timer.
>     m_regPtr->regTCR |= REG_TMR_TCR_ENABLE_MASK;
> 
> -Tim
>

Tim,
It's been a little bit of time since you posted this message so you've
probably already found the answer to your problem.  In case you
haven't though ....

I'm a little newer to LPC as well, and I'm also working on the LPC2220
(but I'm sure the timer operations are very similar), so you'll
probably want to take this info with a grain of salt.  Also forgive me
if I misinterpret your code. 

My understanding of the timer registers are the following though:
- The MCR register is set just one time, afterwards there should be no 
  need to change it.  You show that you disable the timer counter TCR,
  and with the timer disabled there shouldn't be any timer interrupts 
  happening.
- If the MR0R, MR1R, MR2R, or MR3R bit in the MCR register is set to 
  1 the TC will be reset to 0x00000000 when a match occurs.  Otherwise
  the TC will just stay at the current value, and in this case you 
  would have to manually set the TC to 0x00000000 before re-starting 
  it.  This would be your case, because the timer value didn't meet 
  the match value yet (since a character was received in time).
- I'm not sure which eval package you have (if any), but the code that 
  came with mine had the following in using the TCR to reset the 
  TC:

  T1IR = 0xff;  // Clear timer 0 interrupt line.
  T1TCR = 0;    // Disable timer 0.
  T1TCR = 2;    // Reset timer 0 on next positive edge of PCLK.
  T1TCR = 0;    // Disable timer again.

  This code, however, was only for timer initialization.  After that 
  there was only a 

    T0IR = 0xff;

  in the actual timer interrupt handler.  So I'm assuming that your 
  code should never reach this point (in the case where characters are 
  being received).  If I'm interpreting your code correctly, the 
  portion where you have:

    m_regPtr->regTCR |= REG_TMR_TCR_RESET_MASK;
    m_regPtr->regTCR &= ~REG_TMR_TCR_RESET_MASK;

  is probably the same as what I put above, for resetting the TC.  In 
  this case, it may just be that there isn't enough time given for the 
  next PCLK to go positive to reset the TC before continuing on with 
  the rest of your code.  Don't know how time or space critical the 
  rest of your code is but maybe you could place a very small FOR loop 
  right after the above writes to the TCR.  What is your VPBDIV set 
  for?  1/4th of CCLK?

If all of this doesn't work, you'll notice that the TC IS a writable
register.  You may want to try just writing 0x00000000 to it after
disabling through TCR.  I'm not sure if this will take up more time
though, compared to just resetting it.

Hope this helps any.  Again, still pretty new to this processor, so if
anyone else has any ideas...

Jeff Davis.
	

The 2024 Embedded Online Conference