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);

串口助手打印信息

原文地址:https://www.cnblogs.com/AresGuangjie/p/12392952.html

时间: 2024-08-30 14:51:24

C语言——软件定时器的相关文章

ucosiii浅析内核对象-软件定时器

内核对象和各种内核机制的函数接口都在os.h里声明,实现在各自的.c文件,比如os_tmr.c和os_time.c. C语言全局变量一般会默认初始化:局部变量如若不初始化,会分配垃圾数据的:建议使用时都手动初始化. 其实使用内核对象时,就类似与使用任务,只不过在创建对象之前,要先声明一个内核对象. 好了,上面闲聊了几句,今天来说说ucosiii的几个内核对象. 首先说"软件定时器",其实单纯的讲就是定时作用,这里我们要注意的就是,使用它方法和使用任务类似:那么我们就先来分析分析任务的执

毫秒,微妙级别软件定时器

单片机开发中,软件定时器是常用的工具.定时执行特定任务和延时功能,都可以用软件定时器实现. 常见的延时函数的实现做法有: 1. 使用空指令进行延时,通过控制空指令的执行次数,进行延时.优点:不需要占用系统外设.缺点:系统运行指定个空指令的时间不稳定,中途出现的中断处理会严重影响计时的精确性. 2.使用单片机的定时器外设,设定特定的时间产生中断,进行计时.优点:计时准确,不受其他中断影响计时.缺点:浪费单片机外设资源,并且延时处理不能嵌套调用,灵活性不够. 这里要介绍的是利用单片机内部的sysTi

实现自己的软件定时器

为什么要实现软件定时器: 在芯片平台上,地址空间也是相当宝贵的,如果保留了更多的硬件定时器的话,就需要更多的地址空间,那么我们能不能作个折中方案呢?答案是肯定的,我们可以使用一个硬件定时器,来模拟实现一个软件定时器,可以满足更多的定时需求,需要注意的一点就是软件定时器精度可能会有稍微误差,因为会涉及到任务调度.锁中断等,在对定时精度要求不高的场景,可以考虑使用软件定时器.Linux内核中的timer_list精度为10ms,这里我们来实现一套精度为1ms的软件定时器(当然可以实现精度为微秒级的,

高效软件定时器的设计

软件定时器在协议栈等很多场景都有广泛的应用,有时候会有大量的定时器同时处于工作状态,它们的超时时间各异,要高效的保证每个定时器都能够较为准确的超时并执行到其回调函数并不是一件易事.本文分析嵌入式实时操作系统Nucleus的定时器方案,它巧妙的管理了一条按照相对时间来排序的双向链表,避免每次tick中断都要遍历链表检查超时和更新剩余时间,实现了一种相当高效的软件定时器. 结构体TM_TCB来表示动态创建的定时器,其定义如下 typedef struct TM_TCB_STRUCT { /*Nucl

模仿linux内核定时器代码,用python语言实现定时器

大学无聊的时候看过linux内核的定时器,现在已经想不起来了,也不知道当时有没有看懂,现在想要模仿linux内核的定时器,用python写一个定时器,已经想不起来它的设计原理了,找了一篇blog,linux 内核定时器 timer_list详解. 看了好一会才有些明白,开始参照着用python写了一个.如果在设计服务器的时候,有大量需要精确到秒和秒以下的事件,自己写一个定时器,维护一个类似与内核timer_vec的数据结构,处理服务的定时事件,还是蛮高效的. 附上python代码,github:

软件定时器-闹钟提醒我们该吃饭吃饭,该睡觉睡觉

闹钟提醒我们该吃饭吃饭,该睡觉睡觉 原文地址:http://blog.csdn.net/u011833609/article/details/28862125 softwaretimer.h #ifndef _SOFTWARETIMER_H_ #define _SOFTWARETIMER_H_ typedef enum{z_false = 0, z_true = !z_false} z_bool; typedef unsigned char z_uchar; typedef unsigned c

μC/OS-II中使用软件定时器

在试着将μC/OS-II移植到ARM7芯片(LPC2138)上的过程中,发现使用OSTmrCreate创建的OSTmr始终都不能执行CallbackFunction,OS版本是v2.85,最后是这么解决的. 在文档<uCOS-II-RefMan.PDF>中找到了关于“OSTmrSignal()”这个函数的一段描述: OSTmrSignal() is called either by a task or an ISR to indicate that it’s time to update th

高质量,高效率的多国语言软件开发(Web/PC/Mobile),使用接口约束/调用不同语言资源

偶然间翻出了几年前写的一个小程序,把当时的资料整理整理分享一下. 当时为了给自己的软件实现多国语言功能,而开发的辅助工具:SE String Resource. 这是当时基于自己另一款 IDE 软件抽取的框架而开发的,并不是很复杂. 以下资料根据当时的记录整理,难免错漏,请见谅. SE String Resource 是一款辅助多国语言软件开发的实用工具,根本目的在于通过生成接口来约束不同语言资源的实现,使开发人员可以基于接口调用资源,多语言开发时不但对语言资源的可控性好,并且省时省力.除此之外

软件定时器osTimerCreate返回NULL

CMSIS-RTOS是对FreeRtos的封装,函数名比較适合纯软件编程. 如今的版本号是1.0.2. id1 = osTimerCreate(osTimer(Timer_1), osTimerOnce, NULL); 可是这个osTimerCreate总是返回0x00000000. 就是创建软件定时器不成功. watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/di