【FreeRTOS】14.STM32移植-软件定时器

软件定时器

硬件定时器功能强大,遗憾数量较少。故可以使用软件定时器来拓展,软件定时器允许设置一段时间,当设置的时间达到后就执行指定的功能函数,模拟实现定时器中断的功能。

回调函数

被定时器调用的函数叫定时器回调函数,回调函数执行的间隔叫定时器周期。软件定时器的回调函数在定时器服务任务中执行的,一定不用在回调函数中调用任何会阻塞的任务API函数,如vTaskDelay、vTaskDelayUnti、阻塞信号量等。

定时器服务任务与队列

定时器是可选的、不属于FreeRTOS内核的功能,由定时器服务任务提供。

FreeRTOS提供了许多定时器相关的API函数,这些API函数大多使用队列发送命令给定时器服务任务。这个队列叫定时器命令队列,仅供FreeRTOS的软件定时器使用,用户不能直接访问。

定时器任务的创建过程:vTaskStartScheduler->xTimerCreateTimerTask->xTaskCreate->prvTimerTask(“Tmr Svc”)->prvProcessReceivedCommands

定时器配置

configUSE_TIMERS 为一启用软件定时器。

configTIMER_TASK_PRIORITY 设置为最高优先级,即(configMAX_PRIORITIES-1)

configTIMER_QUEUE_LENGTH 软件定时器队列长度

configTIMER_TASK_STACK_DEPTH 定时器的堆栈大小,默认(configMINIMAL_STACK_SIZE*2) =260 。注意回调函数申请的空间不要太复杂。

定时器分单次定时器和周期性定时器。

软件定时器API函数

  • 创建软件定时器:返回值为句柄
xTimerCreate() // 动态
xTimerCreateStatic() // 静态 

动态创建参数说明

const char * const pcTimerName,             // 定时器的名字
const TickType_t xTimerPeriodInTicks,       // 定时器的周期节拍数,可以使用portTICK_PERIOD_MS将ms转换为节拍数
const UBaseType_t uxAutoReload,             // 是否自动重装载,pdTRUE为自动重装载
void * const pvTimerID,                     // 定时器ID,每个ID对应一个回调函数,允许ID相同对应同一个回调函数。
TimerCallbackFunction_t pxCallbackFunction  // 回调函数,执行定时器时间到了的功能函数
// 返回值为句柄

新创建的软件定时器都是未运行的,处于休眠状态。需使用start开启

  • 复位软件定时(定时器的时间重新计时)
xTimerReset()            // 任务级复位软件定时器
xTimerResetFromISR()     // 中断级复位软件定时器  

任务级复位定时器参数说明

TimerHandle_t xTimer       // 定时器句柄
TickType_t    xTickToWait  // 阻塞时间,即进入队列的阻塞时间
  • 开启软件定时器
xTimerStart()           // 任务级开启软件定时器
xTimerStartFromISR()    // 中断级开启软件定时器

任务级开启定时器参数说明

TimerHandle_t xTimer       // 定时器句柄
TickType_t    xTickToWait  // 阻塞时间,即进入队列的阻塞时间
  • 停止软件定时器
xTimerStop()           // 任务级停止软件定时器
xTimerStopFromISR()    // 中断级停止软件定时器

实验

使用按键控制定时器的开始和停止,观察重装载和单次定时器的区别。

代码
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "string.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "queue.h"
#include "timer.h"
#include "timers.h"
/************************************************

************************************************/

//任务优先级
#define START_TASK_PRIO		1
//任务堆栈大小	
#define START_STK_SIZE 		128  
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);


//任务优先级
#define TIMCTRL_TASK_PRIO		2
//任务堆栈大小	
#define TIMCTRL_STK_SIZE 		128  
//任务句柄
TaskHandle_t TimCtrl_Handler;
//任务函数
void tim_ctrl_task(void *pvParameters);

TimerHandle_t  ReloadTimerHandle;
TimerHandle_t OneShotTimerHandle;
// 定时器回调函数
void ReloadTimerCallback( TimerHandle_t xTimer );
// 定时器回调函数
void OneShotTimerCallback( TimerHandle_t xTimer );

int main(void)
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4	 
	delay_init();	    				//延时函数初始化	 
	uart_init(115200);					//初始化串口
	LED_Init();		  					//初始化LED
	KEY_Init();	
	
    xTaskCreate((TaskFunction_t )start_task,            //任务函数
                (const char*    )"start_task",          //任务名称
                (uint16_t       )START_STK_SIZE,        //任务堆栈大小
                (void*          )NULL,                  //传递给任务函数的参数
                (UBaseType_t    )START_TASK_PRIO,       //任务优先级
                (TaskHandle_t*  )&StartTask_Handler);   //任务句柄              
    vTaskStartScheduler();          //开启任务调度
}

//开始任务任务函数
void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
	
	// 创建定时器
	ReloadTimerHandle = xTimerCreate((const char *   )         "Reload Timer",
									 (TickType_t     )         1000,                   // 时钟节拍数
									 (UBaseType_t    )         pdTRUE,                 //uxAutoReload,是否自动重装载
								     (void *         )         1,                      //pvTimerID,定时器ID
									 (TimerCallbackFunction_t) ReloadTimerCallback );  // 回调函数
								 
	// 创建定时器
	OneShotTimerHandle = xTimerCreate((const char *   )        "One Shot Timer",
									 (TickType_t      )         2000,                   // 时钟节拍数
									 (UBaseType_t     )         pdFALSE,                 //uxAutoReload,是否自动重装载
								     (void *          )         2,                      //pvTimerID,定时器ID
									 (TimerCallbackFunction_t) OneShotTimerCallback );  // 回调
	
	if(ReloadTimerHandle&&OneShotTimerHandle)		
		printf("ReloadTimerHandle&&OneShotTimerHandle Create Sucess\r\n");	
	
	xTaskCreate((TaskFunction_t) tim_ctrl_task,
				(const char *  ) "tim_ctrl_task",
				(uint16_t      ) TIMCTRL_STK_SIZE,
				(void *        ) NULL,
				(UBaseType_t   ) TIMCTRL_TASK_PRIO,
				(TaskHandle_t* ) &TimCtrl_Handler);
										
    vTaskDelete(StartTask_Handler); //删除开始任务
    taskEXIT_CRITICAL();            //退出临界区
}

//任务函数
void tim_ctrl_task(void *pvParameters)
{
	u8 key = 0;
	BaseType_t err;
	while(1)
	{
		key = KEY_Scan(0);
		switch(key)
		{
			case WKUP_PRES:
				err = xTimerStart(ReloadTimerHandle,0);
				if(err == pdTRUE)
					printf("++Reload Timer Start Sucess!!!\r\n");
				else
					printf("Reload Timer Start Failed\r\n");
				break;
			case KEY1_PRES:
				err = xTimerStop(ReloadTimerHandle,0);
				if(err == pdTRUE)
					printf("--Reload Timer Stop Sucess!!!\r\n");
				else
					printf("Reload Timer Stop Failed\r\n");
				break;
			case KEY0_PRES:
				err = xTimerStart(OneShotTimerHandle,0);
				if(err == pdTRUE)
					printf("+OneShot Timer Start Sucess!!!\r\n");
				else
					printf("OneShot Timer Start Failed\r\n");
				break;
			case KEY2_PRES:
				err = xTimerStop(OneShotTimerHandle,0);
				if(err == pdTRUE)
					printf("-OneShot Timer Stop Sucess!!!\r\n");
				else
					printf("OneShot Timer Stop Failed\r\n");
				break;				
		}
        vTaskDelay(10);                           //延时1s,也就是1000个时钟节拍	
	}
}


// 定时器回调函数
void ReloadTimerCallback( TimerHandle_t xTimer )
{
	static u8 times = 0;
	LED0=!LED0;
	times++;
	printf("RUNNING %d,Reload Timer\r\n",times);
}

// 定时器回调函数
void OneShotTimerCallback( TimerHandle_t xTimer )
{
	static u8 times = 0;
	LED1=!LED1;
	times++;
	printf("RUNNING %d,OneShot Timer\r\n",times);
}


你可能感兴趣的:(FreeRTOS,stm32,操作系统,freertos)