<FreeRTOS入门第八节>软件定时器

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

昨天懒了休息了一天,今天继续肝软件定时器


一、FreeRTOS软件定时器是什么?

FreeRTOS软件定时器是FreeRTOS自带的定时器。主要包括,定时器的创建、开始、停止、复位,其中定时器创建又分为单次定时器和循环定时器。
当定时器运行时触发复位,下次开始是重新开始计算定时时间。

二、定时器API介绍

1.定时器配置

按照下面选中的条件编译代码编写添加


#define configTIMER_TASK_PRIORITY (configMAX_PRIORITIES-1)
#define configTIMER_QUEUE_LENGTH 5
#define configTIMER_TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE*2)

在这里插入图片描述
然后修改configUSE_TIMERS的宏
在这里插入图片描述
然后在主函数main.c添加Timers.h头文件
在这里插入图片描述
到这里就配置完成了

2.定时器创建

在这里插入图片描述
老规矩这里只讲动态创建定时器

/*
	创建动态定时器
	pcTimerName:定时器的名字
	xTimerPeriodInTicks:定时器的定时节拍(ms)
	uxAutoReload:单次循环还是多次循环 pdTRUE单次   pdFALSE 多次
	pvTimerID:第几个定时器
	pxCallbackFunction:定时器执行函数
	这个是带TimerHandle_t返回值类型的函数
	成功:其他值
	失败:NULL
*/
        TimerHandle_t xTimerCreate( const char * const pcTimerName,
                                    const TickType_t xTimerPeriodInTicks,
                                    const UBaseType_t uxAutoReload,
                                    void * const pvTimerID,
                                    TimerCallbackFunction_t pxCallbackFunction )

3.定时器开始

在这里插入图片描述
这个是一个宏定义,主体源码看xTimerGenericCommand();

/*
	开启定时器
	xTimer:定时器句柄
	xTicksToWait:任务阻塞时间
	这是带BaseType_t的返回值的函数
	成功:pdTRUE
	失败:pdFLASE
*/
#define xTimerStart( xTimer, xTicksToWait ) \
    xTimerGenericCommand( ( xTimer ), tmrCOMMAND_START, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )

4.定时器停止

在这里插入图片描述
又是一个宏。具体源码看xTimerGenericCommand();

/*
	停止定时器
	xTimer:定时器句柄
	xTicksToWait:任务阻塞时间
	这是带BaseType_t的返回值的函数
	成功:pdTRUE
	失败:pdFLASE
*/
#define xTimerStop( xTimer, xTicksToWait ) \
    xTimerGenericCommand( ( xTimer ), tmrCOMMAND_STOP, 0U, NULL, ( xTicksToWait ) )

5.定时器复位

在这里插入图片描述
又是一个宏。具体源码看xTimerGenericCommand();

/*
	复位定时器
	xTimer:定时器句柄
	xTicksToWait:任务阻塞时间
	这是带BaseType_t的返回值的函数
	成功:pdTRUE
	失败:pdFLASE
*/
#define xTimerReset( xTimer, xTicksToWait ) \
    xTimerGenericCommand( ( xTimer ), tmrCOMMAND_RESET, ( xTaskGetTickCount() ), NULL, ( xTicksToWait ) )

2.案例

这里因为我想和原子一样使用按键于是我就自己写了一个简单的按键读取。记住这里有个坑就是key0和key1需要设置成上拉输入,不然读不出值。记住一定要看电路图
key.c

#include "Key.h"

static void Key_GPIO_init(void){
	GPIO_InitTypeDef GPIO_Init;
	
	
	
	GPIO_Init.Pin=Key1;
	GPIO_Init.Mode=GPIO_MODE_INPUT;
	GPIO_Init.Pull=GPIO_PULLDOWN;
	__HAL_RCC_GPIOA_CLK_ENABLE();
	HAL_GPIO_Init(GPIO_KEY1,&GPIO_Init);
	
	GPIO_Init.Pin=Key2|Key3;
	GPIO_Init.Mode=GPIO_MODE_INPUT;
	GPIO_Init.Pull=GPIO_PULLUP;
	__HAL_RCC_GPIOE_CLK_ENABLE();
	HAL_GPIO_Init(GPIO_KEY2_3,&GPIO_Init);
	
}
static void Non_delay_ms(uint32_t time){
	for(int i=0;i<time;i++){
		for(int j=0;j<1200;j++){
		__nop();
		}
	}
	
	
}
uint8_t Key_config(void){
	uint8_t Key_Value;
	uint8_t key_statc;
	Key_GPIO_init();
	if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY1,Key1))==1){
		Non_delay_ms(100);
		if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY1,Key1))==1){
			return Key_Value=1;	
		}		
	}else if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY2_3,Key2))==0){
		Non_delay_ms(100);
		if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY2_3,Key2))==0){
		return Key_Value=2;				
		}
		
	}else if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY2_3,Key3))==0){
		Non_delay_ms(100);
		if((Key_Value=HAL_GPIO_ReadPin(GPIO_KEY2_3,Key3))==0){
			return Key_Value=3;			
		}
		
	}
	return Key_Value=0;
	
	
	
}

key.h

#ifndef __Key_H
#define __Key_H
#include "main.h"
#define Key1 GPIO_PIN_0
#define GPIO_KEY1 GPIOA

#define Key2 GPIO_PIN_3
#define Key3 GPIO_PIN_4
#define GPIO_KEY2_3 GPIOE
uint8_t Key_config(void);



#endif

main.c

#include "main.h"
#include "usart.h"
#include "gpio.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "Timers.h"
#include "stdio.h"
#include "Key.h"
#ifdef __GNUC__ //printf重定向
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif
PUTCHAR_PROTOTYPE
{
	HAL_UART_Transmit(&huart1, (uint8_t*)&ch,1,HAL_MAX_DELAY);
    return ch;
}

TaskHandle_t HandlerTask1;
TaskHandle_t Task_Name4;


BaseType_t xReturn;
SemaphoreHandle_t Task1semaphore;

TimerHandle_t AutoTimerTask;
TimerHandle_t OneTimerTask;

void AutoTimerFunction(TimerHandle_t xTimer);
void OneTimerFunction(TimerHandle_t xTimer);

void SystemClock_Config(void);
StackType_t xTask3Static[128];
StaticTask_t xTaskTCB;

StackType_t xIdle3Static[128];
StaticTask_t xIdleTCB;

StackType_t xTimerStatic[526];
StaticTask_t xTimerTCB;
void vApplicationGetIdleTaskMemory( StaticTask_t ** ppxIdleTaskTCBBuffer,StackType_t ** ppxIdleTaskStackBuffer,uint32_t * pulIdleTaskStackSize ){
			*ppxIdleTaskTCBBuffer=&xIdleTCB;				
			*ppxIdleTaskStackBuffer=xIdle3Static;
			*pulIdleTaskStackSize=128;
}
void vApplicationGetTimerTaskMemory( StaticTask_t ** ppxTimerTaskTCBBuffer,
                                          StackType_t ** ppxTimerTaskStackBuffer,
                                              uint32_t * pulTimerTaskStackSize ){
		 	* ppxTimerTaskTCBBuffer=&xTimerTCB;
			* ppxTimerTaskStackBuffer=xTimerStatic;
			* pulTimerTaskStackSize=526;																																															
}

void AutoTimerFunction(TimerHandle_t xTimer){
	printf("AutoTimer Begin...\r\n");
	
}

void OneTimerFunction(TimerHandle_t xTimer){
	printf("OneTimer Begin...\r\n");
	
}


void Task1Function( void * param){
		
	for(;;){
		
		
		vTaskDelay(100);
	}
}
void Task2Function(void* param){
		uint8_t num;
		
  for(;;)
  {
		num=Key_config();
		if(AutoTimerTask!=NULL & OneTimerTask!=NULL){
			switch(num){
				case 1:
						xTimerStart(AutoTimerTask,0);	
				break;
				case 2:
					  xTimerStart(OneTimerTask,0);
				break;
				case 3:
						xTimerStop(AutoTimerTask,0);
						xTimerStop(AutoTimerTask,0);
					
				break;
			}
			
		}
		vTaskDelay(100);
  }
}
void Task3Funtion(void* param){
	TickType_t st_time=xTaskGetTickCount(); 

	while(1){
		uint32_t num =1;
		xTaskDelayUntil(&st_time,30);
		
	}
	
}

void Task4Funtion(void* param){
	taskENTER_CRITICAL();
	//创建timer
	AutoTimerTask=xTimerCreate((const char *) "AutoTimer",
														 (TickType_t) 1000,
														(UBaseType_t) pdTRUE,
														(void*) 1,
														(TimerCallbackFunction_t) AutoTimerFunction
	);
	OneTimerTask=xTimerCreate((const char *) "OneTimer",
														 (TickType_t) 2000,
														(UBaseType_t) pdFALSE,
														(void*) 2,
														(TimerCallbackFunction_t) OneTimerFunction
	);
	//创建任务
	xReturn=xTaskCreate(Task1Function,"Task1",128,NULL,2,&HandlerTask1);
	xTaskCreate(Task2Function,"Task2",128,NULL,2,NULL);
 	xTaskCreateStatic(Task3Funtion,"Task3",128,NULL,2,xTask3Static,&xTaskTCB);
	if(xReturn == pdPASS){
			uint8_t buffS[20]="Task1 Create OK..\r\n";
			HAL_UART_Transmit(&huart1,(uint8_t*)buffS,strlen(buffS)*sizeof(char),HAL_MAX_DELAY);
			
		}
	vTaskDelete(Task_Name4);
	taskEXIT_CRITICAL();
}



int main(void)
{
  
	
	HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
	MX_USART1_UART_Init();
	
	xTaskCreate(Task4Funtion,"Task4",600,NULL,1,&Task_Name4);
	
  vTaskStartScheduler();
	
  while (1)
  {
   
  }
 
}


void SystemClock_Config(void)
{
	
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};


  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

 
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

void Error_Handler(void)
{
 
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT

void assert_failed(uint8_t *file, uint32_t line)
{

}
#endif /* USE_FULL_ASSERT */

效果展示
在这里插入图片描述


总结

定时器其实也bnan,主要包括了创建,开始,停止,复位。
天下风云出我辈,一入江湖岁月摧。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
FreeRTOS 中,软件定时器和硬件定时器是两种不同的定时器实现方式,用于实现任务的定时调度和时间管理。 1. 软件定时器(Software Timer): 软件定时器FreeRTOS 提供的一种基于软件定时器机制,通过 FreeRTOS 内核的任务调度器进行管理。软件定时器主要由 `xTimerCreate()`、`xTimerStart()`、`xTimerStop()` 等 API 函数来创建、启动、停止和删除。软件定时器适用于需要在任务中使用的相对较低频率的定时操作。 通过软件定时器,可以创建多个定时器以满足不同任务的需求,并且可以在定时器到期时触发回调函数来执行特定的操作。软件定时器使用 FreeRTOS 的任务调度器进行管理,因此,如果有其他高优先级任务需要执行,软件定时器会在适当的时机被暂停,并在下一个合适的时间点继续执行。 2. 硬件定时器(Hardware Timer): 硬件定时器是嵌入式系统中的硬件设备,可由硬件芯片提供。硬件定时器通常由专用寄存器和计数器组成,可用于生成精确的时间延迟或周期性触发中断。在 FreeRTOS 中,可以将硬件定时器软件定时器结合使用,以提供更精确和高频率的定时操作。 使用硬件定时器需要根据硬件平台和具体的芯片手册进行配置和初始化。一旦硬件定时器设置完成,可以在中断服务程序中处理定时器中断,并在中断处理程序中触发所需的操作。 需要根据具体的应用场景和需求来选择使用软件定时器还是硬件定时器软件定时器适用于相对较低频率和较少精度要求的任务调度,而硬件定时器适用于高频率和精确性要求较高的定时操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

单片有机机

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值