自定义循环队列、软件定时器、事件集,实用嵌入式代码库

这篇具有很好参考价值的文章主要介绍了自定义循环队列、软件定时器、事件集,实用嵌入式代码库。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、介绍

本篇博文分享一个很实用的嵌入式代码库。
它可灵活应用到有无RTOS的程序中,采用C语言面向对象的思路实现各个功能,尽可能最大化的复用代码,目前为止工具包包含:循环队列、软件定时器、事件集
网址:https://download.csdn.net/download/m0_38106923/87765476?spm=1001.2014.3001.5503

  • Queue 循环队列
    1. 支持动态、静态方式进行队列的创建与删除。
    2. 可独立配置缓冲区大小。
    3. 支持数据最新保持功能,当配置此模式并且缓冲区已满,若有新的数据存入,将会移除最早数据,并保持缓冲区已满。
  • Timer 软件定时器
    1. 支持动态、静态方式进行定时器的创建与删除。
    2. 支持循环单次模式。
    3. 可配置有无超时回调函数。
    4. 可配置定时器工作在周期间隔模式。
    5. 使用双向链表,超时统一管理,不会因为增加定时器而增加超时判断代码。
  • Event 事件集
    1. 支持动态、静态方式进行事件集的创建与删除。
    2. 每个事件最大支持32个标志位。
    3. 事件的触发可配置为**“标志与”“标志或”**。

2 、文件目录

toolkit
├── include                         // 包含文件目录
|   ├── toolkit.h                   // toolkit头文件
|   └── toolkit_cfg.h               // toolkit配置文件
├── src                             // toolkit源码目录
|   ├── tk_queue.c                  // 循环队列源码
|   ├── tk_timer.c                  // 软件定时器源码
|   └── tk_event.c                  // 事件集源码
├── samples                         // 例子
|   ├── tk_queue_samples.c          // 循环队列使用例程源码
|   ├── tk_timer_samples.c          // 软件定时器使用例程源码
|   └── tk_event_samples.c          // 事件集使用例程源码
└── README.md                       // 说明文档

3 、函数定义

3.1 配置文件


  • ToolKit配置项

    宏定义 描述
    TOOLKIT_USING_ASSERT ToolKit使用断言功能
    TOOLKIT_USING_QUEUE ToolKit使用循环队列功能
    TOOLKIT_USING_TIMER ToolKit使用软件定时器功能
    TOOLKIT_USING_EVENT ToolKit使用事件集功能
  • Queue 循环队列配置项

    宏定义 描述
    TK_QUEUE_USING_CREATE Queue 循环队列使用动态创建和删除
  • Timer 软件定时器配置项

    宏定义 描述
    TK_TIMER_USING_CREATE Timer 软件定时器使用动态创建和删除
    TK_TIMER_USING_INTERVAL Timer 软件定时器使用间隔模式
    TK_TIMER_USING_TIMEOUT_CALLBACK Timer 软件定时器使用超时回调函数
  • Event 事件集配置项

    宏定义 描述
    TK_EVENT_USING_CREATE Event 事件集使用动态创建和删除

说明:当配置TOOLKIT_USING_ASSERT后,所有功能都将会启动参数检查。

3.2 Queue 循环队列API函数


以下为详细API说明及简要示例程序,综合demo可查看tk_queue_samples.c示例。

3.2.1 动态创建队列

注意:当配置TOOLKIT_USING_QUEUE后,才能使用此函数。此函数需要用到malloc

struct tk_queue *tk_queue_create(uint16_t queue_size, uint16_t max_queues, bool keep_fresh);
参数 描述
queue_size 缓存区大小(单位字节)
max_queues 最大队列个数
keep_fresh 是否为保持最新模式,true:保持最新;false:默认(存满不能再存)
返回值 创建的队列对象(NULL为创建失败)

队列创建示例:

int main(int argc, char *argv[])
{
    /* 动态方式创建一个循环队"queue",缓冲区大小50字节,不保持最新 */
    struct tk_queue *queue = tk_queue_create(50, 1, false);
    if( queue == NULL){
        printf("队列创建失败!\n");
    }
    /* ... */
    /* You can add your code under here. */
    return 0;
}
3.2.2 动态删除队列

注意:当配置TOOLKIT_USING_QUEUE后,才能使用此函数。此函数需要用到free。必须为动态方式创建的队列对象。

bool tk_queue_delete(struct tk_queue *queue);
参数 描述
queue 要删除的队列对象
返回值 true:删除成功;false:删除失败
3.2.3 静态初始化队列
bool tk_queue_init(struct tk_queue *queue, void *queuepool, uint16_t pool_size, uint16_t queue_size, bool keep_fresh);
参数 描述
queue 要初始化的队列对象
*queuepool 队列缓存区
pool_size 缓存区大小(单位字节)
queue_size 队列元素大小(单位字节)
keep_fresh 是否为保持最新模式,true:保持最新;false:默认(存满不能再存)
返回值 true:初始化成功;false:初始化失败

队列创建示例:

int main(int argc, char *argv[])
{
    /* 定义一个循环队列 */
    struct tk_queue queue;
    /* 定义循环队列缓冲区 */
    uint8_t queue_pool[100];
    /* 静态方式创建一个循环队列"queue",缓存区为queue_pool,大小为queue_pool的大小,模式为保持最新 */
    if( tk_queue_init(&queue, queue_pool, sizeof(queue_pool), 
                      sizeof(queue_pool[0]), true) == false){
        printf("队列创建失败!\n");
    }
    /* ... */
    /* You can add your code under here. */
}

3.2.4 静态脱离队列

注意: 会使缓存区脱离与队列的关联。必须为静态方式创建的队列对象。

bool tk_queue_detach(struct tk_queue *queue);
参数 描述
queue 要脱离的队列对象
返回值 true:脱离成功;false:脱离失败
3.2.5 清空队列
bool tk_queue_clean(struct tk_queue *queue);
参数 描述
queue 要清空的队列对象
返回值 true:清除成功;false:清除失败
3.2.6 判断队列是否为空
bool tk_queue_empty(struct tk_queue *queue);
参数 描述
queue 要查询的队列对象
返回值 true:空;false:不为空
3.2.7 判断队列是否已满
bool tk_queue_full(struct tk_queue *queue);
参数 描述
queue 要查询的队列对象
返回值 true:满;false:不为满
3.2.8 从队列中读取一个元素(不从队列中删除)
bool tk_queue_peep(struct tk_queue *queue, void *pval);
参数 描述
queue 队列对象
*pval 读取值地址
返回值 true:读取成功;false:读取失败
3.2.9 移除一个元素
bool tk_queue_remove(struct tk_queue *queue);
参数 描述
queue 要移除元素的对象
返回值 true:移除成功;false:移除失败
3.2.10 向队列压入(入队)1个元素数据
bool tk_queue_push(struct tk_queue *queue, void *val);
参数 描述
queue 要压入的队列对象
*val 压入值
返回值 true:成功;false:失败
3.2.11 从队列弹出(出队)1个元素数据
bool tk_queue_pop(struct tk_queue *queue, void *pval);
参数 描述
queue 要弹出的队列对象
*pval 弹出值
返回值 true:成功;false:失败
3.2.12 查询队列当前数据长度
uint16_t tk_queue_curr_len(struct tk_queue *queue);
参数 描述
queue 要查询的队列对象
返回值 队列数据当前长度
3.2.13 向队列压入(入队)多个元素数据
uint16_t tk_queue_push_multi(struct tk_queue *queue, void *pval, uint16_t len);
参数 描述
queue 要压入的队列对象
*pval 压入数据首地址
len 压入元素个数
返回值 实际压入个数
3.2.14 从队列弹出(出队)多个元素数据
uint16_t tk_queue_pop_multi(struct tk_queue *queue, void *pval, uint16_t len);
参数 描述
queue 要弹出的队列对象
*pval 存放弹出数据的首地址
len 希望弹出的数据个数
返回值 实际弹出个数

3.3 Timer 软件定时器API函数


以下为详细API说明及简要示例程序,综合demo可查看tk_timer_samples.c示例。

3.3.1 软件定时器功能初始化

注意:此函数在使用定时器功能最初调用,目的是创建定时器列表头结点,和配置tick获取回调函数。

bool tk_timer_func_init(uint32_t (*get_tick_func)(void));
参数 描述
get_tick_func 获取系统tick回调函数
返回值 true:初始化成功;false:初始化失败
3.3.2 动态创建定时器

注意:当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到malloc

struct tk_timer *tk_timer_create(void(*timeout_callback)(struct tk_timer *timer));
参数 描述
timeout_callback 定时器超时回调函数,不使用可配置为NULL
返回值 创建的定时器对象(NULL为创建失败)

定时器创建示例:

/* 定义获取系统tick回调函数 */
uint32_t get_sys_tick(void)
{
    return tick;
}

/* 定时器超时回调函数 */
void timer_timeout_callback(struct tk_timer *timer)
{
    printf("timeout_callback: timer timeout:%ld\n", get_sys_tick());
}

int main(int argc, char *argv[])
{
    /* 初始化软件定时器功能,并配置tick获取回调函数*/
    tk_timer_func_init(get_sys_tick);
    
    /* 定义定时器指针 */
    tk_timer_t timer = NULL;
    /* 动态方式创建timer,并配置定时器超时回调函数 */
    timer = tk_timer_create((tk_timer_timeout_callback *)timer_timeout_callback);
    if (timer == NULL)
    {
        printf("定时器创建失败!\n");
        return 0;
    }
    /* ... */
    /* You can add your code under here. */
    return 0;
}

3.3.3 动态删除定时器

当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到free。必须为动态方式创建的定时器对象。

bool tk_timer_delete(struct tk_timer *timer);
参数 描述
timer 要删除的定时器对象
返回值 true:删除成功;false:删除失败
3.3.4 静态初始化定时器
bool tk_timer_init(struct tk_timer *timer, void (*timeout_callback)(struct tk_timer *timer));
参数 描述
timer 要初始化的定时器对象
timeout_callback 定时器超时回调函数,不使用可配置为NULL
返回值 true:创建成功;false:创建失败

队列创建示例:

/* 定义获取系统tick回调函数 */
uint32_t get_sys_tick(void)
{
    return tick;
}

/* 定时器超时回调函数 */
void timer_timeout_callback(struct tk_timer *timer)
{
    printf("timeout_callback: timer timeout:%ld\n", get_sys_tick());
}

int main(int argc, char *argv[])
{
    /* 定义定时器timer */
    struct tk_timer timer;
    bool result = tk_timer_init( &timer,(tk_timer_timeout_callback *)timer_timeout_callback);
    if (result == NULL)
    {
        printf("定时器创建失败!\n");
        return 0;
    }
    /* ... */
    /* You can add your code under here. */
    return 0;
}
3.3.5 静态脱离定时器

注意: 会将timer从定时器链表中移除。必须为静态方式创建的定时器对象。

bool tk_timer_detach(struct tk_timer *timer);
参数 描述
timer 要脱离的定时器对象
返回值 true:脱离成功;false:脱离失败
3.3.6 定时器启动
bool tk_timer_start(struct tk_timer *timer, tk_timer_mode mode, uint32_t delay_tick);
参数 描述
timer 要启动的定时器对象
mode 工作模式,单次: TIMER_MODE_SINGLE循环: TIMER_MODE_LOOP
delay_tick 定时器时长(单位tick)
返回值 true:启动成功;false:启动失败
3.3.7 定时器停止
bool tk_timer_stop(struct tk_timer *timer);
参数 描述
timer 要停止的定时器对象
返回值 true:停止成功;false:停止失败
3.3.8 定时器继续
bool tk_timer_continue(struct tk_timer *timer);
参数 描述
timer 要继续的定时器对象
返回值 true:继续成功;false:继续失败
3.3.9 定时器重启

注意:重启时长为最后一次启动定时器时配置的时长。

bool tk_timer_restart(struct tk_timer *timer);
参数 描述
timer 要重启的定时器对象
返回值 true:重启成功;false:重启失败
3.3.10 获取定时器模式
tk_timer_mode tk_timer_get_mode(struct tk_timer *timer);
参数 描述
timer 要获取的定时器对象
返回值 定时器模式
定时器模式 描述
TIMER_MODE_SINGLE 单次模式
TIMER_MODE_LOOP 循环模式
3.3.11 获取定时器状态
tk_timer_state tk_timer_get_state(struct tk_timer *timer);
参数 描述
timer 要获取的定时器对象
返回值 定时器状态
定时器模式 描述
TIMER_STATE_RUNNING 运行状态
TIMER_STATE_STOP 停止状态
TIMER_STATE_TIMEOUT 超时状态
3.3.12 定时器处理
bool tk_timer_loop_handler(void);
参数 描述
返回值 true:正常;false:异常,在调用此函数前,未初始化定时器功能“tk_timer_func_init

注意:tk_timer_loop_handler函数要不断的循环调用。

3.3.13 超时回调函数

函数原型

typedef void (*timeout_callback)(struct tk_timer *timer);

说明:超时回调函数可定义多个,即一个定时器对应一个回调函数,也可多个定时器对应一个回调函数。

  • 一对一

    /* 定义两个回调函数,对应定时器timer1和timer2 */
    void timer1_timeout_callback(struct tk_timer *timer){
    	printf("定时器1超时!\n");
    }
    void timer2_timeout_callback(struct tk_timer *timer){
    	printf("定时器2超时!\n");
    }
    /* 创建两个定时器,配置单独超时回调函数 */
    timer1 = tk_timer_create((timeout_callback *)timer1_timeout_callback);
    timer2 = tk_timer_create((timeout_callback *)timer2_timeout_callback);
    
  • 多对一

    /* 定时器timer1和timer2共用一个回调函数,在回调函数做区分 */
    void timer_timeout_callback(struct tk_timer *timer){
    	if (timer == timer1)
    		printf("定时器1超时!\n");
        else if (timer == timer2)
            printf("定时器2超时!\n");
    }
    /* 创建两个定时器,使用相同的超时回调函数 */
    timer1 = tk_timer_create((timeout_callback *)timer_timeout_callback);
    timer2 = tk_timer_create((timeout_callback *)timer_timeout_callback);
    

3.4 Event 事件集API函数


以下为详细API说明及简要示例程序,综合demo可查看tk_event_samples.c示例。

3.4.1 动态创建一个事件

注意:当配置TOOLKIT_USING_EVENT后,才能使用此函数。此函数需要用到malloc

struct tk_event *tk_event_create(void);
参数 描述
返回值 创建的事件对象(NULL为创建失败)
3.4.2 动态删除一个事件

当配置TOOLKIT_USING_TIMER后,才能使用此函数。此函数需要用到free。必须为动态方式创建的事件对象。文章来源地址https://www.toymoban.com/news/detail-437636.html

bool tk_event_delete(struct tk_event *event);
参数 描述
event 要删除的事件对象
返回值 true:删除成功;false:删除失败
3.4.3 静态初始化一个事件
bool tk_event_init(struct tk_event *event);
参数 描述
event 要初始化的事件对象
返回值 true:创建成功;false:创建失败
3.4.4 发送事件标志
bool tk_event_send(struct tk_event *event, uint32_t event_set);
参数 描述
event 发送目标事件对象
event_set 事件标志,每个标志占1Bit,发送多个标志可“|”
返回值 true:发送成功;false:发送失败
3.4.5 接收事件
bool tk_event_recv(struct tk_event *event, uint32_t event_set, uint8_t option, uint32_t *recved);
参数 描述
event 接收目标事件对象
event_set 感兴趣的标志,每个标志占1Bit,多个标志可“|”
option 操作,标志与:TK_EVENT_OPTION_AND; 标志或:TK_EVENT_OPTION_OR; 清除标志:TK_EVENT_OPTION_CLEAR
返回值 true:发送成功;false:发送失败

到了这里,关于自定义循环队列、软件定时器、事件集,实用嵌入式代码库的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【javaEE】阻塞队列、定时器、线程池

    目录 🌴一、阻塞队列 1.概念 2.生产者消费者模型 3.阻塞队列的实现 🏹二、定时器 1.引出定时器 2.定时器的实现 🔥三、线程池 1.引出线程池 2.ThreadPoolExecutor 构造方法 3.标准数据库的4种拒绝策略【经典面试题】【重点掌握】 4.线程池的实现   1.概念 ✨对于队列,首先我们想

    2023年04月21日
    浏览(44)
  • QT(9.3)定时器,绘制事件

    自定义一个闹钟 pro文件: 头文件: 自定义函数:   主函数: 运行结果:

    2024年02月10日
    浏览(38)
  • ESP32---定时器+消息队列的使用

     创建消息队列 初始化定时器和中断 创建任务 在任务中执行事件  前面是默认配置,设置定时器的闹钟(多久进一次中断),使能定时器,注册中断函数,开启定时器  在这里发送消息队列 是个结构体   任务里面就接受到消息 就让初始化的结构体中秒加1 如果秒大于了100 就log一

    2024年02月11日
    浏览(50)
  • 多线程案例 | 单例模式、阻塞队列、定时器、线程池

    单例模式 单例模式是 设计模式 的一种 什么是设计模式? 设计模式好比象棋中的 “棋谱”,红方当头炮,黑方马来跳,针对红方的一些走法,黑方应招的时候有一些固定的套路,按照套路来走局势就不会吃亏,也就发明了一组\\\"棋谱\\\",称为设计模式 软件开发中也有很多常见

    2024年02月15日
    浏览(48)
  • 【JavaEE初阶】多线程(四)阻塞队列 定时器 线程池

    概念 阻塞队列是一种特殊的队列. 也遵守 “ 先进先出 ” 的原则. 阻塞队列能是一种线程安全的数据结构, 并且具有以下特性: 当队列满的时候, 继续入队列就会阻塞, 直到有其他线程从队列中取走元素. 当队列空的时候, 继续出队列也会阻塞,直到有其他线程往队列中插入元素

    2023年04月26日
    浏览(54)
  • 【Java】多线程案例(单例模式,阻塞队列,定时器,线程池)

    ❤️ Author: 老九 ☕️ 个人博客:老九的CSDN博客 🙏 个人名言:不可控之事 乐观面对 😍 系列专栏: 单例模式是设计模式之一。代码当中的某个类,只能有一个实例,不能有多个。单例模式分为:饿汉模式和懒汉模式 饿汉模式表示很着急,就想吃完饭剩下很多碗,然后一

    2024年02月06日
    浏览(44)
  • 对定时器中影子寄存器以及更新操作和更新事件理解

    本人是stm32初学者,近期在看定时器参考文档时遇到些阻碍,再参考了众多CSDN博主的文章后,得到了一些个人理解,将其发布出来,本文也对一些参考的文章进行了不少复制粘贴同时也在这些文章必要位置加入了个人看法,文章链接附在最后 由于本人是初学者,本文一定存在

    2024年02月05日
    浏览(42)
  • FreeRTOS(6)----软件定时器

    软件定时器允许设置一段时间, 当设定的时间到达之后就会执行指定的功能函数 ,被定时器调用的这个函数叫做定时器的回调函数。 回调函数的两次执行间隔 叫做定时器的定时周期。 回调函数是在定时器服务任务中执行的,因为定时器服务任务是由内核产生,无法由用户

    2024年02月05日
    浏览(37)
  • STM32软件定时器

    目录 什么是定时器? 软件定时器优缺点 软件定时器原理 软件定时器相关配置 单次定时器和周期定时器 软件定时器相关 API 函数 1. 创建软件定时器 2. 开启软件定时器 3. 停止软件定时器 4. 复位软件定时器 5. 更改软件定时器定时时间 实操 cubeMX配置 代码实现  简单可以理解为

    2024年02月11日
    浏览(38)
  • Java 多线程系列Ⅳ(单例模式+阻塞式队列+定时器+线程池)

    设计模式就是软件开发中的“棋谱”,软件开发中也有很多常见的 “问题场景”。针对这些问题场景,大佬们总结出了一些固定的套路。按照这些套路来实现代码可能不会很好,但至少不会很差。当前阶段我们需要掌握两种设计模式: (1)单例模式 (2)工厂模式 概念/特征

    2024年02月09日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包