前言:
眼前朋友们对“单片机一个for循环时间是多少”都比较关切,你们都想要了解一些“单片机一个for循环时间是多少”的相关内容。那么小编也在网摘上汇集了一些对于“单片机一个for循环时间是多少””的相关文章,希望朋友们能喜欢,看官们一起来学习一下吧!这是一个非常实用的单片机时间片轮询任务的程序,在51 stc等小容量单片机上也能非常好的执行。每新增一个任务,仅需要新增6个字节的变量来管理,非常小巧。
具有新增任务和删除任务的功能。
新增任务具有一次执行和循环执行两种模式。
// TASKPROCES.h 头文件#ifndef __TASKPROCES_H__#define __TASKPROCES_H__#define TASKS_MAX 10 //最大可运行任务数typedef void (*TaskHook)(void);void TaskRemarks(void);void TaskProcess(void);void Create_Task(uint16_t Time_Cnt,uint16_t Reload, TaskHook task);void Delete_Task(TaskHook task);void Init_TaskList(void);#endif
在头文件中有一个地方需要注意
#define TASKS_MAX 10 //最大可运行任务数
通过这个宏可以设置本程序可以执行最大多少个任务。
接下来就是 TASKPROCES.c 文件,对这几个函数的具体实现了
// TASKPROCES.c C文件typedef struct { uint8_t Run; // 程序运行标记:0-不运行,1运行 置1时可以运行程序了 uint16_t Timer; // 计时器计数值,看定时器调度时间 uint16_t TimeReset; // 为0时不能重复调用 TaskHook task_handle; // 要运行的任务函数} TASK_COMPONENTS; // 别名TASK_COMPONENTS TaskComps[ TASKS_MAX ];/*******************************************************************************函 数 名: void Init_TaskList(void)输入参数: 返回参数: 功能描述: 初始化任务结构体*******************************************************************************/void Init_TaskList(void){ uint8_t id = 0; for (id = 0;id < TASKS_MAX; id++) { TaskComps[id].Run = FALSE; // 首先停止 TaskComps[id].Timer = 0; // 计数值 TaskComps[id].TimeReset = 0; // 重装值 TaskComps[id].task_handle = 0; // 函数名,指针类型 }}/*******************************************************************************函 数 名: void Create_Task(uint16_t Time_Cnt,uint16_t Reload, TaskHook task)输入参数: 返回参数: 功能描述: 创建定时任务。*******************************************************************************/void Create_Task(uint16_t Time_Cnt,uint16_t Reload, TaskHook task){ uint8_t id; for (id = 0;id < TASKS_MAX; id++) { if (TaskComps[id].task_handle == 0) { id += 99;} } id -= 100; TaskComps[id].Run = FALSE; // 首先停止 TaskComps[id].Timer = Time_Cnt; // 计数值 TaskComps[id].TimeReset = Reload; // 重装值 TaskComps[id].task_handle = task; // 函数名,指针类型}/*******************************************************************************函 数 名: void Delete_Task(TaskHook task)输入参数: 返回参数: 功能描述: 删除(取消)定时任务。*******************************************************************************/void Delete_Task(TaskHook task){ uint8_t id = 0; if (task == 0) return; for (id = 0;id < TASKS_MAX; id++) { if (TaskComps[id].task_handle == task) id += 99; } if (id < 100) //没有匹配的任务 return; id -= 100; TaskComps[id].Run = FALSE; // 首先停止 TaskComps[id].Timer = 0; // 计数值 TaskComps[id].TimeReset = 0; // 重装值 TaskComps[id].task_handle = 0; // 函数名,指针类型 while ((id + 1) < TASKS_MAX) { TaskComps[id].Run = TaskComps[id + 1].Run; TaskComps[id].Timer = TaskComps[id + 1].Timer; TaskComps[id].TimeReset = TaskComps[id + 1].TimeReset; TaskComps[id].task_handle = TaskComps[id + 1].task_handle; id++; }}/*******************************************************************************函 数 名: void TaskRemarks(void)输入参数: 返回参数: 功能描述: 在定时器中断中调用此函数*******************************************************************************/void TaskRemarks(void){ uint8_t i; for (i=0; i < TASKS_MAX; i++) // 逐个任务时间处理 { if (TaskComps[i].Timer) // 时间不为0 { TaskComps[i].Timer--; // 减去一个节拍 if (TaskComps[i].Timer == 0) // 时间减完了 { // 有值时才能继续赋值,产生下次触发 TaskComps[i].Timer = TaskComps[i].TimeReset; // 恢复计时器值,从新下一次 TaskComps[i].Run = TRUE; // 任务可以运行 } } }}/*******************************************************************************函 数 名: TaskProcess()输入参数: 返回参数: 功能描述: 遍历任务标志*******************************************************************************/uint8_t task_cnt = 0;void TaskProcess(void){ if (TaskComps[task_cnt].Run == TRUE) // 时间不为0 { TaskComps[task_cnt].task_handle(); // 运行任务 TaskComps[task_cnt].Run = FALSE; // 标志清0 } if (++task_cnt > TASKS_MAX) task_cnt = 0; }
//Delete_Task 删除(取消)定时任务。函数中的for循环说明
for (id = 0;id < TASKS_MAX; id++)
{
if (TaskComps[id].task_handle == task)
id += 99; //使id 大于TASKS_MAX 不满足循环条件
}
if (id < 100) //没有匹配的任务
return;
id -= 100; //减去100,可以知道id循环到几的时候if成立的
假设TASKS_MAX定义可以运行任务数量小于100(超过之后需要改变一些写法了)这是前提。
1.在for循环中,if条件成立时,对变量id加上99,目的是让它立即退出循环,进行下一步动作。
而for循环退出时,会对变量id再次自加“id++”之后判断“id < TASKS_MAX”。这就是之后“i-=100”
的原因。
2.退出for循环之后,如果id变量没有超过100,那就是之前for循环中if条件一直没能成立,退出当前函数
3.如果大于100了,那就说明在for循环中if条件成立过了,
id减去100就可以知道是循环第几次的时候if条件成立的
4.这样就能通过id的值知道if条件是否成立以及成立时的id值了
//Create_Task 创建任务函数中的for循环说明
for (id = 0;id < TASKS_MAX; id++)
{
if (TaskComps[id].task_handle == 0)
{ id += 99;}
}
id -= 100;
TaskComps[id].Run = FALSE; // 首先停止
TaskComps[id].Timer = Time_Cnt; // 计数值
TaskComps[id].TimeReset = Reload; // 重装值
TaskComps[id].task_handle = task; // 函数名,指针类型
创建任务和删除定时任务的for循环逻辑一样,创建任务时需要确定当前结构体数组有没有空位
if (TaskComps[id].task_handle == 0) 查找没有被赋予指针的位置,只有当这个函数指针
为空时才表示可以使用。
如果这个TaskComps[0],TaskComps[1],TaskComps[2]均已赋值,TaskComps[3],TaskComps[4]...
没有赋值if条件就会一直成立,id会一直自加直到“id < TASKS_MAX”条件不成立而退出。
所以
1.当id循环一旦查找到空指针位置时,自加99(for循环的i++还会加1)后退出循环
2.接下来直接将id减去100可以知道id在for循环中值为多少时if条件成立的,即此编号指针为空
3.对该空指针赋值,实现添加任务
以下是主程序中的内容,注释已经非常详细,不再赘述。
需要注意的是,一定要将TaskRemarks();放在定时器中断中去执行,将定时器中断
配置为1ms,当然也可以是其它值。
void fun1(void){ LED = ~LED;}void fun2(void){ //放置需要进行的任务}/*******************************************************************************函 数 名: void main(void)输入参数: 返回参数: 功能描述: 遍历任务标志*******************************************************************************/void main(void){ Sys_Bsp_Init(); //初始化一个1ms的定时器 定时器中调用TaskRemarks(); Init_TaskList(); //初始化任务结构体 Create_Task(200,200,fun1);//fun1任务 200ms后执行 执行后按照200ms周期持续运行 Create_Task(100,0,fun2); //fun2任务 100ms后执行,仅执行一次 //Delete_Task(fun2); //可以删除任务,将结构体空间腾出,方便新增其它临时任务 while(1) { TaskProcess(); //查询就绪的函数 } }
标签: #单片机一个for循环时间是多少