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
LPC2138 Timer
Started by ●February 6, 2006
Reply by ●February 15, 20062006-02-15
--- 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.