STM32第二十六课(Freertos, HAL,cubemx,soft timer)

freertos提供了soft timer。

如果使用了soft timer,那么OS中,需要存在一个专门的任务,soft timer task。简称STT。在freertos中,STT就是DaemonTask。任务中,可以设置一个时刻,当时刻到的时候,soft timer task会调用注册的callback,
注意,callback运行在DaemonTask中,不会有独立的任务资源。
所以,在callback中,不能调用任何可能阻塞STT的API。
例如,taskDelay,taskDelayUntil之类的API。
再例如,RPC类的API,访问信号量,访问队列等。

freertos提供了一系列和soft timer相关的API。
这些API,向soft timer command queue发送命令消息。STCQ是不能被用户直接访问的。

例如,
在用户任务中,调用了xTimerReset这个API,
OS执行这个API时,是向STCQ发送一个cmd,当DaemonTask获得CPU后,会从STCQ中获取命令消息,然后解析,执行,并调用callback。

++++++++++++++++++++++++++++++++++++
常用的soft timer相关的API有,

xTimerStart----启动soft timer,开始更新tick counter,并在每个tick,执行STCQ中的命令,检查是否有callback需要被调用。等。

xTimerStop----停止soft timer。

xTimerReset----将tick counter的值归零,但是并不是停止soft timer,而是重新开始计数。

对应的fromisr版本的API,用于ISR中。
++++++++++++++++++++++++++++++++++++
来看看soft_timer_task。

//TimerControl的任务函数
void soft_timer_task(void *pvParameters)
{
	u8 key,num;
	
	for(;;)
	{
			key = KEY_Scan(0);
			switch(key)
			{
				case WKUP_PRES:     //当key_up按下的话打开周期定时器
					xTimerStart(AutoReloadTimer_Handle,0);	//开启周期定时器
					printf("开启定时器1\r\n");
					break;
				case KEY0_PRES:		//当key0按下的话打开单次定时器
					xTimerStart(OneShotTimer_Handle,0);		//开启单次定时器
					printf("开启定时器2\r\n");
					break;
				case KEY1_PRES:		//当key1按下话就关闭定时器
					xTimerStop(AutoReloadTimer_Handle,0); 	//关闭周期定时器
					xTimerStop(OneShotTimer_Handle,0); 		//关闭单次定时器
					printf("关闭定时器1和2\r\n");
					break;	
			}
				
			num++;
			if(num==50) 	//每500msLED0闪烁一次
			{
				num=0;
				LED0=!LED0;	
			}
			
	        vTaskDelay(10); //延时10ms,也就是10个时钟节拍
	}
}

这是一个前台任务,一个输入任务。
扫描按键,根据不同的按键状态,向不同的soft timer内核对象的STCQ发送cmd。
每个soft timer,都有对应于自己的DaemonTask.
DaemonTask运行时,会检查tick counter的计数,如果时间到,则会调用注册到soft timer中的callback。

+++++++++++++++++++++++++++++++++++++++++++
来看看soft timer 和callback的关系。

void start_task(void *pvParameters)
{
    taskENTER_CRITICAL();           //进入临界区
    
    //创建软件周期定时器
    AutoReloadTimer_Handle=xTimerCreate((const char*		)"AutoReloadTimer",
									    (TickType_t			)1000,
							            (UBaseType_t		)pdTRUE,
							            (void*				)1,
							            (TimerCallbackFunction_t)AutoReloadCallback); //周期定时器,周期1s(1000个时钟节拍),周期模式
    //创建单次定时器
	OneShotTimer_Handle=xTimerCreate((const char*			)"OneShotTimer",
							         (TickType_t			)2000,
							         (UBaseType_t			)pdFALSE,
							         (void*					)2,
							         (TimerCallbackFunction_t)OneShotCallback); //单次定时器,周期2s(2000个时钟节拍),单次模式					  
    //创建定时器控制任务
    xTaskCreate((TaskFunction_t )timercontrol_task,             
                (const char*    )"timercontrol_task",           
                (uint16_t       )TIMERCONTROL_STK_SIZE,        
                (void*          )NULL,                  
                (UBaseType_t    )TIMERCONTROL_TASK_PRIO,        
                (TaskHandle_t*  )&TimerControlTask_Handler);    
                
    vTaskDelete(StartTask_Handler); //自删
    
    taskEXIT_CRITICAL();            //退出临界区
}

在创建soft timer的时候,注册了callback。

+++++++++++++++++++++++++++++++++++++++++++
来看看callback。

void AutoReloadCallback(TimerHandle_t xTimer)
{
	static u8 tmr1_num=0;
	tmr1_num++;									//周期定时器执行次数加1
	LCD_ShowxNum(70,111,tmr1_num,3,16,0x80); 	//显示周期定时器的执行次数
	LCD_Fill(6,131,114,313,lcd_discolor[tmr1_num%14]);//填充区域
}

void OneShotCallback(TimerHandle_t xTimer)
{
	static u8 tmr2_num = 0;
	tmr2_num++;		//周期定时器执行次数加1
	LCD_ShowxNum(190,111,tmr2_num,3,16,0x80);  //显示单次定时器执行次数
	LCD_Fill(126,131,233,313,lcd_discolor[tmr2_num%14]); //填充区域
	LED1=!LED1;
    printf("定时器2运行结束\r\n");
}

callback在DaemonTask中被调用执行。
从虚拟CPU的角度看,DaemonTask在tick counter不满足条件时自旋,知道tick counter满足条件时,跳出自旋,开始执行callback。

+++++++++++++++++++++++++++++++++++++++++++++

版权声明:本文为CSDN博主「Huskar_Liu」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_42418557/article/details/122157431

生成海报
点赞 0

Huskar_Liu

我还没有学会写个人说明!

暂无评论

发表评论

相关推荐

RT-Thread Studio移植LAN8720A驱动

RTT网络协议栈驱动移植(霸天虎) 1、新建工程 ​ 工程路径不含中文路径名,工程名用纯英文不含任何符号。 2、用CubeMx配置板子外设 2.1、配置时钟 ​ 按照自己板子配置相应时钟。

Lin总线通信在STM32作为主机代码以及从机程序

距离上次做资料准备已经过去六天了。最近在学车,上周末就没有开电脑。这周开始进行了Lin通信的代码整理,目前是可以正常通信的了,采用的是增强型校验方式。后期再进一步跟进研究。。。更新一博,留

4路红外循迹模块使用教程

4路红外循迹模块使用教程 个人原创博客:点击浏览模块详细信息: 工作电压:DC 3.3V~5V 工作电流:尽量选择1A以上电源供电 工作温度:-10℃~50℃ 安装孔

HAL库串口中断

一,配置串口初始化 void MX_USART1_UART_Init(void) {huart1.Instance USART1;huart1.Init.BaudRate 115200;huart1.Init.WordLen