Basic principles of software timers

The front-end system and the multitasking operating system have little difference in simple functions. The only thing that is not easy is that the front-end system does not have a suitable software timer. Encapsulate a layer of software timer interface, which will do more with less for subsequent function development.

Define the structure array, its basic members are as follows:

static uint32_t hw_interrupt_timer_ticks = 0;//timer ticks
typedef void (*timer_callback)(void);
//软件定时器最大个数
#define SW_TIMER_MAX  10

typedef struct
{
    
    
    uint32 delay;                //延迟时间,实际是当前时间+期望延时的时间后的tick
    uint32 auto_repeat;			 //执行后自动重载时间,为0表示只执行一次
    timer_callback callback;     //回调函数
} timer_struct;
timer_struct my_timer[SW_TIMER_MAX] = {
    
    0};    //定时器参数数组,最大支持10个

//启动定时器,index可按需求定为枚举类型,必须小于SW_TIMER_MAX
void timer_start(uint8 index, uint32 delay, bool loop, timer_callback callback)void timer_stop(uint8 index)//停止定时器,delay清零,回调函数置为NULL
bool timer_is_running(uint8 index)//当前定时器是否在计时运行中,判断delay是否非0

The implementation of the start timer interface provided by the application can refer to the following:

static void timer_start(uint8 index, uint32 delay, bool loop, timer_callback callback)
{
    
    
    if((index >= SW_TIMER_MAX) || (delay == 0) || (callback == NULL))
    {
    
    
        return;
    }

    my_timer[index].delay = hw_timer_ticks + delay;
    if(loop)//自动重载
    {
    
    
        my_timer[index].auto_repeat = delay;
    }
    else
    {
    
    
        my_timer[index].auto_repeat = 0;
    }

    my_timer[index].callback = callback;
}

Use hardware timing interrupts, such as 1ms interrupt once, each interrupt hw_timer_ticks increments once. In the main program, if hw_timer_ticks is greater than delay, it means that the current timer task has timed out and the callback is executed. This is suitable for 8-bit microcontroller systems. If the hardware resources are limited or the system clock is too low, the accuracy of the hardware timing interrupt can be adjusted. In this way, only one hardware timer is required for the execution of events when multiple timers are used.

static void timer_loop(void)
{
    
    
    uint8 i = 0, n = 0, min = 0;
    for(i = 0 ; i < SW_TIMER_MAX ; i++)
    {
    
    
        if(my_timer[i].delay > 0 && my_timer[i].callback != NULL)
        {
    
    
            if(hw_timer_ticks >= my_timer[i].delay)
            {
    
    
                if(my_timer[i]->auto_repeat > 0)
                {
    
    
                    my_timer[i].delay = hw_timer_ticks + my_timer[i]->auto_repeat;
                }
                else
                {
    
    
                    my_timer[i].delay = 0; //stop
                }
                my_timer[i].callback();
            }
        }
    }
}

After the basic framework is implemented, the application layer only needs simple operations to achieve, such as reading the ADC result every 60 seconds at a fixed time, and turning off the LED display after a delay of 30 seconds.

static void timer_start(READ_ADC_TIMER_ID, 60*1000, TRUE, read_adc_callback);
static void timer_start(LED_ON_TIMEROUT_TIMER_ID, 30*1000, FALSE, led_on_timeout_callback);

The disadvantage of this scheme is that the my_timer array subscript index is bound to the application. Even if not all of them are used, the main program must query all array members every time; even if it is clear that only 9 of 11 timed tasks are running at the same time , the interface cannot Meet the demand.

Increase the interface for applying for timer resources, get the unused ones from the 10 timer pools, return the index subscript, and then pass in timer_statrt. The same definition can meet the simultaneous running of 10 timed tasks, which improves the timer's performance. Utilization rate.

Because the main program checks the timer status in turn, plus the execution time of the previous callback function, there is a certain error between the actual execution callback time and the expected delay time. In the case of sufficient hardware resources, you can change the array to a linked list, sort by delay from small to large, and insert the newly-started timers into appropriate positions in order, so that the main program query speed will be accelerated. In the latest software timer, That is, it can sleep to save power before the first software timer expires. Or divide it into multiple arrays to map different priorities and time precisions, so as to improve the time accuracy of the callback function execution.

If a worker wants to do well, he must first sharpen his tools, and the perfect foundation can support the complex and changeable application layer.

Insert picture description here

Guess you like

Origin blog.csdn.net/chengjunchengjun/article/details/108821006
Recommended