FreeRTOS学习
1、动态创建任务
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedGpioInit();
KeyInit();
FreeRTOS_Start();
}
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
TaskHandle_t task3_handle;
void StartTask(void);
void Task1(void);
void Task2(void);
void Task3(void);
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
//启动调度器
vTaskStartScheduler();
}
void StartTask(void)
{
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task2_handle
);
xTaskCreate(
(TaskFunction_t) Task3,
(char *) "Task3",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task3_handle
);
vTaskDelete(NULL);
taskEXIT_CRITICAL();
}
void Task1(void)
{
while(1)
{
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
vTaskDelay(500);
}
}
void Task2(void)
{
while(1)
{
LED_TOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN);
vTaskDelay(500);
}
}
void Task3(void)
{
while(1)
{
if(KeyScan() == 0)
{
if(task1_handle != NULL) vTaskDelete(task1_handle);
task1_handle = NULL;
}
vTaskDelay(500);
}
}
2、静态创建任务
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
/* 启动任务的配置 */
#define START_TASK_STACK 128
#define START_TASK_PRIORITY 1
TaskHandle_t start_task_handle;
StackType_t start_task_stack[START_TASK_STACK]; // 静态任务的任务栈,以数组形式存储
StaticTask_t start_task_tcb; // 静态任务的TCB结构体类型
void start_task(void);
/* 任务1的配置 */
#define TASK1_STACK 128
#define TASK1_PRIORITY 2
TaskHandle_t task1_handle;
StackType_t task1_stack[TASK1_STACK]; // 静态任务的任务栈,以数组形式存储
StaticTask_t task1_tcb; // 静态任务的TCB结构体类型
void task1(void);
/* 任务2的配置 */
#define TASK2_STACK 128
#define TASK2_PRIORITY 3
TaskHandle_t task2_handle;
StackType_t task2_stack[TASK2_STACK]; // 静态任务的任务栈,以数组形式存储
StaticTask_t task2_tcb; // 静态任务的TCB结构体类型
void task2(void);
/* 任务3的配置 */
#define TASK3_STACK 128
#define TASK3_PRIORITY 4
TaskHandle_t task3_handle;
StackType_t task3_stack[TASK3_STACK]; // 静态任务的任务栈,以数组形式存储
StaticTask_t task3_tcb; // 静态任务的TCB结构体类型
void task3(void);
/* ======================= 静态创建方式,需要手动指定2个特殊任务的资源=============================== */
/* 空闲任务的配置 */
StackType_t idle_task_stack[configMINIMAL_STACK_SIZE]; // 静态任务的任务栈,以数组形式存储
StaticTask_t idle_task_tcb; // 静态任务的TCB结构体类型
/* 软件定时器任务的配置 */
StackType_t timer_task_stack[configTIMER_TASK_STACK_DEPTH]; // 静态任务的任务栈,以数组形式存储
StaticTask_t timer_task_tcb; // 静态任务的TCB结构体类型
/* 分配空闲任务的资源 */
void vApplicationGetIdleTaskMemory(StaticTask_t **ppxIdleTaskTCBBuffer,
StackType_t **ppxIdleTaskStackBuffer,
uint32_t *pulIdleTaskStackSize)
{
*ppxIdleTaskTCBBuffer = &idle_task_tcb;
*ppxIdleTaskStackBuffer = idle_task_stack;
*pulIdleTaskStackSize = configMINIMAL_STACK_SIZE;
}
/* 分配软件定时器任务的资源 */
void vApplicationGetTimerTaskMemory(StaticTask_t **ppxTimerTaskTCBBuffer,
StackType_t **ppxTimerTaskStackBuffer,
uint32_t *pulTimerTaskStackSize)
{
*ppxTimerTaskTCBBuffer = &timer_task_tcb;
*ppxTimerTaskStackBuffer = timer_task_stack;
*pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH;
}
/**
* @description: 启动FreeRTOS
* @return {*}
*/
void FreeRTOS_Start(void)
{
/* 1.创建一个启动任务 */
start_task_handle = xTaskCreateStatic(
(TaskFunction_t)start_task, // 任务函数的地址
(char *)"start_task", // 任务名字符串
(uint32_t)START_TASK_STACK, // 任务栈大小,默认最小128,单位4字节
(void *)NULL, // 传递给任务的参数
(UBaseType_t)START_TASK_PRIORITY, // 任务的优先级
(StackType_t *)start_task_stack, // 我们创建的任务栈(数组存储)的地址
(StaticTask_t *)&start_task_tcb // 我们创建的tcb的地址
);
/* 2.启动调度器:会自动创建空闲任务和软件定时器(如果开启),
静态创建的方式需要去实现2个分配资源的接口函数 */
vTaskStartScheduler();
}
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedGpioInit();
KeyInit();
FreeRTOS_Start();
}
/**
* @description: 启动任务:用来创建其他Task
* @param {void} *pvParameters
* @return {*}
*/
void start_task(void)
{
/* 进入临界区:保护临界区里的代码不会被打断 */
taskENTER_CRITICAL();
/* 使用静态创建3个任务 */
task1_handle = xTaskCreateStatic(
(TaskFunction_t)task1,
(char *)"task1",
(configSTACK_DEPTH_TYPE)TASK1_STACK,
(void *)NULL,
(UBaseType_t)TASK1_PRIORITY,
(StackType_t *)task1_stack, // 我们创建的任务栈(数组存储)的地址
(StaticTask_t *)&task1_tcb // 我们创建的tcb的地址
);
task2_handle = xTaskCreateStatic(
(TaskFunction_t)task2,
(char *)"task2",
(configSTACK_DEPTH_TYPE)TASK2_STACK,
(void *)NULL,
(UBaseType_t)TASK2_PRIORITY,
(StackType_t *)task2_stack, // 我们创建的任务栈(数组存储)的地址
(StaticTask_t *)&task2_tcb // 我们创建的tcb的地址
);
task3_handle = xTaskCreateStatic(
(TaskFunction_t)task3,
(char *)"task3",
(configSTACK_DEPTH_TYPE)TASK3_STACK,
(void *)NULL,
(UBaseType_t)TASK3_PRIORITY,
(StackType_t *)task3_stack, // 我们创建的任务栈(数组存储)的地址
(StaticTask_t *)&task3_tcb // 我们创建的tcb的地址
);
/* 启动任务只需要执行一次即可,用完就删除自己 */
vTaskDelete(NULL);
/* 退出临界区 */
taskEXIT_CRITICAL();
}
void task1(void)
{
while(1)
{
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
vTaskDelay(500);
}
}
void task2(void)
{
while(1)
{
LED_TOGGLE(LED1_GPIO_PORT,LED1_GPIO_PIN);
vTaskDelay(500);
}
}
void task3(void)
{
while(1)
{
if(KeyScan() == 0)
{
if(task1_handle != NULL) vTaskDelete(task1_handle);
task1_handle = NULL;
}
vTaskDelay(500);
}
}
3、任务挂起与回复
3.1、任务挂起
/*传入参数为任务句柄,若传入NULL,则代表挂起当前任务*/
vTaskSuspend(task1_handle);
3.2 任务恢复
/* 任务恢复,传入参数为任务句柄*/
vTaskResume(task1_handle);
3.3 挂起任务调度器
仅执行当前任务
vTaskSuspendAll();
3.4 恢复任务调度器
xTaskResumeAll();
3.5 打印任务状态
/* 传入参数为字符串 */
vTaskList(str);
3.6 中断管理
/*执行此函数后,在中断优先级阈值以下的中断将被屏蔽*/
portDISABLE_INTERRUPTS();
/* 使能中断 */
portENABLE_INTERRUPTS();
5、时间函数
/* 相对延时,每隔n个时间片执行一次代码,不能保证代码执行时间相同 */
vtaskDelay(n);
/* 绝对延时,代码整体执行时间为n个时间片,保证代码执行周期*/
xTaskDelayUntil();
6、任务之间通过队列传输数据
#include "main.h"
#include "driver_led.h"
#include "driver_key.h"
#include "driver_uart.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
/* 队列句柄*/
QueueHandle_t handle1;
void StartTask(void)
{
/* 创建一个队列 */
handle1 = xQueueCreate(1,sizeof(char *));
if(handle1 == NULL) UartSendData("task err");
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:负责创建一个字符串,通过队列发送出去
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
char* str = "tehsjncncncncc";
while(1)
{
if(KeyScan() == KEY0)
{
/* 往队列插入一个值,并设置阻塞等待*/
xQueueSend(handle1,&str,portMAX_DELAY);
UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函数作用:接收数据任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
char *buffer;
BaseType_t res;
while(1)
{
/* 接收队列的任务,并进入阻塞等待*/
res = xQueueReceive(handle1,&buffer,portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("buffer:\r\n");
UartSendData(buffer);
UartSendData("\r\n");
}
vTaskDelay(500);
}
}
7、二进制信号量释放与接收
7.1 二进制信号量
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
/* 队列句柄*/
QueueHandle_t handle1;
SemaphoreHandle_t semaphore_handle;
void StartTask(void)
{
/* 创建一个信号量 */
vSemaphoreCreateBinary(semaphore_handle);
if(semaphore_handle != NULL) UartSendData("Create success!\r\n");
/* 创建一个队列 */
handle1 = xQueueCreate(1,sizeof(char *));
if(handle1 == NULL) UartSendData("task err");
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 2,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:释放信号量
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
BaseType_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 释放信号量 */
res = xSemaphoreGive(semaphore_handle);
if (res == pdPASS) UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函数作用:接收信号量
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
BaseType_t res;
while(1)
{
/* 接收信号量是否释放 */
res = xSemaphoreTake(semaphore_handle, portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("Take success!\r\n");
UartSendData("\r\n");
}
vTaskDelay(500);
}
}
7.2 互斥二进制信号量
它会将阻塞高优先级的低优先级提升,从而保证高优先级不会被低优先级阻塞。
8、计数信号量释放与接收
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
/* 队列句柄*/
QueueHandle_t handle1;
void StartTask(void)
{
UBaseType_t Count = 0;
/* 创建一个信号量 */
handle1 = xSemaphoreCreateCounting(100, 0);
if(!(handle1 == NULL))
{
UartSendData("Create success!\r\n");
Count = uxSemaphoreGetCount(handle1);
sprintf(str, "the init count: %d", Count);
UartSendData(str);
}
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:释放信号量
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
BaseType_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 释放信号量 */
res = xSemaphoreGive(handle1);
if (res == pdPASS) UartSendData("Send Pass\r\n");
}
vTaskDelay(20);
}
}
/*
* 函数作用:接收信号量
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
char str[100];
UBaseType_t Count = 0;
BaseType_t res;
while(1)
{
/* 接收信号量是否释放 */
res = xSemaphoreTake(handle1, portMAX_DELAY);
if(res == pdPASS)
{
UartSendData("Take success!\r\n");
UartSendData("\r\n");
UartSendData(str);
}
Count = uxSemaphoreGetCount(handle1);
sprintf(str, "the init count: %d\r\n", Count);
UartSendData(str);
vTaskDelay(1000);
}
}
9、队列集
10、事件标志组
比信号量更灵活,每一个bit位都代表一个信号量。
#include "main.h"
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
EventGroupHandle_t event_handle;
void StartTask(void)
{
UBaseType_t Count = 0;
/* 创建一个信号量 */
event_handle = xEventGroupCreate();
if(!(event_handle == NULL))
{
UartSendData("Create success!\r\n");
}
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:发送事件
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
#define EVENTBIT_0 (1 << 0)
#define EVENTBIT_1 (1 << 1)
void Task1(void)
{
EventBits_t res;
while(1)
{
xEventGroupSetBits(event_handle, 1<<3);
if(KeyScan() == KEY0)
{
/* 设置标志位*/
res = xEventGroupSetBits(event_handle, EVENTBIT_0);
sprintf(str,"event flag: %#x\r\n", res);
UartSendData(str);
res = xEventGroupSetBits(event_handle, EVENTBIT_1);
sprintf(str,"event flag: %#x\r\n", res);
UartSendData(str);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(20);
}
}
/*
* 函数作用:接收事件
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
EventBits_t res;
while(1)
{
/* 接收信号量是否释放 */
res = xEventGroupWaitBits(
event_handle, // 事件句柄
((EVENTBIT_0 | EVENTBIT_1)), // 等待的标志位
pdTRUE, // 是否清楚标志位
pdTRUE, // 是否等待标志位
portMAX_DELAY // 等待事件
);
sprintf(str, "task2: %x\r\n", res);
UartSendData(str);
}
}
11 任务通知
11.1 任务通知模拟信号量
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:任务通知发送
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if(KeyScan() == KEY0)
{
/* 实际使取出task2的通知值,然后+1*/
xTaskNotifyGive(task2_handle);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函数作用:任务通知接收
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while(1)
{
res_notify = ulTaskNotifyTake(
pdTRUE, //接收完通知后,是否对通知值处理,pdTRUE:置0;pdFALSE:-1
portMAX_DELAY //设置等待时间
);
sprintf(str, "task2 notify: %d\r\n", res_notify);
UartSendData(str);
}
}
11.2 任务通知模拟消息队列(邮箱)
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:模拟消息队列发送
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if(KeyScan() == KEY0)
{
xTaskNotify(task2_handle, // 要发送的任务句柄
100, // 要发送的数据
eSetValueWithOverwrite // 发送方式
);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函数作用:模拟消息队列接收
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while(1)
{
xTaskNotifyWait(
0x00000000, // 接收通知前是否清楚通知值,按位,全为0表示不不清楚
0xffffffff, // 接收通知后是否要清楚通知值,按位,全为f表示清楚
&res_notify, // 接受值存放地址
portMAX_DELAY // 等待事件
);
sprintf(str, "task2 notify: %d\r\n", res_notify);
UartSendData(str);
}
}
11.3 模拟事件标志组
#include "main.h"
#include "portmacro.h"
#include "projdefs.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void Task2(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
while(1)
{
HAL_Delay(1000);
UartSendData("hello\r\n");
LED_TOGGLE(LED0_GPIO_PORT,LED0_GPIO_PIN);
}
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
TaskHandle_t task2_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
void StartTask(void)
{
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate(
(TaskFunction_t) Task1,
(char *) "Task1",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 3,
(TaskHandle_t*) &task1_handle
);
xTaskCreate(
(TaskFunction_t) Task2,
(char *) "Task2",
(uint16_t) 128,
(void *) NULL,
(UBaseType_t) 4,
(TaskHandle_t*) &task2_handle
);
vTaskDelete(NULL); //删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:模拟事件标志组发送
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while(1)
{
if (KeyScan() == KEY0) {
xTaskNotify(task2_handle, // 要发送的任务句柄
1 << 8, // 要发送的数据位
eSetBits // 发送方式
);
UartSendData("KEY0 PRESS!\r\n");
}
vTaskDelay(200);
}
}
/*
* 函数作用:模拟事件标志组接收
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task2(void)
{
uint32_t res_notify;
while (1) {
xTaskNotifyWait(
0x00000000, // 接收通知前是否清楚通知值,按位,全为0表示不不清楚
0xffffffff, // 接收通知后是否要清楚通知值,按位,全为f表示清楚
&res_notify, // 接受值存放地址
portMAX_DELAY // 等待时间
);
sprintf(str, "task2 notify: %0x\r\n", res_notify);
UartSendData(str);
}
}
12、软件定时器
#include "main.h"
#include <stdint.h>
void StartTask(void);
void Task1(void);
void FreeRTOS_Start(void);
int main(void)
{
// 初始化HAL库函数必须要调用此函数
HAL_Init();
// 系统时钟即AHB/APB时钟配置
SystemClock_Config();
// 初始化LED
LedInit();
KeyInit();
UartInit(115200);
FreeRTOS_Start();
}
/* 任务句柄,用以保存不同任务的配置 */
TaskHandle_t start_task_handle;
TaskHandle_t task1_handle;
/*
* 函数作用:常规写法,起始任务,用以创建其他任务
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void FreeRTOS_Start(void)
{
xTaskCreate(
(TaskFunction_t) StartTask, //任务函数的地址
(char *) "StartTask", //任务函数的名称
(uint16_t) 128, //任务函数栈空间大小
(void *) NULL, //任务函数的参数
(UBaseType_t) 1, //任务函数的优先级
(TaskHandle_t*) &start_task_handle //任务函数的句柄
);
/* 启用调度器,负责任务切换*/
vTaskStartScheduler();
}
char str[100];
void TimerCallBack_1(TimerHandle_t timer);
TimerHandle_t timer_handle_1;
/*
* 函数作用:开始任务回调函数
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void StartTask(void)
{
/* 创建软件定时器,由软件定时器任务(通过定义宏,由系统创建)控制*/
timer_handle_1 = xTimerCreate("time_1", // 创建名称
500, // 定时器延迟时间
pdTRUE, // 是否重载(周期/一次)
(void *)1, // 定时器唯一ID
TimerCallBack_1 // 定时器回调函数
);
/* 进入临界保护区,保证在临界区的代码不会被打断*/
taskENTER_CRITICAL();
xTaskCreate((TaskFunction_t)Task1, (char *)"Task1", (uint16_t)128,
(void *)NULL, (UBaseType_t)3, (TaskHandle_t *)&task1_handle);
vTaskDelete(NULL); // 删除任务本身
/* 退出临界保护区*/
taskEXIT_CRITICAL();
}
/*
* 函数作用:开启软件定时器
* 输入参数:无
* 返回值:无
* 作者:LSK
*/
void Task1(void)
{
EventBits_t res;
while (1) {
if (KeyScan() == KEY0) {
/* 开启软件定时器*/
xTimerStart(timer_handle_1, // 定时器句柄
portMAX_DELAY); // 等待时间
UartSendData(("timer start!\r\n"));
}
vTaskDelay(200);
}
}
/*
* 函数作用:定时器回调函数
* 输入参数:定时器句柄
* 返回值:无
* 作者:LSK
*/
void TimerCallBack_1(TimerHandle_t timer)
{
if(timer == timer_handle_1)
{
UartSendData("Call back!\r\n");
LED_TOGGLE(LED0_GPIO_PORT, LED0_GPIO_PIN);
}
}

浙公网安备 33010602011771号