找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1029|回复: 7
收起左侧

关于如何提高代码的执行效率

  [复制链接]
ID:446156 发表于 2024-11-8 18:19 | 显示全部楼层 |阅读模式
我要讲的提高代码效率的方法很简单,不涉及底层。简单讲就是程序非阻塞。
何为阻塞?阻塞就是程序停在那里一动不动,比如
  1. while(a==0);
复制代码
又或者使用for循环做的延时
  1. void delay(int time)
  2. {
  3.      int i=0;
  4.      for(i=0;i<time;i++);
  5. }
复制代码
要想程序执行效率高就不能使用毫秒级的阻塞写法,极短的阻塞是可以的比如IIC的电平翻转的间隔延时。非阻塞写法的一大重要方法就是状态机,以常用的LED闪烁为例。我们先准备三个函数。
  1. void DelayTimeCount_ms(uint16_t *DelayTime_Count)
  2. {
  3.      if(*DelayTime_Count==0)
  4.      {
  5.          *DelayTime_Count=0;
  6.      }
  7.      else
  8.      {
  9.          *DelayTime_Count-=1;
  10.      }
  11. }
  12. void Set_Delay_Time(uint16_t Time,uint16_t *DelayTime_Count)
  13. {
  14.      *DelayTime_Count=Time;
  15. }
  16. uint8_t CheckDelay(uint16_t *DelayTime_Count)
  17. {
  18.      if(*DelayTime_Count==0)
  19.      {
  20.          return 0;
  21.      }
  22.      else
  23.      {
  24.          return 1;
  25.      }
  26. }
复制代码
我们再创建一个全局变量用于设置LED闪烁间隔
  1. uint16_t DelayTime_LED;
复制代码
接下来写一个LED闪烁函数并把其放在大循环调用
  1. void LED_Twinkle(uint16_t HarfPeriod)
  2. {
  3.     static uint8_t Status=0;

  4.     switch(Status)
  5.     {
  6.         case 0:
  7.         {
  8.             LED(ON);
  9.             Set_Delay_Time(HarfPeriod,&DelayTime_LED);
  10.             Status++;
  11.         }break;
  12.         case 1:
  13.         {
  14.             if(CheckDelay(&DelayTime_LED) == 0)
  15.             {
  16.                 Status++;
  17.             }
  18.         }break;
  19.         case 2:
  20.         {
  21.             LED(OFF);
  22.             Set_Delay_Time(HarfPeriod,&DelayTime_LED);
  23.             Status++;
  24.         }break;
  25.         case 3:
  26.         {
  27.             if(CheckDelay(&DelayTime_LED) == 0)
  28.             {
  29.                 Status = 0;
  30.             }
  31.         }break;
  32.     }
  33. }
复制代码
接下来我们还需要对DelayTime_LED进行处理
  1. DelayTimeCount_ms(&DelayTime_LED);
复制代码
上边这条语句需要放在滴答中断里(51没有专用滴答定时器可以用普通定时器模拟一个或者直接扔到大循环里也行)。可以发现用这种方法程序会飞快地循环不会在某个地方停下来。
这玩意没啥技术含量无非就是多写几行代码。如果有兴趣的话可以看看我发的矩阵键盘驱动和modbus主机驱动里边有更详细的应用。



评分

参与人数 2黑币 +85 收起 理由
1109 + 15 赞一个!
admin + 70 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:401564 发表于 2024-11-9 09:36 | 显示全部楼层
太复杂了
先声明一个全局变量  u8 time_sys = 0;
然后,开启定时器和中断,在中断中 time_sys++;就什么都不用管,这就是一个低配版的STM32滴答定时器了

void key_disp_sw(u8 i)
{
        static u8 ren = 0;
        static u16 key_ms = 0;//
        if(ren != i)
        {
                ren = i;
                key_ms = (key_ms < 250) ? (key_ms + 1) : key_ms;
                if((key_ms >= 延时时间) && (触发条件))
                {
                  ......................................................
                        key_ms = 0;
                     清除触发条件;
                }
        }
}


key_disp_sw(time_sys);
回复

使用道具 举报

ID:446156 发表于 2024-11-9 11:21 | 显示全部楼层
Y_G_G 发表于 2024-11-9 09:36
太复杂了
先声明一个全局变量  u8 time_sys = 0;
然后,开启定时器和中断,在中断中 time_sys++;就什么都不 ...

复杂在那里
回复

使用道具 举报

ID:57414 发表于 2024-11-9 20:38 | 显示全部楼层
看懂了,谢谢楼主!
回复

使用道具 举报

ID:401564 发表于 2024-11-11 00:17 | 显示全部楼层

一样的功能,一样的效率,一样的原理
看你代码多少行,我的代码多少行
回复

使用道具 举报

ID:446156 发表于 2024-11-11 08:29 | 显示全部楼层
Y_G_G 发表于 2024-11-11 00:17
一样的功能,一样的效率,一样的原理
看你代码多少行,我的代码多少行

我要建立一个通用框架,并非就事论事
回复

使用道具 举报

ID:301191 发表于 2024-11-16 13:51 | 显示全部楼层
顶一下
回复

使用道具 举报

ID:108361 发表于 2025-4-16 11:10 | 显示全部楼层
建立通用框架,就不用造什么轮子,直接freertos;就是论事,就用一个全局变量在定时器里++做滴答计数,主循环检测时间是否达到预设值
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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