stm32c8t6之freertos软件定时器

        像我们使用电stm32单片机或者51单片机当中,都有定时器这个外设。而freertos也不例外,它自己也有定时器的功能。

软件定时器的创建和删除

#include "timers.h"

TimerHandle_t timer1_Handle;                    //创建句柄

timer1_Handle = xTimerCreate("timer1Task",1000,pdTRUE,(void*)1,timer1Task);    //创建函数

xTimerDelete(timer1_Handle,0);                  //删除函数

        首先先定义软件定时器的头文件和句柄,然后调用xTimerCreate()函数创建软件定时器。xTimerCreate()函数有5个参数,第一个是函数名,个人建议给和回调函数一样的名字即可;第二个是定时时间,单位为ms;第三个参数是模式设置,软件定时器有两个模式,周期模式和单次模式。周期模式就是一直定时1000ms,不断循环,单次模式就是定时一次就自动结束了。选择pdTRUE为周期模式,选择pdFALSE为单次模式;第四个参数是定时器编号,每个定时器最好都别设置一样的编号,需要(void*)进行强转;最好一个参数是回调函数名,软件定时器将一直执行这个回调函数里的逻辑代码。

        最后是删除函数,第一个参数是定时器句柄,第二个参数是等待时间,给0的话就是一调用直接删除。删除函数更多的是使用在周期定时器上面,单次定时器调用完一次之后系统会自动删除。

软件定时器的开始和停止

xTimerStart(timer1_Handle,0);    //开始定时器

xTimerStop(timer1_Handle,0);     //停止定时器

        开始定时器函数xTimerStart()函数和停止定时器函数xTimerStop()函数的用法都是一样的。它们都有两个参数,第一个参数是定时器的句柄,第二个参数是等待事件,给0就是直接开始或者直接停止。但是这两个函数都不能在中断里使用,中断有中断自己的开始和停止函数。

xTimerStartFromISR(timer1_Handle,pdTRUE);        //开始定时函数

xTimerStopFromISR(timer1_Handle,pdTRUE);         //停止定时函数

        第一个参数是定时器句柄,第二个可以给pdTRUE或者pdFALSE。

获取定时器的值

TickType_t tick_num2;

tick_num2 = xTaskGetTickCount();

        xTaskGetTickCount()函数可以返回定时器的值,我们定义一个变量来接收即可。 

软件定时器实验

        定义两个定时器,一个周期定时器,一个单次定时器,看看他们的效果。 

开始任务创建

TimerHandle_t timer1_Handle;			//周期定时句柄
TimerHandle_t timer2_Handle;			//单次定时句柄


TaskHandle_t startTask_handler;     	//总任务的句柄
TaskHandle_t ledTask_handler;			//led的句柄
TaskHandle_t timer1Task_handler;		//获取信号量的句柄
TaskHandle_t timer2Task_handler;		//释放信号量的句柄


void startTask(void *arg)
{
	BaseType_t xReturn = pdFALSE;														//创建接收值
	
	taskENTER_CRITICAL();    															//临界区
	
	
	xReturn = xTaskCreate(ledTask,"ledTask",64,NULL,1,&ledTask_handler);				//创建led任务
	
	//创建定时器1
	timer1_Handle=xTimerCreate("timer1Task",1000,pdTRUE,(void*)1,timer1Task);
	
	if(timer1_Handle != NULL) 
	{
		xTimerStart(timer1_Handle,0);	//开启周期定时器
	}
	
	//创建定时器2
	timer2_Handle=xTimerCreate("timer2Task",5000,pdFALSE,(void*)2,timer2Task); 
	
	if(timer2_Handle != NULL) 
	{
		xTimerStart(timer2_Handle,0);	//开启单次定时器
	}
	
	if(xReturn == pdTRUE)
	{
		printf("Task create ok\n");
	}
	else
	{
		printf("Task create error\n");
	}
	
	vTaskDelete(startTask_handler);														//删除开始任务
	
	taskEXIT_CRITICAL();																//临界区
	
}

        开始任务startTask(vois *arg)创建了3个任务,分别是led任务,周期定时器任务和单次定时器任务。 

led任务

void ledTask(void *arg)
{
	while(1)
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_8);
		vTaskDelay(500);
		GPIO_ResetBits(GPIOB,GPIO_Pin_8);
		vTaskDelay(500);
	}
}

        led任务主要起到一个心跳包的作用,我们可以观察led是否一直闪烁来判断我们的程序是否运行正常。

周期定时器任务

int timer1Index = 0;

void timer1Task(void *arg)
{
	TickType_t tick_num1;
	
	timer1Index++;						// 每回调一次加一 

	tick_num1 = xTaskGetTickCount();	// 获取滴答定时器的计数值 
	
	printf("timer1 callback %d times\n", timer1Index);
	printf("timer1 data = %d\n", tick_num1);
	
}

        定义一个全局变量timer1Index来记录调用次数,tick_num1用来记录定时器的值,这个任务是每1秒调用一次,不停循环。

单次定时器任务

int timer2Index = 0;

void timer2Task(void *arg)
{
	TickType_t tick_num2;
	
	timer2Index++;						// 每回调一次加一 

	tick_num2 = xTaskGetTickCount();	// 获取滴答定时器的计数值 
	
	printf("=========================================\n");
	printf("timer2 callback %d times\n", timer2Index);
	printf("timer2 data = %d\n", tick_num2);
	printf("=========================================\n");
}

       定义一个全局变量timer2Index来记录调用次数,tick_num2用来记录定时器的值,这个任务是5秒调用一次,调用完就自动删除。

实验现象

stm32c8t6之freertos软件定时器_第1张图片stm32c8t6之freertos软件定时器_第2张图片 

        第一张图片,刚开始按下复位键,串口打印Task create ok,代表所有任务创建成功。随后周期定时器timer1不停执行,到第5次时,单次定时器timer2也调用了。

        但是由第2张图可以看到,当周期定时timer1调用第10次时,单次定时器timer2没有调用,因为它已经被删除了。

源码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "key.h"
#include "queue.h"
#include "led.h"
#include "stdlib.h"
#include "semphr.h"
#include "timers.h"


TimerHandle_t timer1_Handle;			//周期定时句柄
TimerHandle_t timer2_Handle;			//单次定时句柄


TaskHandle_t startTask_handler;     	//总任务的句柄
TaskHandle_t ledTask_handler;			//led的句柄
TaskHandle_t timer1Task_handler;		//获取信号量的句柄
TaskHandle_t timer2Task_handler;		//释放信号量的句柄
					
int timer1Index = 0;
int timer2Index = 0;

void ledTask(void *arg)
{
	while(1)
	{
		GPIO_SetBits(GPIOB,GPIO_Pin_8);
		vTaskDelay(500);
		GPIO_ResetBits(GPIOB,GPIO_Pin_8);
		vTaskDelay(500);
	}
}

void timer1Task(void *arg)
{
	TickType_t tick_num1;
	
	timer1Index++;						// 每回调一次加一 

	tick_num1 = xTaskGetTickCount();	// 获取滴答定时器的计数值 
	
	printf("timer1 callback %d times\n", timer1Index);
	printf("timer1 data = %d\n", tick_num1);
	
}

void timer2Task(void *arg)
{
	TickType_t tick_num2;
	
	timer2Index++;						// 每回调一次加一 

	tick_num2 = xTaskGetTickCount();	// 获取滴答定时器的计数值 
	
	printf("=========================================\n");
	printf("timer2 callback %d times\n", timer2Index);
	printf("timer2 data = %d\n", tick_num2);
	printf("=========================================\n");
}

void startTask(void *arg)
{
	BaseType_t xReturn = pdFALSE;														//创建接收值
	
	taskENTER_CRITICAL();    															//临界区
	
	
	xReturn = xTaskCreate(ledTask,"ledTask",64,NULL,1,&ledTask_handler);				//创建led任务
	
	//创建定时器1
	timer1_Handle=xTimerCreate("timer1Task",1000,pdTRUE,(void*)1,timer1Task);
	
	if(timer1_Handle != NULL) 
	{
		xTimerStart(timer1_Handle,0);	//开启周期定时器
	}
	
	//创建定时器2
	timer2_Handle=xTimerCreate("timer2Task",5000,pdFALSE,(void*)2,timer2Task); 
	
	if(timer2_Handle != NULL) 
	{
		xTimerStart(timer2_Handle,0);	//开启单次定时器
	}
	
	if(xReturn == pdTRUE)
	{
		printf("Task create ok\n");
	}
	else
	{
		printf("Task create error\n");
	}
	
	vTaskDelete(startTask_handler);														//删除开始任务
	
	taskEXIT_CRITICAL();																//临界区
	
}


int main(void)
{
	LED_Init();
	usrt1_init(9600);
	xTaskCreate(startTask,"startTask",512,NULL,1,&startTask_handler);					//创建开始任务
	vTaskStartScheduler();
}

 

 

 

 

         

 

 

你可能感兴趣的:(FreeRtos,stm32,嵌入式硬件,单片机)