函数表驱动法

前言

这篇文章中,简单介绍了过长的if-else判断解决办法,里面提到了一个方法——函数表驱动法。由于本人在单片机开发中经常需要用到状态机轮询,这里可以使用switch-case和函数表驱动。下面给出一个在VS2013环境下编译通过的示例,方便以后移植。

代码清单

#include "stdafx.h"

//事件
/****************************************/
enum user_event{
    EVENT_A,
    EVENT_B,
    EVENT_C,
    EVENT_D,
};

//保存当前的事件状态
static user_event cur;
void setEvent(user_event c)
{
    cur = c;
}

user_event getEvent(void)
{
    return cur;
}
/******************************************/


//函数指针
typedef void (*EventFuncHandlePtr)(void);

//驱动表类型
//  ev:事件
//  phandle:事件处理函数指针
//  next_ev:设置下一个事件状态
typedef struct
{
    user_event ev;
    EventFuncHandlePtr phandle;
    user_event next_ev;
}EventTableType;

//事件处理函数
/*************************************/
void a_HandleFunc(void)
{
    printf("A\r\n");
}

void b_HandleFunc(void)
{
    printf("B\r\n");
}

void c_HandleFunc(void)
{
    printf("C\r\n");
}

void d_HandleFunc(void)
{
    printf("D\r\n");
}
/***************************************/

//函数驱动表
static EventTableType eventMap[] =
{
    { EVENT_A, a_HandleFunc, EVENT_B },
    { EVENT_B, b_HandleFunc, EVENT_D },
    { EVENT_C, c_HandleFunc, EVENT_A },
    { EVENT_D, d_HandleFunc, EVENT_D },
};

void funcSwitchCase(void)
{
    switch (getEvent())
    {
    case EVENT_A:
        a_HandleFunc();
        setEvent(EVENT_B);
        break;
    case EVENT_B:
        b_HandleFunc();
        setEvent(EVENT_D);
        break;
    case EVENT_C:
        c_HandleFunc();
        setEvent(EVENT_A);
        break;
    case EVENT_D:
        d_HandleFunc();
        setEvent(EVENT_D);
        break;
    default:
        break;
    }

}

//函数驱动,替代switch-case
void funcTableDevice(void)
{
    int i;
    for (i = 0; i < sizeof(eventMap) / sizeof(eventMap[0]); i++){
        if (getEvent() == eventMap[i].ev){
            //事件处理函数
            eventMap[i].phandle();
            //设置下一个事件状态
            setEvent(eventMap[i].next_ev);
            break;      //跳出
        }
    }
}

//主函数
/********************************************/
int main(int argc, _TCHAR* argv[])
{
    //事件顺序:C-A-B-D
    setEvent(EVENT_C);
    //如果事件D没发生,循环执行
    while (getEvent() != EVENT_D)
    {
        //funcSwitchCase();
        funcTableDevice();
    }

    return 0;
}

编译运行后会打印输出:

C
A
B
请按任意键继续…

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
STM32F103是意半导体公司(STMicroelectronics)推出的一款32位微控制器,具有强大的处理能力和丰富的外设接口。在STM32F103上实现LCD图片显示需要编写相关的驱动函数,主要包括初始化函数和显示函数。 首先,需要编写初始化函数,用于配置STM32F103的外设和LCD显示屏的参数。具体步骤包括选择合适的时钟源、配置GPIO引脚、设置时序和信号参数等。初始化函数的目的是为了让STM32F103和LCD显示屏之间能够正常通信。 接下来,编写显示函数。在显示函数中,需要先选择显示区域,确定图片在LCD屏幕上的位置和大小。然后,将图片的数据逐个点写入到LCD的显存中。写入显存的方可以是逐点、逐行或者逐块进行。具体的写入方需要根据LCD显示屏的型号和驱动芯片的规格进行设置。 在编写驱动函数时,还需要注意扫描方向、像素位宽、像素格式等参数的配置。此外,还需要考虑屏幕刷新的速度和功耗等方面的问题。对于一些特殊功能的要求,还需要参考LCD显示屏的手册和数据手册。 总结起来,STM32F103的LCD图片显示驱动函数主要包括初始化函数和显示函数。初始化函数用于配置STM32F103和LCD显示屏之间的通信,显示函数用于将图片数据写入到LCD的显存中,从而实现图片的显示。编写驱动函数需要根据具体的LCD显示屏的规格和要求,来进行相关的参数配置和功能实现。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值