不使用RTOS,单片机也可以进行任务调度。

嵌入式电子 2023-12-05 13:34

1、介绍

一种无OS的MCU实用软件框架,包括任务轮询管理,命令管理器、低功耗管理、环形缓冲区等实用模块。系统中广泛利用自定义段技术减少各个模块间的耦合关系,大大提供程序的可维护性。

2、主要功能

  • 支持模块自动化管理,并提供不同优先等级初始化声明接口。
  • 支持任务轮询管理,通过简单的宏声明即可实现,不需要复杂的声明调用。
  • 支持低功耗管理,休眠与唤醒通知。
  • 支持命令行解析,命令注册与执行。
  • blink设备支持,统一管理LED、震动马达、蜂鸣器

3、使用说明

完整的代码可以参考工程文件,系统开发平台如下:
MCU:STM32F401RET6
IDE:IAR 7.4或者Keil MDK 4.72A

3.1 任务初始化及任务轮询管理(module)

使用此模块前需要系统提供滴答定时器,用于驱动任务轮询作业。(参考platform.c)
//定时器中断(提供系统滴答)void SysTick_Handler(void){    systick_increase(SYS_TICK_INTERVAL); //增加系统节拍}
注册初始化入口及任务(参考自key_task.c)
static void key_init(void){    /*do something*/}
static void key_scan(void){ /*do something*/}
module_init("key", key_init); //注册按键初始化接口driver_register("key", key_scan, 20);      //注册按键任务(20ms轮询1次)

3.2 命令管理器(cli)

适用于在线调试、参数配置等(参考使用cli_task.c),用户可以通过串口输出命令行控制设备行为、查询设备状态等功能。

命令格式:

cli支持的命令行格式如下:
<cmd name> < param1> < param2> < paramn>  < \r\n ><cmd name> ,< param1>, < param2>, < paramn>,  < \r\n >
每行命令包含一个命令名称+命令参数(可选),命令名称及参数可以通过空格或者','进行分隔。

系统默认命令:

cli系统自带了2条默认命令,分别是"?"与"help"命令,输入他们可以列出当前系统包含的命令列表,如下所示:
?         - alias for 'help'help      - list all command.pm        - Low power control commandreset     - reset systemsysinfo   - show system infomation.

适配命令管理器:

完整的例子可以参考cli_task.c.
static cli_obj_t cli;                               /*命令管理器对象 */
/* * @brief 命令行任务初始化 * @return none */ static void cli_task_init(void){ cli_port_t p = {tty.write, tty.read}; /*读写接口 */ cli_init(&cli, &p); /*初始化命令行对象 */ cli_enable(&cli); cli_exec_cmd(&cli,"sysinfo"); /*显示系统信息*/}
/* * @brief 命令行任务处理 * @return none */ static void cli_task_process(void){ cli_process(&cli);}
module_init("cli", cli_task_init); task_register("cli", cli_task_process, 10);          /*注册命令行任务*/


命令注册:

以复位命令为例(参考cmd_devinfo.c):
#include "cli.h"//.../*  * @brief       复位命令 */ int do_cmd_reset(struct cli_obj *o, int argc, char *argv[]){    NVIC_SystemReset();    return 0;}cmd_register("reset",do_cmd_reset, "reset system");


3.3 低功耗管理器(pm)

控制间歇运行,降低系统功耗。其基本的工作原理是通过轮询系统中各个模块是否可以允许系统进入低功耗。实际上这是一种判决机制,所有模块都具有有票否决权,即只要有一个模块不允许休眠,那么系统就不会进入休眠状态。pm模块在休眠前会统计出各个模块会返回最小允许休眠时长,并以最小休眠时长为单位进行休眠。

如何适配:

使用前需要通过pm_init进行初始化适配,并提供当前系统允许的最大休眠时间,进入休眠的函数接口,基本的接口定义如下:
/*低功耗适配器 ---------------------------------------------------------*/typedef struct {    /**     * @brief    系统最大休眠时长(ms)     */      unsigned int max_sleep_time;    /**     * @brief     进入休眠状态     * @param[in] time - 期待休眠时长(ms)     * @retval    实际休眠时长     * @note      休眠之后需要考虑两件事情,1个是需要定时起来给喂看门狗,否则会在休眠     *            期间发送重启.另外一件事情是需要补偿休眠时间给系统滴答时钟,否则会     *            造成时间不准。     */         unsigned int (*goto_sleep)(unsigned int time);}pm_adapter_t;void pm_init(const pm_adapter_t *adt);
void pm_enable(void);
void pm_disable(void);
void pm_process(void);
完成的使用例子可以参考platform-lowpower.c,默认情况下是禁用低功耗功能的,读者可以去除工程中原来不带低功耗版本的platform.c,并加入platform-lowpower.c文件进行编译即可使用。

注册低功耗设备:

以按键扫描为例,正常情况下,如果按键没有按下,那么系统休眠可以进入休眠状态,对按键功能是没有影响的。如果按键按下时,那么系统需要定时唤醒并轮询按键任务。
所以在一个低功耗系统下,为了不影响按键实时性需要处理好两个事情:
  1. 系统休眠状态下,如果有按键按下,那系统系统应立即唤醒,以便处理接下来的扫描工作。
  2. 如果按键按下时,系统可以进入休眠,但需要定时唤醒起来轮询按键任务。
对于第一种情况,将按键配置为边沿中断唤醒即可,以STM32F4为例(参考key_task.c),它支持外部中断唤醒功能。
/*  * @brief       按键 io初始化 *              PC0 -> key; * @return      none */ static void key_io_init(void){    /* Enable GPIOA clock */    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);
gpio_conf(GPIOC, GPIO_Mode_IN, GPIO_PuPd_UP, GPIO_Pin_0); //低功耗模式下,为了能够检测到按键,配置为中断唤醒 RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOC, EXTI_PinSource0); exti_conf(EXTI_Line0, EXTI_Trigger_Falling, ENABLE); nvic_conf(EXTI0_IRQn, 0x0F, 0x0F); key_create(&key, readkey, key_event); /*创建按键*/}
对于第二种情况,可以通过pm_dev_register来处理,当系统请求休眠时,如果此时按键按下,则返回下次唤醒时间即可,如下面的例子所示。
//参考key_task.c#include "pm.h"                                     /* * @brief    休眠通知 */static unsigned int  key_sleep_notify(void){    return key_busy(&key) || readkey() ? 20 : 0;    /* 非空闲时20ms要唤醒1次*/} pm_dev_register("key", NULL, key_sleep_notify, NULL);


3.4 blink模块

具有闪烁特性(led, motor, buzzer)的设备(led, motor, buzzer)管理:
使用步骤:
  • 需要系统提供滴答时钟,blick.c中是通过get_tick()接口获取,依赖module模块
  • 需要在任务中定时进行轮询
或者通过"module"模块的任务注册来实现:
task_register("blink", blink_dev_process, 50);  //50ms轮询1次

LED驱动:

blink_dev_t led;                             //定义led设备
/* *@brief 红色LED控制(GPIOA.8) *@param[in] on - 亮灭控制 */static void led_ctrl(int on){ if (on) GPIOA->ODR |= (1 << 8); else GPIOA->ODR &= ~(1 << 8);}
/* *@brief led初始化程序 */void led_init(void){ led_io_init(void); //led io初始化 blink_dev_create(&led, led_ctrl); //创建led设备 blink_dev_ctrl(&led, 50, 100, 0); //快闪(50ms亮, 100ms灭)}

3.5 按键管理模块

类似blink模块,使用之前有两个注意事项:
  • 需要系统提供滴答时钟,key.c中是通过get_tick()接口获取,依赖module模块
  • 需要在任务中定时进行轮询
key_t key;                             //定义按键管理器
/* *@brief 按键事件 *@param[in] type - 按键类型(KEY_PRESS, KEY_LONG_DOWN, KEY_LONG_UP) *@param[in] duration - 长按持续时间 */void key_event(int type, unsigned int duration){ if (type == KEY_PRESS) { //短按 } else if (type == KEY_LONG_DOWN) { //长按 }}
//读取键值(假设按键输出口为STM32 MCU PA8)int read_key(void){ return GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8) == Bit_RESET;}
/* *@brief 按键初始化 */void key_init(void){ //打开GPIO 时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //配置成输入模式 gpio_conf(GPIOA, GPIO_Mode_IN, GPIO_PuPd_NOPULL, GPIO_Pin_8); //创建1个按键 key_create(&key, read_key, key_event); }
来源:https://gitee.com/moluo-tech/CodeBrick


关注公众号,加星标,回复1024获取学习资料,每天进步一点点。


声明:

本号原创、转载的文章、图片等版权归原作者所有,如有侵权,请联系删除。

关注、点赞、在看、转发,支持优质内容! 

评论 (0)
  •  配图来自Canva可画受宏观环境影响,降本增效成为多数企业发展的主旋律。企业大规模缩减开支成为了市场常态,这使得多数SaaS企业TO B端的生意受阻,一些关于SaaS寒冬的传言愈演愈烈,作为SaaS领域最重要的细分赛道之一,CRM SaaS也处于不温不火状态。头部CRM SaaS厂商的运营情况往往综合反映行业的景气程度,是整个行业的晴雨表。在海外,美国客户关系管理软件巨头Salesforce深陷裁员风波。知情人士称,美国客户关系管理软件巨头Salesforce将裁员近700人,约占该
    刘旷 2024-02-23 11:24 78浏览
  • 固态光耦合器是一种光学器件,通常用于隔离和传递电信号或数据信号的装置。在不断发展的电子领域中,一个经常被忽视的关键组件是固态光耦合器。尽管它对于确保电子系统的顺利运行具有重要意义,但许多用户发现自己缺乏对其内部工作原理以及相对于传统同行的优势的详细了解。固态光耦合器基础知识:固态光耦合器,也称为光隔离器,是设计用于使用光波传输电信号的重要组件。与传统设备不同,这些设备利用半导体技术,结合发光二极管(LED)和光电探测器来实现信号隔离。内部组成及工作原理:让我们深入研究这些非凡组件的核心。典型的固
    腾恩科技-彭工 2024-02-23 16:18 61浏览
  • 在不断发展的技术领域,光耦合器在确保无缝通信和可靠信号传输方面的作用变得越来越关键。本文深入探讨了光耦合器的复杂性,阐明了其重要性,探索了进步,并解决了光耦合器技术人员面临的常见问题。光耦合器基础知识:光耦合器,也称为光隔离器,是电子电路中的重要组件,旨在使用光波传输电信号。核心原理涉及通过光束传输信号,确保输入和输出之间的电气隔离。智能光耦合器的演变:随着智能光耦合器的出现,光耦合器的传统用途得到了扩展。这标志着一个革命性的时代,光耦合器无缝集成到智能系统中,实现互联世界中各种设备之间的通信。
    腾恩科技-彭工 2024-02-23 16:16 54浏览
  • 概述 AP8P059 是一款集成低压 LDO、光 控、充电控制、过充保护、欠压保护、PIR 感应、延时为一体的人体感应太阳能 LED 灯控制芯片,只需要很少的外接元件,适 用于锂电池供电的PIR人体感应LED灯具 的应用。 外置的一级带通增益放大 器便于客户调整感应灵敏度,可与多个品 牌 PIR 传感器匹配,进行信号预处理。 还内置了高精度高PSRR的 LDO,该 LDO 给 PIR 传感器供电,可有 效抑制电源和环境噪声,提高抗干扰能力。 采用了 SOP8 封装。 特点  工作待机电
    Auguss 2024-02-23 15:00 56浏览
  • 在一个繁忙的化工厂里,三个控制方法——概率控制、PID控制与前馈控制,各自担当着重要的角色。一天,化工厂接到一个紧急任务,需要生产一种新型的高分子材料。这种材料的生产过程对温度、压力和流量的控制要求极高,稍有差池就会导致产品质量不达标。面对这一挑战,化工厂决定让三种控制方法联手,共同确保生产过程的稳定性和精确性。概率控制首先站了出来。它说:“我先来做个大概的预测,根据历史数据和经验,我们可以估算出生产过程中可能出现的各种情况及其概率。这样,我们就可以提前做好准备,应对可能出现的风险。”PID控制
    丙丁先生 2024-02-23 05:38 72浏览
  • 来源:虹科工业智能互联 虹科技术丨PTP时钟源设备全攻略:从普通时钟到透明时钟的进阶之路原文链接:https://mp.weixin.qq.com/s/ArBtuLpU6mXax4QWmZDKfQ欢迎关注虹科,为您提供最新资讯!#PTP #普通时钟 #透明时钟导读在现代通信技术中,精确时间同步对于保障网络性能至关重要。PTP(Precision Time Protocol)时钟源设备作为实现高精度时间同步的关键组件,其配置和选择对于网络架构师和工程师来说至关重要。本文将探讨普通时钟和透明时钟的特
    虹科电子科技 2024-02-22 16:15 89浏览
  • 在《WiMinet 评说 1.2:多跳无线网络的现状》一文中,我们提到:在室外长距离的无线自组织网络中,由于节点之间的链路损耗较大,其链路预算相对不足,其包误码率PER会相应升高,也就是丢包概率 p 会比较大;而在一个大规模网络中,某些分支节点的通讯链路又会比较深,也就是网络跳数 n 比较大,在这种情况下其通讯成功率Pn自然也就显著下降了,人们的切身感受就是这个链路不太稳定。 此时人们的第一反应自然是上 TCP 算法,在发送节点启用 TCP Client 算法,在接收点启用 TCP Se
    微网高通WiMinet 2024-02-23 15:24 51浏览
  • 产品描述AP2915 是一款可以一路灯串切换两路灯串的降压恒流驱动器,高效率、外围简单、内置功率管,适用于5-80V 输入的高精度降压 LED 恒流驱动芯片。内置功率管输出最大功率可达 12W,最大电流 1.2A。AP2915 一路灯亮切换两路灯亮,其中一路灯亮可以全亮,可以半亮。AP2915 工作频率固定在 150KHZ左右,同时内置抖频电路,可以降低对其他设备的 EMI干扰。另外采用平均电流采样模式,可以提高宽输入电压情况下的电流精度。AP2915 带有输出短路保护功能,5V~80V 输入条
    Auguss 2024-02-23 14:14 59浏览
  • 披星戴月,跋山涉水,我们的爱车始终与我们“并肩作战”,年底也需要“犒劳”一下,做个“全身SPA”。缺少的油液及时补充,磨损的轮胎、刹车片及时更换,老旧的小零件也要适当换新。“SPA”清单检查刹车系统检查刹车片磨损情况,如果磨损过度,需要更换新的刹车片;检查刹车盘是否磨损、刹车油是否需要更换。检查油液包括机油、刹车油、转向助力油、防冻液等,要检查油液是否充足、是否需要更换或添加。检查机油滤清器查看密封圈是否完好,如果发现密封圈已经损坏或老化,需要更换新的密封圈。检查轮胎检查轮胎气压是否正常、轮胎表
    艾迈斯欧司朗 2024-02-23 18:25 33浏览
  • 双方的合作可助力开发人员在两分钟内将新开发板配置入网 致力于以安全、智能无线连接技术,建立更互联世界的全球领导厂商Silicon Labs(亦称“芯科科技”,NASDAQ:SLAB)日前宣布,公司与开源硬件和软件领域的全球领导者Arduino建立了新的合作伙伴关系,将支持Arduino开发者社区的3,300万用户更好地实现Matter over Thread应用的无缝开发。Arduino的首个Matter软件库是与芯科科技合作开发的,目前可在芯科科技的xG24 Explorer套件和
    电子科技圈 2024-02-23 11:44 70浏览
  • 在科研的世界里,概率论就像一座坚实的桥梁,连接着理论与实践。说到概率论,不得不提门捷列夫纸牌和法拉第抛磁铁这两个有趣的故事。门捷列夫,这位化学界的巨匠,不仅在元素周期表上做出了卓越贡献,还以他的智慧和幽默为概率论教学带来了乐趣。据说,在一次概率论的课堂上,他拿出了一副特制的纸牌,牌面上印有各种化学元素和反应。学生们通过洗牌、抽牌等游戏形式,亲身感受到了概率的奥妙,这不仅使概率论变得生动有趣,还加深了对这一学科的理解。而法拉第,这位电磁学领域的先驱,也曾在科研中巧妙地运用了概率论。他著名的抛磁铁实
    丙丁先生 2024-02-23 05:32 69浏览
我要评论
0
0
点击右上角,分享到朋友圈 我知道啦
请使用浏览器分享功能 我知道啦