找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 698|回复: 12
打印 上一主题 下一主题
收起左侧

关于如何提高代码的执行效率-进阶篇

[复制链接]
跳转到指定楼层
楼主
ID:446156 发表于 2025-3-10 10:55 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我在上一篇帖子简单展示了如何使用状态机来替代阻塞延时,这一篇我将向大家展示如何使用结构体和函数指针来构建对象。假设有个需求是需要三个LED分别按照5HZ、1HZ和0.5HZ的频率来闪烁,我们应该怎么实现它呢?如果按照上篇的解决方案需要三个LED_Twinkle函数,只是函数内部关于开关LED的部分不一样。这样存在一个问题,假如LED_Twinkle是一个非常复杂函数,那么写三遍非常费时费力容易出bug并且编译出的可执行文件体积还大。于是乎面向对象和代码分层呼之欲出,废话不多说先上代码。

  1. struct LED_Obj
  2. {
  3.    uint8_t Status;
  4.    uint16_t DelayTime_LED;
  5.    void (*LED_OnOff)(uint8_t Com);
  6. };
  7. void LED1_OnOff(uint8_t Com)
  8. {
  9.    if(Com != 0)
  10.    {
  11.      LED1(ON);
  12.    }
  13.    else
  14.    {
  15.      LED1(OFF);
  16.    }
  17. }
  18. void LED2_OnOff(uint8_t Com)
  19. {
  20.    if(Com != 0)
  21.    {
  22.      LED2(ON);
  23.    }
  24.    else
  25.    {
  26.      LED2(OFF);
  27.    }
  28. }
  29. void LED3_OnOff(uint8_t Com)
  30. {
  31.    if(Com != 0)
  32.    {
  33.      LED3(ON);
  34.    }
  35.    else
  36.    {
  37.      LED3(OFF);
  38.    }
  39. }
  40. struct LED_Obj LED1 =
  41. {
  42.    .LED_OnOff = LED1_OnOff
  43. };
  44. struct LED_Obj LED2 =
  45. {
  46.    .LED_OnOff = LED2_OnOff
  47. };
  48. struct LED_Obj LED3 =
  49. {
  50.    .LED_OnOff = LED3_OnOff
  51. };
  52. void DelayTimeCount_ms(uint16_t *DelayTime_Count)
  53. {
  54.    if(*DelayTime_Count==0)
  55.    {
  56.      *DelayTime_Count=0;
  57.    }
  58.    else
  59.    {
  60.      *DelayTime_Count-=1;
  61.    }
  62. }
  63. void Set_Delay_Time(uint16_t Time,uint16_t *DelayTime_Count)
  64. {
  65.    *DelayTime_Count=Time;
  66. }
  67. uint8_t CheckDelay(uint16_t *DelayTime_Count)
  68. {
  69.    if(*DelayTime_Count==0)
  70.    {
  71.      return 0;
  72.    }
  73.    else
  74.    {
  75.      return 1;
  76.    }
  77. }
  78. void LED_Twinkle(struct LED_Obj *LED,uint16_t HarfPeriod)
  79. {
  80.    switch(LED->Status)
  81.    {
  82.      case 0:
  83.      {
  84.         LED->LED_OnOff(ON);
  85.         Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
  86.         LED->Status++;
  87.       }break;
  88.      case 1:
  89.      {
  90.         if(CheckDelay(&LED->DelayTime_LED) == 0)
  91.         {
  92.            LED->Status++;
  93.         }
  94.      }break;
  95.      case 2:
  96.      {
  97.         LED->LED_OnOff(OFF);
  98.         Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
  99.         LED->Status++;
  100.       }break;
  101.      case 3:
  102.      {
  103.        if(CheckDelay(&LED->DelayTime_LED) == 0)
  104.        {
  105.          LED->Status = 0;
  106.        }
  107.      }break;
  108.    }
  109. }
  110. void LED_Run(void)
  111. {
  112.    LED_Twinkle(&LED1,100);
  113.    LED_Twinkle(&LED2,500);
  114.    LED_Twinkle(&LED3,1000);
  115. }
  116. void Task_1mS(void)
  117. {
  118.    DelayTimeCount_ms(&LED1.DelayTime_LED);
  119.    DelayTimeCount_ms(&LED2.DelayTime_LED);
  120.    DelayTimeCount_ms(&LED3.DelayTime_LED);
  121. }
复制代码



这段代码涉及到结构体和函数指针的语法知识,关于语法这里不再赘述,我来介绍一下这段代码是如何面向对象和分层的。
结构体:

struct LED_Obj
{
    uint8_t Status;
    uint16_t DelayTime_LED;
    void (*LED_OnOff)(uint8_t Com);
};



该结构体成员包括运行状态变量(Status)、LED开关延时变量(DelayTime_LED)以及作为上下层接口用来控制LED开关的函数指针(*LED_OnOff)(uint8_t Com)
硬件层部分:

void LED1_OnOff(uint8_t Com);
void LED2_OnOff(uint8_t Com);
void LED3_OnOff(uint8_t Com);
这三个函数就是控制IO来实现LED开关
结构体实例化(对象):


struct LED_Obj LED1 =
{
    .LED_OnOff = LED1_OnOff
};
struct LED_Obj LED2 =
{
    .LED_OnOff = LED2_OnOff
};
struct LED_Obj LED3 =
{
    .LED_OnOff = LED3_OnOff
};



因为我们有3个LED需要控制,所以需要创建3个LED_Obj对象并实现硬件层和应用层的连接(函数指针初始化,指向一个函数)
应用层:


void LED_Twinkle(struct LED_Obj *LED,uint16_t HarfPeriod)
{
    switch(LED->Status)
    {
        case 0:
        {
            LED->LED_OnOff(ON);
            Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
            LED->Status++;
        }break;
        case 1:
        {
            if(CheckDelay(&LED->DelayTime_LED) == 0)
            {
                LED->Status++;
            }
        }break;
        case 2:
        {
            LED->LED_OnOff(OFF);
            Set_Delay_Time(HarfPeriod,&LED->DelayTime_LED);
            LED->Status++;
        }break;
        case 3:
        {
            if(CheckDelay(&LED->DelayTime_LED) == 0)
            {
                LED->Status = 0;
            }
        }break;
    }
}
void LED_Run(void)
{
    LED_Twinkle(&LED1,100);
    LED_Twinkle(&LED2,500);
    LED_Twinkle(&LED3,1000);
}
void Task_1mS(void)
{
    DelayTimeCount_ms(&LED1.DelayTime_LED);
    DelayTimeCount_ms(&LED2.DelayTime_LED);
    DelayTimeCount_ms(&LED3.DelayTime_LED);
}

至此,我们就实现了三个LED的分别控制。



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏2 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:446156 发表于 2025-3-10 11:08 | 只看该作者
注意LED(ON)属于形式代码,对于stm32来说可能是HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);或者PAout(15) = 0;对于51单片机来说可能是P1^0 = 0;
回复

使用道具 举报

板凳
ID:33522 发表于 2025-3-12 07:58 | 只看该作者
虽然看不懂,但是得先点赞
回复

使用道具 举报

地板
ID:446156 发表于 2025-3-12 16:46 | 只看该作者
wwzgch 发表于 2025-3-12 07:58
虽然看不懂,但是得先点赞

我步子迈大啦?
回复

使用道具 举报

5#
ID:33522 发表于 2025-3-12 21:41 | 只看该作者

是我这理解能力有待进步,平时都是用8位机。都是简单的写法,向群主学习
回复

使用道具 举报

6#
ID:118322 发表于 2025-3-13 09:05 | 只看该作者
间下AI怎么写
回复

使用道具 举报

7#
ID:446156 发表于 2025-3-13 10:06 | 只看该作者
wwzgch 发表于 2025-3-12 21:41
是我这理解能力有待进步,平时都是用8位机。都是简单的写法,向群主学习

我回复你之后,你的页面右上角头像左边那里会有提醒吗
回复

使用道具 举报

8#
ID:446156 发表于 2025-3-13 16:06 | 只看该作者
大家可以把我上边的代码复制到deepseek,NNT的比我解释的都好
回复

使用道具 举报

9#
ID:446156 发表于 2025-3-13 16:22 | 只看该作者
我并没有系统学习过面向对象编程,只是在工作中经常遇到很多重复功能,比如有好多个DS18B20接口(独立总线),有好多个同型号的IIC设备(独立总线),有好多个PID控制器等等。经过不断摸索不断尝试,发现这种编写代码的方法最高效最易读最易维护,直到后来我才知道原来我这种写作方法就是面向对象。状态机+面向对象可以使工作特别高效,我现在连操作系统都看不上(项目没那么复杂)。希望初学者不要像我一样多走好几年弯路,提早走向面向对象编程的怀抱。
回复

使用道具 举报

10#
ID:33522 发表于 2025-3-13 18:49 | 只看该作者
qinlu123 发表于 2025-3-13 10:06
我回复你之后,你的页面右上角头像左边那里会有提醒吗

消息里面会有提醒,平时我登陆这个网站不多
回复

使用道具 举报

11#
ID:446156 发表于 2025-3-14 07:54 | 只看该作者
发表于 2025-3-13 18:49
消息里面会有提醒,平时我登陆这个网站不多

@admin为啥我没有提醒
回复

使用道具 举报

12#
ID:33522 发表于 2025-3-14 10:51 | 只看该作者
qinlu123 发表于 2025-3-13 16:22
我并没有系统学习过面向对象编程,只是在工作中经常遇到很多重复功能,比如有好多个DS18B20接口(独立总线 ...

是的,不想被淘汰就要不断的学习新的编程思想和技巧。楼主平时都用什么MCU做方案
回复

使用道具 举报

13#
ID:624769 发表于 2025-3-14 23:35 | 只看该作者
标题和内容不符,
标题是: 关于如何提高代码的执行效率
而实际是: 反而降低了执行效率
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表