实现简单的多任务轮询(C语言)

实现简单的多任务轮询(C语言)

  • 前言
  • 总体思路
  • 实现过程
  • 调用示例
  • 完整代码

前言

好久没有做MCU的项目了,最近因为工作需要接手一个STM32的项目,因为项目要求比较简单,也就没有用到操作系统,而是用了简单的状态机+任务轮询的方式。闲暇之余写下这篇简短的博客,记录一下自己的所知所想,也希望对那些刚进入MCU的新手们,能有些许的帮助。

总体思路

利用状态机的方式,在一个循环中不停的去判断每一个任务的执行标识,当判断标识为真时,则执行响应的任务,任务执行结束后及时的清除任务标识。

实现过程

先定义一个任务的结构体,结构体中包含任务的执行函数和是否需要执行的标识。

typedef struct __TASK{
	int (*func)(void *);		//任务执行的函数,执行时会传入下面的参数
	void *arg;						//任务执行时带入的参数
	int flag;
} task_t;

在定义一个任务组用于管理这些需要被轮询的任务:

typedef struct __TASK_GRP{
	task_t *task_list;			//需要执行任务集合
	int list_size;				//list的大小
}taskGrp_t;

下面定义两个宏用于定义和初始化一个任务列表和任务组。注意下面的方法在有些编译器中不支持,目前我知道的就是在keil下的C89就不支持这种方式。

#define TASK_LIST_INIT(name,size) 	task_t name[size]={0};
#define TASK_GPR_INIT(name,list,size) \
struct __TASK_GRP name={ \
	.task_list = list, \
	.list_size = size, \
};	

有些人看到这个肯定有点懵!其实上面的方式就是利用在定义变量时对变量进行初始化,然后再用宏把这个过程包装起来就行,在使用的时候只需要调用宏并传入响应的参数就行。例如:TASK_GPR_INIT(task_group,task_list,TASK_SIZE);
等价于
struct __TASK_GRP task_group={
.task_list = task_list,
.list_size = TASK_SIZE,
};
然后定义几个函数用于对任务组和任务进行操作:

初始化一个任务组,目的和上面提高的两个初始化相同。两种方式调用哪个都可以。

void task_grop_init(taskGrp_t *grp,task_t *list,int size)
{
	
	grp->task_list = list;
	grp->list_size = size;
	memset(list,0,sizeof(task_t)*size);
}

将要执行的操作函数添加到任务组中相应的任务中。flag标识用于是否默认激活任务。

void task_add_to_list(taskGrp_t *grp,int index,int (*func)(void *),void *arg,int flag)
{
	grp->task_list[index].func = func;
	grp->task_list[index].arg = arg;
	grp->task_list[index].flag = flag;
}

激活索引为index的任务,让其能参与轮询。

void activate_task(taskGrp_t *grp,int index)
{
	grp->task_list[index].flag = 1;
}

开始任务轮询操作,里面是一个大循环,会一直查找任务状态并执行相应任务。当判断到任务的返回值为1时则认为任务一次执行完成,将关闭任务,只有等待下一次重新激活后,才重新执行相应任务。

void start_polling(struct __TASK_GRP *grp)
{
	int i=0;
	if(grp->task_list != NULL){
		while(1){
			for(i=0;ilist_size;i++){
				if((grp->task_list[i].flag)&&(grp->task_list[i].func != NULL)){
					grp->task_list[i].flag = grp->task_list[i].func(grp->task_list[i].arg) ? 0 : 1;
				}else{
					grp->task_list[i].flag = 0;
				}			
			}
		}
	}
}

调用示例

enum{
	TASK_1,
	TASK_2,
	TASK_3,
	TASK_SIZE
}TASK_INDEX;

TASK_LIST_INIT(task_list,TASK_SIZE);
TASK_GPR_INIT(task_group,task_list,TASK_SIZE);

int task1_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}

int task2_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}
int task3_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}

int main(void)
{
	task_add_to_list(&task_group,TASK_1,task1_func,NULL,1);
	task_add_to_list(&task_group,TASK_2,task2_func,NULL,1);
	task_add_to_list(&task_group,TASK_3,task3_func,NULL,1);
	start_polling(&task_group);
}

完整代码

task.h

#ifndef __TASK_H__
#define __TASK_H__

#define TASK_LIST_INIT(name,size) 	task_t name[size]={0};
#define TASK_GPR_INIT(name,list,size) \
struct __TASK_GRP name={ \
	.task_list = list, \
	.list_size = size, \
};	




typedef struct __TASK{
	int (*func)(void *);
	void *arg;						//任务执行时带入的参数
	int flag;
} task_t;


typedef struct __TASK_GRP{
	task_t *task_list;			//需要执行任务表
	int list_size;				//list的大小
}taskGrp_t;


extern void task_grop_init(taskGrp_t *grp,task_t *list,int size);
extern void task_add_to_list(taskGrp_t *grp,int index,int (*func)(void *),void *arg,int flag);
extern void activate_task(taskGrp_t *grp,int index);
extern void start_polling(struct __TASK_GRP *grp);
#endif /* __TASK_H__ */

task.c

#include 
#include "task.h"

void task_grop_init(taskGrp_t *grp,task_t *list,int size)
{
	
	grp->task_list = list;
	grp->list_size = size;
	memset(list,0,sizeof(task_t)*size);
}

void task_add_to_list(taskGrp_t *grp,int index,int (*func)(void *),void *arg,int flag)
{
	grp->task_list[index].func = func;
	grp->task_list[index].arg = arg;
	grp->task_list[index].flag = flag;
}

void activate_task(taskGrp_t *grp,int index)
{
	grp->task_list[index].flag = 1;
}

void start_polling(struct __TASK_GRP *grp)
{
	int i=0;
	if(grp->task_list != NULL){
		while(1){
			for(i=0;ilist_size;i++){
				if((grp->task_list[i].flag)&&(grp->task_list[i].func != NULL)){
					grp->task_list[i].flag = grp->task_list[i].func(grp->task_list[i].arg) ? 0 : 1;
				}else{
					grp->task_list[i].flag = 0;
				}			
			}
		}
	}
}

main.c

#include 
#include "task.h"

enum{
	TASK_1,
	TASK_2,
	TASK_3,
	TASK_SIZE
}TASK_INDEX;

TASK_LIST_INIT(task_list,TASK_SIZE);
TASK_GPR_INIT(task_group,task_list,TASK_SIZE);

int task1_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}

int task2_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}
int task3_func(void *arg)
{
	int retval=0;
	static int step=0;
	switch(step){
	case 0:
		printf("%s step %d\n",__func__,step);
		step=1;
		break;
	case 1:
		printf("%s step %d\n",__func__,step);
		step=2;
		break;
	case 2:
		printf("%s step %d\n",__func__,step);
		step=0;
		retval=1;
		break;
	}
	return retval;
}

int main(void)
{
	task_add_to_list(&task_group,TASK_1,task1_func,NULL,1);
	task_add_to_list(&task_group,TASK_2,task2_func,NULL,1);
	task_add_to_list(&task_group,TASK_3,task3_func,NULL,1);
	start_polling(&task_group);
}

你可能感兴趣的:(经验分享,c++)