嵌入式开发技巧:舍弃标志位,用宏定义函数实现程序单次运行

一、介绍

在嵌入式开发过程中,我们经常会使用标志位实现部分代码的单次执行。如下:

cpp 复制代码
uint8_t Flag = 0;//标志位

while(1)
{
    if(Flag == 0)
    {
        LED_ON();//LED点亮
        Flag == 1;
    }
}

这样,我们就实现了只运行一次LED_ON函数,也就是单次执行。

如果复杂一点的程序想实现单次执行,用标志位的话就会让程序就会变得非常不美观,可读性也变得更差了,非常的不优雅。

那如果我使用宏定义函数实现单次执行

cpp 复制代码
while(1)
{
    RunOnce(block1,//单次执行,只运行一次
    {
        LED_ON();
        //可添加其他代码
    });
}

又或者是printf实现单次执行

cpp 复制代码
int main(void) 
{

    RunOnce(block1, {printf("代码块1执行了一次!\n");});// 首次执行代码块
    
    RunOnce(block1, {printf("代码块1执行了一次!\n");});// 已执行过,不执行

    ResetOnce(block1);  // 重置block1的状态
    RunOnce(block1, {printf("代码块1执行了一次!\n");});  // 重置后可再次执行
    
    return 0;
}

怎么样,用了宏定义函数之后,实现程序的单次执行是不是变得更加的优雅了?

话不多说,直接看例程

二、例程

我OnceRun_Port.h这个头文件用来装宏定义函数。引用这个头文件之后,就可以直接使用,有非常强的复用性。

OnceRun_Port.h

cpp 复制代码
#ifndef __OnceRun_Port_h_
#define __OnceRun_Port_h_

#include <stdio.h>

// 宏定义:为代码块生成单次执行功能,需指定唯一标识名name
// block为待执行的代码块(可包含多条语句,用{}括起)
#define RunOnce(name, block) do \
    { \
        static int name##_executed = 0; \
        if (!name##_executed) \
        { \
            block; \
            name##_executed = 1; \
        } \
    } while(0)

// 宏定义:重置指定标识名的代码块执行状态
#define ResetOnce(name) do \
    { \
        static int name##_executed; \
        name##_executed = 0; \
    } while(0)

#endif

使用方法

cpp 复制代码
int main(void) 
{
    // 测试代码块1:单次执行
    printf("代码块1第1次:");
    RunOnce(block1, 
        {  
            printf("代码块1执行了一次!\n");
            // 可添加更多语句,例如:
            // printf("代码块1的第二行语句\n");
        }
    );  // 首次执行代码块
    
    printf("代码块1第2次:");
    RunOnce(block1, 
        {
            printf("代码块1执行了一次!\n");
        }
    );  // 已执行过,不执行
    
    // 测试代码块2:独立于代码块1
    printf("\n代码块2第1次:");
    RunOnce(block2, 
        {  // 标识名block2,独立状态
            printf("代码块2执行了一次!\n");
        }
    );  // 首次执行
    
    printf("代码块2第2次:");
    RunOnce(block2, 
        {
            printf("代码块2执行了一次!\n");
        }
    );  // 已执行过,不执行
    
    // 重置代码块1后再次执行
    printf("\n重置代码块1后:");
    ResetOnce(block1);  // 重置block1的状态
    RunOnce(block1, 
        {
            printf("代码块1执行了一次!\n");
        }
    );  // 重置后可再次执行
    
    return 0;
}

三、注意事项

当你调用ResetOnce函数后,可能会出现警告,显示"block1_executed"从未使用过。这个警告可以无需理会,我调用之后ResetOnce仍然能重置代码块,不影响使用。

相关推荐
世人万千丶5 小时前
鸿蒙Flutter Flex多子组件权重分配
学习·flutter·华为·harmonyos·鸿蒙
圣光SG8 小时前
Servlet学习笔记
笔记·学习·servlet
奋发向前wcx8 小时前
y1,y2总复习笔记5 2026.7.19
数据结构·笔记·算法
@Mike@10 小时前
02-数据库学习笔记(SQL引擎)
数据库·笔记·学习
六点_dn10 小时前
RabbitMQ学习笔记-定义与作用
笔记·学习·rabbitmq
我的xiaodoujiao11 小时前
快速学习Python基础知识详细图文教程9--函数进阶
开发语言·python·学习·测试工具
sramdram11 小时前
基于32位微控制器的FOC汽车水泵方案
单片机·嵌入式硬件·汽车·微控制器·32位微控制器
世人万千丶12 小时前
鸿蒙Flutter Flexible与Expanded的区别
学习·flutter·harmonyos·鸿蒙
香辣牛肉饭13 小时前
【算法】动态规划 最长公共子序列(LCS)
经验分享·笔记·算法·动态规划
迷途呀13 小时前
Python:函数中的参数类型
开发语言·笔记·python·langchain·nlp