可以用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;
我对一种构造感兴趣,我可以在其中简单地键入 TASK
或 if( 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
值中是否存在差距并不重要。
当我创建一个新的软件项目时,我通过一个脚本来创建文件夹、复制和移动一些文件并生成一些源代码。
其中一个复制的文件名为 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;
我对一种构造感兴趣,我可以在其中简单地键入 TASK
或 if( 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
值中是否存在差距并不重要。