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

一、介绍

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

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仍然能重置代码块,不影响使用。

相关推荐
不会代码的小猴6 小时前
21. 泛型编程上
开发语言·c++·笔记·算法
捷瑞电子工坊7 小时前
嵌入式秋招面经:5大核心模块高频考题与实战避坑总结
c语言·stm32·嵌入式工程师·rtos·通信协议·嵌入式面试
大爱编程♡8 小时前
GPIO-I2C
stm32·单片机·嵌入式硬件
摇滚侠8 小时前
《SpringBoot 3:入门与应用实战》第 2 章 IOC 思想与实现 阅读笔记 1
spring boot·笔记·后端
蒸蒸yyyyzwd8 小时前
秋招不熟悉力扣学习笔记1
笔记·学习·leetcode
振南的单片机世界9 小时前
PVD掉电中断——让单片机“咽气前”写完遗书
arm开发·stm32·单片机·嵌入式硬件
LuminousCPP10 小时前
数据结构-双向循环链表
c语言·数据结构·笔记·链表
小弥儿10 小时前
GitHub今日热榜 | 2026-08-11:图原生基础设施首日登顶
学习·开源·github
302wanger11 小时前
【阅读笔记】当AI拿走一切之后
笔记
续写烂尾12 小时前
SD NAND存储实测:正点原子STM32精英板SDIO读写验证全流程
stm32·单片机·嵌入式硬件