单片机定时器最大定时时间计算时间片轮询架构任务中有长延时怎么办?

1. 基于时间片的轮询调度算法(仅局限单核CPU芯片):
利用定时器为每个任务函数设定执行时间间隔,保证使用频率高的函数多次被调用,提高单核芯片的资源利用率。如果只是简单地将A、B两个函数放在while中,那么在一定时间内这两个函数调用的次数是一致的,,这样就浪费了单核芯片的资源。
2. 例子:
函数A(100μs执行一次----使用频率高),函数B(1000μs执行一次----使用频率低)。那么在1ms 内 函数A 执行了10次,而函数B只执行1次当然你要保证函数A在100μs内执行完毕、函数B在1000μs内执行完毕如果超出时间的话系统会变得卡顿。有部分的函数可能没有别执行到。毕竟单核芯片只在很短时间内只做一件事。
3. PS
1、从微观上单核芯片在某一个和短时间时间段只执行一件事。从宏观上 (比如:1S):单核芯片执行多件事情;2、任务函数最好不要出现delay等延时函数,不然整个系统变得卡顿。
4. 为了更好地理解上述描述,可以结合以下代码理解(基于STM32F103C8T6芯片编写)API_Schedule.c#include "API_Schedule.h"
#include "stdlib.h"
/************任务初始化,每一个结构体都代表一个任务,添加任务和删减任务都在这里完成************/
struct TaskStruct TaskST[]=
{
//
计时
多少ms调用一次
任务运行标志位
任务函数指针
{ 0,
5000,
0,
LedFlash},
{ 0,
1000,
0,
UARTFC},
{ 0,
500,
0,
UserTestMode},
};
/*******************************搭建时间片轮询机制代码框架********************************/
//记录任务数量
u8 TaskCount= sizeof(TaskST)/sizeof(TaskST[0]);
//放在“TIM2_IRQHandler”中断执行,用于任务计时
void OS_IT_RUN(void)
{
u8 i;
for(i=0;i<TaskCount;i++)//遍历所有循环
{
if(!TaskST[i].TaskStatus)
{
if(++TaskST[i].TaskTickNow >= TaskST[i].TaskTickMax)//计时,并判断是否到达定时时间
{
TaskST[i].TaskTickNow = 0;
TaskST[i].TaskStatus = 1;
}
}
}
}
//放在main函数中执行,自带死循环,用于执行挂起的任务
void PeachOSRun(void)
{
u8 j=0;
while(1)
{
if(TaskST[j].TaskStatus)//判断一个任务是否被挂起
{
TaskST[j].FC();
//执行该任务函数
TaskST[j].TaskStatus=0;
//取消任务的挂起状态
}
if(++j>=TaskCount)//相当于不断循环遍历所有的任务
j=0;
}
}
/*************************计划表中的任务*****************************/
void LedFlash(void)
{
//printf("Led \n");//调试用,需要自己添加uart外设后再使用这段代码
}
void UARTFC(void)
{
//printf("UARTFC \n");//调试用
}
void UserTestMode(void)
{
//printf("UserTestMode \n");//调试用
}
API_Schedule.h#ifndef __API_SCHEDULE_H__
#define __API_SCHEDULE_H__
#include "stm32f10x.h"
//框架运行所需的函数声明
void PeachOSRun(void);
void OS_IT_RUN(void);
/*
用与存储一个任务运行的数据
*/
struct TaskStruct
{
u16 TaskTickNow;//用于计时
u16 TaskTickMax;//设置计时时间
u8 TaskStatus;//任务运行标志位
void (*FC)();//任务函数指针
};
extern struct TaskStruct TaskST[]; //声明为结构体数据,那样多个任务时方便管理
//用于示例的任务函数声明
void LedFlash(void);
void UARTFC(void);
void UserTestMode(void);
#endif
bsp_time.c#include "bsp_time.h"
//中断初始化
void Time2_NVIC_Init()
{
NVIC_InitTypeDef NVIC_InitStruct;
NVIC_InitStruct.NVIC_IRQChannel
= TIM2_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
NVIC_InitStruct.NVIC_IRQChannelSubPriority
= 2;
NVIC_InitStruct.NVIC_IRQChannelCmd
= ENABLE;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_Init(&NVIC_InitStruct);
}
//定时器初始化
void Time2_Init(u16 arr,u16 psr)
{
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
TIM_TimeBaseInitStruct.TIM_ClockDivision
= 0;
TIM_TimeBaseInitStruct.TIM_CounterMode
= TIM_CounterMode_Up;
TIM_TimeBaseInitStruct.TIM_Period
= arr;
TIM_TimeBaseInitStruct.TIM_Prescaler
= psr;
TIM_TimeBaseInitStruct.TIM_RepetitionCounter
= 0;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);
TIM_ITConfig(TIM2, TIM_IT_Update,ENABLE);
TIM_Cmd(TIM2, ENABLE);
Time2_NVIC_Init();
}
//定时器中断
void TIM2_IRQHandler(void)
{
if(TIM_GetITStatus(TIM2,TIM_IT_Update) != RESET)
{
OS_IT_RUN();
TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
}
bsp_time.h#ifndef __TIME_H
#define __TIME_H
#include "stm32f10x.h"
#include "API_Schedule.h"
void Time2_Init(u16 arr,u16 psr);
#endif
main.c#include "stm32f10x.h"
#include "bsp_time.h"
#include "API_Schedule.h"
int main(void)
{
Time2_Init(71,1000);
PeachOSRun();
}
}
转载自知乎向导:题外话:导师给我列了要自己去学的东西Solidworks,单片机,C语言直到现在我学得也不多,这段时间挣扎在office二级计算机的题库里。因为感觉自己在学校里视图表达方法那部分,剖视图(半剖、全剖、局剖)、局部视图、学的真的不行。看阀盖阀门阀杆这些零件图的时候发现的这个问题,所以也在找视频找书看。也是在给计算机绘图铺点基础。因为如果画图只是为了照着样例抄图的话,有点囫囵吞枣的感觉,尤其是看着样例,发现自己真的不知道样例在表达什么东西的时候,感觉挺不开心的,撇嘴。单片机有借书来看,导师给了套arduino的入门套件,会慢慢记录自己最近在学的东西。就像记笔记一样借了书有项目可以玩,书里有很多好玩的项目:四旋翼飞行器飞控,微四轴飞行棋,自洞平衡小车项目,超有意思。学单片机也有激励的目标:全国大学生工程训练综合能力竞赛需要用到,当然离做出来东西我觉得有点远,边学边看吧,目标就是用来激励自己的。看书觉得有些头大但是看了向导的文章觉得举例子就觉得很好理解时间片轮询--思路实际上大部分文章把时间片轮询框架讲复杂了,它的内涵是:将每个工作划分为一个子任务,你可以把子任务看成一个个工作人员每个任务通过主程序定时去检查或者询问,你可以把主程序看成一位领导者领导定时询问每位工作人员你准备好了吗?或者工作做完了吗?进度如何?假设你是其中的一位工作人员你的工位位置有几个信号灯(指示牌),空闲、计数、准备好、忙碌中,这就是工作状态(状态机的状态)领导只是问你一句你的工作状态,简单直接点,你就回复你现在的状态是什么就行了接着领导又去问其他人员如果你已经准备好了去做一件事了,那就去做,领导会把一定的资源给你(例如材料、工具、场地,这时候其他人如果同时也要用这些东西可能要等等了)假设这个工作是西红柿装箱,几个人同时往一个箱子里面装,你装了一个西红柿,占去了一点时间,这个时候不是等着你装完,其他人再去装,而是你装了一个西红柿,如果其他人也准备好了,这个箱子会用传送带先送给其他人装,假设有三个人,那个这个传送带就在三个人之间来回跑。为什么来回跑,这是因为单片机资源是有限的,箱子(寄存器)就是那么多。资源受限,所以导致单片机只能压榨时间,把每个时间段细分,每个时间段分给不同的人。以上就是时间片轮询经过一定的时间,根据每个人的情况不同,分配不同的轮询时间,干得快的,1ms就问你一次,干得慢的100ms问你一次根据每个人的状态,分配资源和让一个人执行一段程序(做一件工作)不等任何人,而是问一下就根据状态分配资源如果这个人睡着了,怎么问都没回应,也不会再管你,划分时间片给其他人干活,你的这部分工作可能出错,但是如果不是关键程序,甚至不影响继续运行除了单片机入口的死循环,没有其他死循环子程序(子任务)如果有一段子任务必须执行完,才能做其他工作,那么这不是时间片轮询以上为时间片轮询要点时间片划分序号主/子任务时间片备注1定时器最小时间片1ms2键盘扫描20ms3数码管显示30ms4LED状态指示灯300ms5时钟60ms6789发布于 2021-02-10 00:36}

我要回帖

更多关于 单片机定时器最大定时时间计算 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信