Timer Interrupt Clarification

Thread Starter

Vihaan@123

Joined Oct 7, 2025
251
Some of the basic doubts i have in embedded programming as below
1781092995407.png

In case if i use a single timer of 1ms then if i can count a variable if it becomes 2, i can execute 2ms functions else it becomes 10 i can execute 10ms functions. Is this the method followed? In case if i use 2 different timers will there be a problem of collision between 2ms and 10ms tasks? I am sorry if it is silly question.
 
Some of the basic doubts i have in embedded programming as below
View attachment 368219

In case if i use a single timer of 1ms then if i can count a variable if it becomes 2, i can execute 2ms functions else it becomes 10 i can execute 10ms functions. Is this the method followed? In case if i use 2 different timers will there be a problem of collision between 2ms and 10ms tasks? I am sorry if it is silly question.
Your diagram refers to ADC interrupts but you talk only about timer interrupts so I'm not sure exactly what you're asking.

I think you're asking if a 1ms repeating timer interrupt can be used to manage multiple different time intervals.

Yes, you could do that, you could have a an array of little activity structs, each structure containing a counter and limit and a handler address.

On every timer interrupt you could increment the count in each struct, compare that count with the corresponding limit, if the limit is reached you'd reset that count to zero and execute the handler.

There are things to think about though, for example if we had three intervals setup at 1, 5 and 10 ms, then every ten milliseconds we'd have to execute all three handlers, but in what order? also that would lead to large burst of interrupt work at the same instant, also all of the handler execution would be done in the (physical) timer interrupt but interrupt handlers should doing as little work as possible, not ideal so we'd need to think about these things.

So yes, one could certainly do what you are asking about.

There are other ways of designing this though.
 
Last edited:

Thread Starter

Vihaan@123

Joined Oct 7, 2025
251
Your diagram refers to ADC interrupts but you talk only about timer interrupts so I'm not sure exactly what you're asking.
I have drawn ADC interrupt to confirm that an ADC interrupt can interrupt the timer. And also if we see there are for example several interrupts
Timer, ADC, PWM, UART etc. how do i make a map of it in my mind and understand it. Can i draw some diagram using some tools, can you show me some examples, it will be great help.

I think you're asking if a 1ms repeating timer interrupt can be used to manage multiple different time intervals.

Yes, you could do that, you could have a an array of little activity structs, each structure containing a counter and limit and a handler address.

On every timer interrupt you could increment the count in each struct, compare that count with the corresponding limit, if the limit is reached you'd reset that count to zero and execute the handler.
Can you show me some example for me to understand better? Or can i write if you can review it and confirm my implementation?

There are other ways of designing this though.
I really want to learn about them, can you show me some code or a link where i can study?
 
I have drawn ADC interrupt to confirm that an ADC interrupt can interrupt the timer. And also if we see there are for example several interrupts
Timer, ADC, PWM, UART etc. how do i make a map of it in my mind and understand it. Can i draw some diagram using some tools, can you show me some examples, it will be great help.


Can you show me some example for me to understand better? Or can i write if you can review it and confirm my implementation?


I really want to learn about them, can you show me some code or a link where i can study?
yes, a little later today when I get a bit of time.
 
Your diagram refers to ADC interrupts but you talk only about timer interrupts so I'm not sure exactly what you're asking.

I think you're asking if a 1ms repeating timer interrupt can be used to manage multiple different time intervals.

Yes, you could do that, you could have a an array of little activity structs, each structure containing a counter and limit and a handler address.

On every timer interrupt you could increment the count in each struct, compare that count with the corresponding limit, if the limit is reached you'd reset that count to zero and execute the handler.

There are things to think about though, for example if we had three intervals setup at 1, 5 and 10 ms, then every ten milliseconds we'd have to execute all three handlers, but in what order? also that would lead to large burst of interrupt work at the same instant, also all of the handler execution would be done in the (physical) timer interrupt but interrupt handlers should doing as little work as possible, not ideal so we'd need to think about these things.

So yes, one could certainly do what you are asking about.

There are other ways of designing this though.
This is my first take, I don't suggest this is a quality design or great idea, but it does show a principle which is all that matters here.

You'd setup a timer and have an interrupt handler for that, here some sample code from Copilot:

C:
TIM_HandleTypeDef htim2;

void timer2_init_1ms(void)
{
    __HAL_RCC_TIM2_CLK_ENABLE();

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = 7200 - 1;   // 72 MHz / 7200 = 10 kHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 10 - 1;        // 10 kHz / 10 = 1 kHz → 1 ms
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;

    HAL_TIM_Base_Init(&htim2);
    HAL_TIM_Base_Start_IT(&htim2);

    HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
    HAL_NVIC_EnableIRQ(TIM2_IRQn);
}

void TIM2_IRQHandler(void)
{
    HAL_TIM_IRQHandler(&htim2);
}

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2)
    {
        // your 1ms code here
    }
}
So in that slotfor you code, that runs ever mS, we'd iterate over a little arrayof structs:


C:
typedef struct
{
    int count;
    int threshold;
    void (*handler)(int);   // pointer to a function taking int, returning void
} Entry;
void my_handler(int value)
{
    // do something with value
}
Entry table[] =
{
    { .count = 0, .threshold = 10, .handler = my_handler_0},
    { .count = 5, .threshold = 20, .handler = my_handler_1},
    { .count = 2, .threshold = 15, .handler = my_handler_2}
};
So now the code in the HAL_TIM_PeriodElapsedCallback function could look like this:

C:
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
    if (htim->Instance == TIM2)
    {
        // enumerate the array
        for (int i = 0; i < tableCount; i++)
        {
            table[i].count++;

            if (table[i].count >= table[i].threshold)
            {
                table[i].count = 0;               // reset
                table[i].handler(i);              // call handler with index
            }
        }
    }
}
Can you see the idea? handler_0 gets called every 10ms, handler_1 gets called every 20ms and handler_2 gets called every 15ms.

This is intended to conevy the idea only, how some data can represent the statesof "virtual" timers.

This code was generated by Copilot in response to me asking it basic questions, you can do that too, you can outline your problem and ask for some different ways to do it, there's no harm in that when learning, I told it to use STM32 HAL as the basis for the code, in reality I'd tell it exactky which specific MCU to use.
 

MrChips

Joined Oct 2, 2009
34,829
Sampling with an ADC can be problematic. A lot depends on the application and what you intend to do with each ADC sample.

Firstly, let us take the 2 ms sample period. That translates to 500 sps.
The sampling theorem dictates that the maximum frequency that can be analyzed is 250 Hz.
Frequencies higher than 250 Hz will be folded back into the 0-250 Hz frequency space. This is known as aliasing.
To prevent aliasing, you need an anti-aliasing filter (a low-pass filter) with a cut-off frequency somewhere below 250 Hz, for example 100 Hz.

Next, we need to understand the effect of clock jitter. How repeatable is the ADC sample clock? If you are relying on the 1 ms timer clock to cause an interrupt and then trigger the ADC on every second interrupt, you are introducing significant clock jitter. This is the variation in time when the ADC is actually triggered to take a sample.

Variation in sample period, dt, translates to variation in sample voltage dv. This contributes to ADC sample noise.

Again, how severe is clock jitter depends on the application.

1781124698755.png
 

Thread Starter

Vihaan@123

Joined Oct 7, 2025
251
If this were in comprehensible English, I'd try to respond.
Code:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>

int main()
{
    while(1)
    {
        if(twomsflag == true)
        {
            twomsflag = false;
        }
        if(tenmsflag == true)
        {
            tenmsflag = false;
        }
    }

    return 0;

}

void TimerInterrupt(void)       // one ms interrupt
{
    twomscounter++;
    tenmscounter++;
    if(twomscounter >= 2)
    {
        twomsflag = true;
        twomscounter = 0;
    }
    if(tenmscounter >= 10)
    {
        tenmsflag = true;
        tenmscounter = 0;
    }

}
So wanted to know if two different timers are used for 2ms and 10ms, which one will execute first?
 

John P

Joined Oct 14, 2008
2,063
All right Vihaan, that's clear enough. In fact it's so simple that it's trivial, except that it isn't--where are the variables tenmscounter and twomscounter defined? And it doesn't make much sense to ask which counter triggers "first" when one of them has one-fifth the frequency of the other.

If the two counters are global, then their values could be set anywhere in the program. If they're local to the interrupt (which means they need to be designated as static) then are you certain that at the start of execution they're both zero? Because if twomscounter ever had the value of 1 while tenmscounter had an even value, then you'd see the tenmsflag getting set during a cycle when the twomscounter didn't reset, whereas if they both started at zero, tenmsflag would always be set during the same interrupt as twomsflag.

And there is an additional trap here, which might be important. Your 1 msec interrupt is asynchronous relative to the loop in main(). You're testing the two flags in sequence, but you don't know when either (or both) of them will change. Assuming a single interrupt might set both flags, is it a problem if the twomsec flag has already been tested and found not to be set, then you test the tenmsec flag and find that it's set when the twomsec flag wasn't? If that matters, maybe you can figure out a solution to it.
 

Thread Starter

Vihaan@123

Joined Oct 7, 2025
251
All right Vihaan, that's clear enough. In fact it's so simple that it's trivial, except that it isn't--where are the variables tenmscounter and twomscounter defined? And it doesn't make much sense to ask which counter triggers "first" when one of them has one-fifth the frequency of the other.
My question was if two timers are used for example Timer1 and Time2 for 2ms and 10ms which one will be triggered at 10th ms, 20th ms etc? The above sample code shown is with one timer so does not have such a problem.
 

MrChips

Joined Oct 2, 2009
34,829
My question was if two timers are used for example Timer1 and Time2 for 2ms and 10ms which one will be triggered at 10th ms, 20th ms etc? The above sample code shown is with one timer so does not have such a problem.
Both timers will be triggered.
Which timer is triggered first? It depends on when the timers were started.
If you start the timers 0.5 ms apart and the two timers are clocked by the same source, then the interrupts will be separated by 0.5 ms.
 

Irving

Joined Jan 30, 2016
5,137
All these structures with call out to routines... What you're doing is implementing a crude task scheduler with masses of overhead. A problem of this nature is a good candidate for a RTOS with a well-tested scheduler and all the benefits of the built-in inter-process communications, priority handling, etc. Don't re-invent the wheel!
 
Top