裸机编程的延时函数与RT-Thread的延时函数的区别

在裸机(以stm32为例)编程中,常用的延时方法如下:

1.循环法

void delay_us(u16 time)
{    
   u16 i=0;  
   while(time--)
   {
      i=10;  //自己定义
      while(i--) ;    
   }
}
//毫秒级的延时
void delay_ms(u16 time)
{    
   u16 i=0;  
   while(time--)
   {
      i=12000;  //自己定义
      while(i--) ;    
   }
}

2.SysTick定时器中断机制
SysTick-系统定时器是CM3内核中的一个外设,内嵌在NVIC中,是一个24位向下递减的计数器,所有基于CM3内核的单片机都具有这个系统定时器,当重装载数值寄存器的值递减到0的时候,系统定时器就产生一次中断,以此循环往复!

*volatile unsigned long time_delay; // 延时时间,注意定义为全局变量
//延时n_ms
void delay_ms(volatile unsigned long nms)
{
    //SYSTICK分频--1ms的系统时钟中断
    if (SysTick_Config(SystemFrequency/1000))
    {
   
        while (1);
    }
    time_delay=nms;//读取定时时间
    while(time_delay);
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
//延时nus
void delay_us(volatile unsigned long nus)
{
 //SYSTICK分频--1us的系统时钟中断
    if (SysTick_Config(SystemFrequency/1000000))
    {
   
        while (1);
    }
    time_delay=nus;//读取定时时间
    while(time_delay);
    SysTick->CTRL=0x00; //关闭计数器
    SysTick->VAL =0X00; //清空计数器
}
 
    //在中断中将time_delay递减。实现延时
void SysTick_Handler(void)
{
    if(time_delay)
        time_delay--;
}*

3.非中断方式,直接操作寄存器

//初始化延迟函数
//当使用OS的时候,此函数会初始化OS的时钟节拍
//SYSTICK的时钟固定为HCLK时钟的1/8
//SYSCLK:系统时钟
void delay_init()
{
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	u32 reload;
#endif
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8);	//选择外部时钟  HCLK/8
	fac_us=SystemCoreClock/8000000;				//为系统时钟的1/8  
#if SYSTEM_SUPPORT_OS  							//如果需要支持OS.
	reload=SystemCoreClock/8000000;				//每秒钟的计数次数 单位为M  
	reload*=1000000/delay_ostickspersec;		//根据delay_ostickspersec设定溢出时间
												//reload为24位寄存器,最大值:16777216,在72M下,约合1.86s左右	
	fac_ms=1000/delay_ostickspersec;			//代表OS可以延时的最少单位	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//开启SYSTICK中断
	SysTick->LOAD=reload; 						//每1/delay_ostickspersec秒中断一次	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//开启SYSTICK    

#else
	fac_ms=(u16)fac_us*1000;					//非OS下,代表每个ms需要的systick时钟数   
#endif
}					
//延时nms
//注意nms的范围
//SysTick->LOAD为24位寄存器,所以,最大延时为:
//nms<=0xffffff*8*1000/SYSCLK
//SYSCLK单位为Hz,nms单位为ms
//对72M条件下,nms<=1864 
void delay_ms(u16 nms)
{	 		  	  
	u32 temp;		   
	SysTick->LOAD=(u32)nms*fac_ms;				//时间加载(SysTick->LOAD为24bit)
	SysTick->VAL =0x00;							//清空计数器
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk ;	//开始倒数  
	do
	{
		temp=SysTick->CTRL;
	}while((temp&0x01)&&!(temp&(1<<16)));		//等待时间到达   
	SysTick->CTRL&=~SysTick_CTRL_ENABLE_Msk;	//关闭计数器
	SysTick->VAL =0X00;       					//清空计数器	  	    
} 

在RT-Thread中延时

  • 使用 RTOS 的很大优势就是榨干 CPU 的性能,永远不能让它闲着,线程如果需要延 时也就不能再让 CPU 空等来实现延时的效果。
    RTOS 中的延时叫阻塞延时,即线程需要延 时的时候, 线程会放弃 CPU 的使用权, CPU 可以去干其它的事情,当线程延时时间到,重
    新获取 CPU 使用权, 线程继续运行,这样就充分地利用了 CPU 的资源,而不是干等着。

    当线程需要延时,进入阻塞状态,那 CPU 又去干什么事情了?如果没有其它线程可以 运行, RTOS 都会为 CPU创建一个空闲线程,这个时候 CPU 就运行空闲线程。 在 RTThread中,空闲线程是系统在初始化的时候创建的优先级最低的线程,空闲线程主体主要是做一些系统内存的清理工作。但是为了简单起见,我们本章实现的空闲线程只是对一个 全局变量进行计数。鉴于空闲线程的这种特性,在实际应用中,当系统进入空闲线程的时 候, 可在空闲线程中让单片机进入休眠或者低功耗等操作

 void rt_thread_delay(rt_tick_t tick)
 {
 struct rt_thread *thread;

 /* 获取当前线程的线程控制块 */
 thread = rt_current_thread; 

 /* 设置延时时间 */
 thread->remaining_tick = tick; 

 /* 进行系统调度 */
 rt_schedule(); 
 }

rt_current_thread 是一个在 scheduler.c
定义的全局变量,用于指向当前正在运行的线程的线程控制块
remaining_tick 是线程控制块的一个成员,用于记录线程需要延时
的时间,单位为 SysTick 的中断周期。比如我们本书当中 SysTick 的中断周期为 10ms,调
用 rt_thread_delay(2)则完成 2*10ms 的延时。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值