0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一种可用于单片机的中断高效处理与事件机制方法

jf_pJlTbmA9 来源:NevermindZZT 作者:NevermindZZT 2023-10-17 15:08 次阅读

嵌入式编程的需求千变万化,要做到系统稳定,又要代码可复用,就要做到高内聚低耦合

前言

我们通常认为,在中断中,不能执行耗时的操作,否则会影响系统的稳定性,尤其对于嵌入式编程。对于带操作系统的程序而言,可以通过操作系统的调度,将中断处理分成两个部分,耗时的操作可以放到线程中去执行,但是对于没有操作系统的情况,又应该如何处理呢

比较常见的,我们可能会定义一些全局变量,作为flag,然后在mainloop中不停的判断这些flag,再在中断中修改这些flag,最后在mainloop中执行具体的逻辑,但是这样,无疑会增加耦合,增加程序维护成本。

cpost

cpost正是应用在这种情况下的一个简单但又十分方便的工具,它可以特别方便的进行上下文的切换,减少模块耦合。

cpost借鉴的Android的handler机制,通过在mainloop中跑一个任务,然后在其他地方,可以是中断,也可以是模块逻辑中,直接抛出需要执行的函数,使其脱离调用处的上下文,运行在mainloop中。cpost还支持延迟处理,可以指定函数在抛出后多久执行

使用

cpost的使用十分简单,这里以使用在嵌入式无操作系统中为例,主要用作中断延迟处理的情况

1、配置系统tick

配置cpost.h中的宏CPOST_GET_TICK(),配置成获取系统tick,以stm32 hal为例

#define     CPOST_GET_TICK()            HAL_GetTick()

2、配置处理进程

在mainloop调用cpostProcess函数

int main(void)
{
    ...
    while (1)
    {
        cpostProcess();
    }
    return 0;
}

3、抛出任务

在中断等需要进行上下文切换的地方调用cpsot接口,使其在mainloop中运行

cpost(intHandler);

原理解析

cpost的原理其实很简单,其代码量也十分少,总共加起来就只有几十行代码,cpost维护了一个而全局的数组

CpostHandler cposhHandlers[CPOST_MAX_HANDLER_SIZE] = {0};

其中,数组的每一个元素表示包含了需要执行的函数和参数,当调用cpost接口时,被post的函数和参数会被保存在这个数组中,然后mainloop中运行的cpostProcess函数会遍历这个数组,当满足条件时,执行对应的函数,从而达到上下文切换的目的

void cpostProcess(void)
{
    for (size_t i = 0; i < CPOST_MAX_HANDLER_SIZE; i++)
    {
        if (cposhHandlers[i].handler)
        {
            if (cposhHandlers[i].time == 0 || CPOST_GET_TICK() >= cposhHandlers[i].time)
            {
                cposhHandlers[i].handler(cposhHandlers[i].param);
                cposhHandlers[i].handler = NULL;
            }
        }
    }
}

其实,cpost的方式,和一开始提到的使用全局的flag进行上下文切换的方法很像,只不过,cpost通过一个数组的维护和直接post函数的方式,省去了维护flag的成本,也不需要将需要执行的函数耦合到mianloop中,从而变得简单易用。

完美解耦 - cevent应用

对于模块化编程来说,如何实现各模块间的解耦一直是一个比较令人头疼的问题,特别是对于嵌入式编程,由于控制逻辑复杂,并且对程序体积有控制,经常容易写出各独立模块之间相互调用的问题。由此,cpost中的cevent组件,通过模仿Android系统中的广播机制,提供了一种非常简单的模块间解耦实现。

原理

cevent借鉴的是Android系统的广播机制,一方面,各模块在工作的时候,都会有多个具体的事件点,在高耦合的编程中,可能会在这些地方调用其他模块的功能,比如说,在通信模块接收到指令的时候,需要闪烁一下指示灯。

使用cevent,我们可以在这些地方抛出一个事件,当前模块不需要关心在这各地方需要执行哪些其他模块的逻辑,由其他模块,或者用户定义一个事件监听,当具体的事件发生时,执行相应的动作。

使用

cevent使用注册的方式监听事件,会依赖于编译环境,目前支持keil,iar,和gcc,对于gcc,需要修改链接文件(.ld),在只读数据区添加:

_cevent_start = .;
KEEP (*(cEvent))
_cevent_end = .;

1、初始化cevent

系统初始化时,调用ceventInit

ceventInit();

2、注册cevent事件监听

在c文件中,调用CEVENT_EXPORT导出事件监听

CEVENT_EXPORT(0, handler, (void *)param);

3、发送cevent事件

在事件发生的地方,调用ceventPost抛出事件

ceventPost(0);

使用cevent解耦模块初始化

嵌入式编程中,我们习惯会在程序启动的时候,调用各个模块的初始化函数,其实这也是一种耦合,会造成main函数中出现很长的初始化代码,借助cevent,我们可以对初始化进行优化解耦。

1、定义初始化事件

定义初始化事件的值,对于初始化,有些模块可能会依赖于其他模块的初始化,会有一个先后顺序要求,所以这里我们可以把初始化分成两个阶段,定义两个事件,当然,如果有更复杂的要求,可以再多分几个阶段,只需要多定义几个事件就行

#define     EVENT_INIT_STAGE1       0
#define     EVENT_INIT_STAGE2       1

2、初始化cevent,抛出事件

在main函数中初始化cevent,并抛出初始化事件

int main(void)
{
    ...
    ceventInit();

    ceventPost(EVENT_INIT_STAGE1);
    ceventPost(EVENT_INIT_STAGE2);
    ...
    return 0;
}

3、注册事件监听

对所有需要初始化的函数注册事件监听,这里我以对letter-shell注册事件监听为例,分为两个部分,初始化串口和初始化shell。

在serial模块中,将串口初始化注册到初始化第一阶段,cevent支持将不大于7个的参数直接传递到注册的监听函数中,下面的注册方式,相当于在EVENT_INIT_STAGE1事件发生的地方,也就是main函数中对应的位置,调用serialInit( debugSerial)

CEVENT_EXPORT(EVENT_INIT_STAGE1, serialInit, (void *)( debugSerial));

然后再shell模块中,将shell初始化函数注册到初始化第二阶段。

CEVENT_EXPORT(EVENT_INIT_STAGE1, shellInit);

使用cevent解耦mainloop

再无操作系统的嵌入式编程中,我们如果同时希望运行多个模块的逻辑,通常是在mainloop中循环调用,这种将函数写入mainloop的做法,也会增加耦合

int main(void)
{
    ...

    while (1)
    {
        // 写在mainloop中的模块逻辑
        shellTask( shell);
        LedProcess();
        ...
    }
    return 0;
}

通过使用cevent,也可以很方便的消除这种耦合

1、定义mainloop事件

定义mainloop事件的值

#define     EVENT_MAIN_LOOP         3

2、在mainloop中抛出事件

去掉mainloop中对其他模块的调用,改为排除mainloop事件

int main(void)
{
    ...

    while (1)
    {
        ceventPost(EVENT_MAIN_LOOP);
    }
    return 0;
}

3、在各模块中注册事件监听

分别在各个模块中,注册对mainloop事件的监听

CEVENT_EXPORT(EVENT_MAIN_LOOP, shellTask, (void *)( shell));
CEVENT_EXPORT(EVENT_MAIN_LOOP, LedProcess);

结语

cevent是一个非常小的模块,本身代码及其简单,但是,通过模仿广播机制,让cevent可以发挥很强大的功能,通过,还可以结合cpost,实现延迟事件等功能。

来源:csdnNevermindZZT

审核编辑 黄宇

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 单片机
    +关注

    关注

    6032

    文章

    44513

    浏览量

    632693
  • 嵌入式
    +关注

    关注

    5068

    文章

    19008

    浏览量

    302965
  • 嵌入式编程
    +关注

    关注

    0

    文章

    27

    浏览量

    10297
收藏 人收藏

    评论

    相关推荐

    一种可用于单片机的0-10V模拟量采集电路()

    在嵌入式系统中会用到0-10V电压信号输出的传感器。 而单片机ADC引脚的输入电压却比较低。 如STM32引脚输入电压最高为3.3V,高于3.3V会导致单片机损坏。 这篇文章介绍一种可用于
    发表于 03-16 14:30 1.2w次阅读
    <b class='flag-5'>一种</b><b class='flag-5'>可用于</b><b class='flag-5'>单片机</b>的0-10V模拟量采集电路(<b class='flag-5'>一</b>)

    单片机中断处理机制详解

    单片机用于物联网、自动控制系统、智能家电等领域,要求单片机能够实时响应外部触发的事件,中断机制单片机
    发表于 10-31 14:46 2708次阅读
    <b class='flag-5'>单片机</b>的<b class='flag-5'>中断</b><b class='flag-5'>处理机制</b>详解

    单片机外部中断的好处

    外部中断单片机实时地处理外部事件的一种内部机制。当外部事件发生时,单片机
    的头像 发表于 10-31 15:58 2154次阅读
    <b class='flag-5'>单片机</b>外部<b class='flag-5'>中断</b>的好处

    单片机开发设计之一种扩展微处理器(单片机)外部中断接口的方法

    一种扩展微处理器/单片机外部中断接口的方法、普通单片机
    发表于 10-28 19:56

    单片机中断处理机制

    单片机中断处理机制什么是中断?为什么要使用中断(中断的特点)什么是
    发表于 12-07 11:14

    Matlab 环境下PC 单片机的串行通信及数据处理

    结合单片机和Matlab 两者的优点,基于事件驱动的中断通信机制,提出一种Matlab 环境下PC
    发表于 05-18 13:09 73次下载

    单片机中断处理技术的应用与研究

    PIC 系列单片机,其硬件结构和指令系统采用了与众不同的设计手法。与51 或者其他系列的单片机相比,PIC 单片机中断机制有其特殊之处,本
    发表于 06-16 09:35 27次下载

    单片机中断处理技术的应用与研究

    单片机中断处理技术的应用与研究   引言   PIC系列单片机中断源已经达到14个.可谓相当丰富;但同时也带来了
    发表于 04-12 14:14 1637次阅读
    <b class='flag-5'>单片机</b>多<b class='flag-5'>中断</b><b class='flag-5'>处理</b>技术的应用与研究

    PC单片机串行通信的一种方法

    PC单片机串行通信的一种方法
    发表于 09-04 14:20 4次下载
    PC<b class='flag-5'>机</b>与<b class='flag-5'>单片机</b>串行通信的<b class='flag-5'>一种</b>新<b class='flag-5'>方法</b>

    51单片机定时器中断_51单片机中断系统_51单片机扩展中断的四种方法

    中断是为使单片机具有对外部或内部随机发生的事件进行处理而设置的。51单片机有5中断源,即有5
    发表于 12-08 10:15 1.1w次阅读
    51<b class='flag-5'>单片机</b>定时器<b class='flag-5'>中断</b>_51<b class='flag-5'>单片机</b><b class='flag-5'>中断</b>系统_51<b class='flag-5'>单片机</b>扩展<b class='flag-5'>中断</b>的四<b class='flag-5'>种方法</b>

    [学习笔记-01]关于单片机中断处理机制()

    单片机中断处理机制什么是中断?为什么要使用中断(中断的特点)什么是
    发表于 11-24 16:21 2次下载
    [学习笔记-01]关于<b class='flag-5'>单片机</b>的<b class='flag-5'>中断</b><b class='flag-5'>处理机制</b>(<b class='flag-5'>一</b>)

    单片机用按钮中断函数

    单片机用按钮中断函数  单片机中断一种能够使单片机响应外部信号的
    的头像 发表于 09-01 10:17 1461次阅读

    单片机中断功能及其应用

    事件的响应和处理。它具有实时性好、可靠性高、效率高等优点,广泛应用于各种电子设备和系统中。 单片机中断的基本概念
    的头像 发表于 01-30 14:45 4941次阅读

    单片机中断机制

    单片机中断机制一种重要的处理方式,它允许单片机在执行主程序的过程中,能够暂停当前任务,转而
    的头像 发表于 10-17 18:03 334次阅读

    单片机有哪些中断类型

    单片机中断是指在单片机执行程序的过程中,当外部设备或内部条件发生某个特定事件时,能够暂停当前正在执行的程序,转而去执行个特定的服务程序(称为中断
    的头像 发表于 10-17 18:12 381次阅读