FreeRTOS之delay定时器

本文介绍了如何在FreeRTOS中修改滴答定时器的中断服务函数,以实现不进行任务切换的延时功能,重点在于确保定时器时钟频率与FreeRTOS系统时钟同步,并调用xPortSysTickHandler。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.FreeRTOS提供的定时器函数会导致任务的切换,但是在实际的应用程序中可能需要不进行任务切换的延时函数。因此,本文根据FreeRTOS的时钟节拍来设置滴答定时器的计数周期。

2.首先,因为是要修改系统的滴答定时器中断服务函数,所以需要将如下的地方进行注释,负责会出现重复定义的错误。

然后重新修改滴答定时器的中断服务函数,在滴答定时器的中断服务里调用xPortSysTickHandler()。

3.初始化滴答定时器:

首先需要将滴答定时器的时钟频率设置为和FreeRTOS一致,并开启滴答定时器的中断。

前面我们说了 FreeRTOS 的系统时钟是由滴答定时器提供的,那么肯定要根据 FreeRTOS 的 系统时钟节拍来初始化滴答定时器了,delay_init()就是来完成这个功能的。FreeRTOS 的系统时 钟节拍由宏 configTICK_RATE_HZ 来设置,这个值我们可以自由设置,但是一旦设置好以后我 们就要根据这个值来初始化滴答定时器,其实就是设置滴答定时器的中断周期。在基础例程中 滴答定时器的时钟频率设置的是 AHB 的 1/8,这里为了兼容 FreeRTOS 将滴答定时器的时钟频 率改为了 AHB,也就是 72MHz!这一点一定要注意!

4.代码:

(1)delay.c:

#include "delay.h"

static uint16_t fac_ms = 8;
static u32 fac_us; 

extern void xPortSysTickHandler(void);

//systickÖжϷþÎñº¯Êý
void SysTick_Handler(void)
{	
    if(xTaskGetSchedulerState()!=taskSCHEDULER_NOT_STARTED)//ϵͳÒѾ­ÔËÐÐ
    {
        xPortSysTickHandler();	
    }
}

//
void delay_init(void)
{
	u32 reload;
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK);//Ñ¡ÔñÍⲿʱÖÓ  HCLK
	fac_us=SystemCoreClock/1000000;				//²»ÂÛÊÇ·ñʹÓÃOS,fac_us¶¼ÐèҪʹÓÃ
	reload=SystemCoreClock/1000000;				//ÿÃëÖӵļÆÊý´ÎÊý µ¥Î»ÎªM  
	reload*=1000000/configTICK_RATE_HZ;			//¸ù¾ÝconfigTICK_RATE_HZÉ趨Òç³öʱ¼ä
												//reloadΪ24λ¼Ä´æÆ÷,×î´óÖµ:16777216,ÔÚ72MÏÂ,Ô¼ºÏ0.233s×óÓÒ	
	fac_ms=1000/configTICK_RATE_HZ;				//´ú±íOS¿ÉÒÔÑÓʱµÄ×îÉÙµ¥Î»	   

	SysTick->CTRL|=SysTick_CTRL_TICKINT_Msk;   	//¿ªÆôSYSTICKÖжÏ
	SysTick->LOAD=reload; 						//ÿ1/configTICK_RATE_HZÃëÖжÏÒ»´Î	
	SysTick->CTRL|=SysTick_CTRL_ENABLE_Msk;   	//¿ªÆôSYSTICK    
}

void delay_us(uint32_t nus)
{
	u32 ticks;
	u32 told,tnow,tcnt=0;
	u32 reload=SysTick->LOAD;				//LOADµÄÖµ	    	 
	ticks=nus*fac_us; 						//ÐèÒªµÄ½ÚÅÄÊý 
	told=SysTick->VAL;        				//¸Õ½øÈëʱµÄ¼ÆÊýÆ÷Öµ
	while(1)
	{
		tnow=SysTick->VAL;	
		if(tnow!=told)
		{	    
			if(tnow<told)tcnt+=told-tnow;	//ÕâÀï×¢ÒâÒ»ÏÂSYSTICKÊÇÒ»¸öµÝ¼õµÄ¼ÆÊýÆ÷¾Í¿ÉÒÔÁË.
			else tcnt+=reload-tnow+told;	    
			told=tnow;
			if(tcnt>=ticks)break;			//ʱ¼ä³¬¹ý/µÈÓÚÒªÑÓ³ÙµÄʱ¼ä,ÔòÍ˳ö.
		}  
	};
}


void delay_xms(uint32_t ms)								//·â×°ÈÎÎñÇл»µÄÑÓʱº¯Êý
{
	if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED)				//Èç¹ûϵͳÒѾ­ÔÚÔËÐУ¬Ôò¿ªÊ¼ÑÓʱ
	{
		if(ms >= fac_ms)
		{
			vTaskDelay(ms / fac_ms);
		}
		ms %= fac_ms;													//µ±OSÎÞ·¨ÌṩÕâôСµÄÑÓʱʱ£¬Ê¹ÓÃÆÕͨÑÓʱ
	}
	delay_ms((uint32_t)(ms*1000));				//ÆÕͨÑÓʱ
}






(2)delay.h:

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f10x.h"
#include "FreeRTOS.h"
#include "task.h"

void delay_init(void);
void delay_us(uint32_t us);									//ÑÓʱ΢Ãë
void delay_ms(uint32_t ms);									//ÑÓʱºÁÃë

void delay_xms(uint32_t ms);								//·â×°ÈÎÎñÇл»µÄÑÓʱº¯Êý

#endif

5.总结:

使用如上的操作步骤就可以设好不进行任务切换的延时函数。需要注意的是将滴答定时器的时钟频率和FreeRTOS设置为一致,并在滴答定时器的中断服务函数里调用FreeRTOS的xPortSysTickHandler()。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值