• 函数调用在嵌入式架构设计中的应用


    函数调用很好理解,即使刚学没多久的朋友也知道函数调用是怎么实现的,即调用一个已经封装好的函数,实现某个特定的功能。

    把一个或者多个功能通过函数的方式封装起来,对外只提供一个简单的函数接口,然后在其他地方调用即可

    函数调用方式

    函数调用难道还能怎么调用?不就封装好直接调用吗???

    函数调用方式分为两种:直接调用和间接调用

    直接调用
    直接调用就是我们平常使用的方式,下面的方式就属于直接调用了。

    1. int SumFun(int a, int b)
    2. {
    3.     return a + b;
    4. }
    5. int main()
    6. {
    7.     // 直接调用定义好的函数
    8.     int sum = SumFun(56);
    9.     printf("sum=%d", sum);
    10.     return 0;
    11. }

    间接调用
    间接调用在初学时很难使用到,这是通过函数指针的方式实现的。

    函数指针本质是一个指针变量,是一个指向函数的指针(函数本身也是有地址的,指向的是函数入口);
    指针函数本质是一个函数,其返回值为指针。

    函数指针的用法如下:

    1. typedef int (*FunctionCB)(intint);
    2. int SumFun(int a, int b)
    3. {
    4.     return a + b;
    5. }
    6. int main()
    7. {
    8.     // 将定义好的函数赋值给函数指针
    9.     FunctionCB pfnSum = SumFun;
    10.     // 通过函数指针间接调用
    11.     int sum = pfnSum(56);
    12.     printf("sum=%d", sum);
    13.     return 0;
    14. }

    什么场景使用

    函数指针在软件架构分层设计中十分重要,因为分层设计中有一个设计原则,那就是下层函数不能直接调用上层函数,那么可以通过函数指针的方式实现;一般称上层通过函数指针赋值给下层的函数为回调函数。

    什么情况会存在需要下层程序需要调用上层程序的呢?
    比如串口数据接收,虽然可以通过查询的方式接收,但是远不及通过串口中断的方式接收及时,当接收完成时,需要立即通知上层读取数据进行处理,而不是等待上层程序查询读取。

    如何实现呢?
    比如硬件抽象层/驱动层中的串口模块实现函数

    1. /************* UART.c 文件 ****************/
    2. static UartRecvCB sg_pfnUartRecv;
    3. // 设置数据帧接收处理回调函数
    4. void UART_SetRecvCallback(UartRecvCB pfnUartRecv)
    5. {
    6.     sg_pfnUartRecv = pfnUartRecv;
    7. }
    8. void UART_Task(void)
    9. {
    10.     if (RecvEnd)
    11.     {
    12.         // 数据一帧接收完成立即调用
    13.         if (sg_pfnUartRecv != NULL)
    14.         {
    15.             sg_pfnUartRecv(UartRecvBuf, UartRecvLength);
    16.         }
    17.     }
    18. }
    19. /************* UART.h 文件 ****************/
    20. typedef void (*UartRecvCB)(const char *, int);
    21. extern void UART_SetRecvCallback(UartRecvCB pfnUartRecv);
    22. extern void UART_Task(void);

    应用层代码中实现回调函数,并调用下层函数。

    1. // 回调函数:串口数据处理
    2. void OnUartRecvProcess(const char *pBuf, int length)
    3. {
    4.     // 处理串口数据
    5.     printf("Recv: %s", pBuf);
    6. }
    7. int main()
    8. {
    9.     UART_SetRecvCallback(OnUartRecvProcess);
    10.     while(1)
    11.     {
    12.         if (TimeFlag)
    13.         {
    14.             UART_Task();
    15.         }
    16.     }
    17. }

    上述示例中通过函数指针的方式间接调用了应用层的函数,而且并不违背分层设计原则
    如果看代码不能立即理解的话,可以尝试通过下图理解:

     

  • 相关阅读:
    QT:debug日志—打不开头文件以及qDebug和Q_CLASSINFO的使用
    事件驱动的微服务、CQRS、SAGA、Axon、Spring Boot
    Python基础入门例程1-NP1 Hello World!
    软件开发和测试
    UG\NX二次开发 连接曲线、连结曲线 UF_CURVE_auto_join_curves
    基于JavaWeb+SSM+购物系统微信小程序的设计和实现
    安全入门day01
    贪心算法——找纸币问题
    浅谈二叉树
    Linux/shell基础命令
  • 原文地址:https://blog.csdn.net/m0_61687959/article/details/128073513