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

一、介绍

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

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

相关推荐
杨云龙UP6 分钟前
从0到1快速学会Linux操作系统(基础),这一篇就够了!
linux·运维·服务器·学习·ubuntu·centos·ssh
头疼的程序员36 分钟前
计算机网络:自顶向下方法(第七版)第八章 学习分享(三)
网络·学习·计算机网络
yoyobravery1 小时前
蓝桥杯第15届单片机满分
单片机·职场和发展·蓝桥杯
_李小白1 小时前
【OSG学习笔记】Day 37: NodeVisitor(顶点访问器)
笔记·学习
程序员雷欧2 小时前
大模型应用开发学习第八天
大数据·人工智能·学习
SccTsAxR2 小时前
算法基石:手撕离散化、递归与分治
c++·经验分享·笔记·算法
晓晓hh2 小时前
JavaSE学习——set集合和Map映射
学习
4caf12 小时前
作业2:6位数码管静态显示
嵌入式硬件·51单片机
西梅汁2 小时前
C++ 观察者模式
笔记
不做无法实现的梦~3 小时前
STM32解析PPM协议
stm32·单片机·嵌入式硬件