C语言——软件定时器

都说程序设计 = 算法 + 数据结构。数据结构是挨踢必修课,不过好像学了数据结构之后也没用来做过啥。不知道做啥,就写个软件定时器。

软件定时器数据结构

typedef struct __software_timer{
    u32 timeout;                                     //初始化时间计数器              
    u32 repeat;                                      //运行间隔:repeat > 0 :周期定时时间  repeat == 0 :只定时一次
    void (*timeout_callback_handler)(void *para);    //超时回调函数
    struct __software_timer *next;
}software_timer_t;

判断软件定时器链表是否为空

/**
  * @brief:         Determine if the software timer list is empty
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:          
  * @version:       v1.0.0
*/
static u8 is_softtimer_list_empty(void)
{
    if(software_timer_list_head.next == NULL)
        return TRUE;
    else
        return FALSE;
}

插入定时器到软件定时器链表

链表使用单向链表

/**
  * @brief:         Insert the software timer node into the linked list
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:           
  * @version:       v1.0.0
*/
static void insert_software_timer(software_timer_t *timer_handle)
{
    software_timer_t *tmp;
    software_timer_t *list_head = &software_timer_list_head;

    if(is_softtimer_list_empty())
    {
        list_head->next = timer_handle;
    }
    else
    {
        tmp = list_head->next;
        while(tmp->next)
        {
            if(timer_handle == tmp)    //定时器已经存在
            {
                printf("The timer already exists\r\n");
                return;
            }
            tmp = tmp->next; 
        }
        tmp->next = timer_handle;
    }
}

将定时器从软件定时器链表移除

/**
  * @brief:         Removes the software timer node from the list
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:              
  * @version:       v1.0.0
*/
static void remove_software_timer(software_timer_t *timer_handle)
{
    software_timer_t *list_head = &software_timer_list_head;
    software_timer_t *tmp = list_head;
    
    if(is_softtimer_list_empty())
        return;
    
    while(tmp && tmp->next != timer_handle)
    {
        tmp = tmp->next;
    }
    
    if(tmp == NULL)
        return;
    
    tmp->next          = timer_handle->next;
    timer_handle->next = NULL;  
}

初始化软件定时器

回调函数不能过长,执行时间不能超过定时时间。

/**
  * @brief:         Initializes the software timer
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:                    
  * @version:       v1.0.0
*/
void software_timer_init(software_timer_t *timer_handle,u32 timeout,u32 repeat,void (*timerout_cb)(void *))
{
    timer_handle->timeout                  = timeout;
    timer_handle->repeat                   = repeat;
    timer_handle->timeout_callback_handler = timerout_cb;
    timer_handle->next                     = (void *)0;
}

启动定时器

/**
  * @brief:         Start timer
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:              
  * @version:       v1.0.0
*/
void software_timer_start(software_timer_t *timer_handle)
{
    insert_software_timer(timer_handle);         
}

停止定时器

/**
  * @brief:         stop timer
  * @param[in]:     None
  * @retval[out]:   None
  * @note:            
  * @author:        AresXu
  * @github:              
  * @version:       v1.0.0
*/
void software_timer_stop(software_timer_t *timer_handle)
{
    remove_software_timer(timer_handle);        
}

定时器处理函数(主函数调用)

/**
  * @brief:         Timer processing function
  * @param[in]:     None
  * @retval[out]:   None
  * @note:          Must be called by the main function  
  * @author:        AresXu
  * @github:        https://github.com/EmbeddedXGJ       
  * @version:       v1.0.0
*/
void software_timer_main_loop(void)
{
    software_timer_t *tmp = &software_timer_list_head;
    tmp = tmp->next;
    
    while(tmp)
    {
        if(tmp->timeout <= 0)
        {
            tmp->timeout_callback_handler((void *)0);

            if(tmp->repeat > 0)
            {
                tmp->timeout = tmp->repeat;
            }
            else     
            {
                software_timer_stop(tmp);
            }
        }
        tmp = tmp->next;
    } 
}

硬件定时器提供时基

1 ms硬件定时器调用函数。

/**
  * @brief:         Provide a heartbeat to the software timer
  * @param[in]:     void
  * @retval[out]:   void
  * @note:          Must be called by 1ms hardware timer  
  * @author:        AresXu
  * @github:        https://github.com/EmbeddedXGJ      
  * @version:       v1.0.0
*/
void software_timer_ticks(void)
{
    software_timer_t *tmp = &software_timer_list_head;
    tmp = tmp->next;
    
    while(tmp)
    {
        if(tmp->timeout > 0)
        {
            tmp->timeout--;
        }
        tmp = tmp->next;
    }
}

在STM32上测试

  • software_timer_test.c:
software_timer_t timer1_t;    
software_timer_t timer2_t;
software_timer_t timer3_t;

void timer1_cb(void *parm)
{
    printf("1000ms >>> dyy\r\n");
}

void timer2_cb(void *parm)
{
    printf("2000ms >>> dyy\r\n");
}

void timer3_cb(void *parm)
{
    printf("500ms  >>> dyy\r\n");
} 

void SoftWareTimer_Init(void)
{
    software_timer_init(&timer1_t,1000,1000,timer1_cb);
    software_timer_init(&timer2_t,2000,2000,timer2_cb);
    software_timer_init(&timer3_t,500,500,timer3_cb);

    software_timer_start(&timer1_t);
    software_timer_start(&timer2_t);
    software_timer_start(&timer3_t);

串口助手打印信息
C语言——软件定时器

相关推荐