可以用C/C++中的宏或者函数来构造递增任务吗?

Can you use a macro or function in C/C++ to construct incrementing tasks?

当我创建一个新的软件项目时,我通过一个脚本来创建文件夹、复制和移动一些文件并生成一些源代码。

其中一个复制的文件名为 roundRobinTasks.cpp。显然,它用于循环任务,例如从串行缓冲区读取数据、处理 CAN 总线通信、监控紧急开关等。

此文件包含一个如下所示的函数:

void processRoundRobinTasks(void) 
{
    static unsigned char taskCounter = 0;

// HIGH PRIORITY ROUND ROBIN TASKS


// LOW PRIORITY ROUND ROBIN TASKS
    switch( ++ taskCounter )
    {
    default: 
        taskCounter = 0;
        
        /* fill in a task */
        break;

    case 1:
        /* fill in a task */
        break;

    case 2:
        /* fill in a task */
        break;
    }
}

此函数在 int main() 中的每个程序周期调用,我将任务分为高优先级或低优先级任务。每个高优先级任务每个周期 运行,只有 1 个低优先级任务每个周期 运行。

taskCounter 是一个不断递增的静态变量。这个想法是,对于每个新任务,您都可以添加一个带有递增数字的新案例标签。如果 taskcounter 变得大于最高任务,默认标签会将其设置回 0。这样就不需要预先定义任务数量。

为了让它看起来更漂亮,我研究了几个宏,很快就找到了这种情况。我已经填写了一些可以填写的细节。

void foobar()
{
    // code
}

void processRoundRobinTasks(void) 
{
HIGH_PRIORITY_TASKS

    foobar() ; 

LOW_PRIORITY_TASKS

    TASK(1)
        REPEAT_MS( 500 )
        TGL( PORTB, 5 ) ;           // is run every 500ms
        END_REPEAT

    TASK(2)
        REPEAT_MS( 50 )
        handleSomething() ;         // is run every 50ms
        END_REPEAT

    TASK(3)
        doSomethingElse() ;
    
    TASK(4)
        /* fill in a task */

    
END_TASKS
}

它可以很好地使用这些宏进行编译,并且工作方式完全相同。

#define HIGH_PRIORITY_TASKS static unsigned char taskCounter = 0;
#define LOW_PRIORITY_TASKS  switch( ++ taskCounter ) \
                            { \
                            default : \
                                taskCounter = 0 ;

#define TASK(x)             break ; case x:
#define END_TASKS           break ; \
                            }

有或没有宏,都可能存在一个小错误。如果用户添加或删除任务并忘记更新所有任务编号,将有可能永远不会调用此示例中的任务。

    default: 
        taskCounter = 0;

        /* fill in a task */
        break;

    case 1:
        /* fill in a task */
        break;

    case 3:             // because task 2 does not exist I will never run     
        /* fill in a task */
        break;

我对一种构造感兴趣,我可以在其中简单地键入 TASKif( Task() ) 而无需输入数字,然后执行实际任务,例如:

void processRoundRobinTasks(void) 
{
HIGH_PRIORITY_TASKS

    foobar() ; 

LOW_PRIORITY_TASKS

    TASK
        REPEAT_MS( 50 )
        handleSomething() ;         // is run every 50ms
        END_REPEAT

    TASK
        doSomethingElse() ;
    
    TASK
        /* fill in a task */

    
END_TASKS
}

我不局限于调用函数。我基本上可以在这段代码中做任何我想做的事。

我认为这不能用一个函数来完成。我暂时想不出任何东西。

这样的事情可以用宏来完成吗? 是否有其他构造,例如带有函数指针的列表?

编辑: 对于宏观仇恨者。该系统的优点是人们不必为每个任务都创建一个函数。恕我直言,有些事情太简单了,无法为其专门提供功能。

我使用过几个 C++ 计时器和任务调度程序库,我从它们那里回来了。尽管它们工作得很好,但我不喜欢它们中的任何一个。我必须为每个定时事件创建一个新的计时器对象。作为一名嵌入式程序员,我有时希望更简单。有些东西越简单越好

例如 REPEAT_MS(interval) 宏,是我有史以来最好的宏。老实说,我支持这个,我在任何地方都使用它(class 方法中除外)。您放在 REPEAT_MS()END_REPEAT 之间的所有内容都会在每个间隔时间重复一次。您不必声明新变量,不必为它们创建对象或初始化,也不必被迫为每件小事创建一个函数。每次使用此宏都会占用四个字节的 RAM。

#define REPEAT_MS(x)    { \
                            static uint32_t previousTime ;\
                            uint32_t currentTime = millis() ;\
                            if( currentTime  - previousTime >= x ) {\
                                previousTime = currentTime ;
                                // code to be repeated goes between these 2 macros
#define END_REPEAT          } \
                        }

我成功地尝试了给定答案的宏,效果非常好。现在忘记更新数字也没关系了。

如果您真的认为这是“不可读的”或“混乱的”,我真的相信您无法编写代码。但是让我们自己保留我们的意见...

这样的事情怎么样:

#define HIGH_PRIORITY_TASKS static unsigned char taskCounter = 1;
#define LOW_PRIORITY_TASKS  switch( taskCounter ) \
                            { \
                            default : \
                                taskCounter = 1 ;

#define TASK(x)                 taskCounter = (x); \
                                break ; \
                            case (x):
#define END_TASKS               taskCounter = 1; \
                                break ; \
                            }

想法是在中断切换之前将 taskCounter 更新到下一个任务。只要“第一个”任务 TASK(1) 存在,taskCounter 值中是否存在差距并不重要。