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

high precision timer using AT89S8252

I am trying to implement a high precision timer using AT89S8252 using the following
code:

void configureTimer0(void)
{
EA = 0;
TMOD &= 0xf0;
TMOD |= 0x01;
ET0 =1;
TH0 = TH_VAL
TL0 = TL_VAL
TR0= 1;
EA = 1;
}

// timer 0 interrupt handle
void timer0 (void) interrupt 1
{
TH0 = TH_VAL;
TL0 = TL_VAL;
P2_1 = !P2_1;
switch(val)
{
case 1: // code
break;
case 2: // code
break;
}
}

void main(void)
{
configureTimer0();
while(1);
}

The problem occurs when I try to insert any code inside the Timer 0 interrupt handle, such as a blinking LED ar a simple switch
statement. The code inside interrupt handle was as simple as possible.
In order to keep a constant rate, I have to use a digital osciloscope to adjust TH_VAL and TL_VAL.

Is there any other way to implement this ? Do I have to constantly calibrate TH_VAL and TL_VAL after inserting any piece of code inside the timer interrupt handle ?


Best regards,

Andre

Parents Reply Children
  • Erik,

    Can you explain your point?

    Stefan

  • 1) The interrupts (according to the manual) always execute the fitst instruction.
    2) access to IE and RETI acn not be interrupted.

    Thus by doing as suggested the timer interrupt can not be interrupted.

    OOPS
    This, of course, does not help if the timer interrupt happens while a higher priority interrupt is already active.

    so
    To make the time "precision" the timer interrupt must be the only interrupt having the highest priority and the EA manipulation can be omitted.

    Erik

  • "1) The interrupts (according to the manual) always execute the fitst instruction."

    Quoting from the manual:

    "Note that if an interrupt of higher priority level goes active prior to S5P2 of the machine cycle labeled C3 in Figure 20 [first machine cycle of LCALL to the ISR], then in accordance with the above rules it will be vectored to during C5 and C6 [the two machine cycles following the first LCALL], without any instruction of the lower priority routine having been executed."

    "2) access to IE and RETI acn not be interrupted."

    Correct, but only if an access to IE/IP or a reti is the instruction actually in progress. A higher priority interrupt occuring during the previous instruction will still be vectored to at the end of that instruction.

    I only know of two ways to maintain an accurate clock using timer interrupts:

    1) Use hardware autoreload.
    2) Choose a software reload value that doesn't require the timer to be stopped or the low byte to be reloaded.

    Stefan

  • Erik:
    To make the time "precision" the timer interrupt must be the only interrupt having the highest priority and the EA manipulation can be omitted

    Stefan:
    Quoting from the manual:

    "Note that if an interrupt of higher priority level goes active prior to S5P2 of the machine cycle labeled C3 in Figure 20 [first machine cycle of LCALL to the ISR], then in accordance with the above rules it will be vectored to during C5 and C6 [the two machine cycles following the first LCALL], without any instruction of the lower priority routine having been executed."

    If the timer interrupt is the only one at the highest priority, your statement above does not apply


    Stefan:
    Correct, but only if an access to IE/IP or a reti is the instruction actually in progress. A higher priority interrupt occuring during the previous instruction will still be vectored to at the end of that instruction.
    as above

    Stefan:
    I only know of two ways to maintain an accurate clock using timer interrupts:

    1) Use hardware autoreload.
    2) Choose a software reload value that doesn't require the timer to be stopped or the low byte to be reloaded.


    That, of course is the right solution; however, the question did not refer to timer 2

    Erik

  • You must note that the timer continues running when interrupt goes active. If a higher priority interrupt exists, you can add a constant to TH0-TL0 and not load a constant. You can adjust constant by calculting time to execute add.

    clr ea
    clr tr0
    xch a,tl0
    add a,#low(constant)
    xch a,tl0
    xch a,th0
    addc a,#high(constant
    xch a,th0
    setb tr0
    setb ea
    

    For example, if you have a constant of 500 cycles, you must load -500 in TH0-TL0. If timer ISR start 20 cycles after timer overflow, TH0-TL0 contains 20. If you add -500 to 20 you obtain 480. So next ISR takes place in 480 cycles and you obtain correctly 500 cycles since current ISR.

    If you use XCH instructions to make addition, you may to not save ACC in timer ISR.

  • Erik:

    "If the timer interrupt is the only one at the highest priority, your statement above does not apply"

    I think that is pretty obvious from the first sentence:

    "Note that if an interrupt of higher priority level goes active..."

    And please note, that was a quotation from the manual, not my statement. The intention was to correct your inaccurate statement:

    "1) The interrupts (according to the manual) always execute the fitst instruction."

    Stefan

  • Eric,

    This is a good solution if programming in assembler, although I note you have not mentioned compensating for the 'lost' timer counts during the period the timer is disabled. Presumably you would recalculate your constant to take this into account?

    In 'C' techniques that rely on code being compiled into a specific sequence of instructions are too difficult to maintain for my liking.

    Stefan

  • Andre,

    Has any of this been of any help to you?

    Stefan