延迟性堵塞与非延迟性堵塞

文章介绍了STM32使用HAL库中延迟函数的概念,包括堵塞延迟和非堵塞延迟的实现方式。通过循环计数实现的延迟函数不利于多任务并行,因此发展到基于软件定时器的非堵塞延迟,允许同时处理多个任务。最后,通过配置定时器中断实现更精确的分时调度,以控制不同LED的闪烁频率。
摘要由CSDN通过智能技术生成

 目录

​​

前言

一、延迟函数是什么?

二、依靠循环次数的堵塞延迟与非堵塞延迟

1.堵塞延迟

2.非堵塞性延迟

三、依靠多路软件定时器的堵塞延迟与非堵塞延迟

1.堵塞延迟

总结



前言

该系列使用STM32HAL库与MDK,芯片是STM32F103C8T6,所有基本环境搭建,与IO基本配置,本章都不详解。主要目的通过LED来区分。延迟性堵塞与非延迟性的区别。

一、延迟函数是什么?

延迟函数:独占性的延迟函数,其在运行时,整个系统都将处于停止等待状态。最常见的等待延迟函数。

代码如下(示例):

/************************************
函数名:Delay_DS
功  能:粗略的延迟函数
参  数:time
返回值:无
*************************************/
void Delay_DS(unsigned int time)
{
	unsigned int i,j;
	for(i=time ;i>0;i--)
		for(j=124;j>0;j--);

}

但这种延迟函数不利于多任务并行,接下来对其进行改造,使其成为软件定时器,具有多任务并行的能力。 

二、依靠循环次数的堵塞延迟与非堵塞延迟

1.堵塞延迟

代码如下(示例):已验证

  while (1)
  {

		LED1_ON();	
		LED3_ON();
		Delay_DS(50000);
		LED1_Off();	
		LED3_Off();
		Delay_DS(50000);		

  }

 无法使两个小灯以不同的频率闪烁,因为必须等待延迟函数运行完,才会执行下一步。

2.非堵塞性延迟

代码如下(示例):已验证

/*******tim.c***********/
#define  Led1_time 60000
#define  Led3_time 20000

extern unsigned char LED1_Delay_Flag;
extern unsigned char LED3_Delay_Flag;
extern unsigned int Led1_cnt;
extern unsigned int Led3_cnt;

void Delay_DS(unsigned int time);
void Delay_FDS(void);

/*******tim.c***********/
unsigned int Led1_cnt=0,Led3_cnt=0;
unsigned char LED1_Delay_Flag=0,LED3_Delay_Flag=0;
/************************************
函数名:Delay_DS
功  能:粗略的延迟函数
参  数:time
返回值:无
*************************************/
void Delay_FDS(void)
{
	if(Led1_cnt)
	{
		Led1_cnt--;
		if(!Led1_cnt)
			LED1_Delay_Flag=1;
	}
	if(Led3_cnt)
	{
		Led3_cnt--;
		if(!Led3_cnt)
			LED3_Delay_Flag=1;
	}
}


/*******main.c***********/

int main(void)
{
unsigned char LED1_flag=1,LED3_flag=1;
  while (1)
  {
		Led1_cnt=Led1_time;
		Led3_cnt=Led3_time;
		while(1)
		{
			if(LED1_Delay_Flag)
			{
				LED1_Delay_Flag=0;//清除延迟完成标志位
				Led1_cnt=Led1_time;//重新赋值
				if(LED1_flag)//亮灭标志位
				{
						LED1_ON();	
						LED1_flag=0;
				}
				else
				{
						LED1_Off();	
						LED1_flag=1;
				}
			}
			if(LED3_Delay_Flag)
			{
				LED3_Delay_Flag=0;
				Led3_cnt=Led3_time;
				if(LED3_flag)
				{
						LED3_ON();	
						LED3_flag=0;
				}
				else
				{
						LED3_Off();	
						LED3_flag=1;
				}	
			}
				Delay_FDS();
		}
	
  }

}

这样便能实现两个LED以不同频率闪烁,但随着任务数变多,主循环的时基也会变长。接下来通过定时器确定稳定的时基。

三、依靠多路软件定时器非堵塞延迟

配置定时器的中断为1MS, 定义不同时间段的任务,来执行不同动作,即分时调度

代码如下(示例):已验证

/***************tim.h*************/

#define  Task_1MS  		1
#define  Task_10MS  	10
#define  Task_100MS  	100
#define  Task_250MS  	250
#define  Task_500MS  	500
#define  Task_1S  		1000
#define  Task_5S  		5000
#define  Task_10S  		10000


extern unsigned int Task_1MS_cnt;
extern unsigned int Task_10MS_cnt;
extern unsigned int Task_100MS_cnt;
extern unsigned int Task_250MS_cnt;
extern unsigned int Task_500MS_cnt;
extern unsigned int Task_1S_cnt;
extern unsigned int Task_5S_cnt;
extern unsigned int Task_10S_cnt;


extern unsigned int Task_1MS_flag;
extern unsigned int Task_10MS_flag;
extern unsigned int Task_100MS_flag;
extern unsigned int Task_250MS_flag;
extern unsigned int Task_500MS_flag;
extern unsigned int Task_1S_flag;
extern unsigned int Task_5S_flag;
extern unsigned int Task_10S_flag;



/***************tim.c*************/


unsigned int Task_1MS_cnt=0;
unsigned int Task_10MS_cnt=0;
unsigned int Task_100MS_cnt=0;
unsigned int Task_250MS_cnt=0;
unsigned int Task_500MS_cnt=0;
unsigned int Task_1S_cnt=0;
unsigned int Task_5S_cnt=0;
unsigned int Task_10S_cnt=0;


unsigned int Task_1MS_flag=0;
unsigned int Task_10MS_flag=0;
unsigned int Task_100MS_flag=0;
unsigned int Task_250MS_flag=0;
unsigned int Task_500MS_flag=0;
unsigned int Task_1S_flag=0;
unsigned int Task_5S_flag=0;
unsigned int Task_10S_flag=0;
/************************************
函数名:HAL_TIM_PeriodElapsedCallback
功  能:1MS定时器中断回调函数
参  数:htim
返回值:无
*************************************/
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
{
	if (htim->Instance == htim2.Instance) 
	{
					//All_LED_ON();
		Task_1MS_cnt--;
		Task_10MS_cnt--;
		Task_100MS_cnt--;
		Task_250MS_cnt--;
		Task_500MS_cnt--;
		Task_1S_cnt--;
		Task_5S_cnt--;
		Task_10S_cnt--;
			
		if(!Task_1MS_cnt)
		{
			Task_1MS_cnt=Task_1MS;
			Task_1MS_flag=1;
		}
		if(!Task_10MS_cnt)
		{
			Task_10MS_cnt=Task_10MS;
			Task_10MS_flag=1;
		}
		if(!Task_100MS_cnt)
		{
			Task_100MS_cnt=Task_100MS;
			Task_100MS_flag=1;
		}
		if(!Task_250MS_cnt)
		{
			Task_250MS_cnt=Task_250MS;
			Task_250MS_flag=1;
		}
		if(!Task_500MS_cnt)
		{
			Task_500MS_cnt=Task_500MS;
			Task_500MS_flag=1;
		}
		if(!Task_1S_cnt)
		{
			Task_1S_cnt=Task_1S;
			Task_1S_flag=1;
		}
		if(!Task_5S_cnt)
		{
			Task_5S_cnt=Task_5S;
			Task_5S_flag=1;

		}
		if(!Task_10S_cnt)
		{
			Task_10S_cnt=Task_10S;
			Task_10S_flag=1;
		}		
	}
}










/***************main.c*************/
int mian (void)
{
unsigned char LED1_flag=1,LED3_flag=1,LED4_flag=1;
  while (1)
  {
		Task_1MS_cnt = Task_1MS;
		Task_10MS_cnt = Task_10MS;
		Task_100MS_cnt = Task_100MS;
		Task_250MS_cnt = Task_250MS;
		Task_500MS_cnt = Task_500MS;
		Task_1S_cnt = Task_1S;
		Task_5S_cnt = Task_5S;
		Task_10S_cnt = Task_10S;
		while(1)
		{
			if(Task_1S_flag)
			{
				Task_1S_flag=0;
				if(LED1_flag)
				{
						LED1_ON();	
						LED1_flag=0;
				}
				else
				{
						LED1_Off();	
						LED1_flag=1;
				}
			}
			if(Task_5S_flag)
			{
				Task_5S_flag=0;
				if(LED3_flag)
				{
						LED3_ON();	
						LED3_flag=0;
				}
				else
				{
						LED3_Off();	
						LED3_flag=1;
				}	
			}
			
			if(Task_10S_flag)
			{
				Task_10S_flag=0;
				if(LED4_flag)
				{
						LED4_ON();	
						LED4_flag=0;
				}
				else
				{
						LED4_Off();	
						LED4_flag=1;
				}	
			}
			
		}
	

}

实物视频如下

堵塞延迟与非堵塞延迟视频-CSDN直播


总结

对延迟函数的理解,以及引出分时调度,小菜鸡刚上路,如有错误,请指教。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值