STM32第二十一课:FreeRTOS事件组&软件定时器


一、事件组

在这里插入图片描述

本质上是任务同步,但比二值信号量优秀的是可以一对多。
我的理解:事件组就是标志位的集合,将多个标志位放到一个集合里。

事件组中的事件位数(或标志数)的多少取决于 configUSE_16_BIT_TICKS or configTICK_TYPE_WIDTH_IN_BITS 是否 用于控制 TickType_t 的类型:

如果 configUSE_16_BIT_TICKS 设置为 1,则事件组内实现的位数(或标志数)为 8; 如果 configUSE_16_BIT_TICKS 设置为 0,则为 24。

如果 configTICK_TYPE_WIDTH_IN_BITS 设置为 TICK_TYPE_WIDTH_16_BITS,则事件组内实现的位数(或标志数)为 8; 如果 configTICK_TYPE_WIDTH_IN_BITS 设置为 TICK_TYPE_WIDTH_32_BITS,则为 24 ;如果 configTICK_TYPE_WIDTH_IN_BITS 设置为 TICK_TYPE_WIDTH_64_BITS,则为 56。

STM32中通常设置24个时间位即可。

1.事件组创建

先添加头文件

#include "event_groups.h"

创建一个时间组句柄

/********************事件组句柄***********************/
EventGroupHandle_t Event;

最后用上面创建的句柄进行承接创建。

Event = xEventGroupCreate();

此时,我们就获得了一个具有24事件位的事件组。
创建完成时,事件组的每位都为0。

2.事件组置位

当发生特殊事件(数据传输完成,解析完成等。。),此时我们就可以使用事件组。让时间组的一位进行置位。
事件组置位函数有两个:

使用环境 置位函数
中断函数中 EventBits_t xEventGroupSetBits( EventGroupHandle_t xEventGroup, const EventBits_t uxBitsToSet )
中断函数中 xEventGroupSetBitsFromISR( xEventGroup, uxBitsToSet, pxHigherPriorityTaskWoken )

参数1:想要置位的事件组是哪个。
参数2:想要置的是哪一位,比如想要置第2位就填0x04(100)
虽然函数不同,但参数基本是一样的。只不过在中断中多一个参数3,参数3填 pdTRUE会开启高优先级事件触发提醒。一般我们不需要,直接填NULL即可。

3.事件组等待

EventBits_t xEventGroupWaitBits(

    const EventGroupHandle_t xEventGroup, /* 事件标志组句柄 */
    const EventBits_t uxBitsToWaitFor, /* 等待被设置的事件标志位 */
    const BaseType_t xClearOnExit, /* 选择是否清零被置位的事件标志位 */
    const BaseType_t xWaitForAllBits, /* 选择是否等待所有标
    TickType_t xTicksToWait ); /* 设置等待时间 */
    )

若设置超时时间:在超时时间中会阻塞等待,超时时会返回当前事件组的值,但不会清0标志位(无论是否设置清0标志位)
设置清0标志位,成功获取时会清0标志位。
若设置超时时间为:portMAX_DELAY,此时该函数就会死等,成功时返回。通常都是portMAX_DELAY
参数4,有pdTRUE和pdFALSE两种状态。
如果这个参数设置为 pdTRUE,要等待第 2 个参数 uxBitsToWaitFor 所指定的标志位全部被置 1,函数才可以返回。当然,超出了在参数xTicksToWait 设置的溢出时间也是会返回的。
如果这个参数设置为 pdFALSE,第 2 个参数uxBitsToWaitFor 所指定的任何标志位被置 1,函数都会返回,超出溢出时间也会返回,

Ret = xEventGroupWaitBits(Event,0x07,pdTRUE,pdFALSE,portMAX_DELAY);

二、软件定时器

软件定时器(或者只是“定时器” )能够让函数在 未来的设定时间执行。 由定时器执行的函数称为定时器的回调函数。 从定时器启动到其回调函数执行之间的时间被称为定时器的周期。 简而言之, 当定时器的周期到期时,定时器的回调函数会被执行。
其实软件定时器就是设置了一个周期,周期结束了就会调用回调函数。
注意:回调函数中不要有阻塞

1.软件定时器创建

添加头文件

#include "times.h"

创建句柄

TimerHandle_t Timer1;//软件定时器

定时器任务创建

	Timer1 = xTimerCreate("Timer1",1000,pdTRUE,(void *)1,vTimerCallback);

参数1:pcTimerName:定时器名字
参数2:xTimerPeriodInTicks:定时周期
参数3:uxAutoReload:
pdTRUE:周期模式
pdFALSE:单次模式
参数4:pvTimerID:定时器ID,用于多个定时器共用同一个回调函数,判断那个定时器超时。

2.软件定时器执行

调用函数:

void vTimerCallback(TimerHandle_t xTimer)
{
	printf("定时器ID:%d\r\n",(u8)pvTimerGetTimerID(xTimer));
	Led_Waterfall();
}

定时器开始执行

	xTimerStart(Timer1,1);

参数1:表示要启动的定时器的句柄。
参数2:表示在启动定时器之前等待的节拍数。如果希望在启动定时器之前有一个延迟,可以设置一个等待时间。

3.例程代码

main.c

#include "stm32f10x.h"
#include "led.h"
#include "delay.h"
#include "delay.h"
#include "string.h"
#include "pwm.h"
#include "adc.h"
#include "su03t.h"
#include "dht11.h"
#include "kqm.h"
#include "usart.h"
#include "key.h"
//使用FreeRtos相关头文件之前,一定要先包含这个#include "FreeRtos.h"
#include "FreeRtos.h"
#include "task.h"
#include "semphr.h"
#include "event_groups.h"
#include "queue.h"
#include "time.h"
EventGroupHandle_t Events;
char D_time[20];
TaskHandle_t liushui_Task;
TimerHandle_t Timer1;//软件定时器

void liu_Task(void *p)
{
	Led_Waterfall();
}
void vTimerCallback(TimerHandle_t xTimer)
{
	printf("定时器ID:%d\r\n",(u8)pvTimerGetTimerID(xTimer));
	Led_Waterfall();
}
int main()
{
	Led_Init();
	Usart1_Config();//初始化串口1
	BaseType_t Ret = pdPASS;
//	Ret = xTaskCreate(liu_Task, //创建任务的任务函数名
//                    "liu_Task",//任务名字
//                    100,//任务栈深度。32位单片机*4
//                    NULL,//创建任务时传递参数,没有就给NULL
//                    1,//任务优先级
//										&liushui_Task);//任务的句柄,用于后边删除,挂起任务
//	if(Ret == pdPASS){
//		printf("流水灯任务创建完成\r\n");
//	}
	Timer1 = xTimerCreate("Timer1",1000,pdTRUE,(void *)1,vTimerCallback);
	xTimerStart(Timer1,1);
	printf("开始调度!\r\n");
	vTaskStartScheduler();
	while(1)
	{
		
	}
}

void vApplicationStackOverflowHook( TaskHandle_t xTask,char *pcTaskName )
{
	printf("任务:%s->栈溢出\r\n",pcTaskName);
	printf("任务剩余空间:%d\r\n",(int)uxTaskGetStackHighWaterMark(xTask));
	while(1)//栈溢出时卡死到钩子函数中
	{}
}

相关推荐

  1. FreeRTOS学习笔记-基于stm32(10)事件标志

    2024-07-16 21:32:05       31 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-16 21:32:05       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-16 21:32:05       72 阅读
  3. 在Django里面运行非项目文件

    2024-07-16 21:32:05       58 阅读
  4. Python语言-面向对象

    2024-07-16 21:32:05       69 阅读

热门阅读

  1. docker部署项目命令

    2024-07-16 21:32:05       19 阅读
  2. ns3-gym入门(二):linear-mesh例子详解

    2024-07-16 21:32:05       16 阅读
  3. 数据结构与算法-09贪心算法&动态规划

    2024-07-16 21:32:05       16 阅读
  4. 访问者模式(大话设计模式)C/C++版本

    2024-07-16 21:32:05       17 阅读
  5. Logstash常用的filter四大插件

    2024-07-16 21:32:05       18 阅读
  6. RTOS中断与任务的同步

    2024-07-16 21:32:05       19 阅读
  7. 哈希表(知识点+leetcode)以及字符串哈希

    2024-07-16 21:32:05       21 阅读
  8. 运维检查:mysql表自增id是否快要用完

    2024-07-16 21:32:05       19 阅读
  9. C++设计模式(装饰器模式)

    2024-07-16 21:32:05       18 阅读
  10. 哪些点权衡素材优秀与否

    2024-07-16 21:32:05       18 阅读
  11. 前端反显后端图片、上传预览图片

    2024-07-16 21:32:05       19 阅读
  12. 使用AIOHTTP模块:提高网络请求效率

    2024-07-16 21:32:05       22 阅读