函数指针在嵌入式系统中的常见用法

一、前言

在嵌入式系统中,函数指针的使用是比较常见的,它可以帮助我们写出更加灵活和通用的代码,并且提高代码的可维护性。这里对常见的函数指针用法进行一下总结,并结合具体代码进行分析。

二、常见用法

1. 回调函数

在嵌入式系统中,回调函数是由某个模块在特定事件发生时调用的函数,通过函数指针传递,当把函数指针作为参数传递给其他函数,后者会回调用户的函数。这个过程分为三步,首先是中断或事件处理逻辑过程,第二步是保存函数指针,当事件或中断发生时会调用函数指针,第三步是注册回调函数,也就是函数指针的初始化,这里会让函数指针指向第一步中的函数。

这是用户函数执行的内容。

保存函数指针,并且把数据通过函数指针传回去。

这里我们对函数指针进行初始化,相当于注册回调函数的过程。

2. 多态的实现

函数指针可以用来实现类似于面向对象编程中的多态行为,不同的设备驱动可以通过函数指针来实现相同的接口,这里以编写UART和I2C的驱动为例。

// 设备驱动接口定义
typedef struct {
    void (*init)(void);
    void (*send)(uint8_t *data, uint16_t length);
    void (*receive)(uint8_t *data, uint16_t length);
} DeviceDriver;

这里定义了一个简单的驱动框架,包括初始化、发送和接收。 然后只要分别实现UART和I2C的初始化函数,发送函数和接收函数,可以通过选择不同的 DeviceDriver 结构体来切换设备驱动,从而实现灵活的驱动管理。这里以串口为例。

    // 定义UART设备驱动
    DeviceDriver uartDriver = {
        .init = UART_Init,
        .send = UART_Send,
        .receive = UART_Receive
    };

    // 选择当前使用的设备驱动
    DeviceDriver *currentDriver;

    // 示例:使用UART设备驱动
    currentDriver = &uartDriver;
    currentDriver->init();
    uint8_t uartDataToSend[] = {0x11, 0x22, 0x33};
    currentDriver->send(uartDataToSend, sizeof(uartDataToSend));
    uint8_t uartDataToReceive[3];
    currentDriver->receive(uartDataToReceive, sizeof(uartDataToReceive));

这种方式使得代码更加模块化和易于维护,同时可以在不修改应用代码的情况下,方便地替换和升级设备驱动。 

3. 函数表

函数表是一组函数指针的集合,一般用函数指针数组表示,可以用来调用不同的函数,实现多态行为或者接口抽象。

switch (oper)
{
    case ADD:
        result = add(op1,op2);
        break;
    case SUB:
        result = sub(op1,op2);
        break;
    case MUL:
        result = mul(op1,op2);
        break;
    case DIV:
        result = div(op1,op2);
        break;
    default:break;
}

double add(double,double);
double sub(double,double);
double mul(double,double);
double div(double,double);

这是实现一个小型计算器的代码,用switch case结构来实现加减乘除运算的选择,这里用函数表对这个过程实现简化。

double (*oper_func[])(double,double) = {add,sub,mul,div};
result = oper_func[oper](op1,op2);

oper从数组中选择正确的函数指针,函数调用操作符将执行这个函数。

3. 状态机

状态机用于控制系统的状态转换和行为,函数指针可以用来实现状态机的状态转换函数。

typedef void (*StateFunc)(void);

// 定义状态函数
void stateA(void);
void stateB(void);

// 定义状态机结构
typedef struct {
    StateFunc currentState;
} StateMachine;

void stateA(void) {
    printf("State A\n");   
    stateMachine.currentState = stateB;
}

void stateB(void) {
    printf("State B\n");
    stateMachine.currentState = stateA;
}

int main() {
    StateMachine stateMachine;
    stateMachine.currentState = stateA;

    // 运行状态机
    for (int i = 0; i < 10; ++i) {
        stateMachine.currentState();
        // 模拟状态切换
        stateMachine.currentState = (stateMachine.currentState == stateA) ? stateB : stateA;
    }

三、总结

函数指针在嵌入式系统中有广泛的应用,通过使用函数指针,可以提高代码的灵活性、可重用性和可维护性。最后,如有错误,欢迎指正!

  • 10
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值