1.设备STM32F103C8T6
2.工程模板
单片机: 部分单片机的程序例程 - Gitee.comhttps://gitee.com/lovefoolnotme/singlechip/tree/master/STM32_FREERTOS/1.%E5%B7%A5%E7%A8%8B%E6%A8%A1%E6%9D%BF
3.代码
1-FreeRTOS移植模板
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
LED_Init();
USART1_Init(115200);
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
LED2=!LED2;
LED3=!LED3;
LED4=!LED4;
vTaskDelay(500);
}
}
2-FreeRTOS任务挂起实验
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
/****************************************************************/
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/****************************************************************/
//任务优先级
#define LED2_TASK_PRIO 3
//任务堆栈大小 (单位字)
#define LED2_STK_SIZE 50
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);
//任务优先级
#define KEY_TASK_PRIO 4
//任务堆栈大小 (单位字)
#define KEY_STK_SIZE 50
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
LED_Init();
KEY_Init();
USART1_Init(115200);
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
//创建KEY任务
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
vTaskDelay(500);
}
}
//LED1任务函数
void led2_task(void *pvParameters)
{
while(1)
{
LED2=!LED2;
vTaskDelay(500);
}
}
//LED1任务函数
void key_task(void *pvParameters)
{
while(1)
{
if(KEY==1) vTaskSuspend(LED2Task_Handler);
else vTaskResume(LED2Task_Handler);
vTaskDelay(100);
}
}
3-FreeRTOS消息队列实验
/******************************2023年10月14日*************************************
此为一个消息队列实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
发送不等待,但是需要按键触发
接收是一直等待,直到接收到队列里面的消息,使用本次实验中的函数接收数据后会删除队列中的数据
宏定义队列长度和单个消息大小都为4
需定义队列句柄
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define SEND_TASK_PRIO 3
//任务堆栈大小
#define SEND_STK_SIZE 50
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO 4
//任务堆栈大小
#define RECEIVE_STK_SIZE 50
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);
QueueHandle_t Test_Queue =NULL; //句柄
#define QUEUE_LEN 4 // 队列的长度,最大可包含多少个消息 */
#define QUEUE_SIZE 4 // 队列中每个消息大小(字节) */
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
/* 创建Test_Queue */
Test_Queue = xQueueCreate((UBaseType_t ) QUEUE_LEN,/* 消息队列的长度 */
(UBaseType_t ) QUEUE_SIZE);/* 消息的大小 */
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建接收任务
xTaskCreate((TaskFunction_t )receive_task,
(const char* )"receive_task",
(uint16_t )RECEIVE_STK_SIZE,
(void* )NULL,
(UBaseType_t )RECEIVE_TASK_PRIO,
(TaskHandle_t* )&ReceiveTask_Handler);
//创建发送任务
xTaskCreate((TaskFunction_t )send_task,
(const char* )"send_task",
(uint16_t )SEND_STK_SIZE,
(void* )NULL,
(UBaseType_t )SEND_TASK_PRIO,
(TaskHandle_t* )&SendTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
LED2=!LED2;
LED3=!LED3;
LED4=!LED4;
vTaskDelay(500);
}
}
void send_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
static uint32_t send_data1 = 1;
while(1)
{
if(KEY==1)
{
xReturn = xQueueSend( Test_Queue, /* 消息队列的句柄 */
&send_data1,/* 发送的消息内容 */
0 ); /* 等待时间 0 */
if(xReturn==pdPASS)
{
OLED_ShowString(3,0,"ok",8,1); //按下显示"ok"
OLED_ShowNum(3,20,send_data1,2,8,1);
OLED_Refresh();
send_data1+=1; //递增
}
}
else {OLED_ShowString(3,0,"no",8,1);OLED_ShowString(3,40," ",8,1);OLED_Refresh();} //没按下时显示"no"
vTaskDelay(100);
}
}
//接收任务函数
void receive_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
uint32_t r_queue; /* 定义一个接收消息的变量 */
while(1)
{
xReturn = xQueueReceive( Test_Queue, /* 消息队列的句柄 */
&r_queue, /* 发送的消息内容 */
portMAX_DELAY); /* 等待时间 一直等(等不到则下面的程序不执行) ,为0则不等*/
if(pdTRUE == xReturn) //接收成功
{
OLED_ShowString(3,40,"get",8,1);
OLED_Refresh();
}
else //接收失败
{
OLED_ShowString(3,40,"fal",8,1);
OLED_Refresh();
}
vTaskDelay(100);
}
}
4-FreeRTOS二值信号量实验
/******************************2023年10月15日*************************************
此为一个二值信号量实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
二值信号量,需要按键触发,按下按键则send任务释放二值信号量、LED4翻转;receive获取二值信号量、LED3翻转
receive任务是一直等待,只要send任务释放则receive获取二值信号量。
需定义二值信号量句柄
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define SEND_TASK_PRIO 3
//任务堆栈大小
#define SEND_STK_SIZE 50
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO 4
//任务堆栈大小
#define RECEIVE_STK_SIZE 50
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);
//创建句柄
SemaphoreHandle_t BinarySem_Handle =NULL;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
/* 创建 BinarySem */
BinarySem_Handle = xSemaphoreCreateBinary();
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建接收任务
xTaskCreate((TaskFunction_t )receive_task,
(const char* )"receive_task",
(uint16_t )RECEIVE_STK_SIZE,
(void* )NULL,
(UBaseType_t )RECEIVE_TASK_PRIO,
(TaskHandle_t* )&ReceiveTask_Handler);
//创建发送任务
xTaskCreate((TaskFunction_t )send_task,
(const char* )"send_task",
(uint16_t )SEND_STK_SIZE,
(void* )NULL,
(UBaseType_t )SEND_TASK_PRIO,
(TaskHandle_t* )&SendTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
vTaskDelay(500);
}
}
void send_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
while(1)
{
if(KEY==1)
{
xReturn = xSemaphoreGive( BinarySem_Handle );//释放二值信号量
if(xReturn==pdPASS) {LED4=!LED4;OLED_ShowString(3,0,"release",8,1);} //释放成功则LED4反转
else OLED_ShowString(3,0,"failed!",8,1);
}
else OLED_ShowString(3,0,"nopress",8,1); //没按下时显示"nopress"
OLED_Refresh();
vTaskDelay(100);
}
}
//接收任务函数
void receive_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
while(1)
{
//获取二值信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if(pdTRUE == xReturn) //获取二值信号量成功
{
OLED_ShowString(3,40,"receive",8,1);
LED3=!LED3; //获取成功则LED3反转
}
else //获取二值信号量失败
{
OLED_ShowString(3,40,"nochange",8,1);
}
OLED_Refresh();
vTaskDelay(100);
}
}
5-FreeRTOS计数信号量实验
/******************************2023年10月15日*************************************
此为一个计数信号量实验,主要使用使用按键、OLED屏幕来观察现象。
主要创建两个任务一个接收,一个发送
计数信号量,需要按键触发,按下按键则send任务释放计数信号量、LED4翻转;receive获取计数信号量、LED3翻转
receive任务是不等待,只要send任务释放则receive才能成功获取二值信号量。
需定义计数信号量句柄
需要修改FreeRTOSConfig.h中的宏定义:
//为1时使用计数信号量
#define configUSE_COUNTING_SEMAPHORES 1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define SEND_TASK_PRIO 3
//任务堆栈大小
#define SEND_STK_SIZE 50
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void send_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define RECEIVE_TASK_PRIO 4
//任务堆栈大小
#define RECEIVE_STK_SIZE 50
//任务句柄
TaskHandle_t ReceiveTask_Handler;
//任务函数
void receive_task(void *pvParameters);
//创建句柄
SemaphoreHandle_t CountSem_Handle =NULL;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
/* 创建 CountSem */
CountSem_Handle = xSemaphoreCreateCounting(5,5);
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建接收任务
xTaskCreate((TaskFunction_t )receive_task,
(const char* )"receive_task",
(uint16_t )RECEIVE_STK_SIZE,
(void* )NULL,
(UBaseType_t )RECEIVE_TASK_PRIO,
(TaskHandle_t* )&ReceiveTask_Handler);
//创建发送任务
xTaskCreate((TaskFunction_t )send_task,
(const char* )"send_task",
(uint16_t )SEND_STK_SIZE,
(void* )NULL,
(UBaseType_t )SEND_TASK_PRIO,
(TaskHandle_t* )&SendTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
vTaskDelay(500);
}
}
void send_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
while(1)
{
if(KEY==1)
{
xReturn = xSemaphoreGive( CountSem_Handle );//释放计数信号量
if(xReturn==pdPASS) {LED4=!LED4;OLED_ShowString(3,0,"release",8,1);} //释放成功则LED4反转
else OLED_ShowString(3,0,"failed!",8,1);
}
else OLED_ShowString(3,0,"nopress",8,1); //没按下时显示"nopress"
OLED_Refresh();
vTaskDelay(100);
}
}
//接收任务函数
void receive_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;/* 定义一个创建信息返回值,默认为pdTRUE */
while(1)
{
//获取计数信号量 xSemaphore,没获取到则不等待
xReturn = xSemaphoreTake(CountSem_Handle,/* 计数信号量句柄 */
0); /* 等待时间 */
if(pdTRUE == xReturn) //获取计数信号量成功
{
OLED_ShowString(3,40,"receive",8,1);
LED3=!LED3; //获取成功则LED3反转
}
else //获取计数信号量失败
{
OLED_ShowString(3,40,"nochang",8,1);
}
OLED_Refresh();
vTaskDelay(100);
}
}
6-FreeRTOS互斥信号量实验 - 优先级翻转
/******************************2023年10月17日*************************************
此为一个优先级翻转实验,主要使用使用OLED屏幕来观察现象。
主要创建三个任务高优先级、中优先级、低优先级
模拟优先级翻转、低优先级任务运行时高优先级任务等待
需定义二值信号量句柄
由于高优先级任务需要的资源(二值信号量)被低优先级任务占据,所以无法执行,挂起(此时任务优先级翻转)
中优先级任务没有使用到被占据的资源(二值信号量),所以中优先级任务不用等待低优先级任务执行完毕
需更改宏定义
//使用互斥信号量
#define configUSE_MUTEXES 1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 3 //这里提高LED任务优先级,防止低优先级任务阻塞了LED任务
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define LowPriority_TASK_PRIO 2 //比LED优先级低
//任务堆栈大小
#define LowPriority_STK_SIZE 512
//任务句柄
TaskHandle_t LowPriority_Task_Handle;
//任务函数
void LowPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define MidPriority_TASK_PRIO 4
//任务堆栈大小
#define MidPriority_STK_SIZE 512
//任务句柄
TaskHandle_t MidPriority_Task_Handle;
//任务函数
void MidPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define HighPriority_TASK_PRIO 5
//任务堆栈大小
#define HighPriority_STK_SIZE 512
//任务句柄
TaskHandle_t HighPriority_Task_Handle;
//任务函数
void HighPriority_Task(void *pvParameters);
//创建句柄
SemaphoreHandle_t BinarySem_Handle =NULL;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;
taskENTER_CRITICAL(); //进入临界区
/* 创建 BinarySem */
BinarySem_Handle = xSemaphoreCreateBinary();
xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建低优先级任务
xTaskCreate((TaskFunction_t )LowPriority_Task,
(const char* )"LowPriority_Task",
(uint16_t )LowPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )LowPriority_TASK_PRIO,
(TaskHandle_t* )&LowPriority_Task_Handle);
//创建中优先级任务
xTaskCreate((TaskFunction_t )MidPriority_Task,
(const char* )"MidPriority_Task",
(uint16_t )MidPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )MidPriority_TASK_PRIO,
(TaskHandle_t* )&MidPriority_Task_Handle);
//创建高优先级任务
xTaskCreate((TaskFunction_t )HighPriority_Task,
(const char* )"HighPriority_Task",
(uint16_t )HighPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )HighPriority_TASK_PRIO,
(TaskHandle_t* )&HighPriority_Task_Handle);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
vTaskDelay(500);
}
}
//低优先级任务函数
void LowPriority_Task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
static uint32_t i=0;
static uint32_t low_see=0;
while(1)
{
OLED_ShowString(3,0,"low_get",8,1);
OLED_Refresh();
//获取二值信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if( xReturn == pdTRUE )
{
OLED_ShowString(3,0,"low_run",8,1);
low_see++;
OLED_ShowNum(60,0,low_see,4,8,1);
OLED_Refresh();
}
/*****************************************************************************
此处可以占据二值信号量,导致高优先级任务无法获取二值信号量无法执行。被迫等待低优先级任务执行完毕。
而中优先级任务不需要获取二值信号量所以不受影响
*****************************************************************************/
for(i=0;i<2000000;i++)//模拟低优先级任务占用信号量
{
taskYIELD();//发起任务调度
}
OLED_ShowString(3,0,"low_giv",8,1);
OLED_Refresh();
xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
LED2=!LED2;
vTaskDelay(500);
}
}
//中优先级任务函数
void MidPriority_Task(void *pvParameters)
{
static uint32_t see=0;
while(1)
{
see++;
OLED_ShowNum(3,20,see,4,8,1); // 用来证明中优先级任务没有被低优先级任务阻塞
OLED_Refresh();
vTaskDelay(500);
}
}
//高优先级任务函数
void HighPriority_Task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
static uint32_t high_see=0;
while(1)
{
OLED_ShowString(3,40,"hig_get",8,1);
OLED_Refresh();
//获取二值信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(BinarySem_Handle,/* 二值信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if(pdTRUE == xReturn)
{
OLED_ShowString(3,40,"hig_run",8,1);
high_see++;
OLED_ShowNum(60,40,high_see,4,8,1);
OLED_Refresh();
}
LED2=!LED2;
xReturn = xSemaphoreGive( BinarySem_Handle );//给出二值信号量
vTaskDelay(500);
}
}
7-FreeRTOS互斥信号量实验-互斥量
/******************************2023年10月17日*************************************
此为一个互斥信号量实验,主要使用使用OLED屏幕来观察现象。
主要创建三个任务高优先级、中优先级、低优先级
模拟低优先级占用资源、低优先级任务运行时高优先级任务等待
需定义互斥信号量句柄
互斥信号量实验与优先级翻转实验的区别就是:
优先级反转实验定义的是二值信号量,只有需要获取二值信号量的任务会被影响;
互斥信号量实验定义的是互斥信号量,所有的任务都会被影响,体现资源占用互斥
需更改宏定义
//使用互斥信号量
#define configUSE_MUTEXES 1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 3 //这里提高LED任务优先级,防止低优先级任务阻塞了LED任务
//任务堆栈大小 (单位字)
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define LowPriority_TASK_PRIO 2 //比LED优先级低
//任务堆栈大小
#define LowPriority_STK_SIZE 512
//任务句柄
TaskHandle_t LowPriority_Task_Handle;
//任务函数
void LowPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define MidPriority_TASK_PRIO 4
//任务堆栈大小
#define MidPriority_STK_SIZE 512
//任务句柄
TaskHandle_t MidPriority_Task_Handle;
//任务函数
void MidPriority_Task(void *pvParameters);
/*******************************************************************************/
//任务优先级
#define HighPriority_TASK_PRIO 5
//任务堆栈大小
#define HighPriority_STK_SIZE 512
//任务句柄
TaskHandle_t HighPriority_Task_Handle;
//任务函数
void HighPriority_Task(void *pvParameters);
//创建句柄
SemaphoreHandle_t MuxSem_Handle =NULL;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
/* 创建 BinarySem */
MuxSem_Handle = xSemaphoreCreateMutex();
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建低优先级任务
xTaskCreate((TaskFunction_t )LowPriority_Task,
(const char* )"LowPriority_Task",
(uint16_t )LowPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )LowPriority_TASK_PRIO,
(TaskHandle_t* )&LowPriority_Task_Handle);
//创建中优先级任务
xTaskCreate((TaskFunction_t )MidPriority_Task,
(const char* )"MidPriority_Task",
(uint16_t )MidPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )MidPriority_TASK_PRIO,
(TaskHandle_t* )&MidPriority_Task_Handle);
//创建高优先级任务
xTaskCreate((TaskFunction_t )HighPriority_Task,
(const char* )"HighPriority_Task",
(uint16_t )HighPriority_STK_SIZE,
(void* )NULL,
(UBaseType_t )HighPriority_TASK_PRIO,
(TaskHandle_t* )&HighPriority_Task_Handle);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=!LED1;
vTaskDelay(500);
}
}
//低优先级任务函数
void LowPriority_Task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;/* 定义一个创建信息返回值,默认为pdPASS */
static uint32_t i=0;
static uint32_t low_see=0;
while(1)
{
OLED_ShowString(3,0,"low_get",8,1);
OLED_Refresh();
//获取二值信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if( xReturn == pdTRUE )
{
OLED_ShowString(3,0,"low_run",8,1);
low_see++;
OLED_ShowNum(60,0,low_see,4,8,1);
OLED_Refresh();
}
/*****************************************************************************
模拟低优先级任务占用资源
*****************************************************************************/
for(i=0;i<2000000;i++)//模拟低优先级任务占用信号量
{
taskYIELD();//发起任务调度
}
OLED_ShowString(3,0,"low_giv",8,1);
OLED_Refresh();
xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥信号量
LED2=!LED2;
vTaskDelay(500);
}
}
//中优先级任务函数
void MidPriority_Task(void *pvParameters)
{
static uint32_t see=0;
while(1)
{
see++;
OLED_ShowNum(3,20,see,4,8,1); // 用来证明中优先级任务没有被低优先级任务阻塞
OLED_Refresh();
vTaskDelay(500);
}
}
//高优先级任务函数
void HighPriority_Task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
static uint32_t high_see=0;
while(1)
{
OLED_ShowString(3,40,"hig_get",8,1);
OLED_Refresh();
//获取互斥信号量 xSemaphore,没获取到则一直等待
xReturn = xSemaphoreTake(MuxSem_Handle,/* 互斥信号量句柄 */
portMAX_DELAY); /* 等待时间 */
if(pdTRUE == xReturn)
{
OLED_ShowString(3,40,"hig_run",8,1);
high_see++;
OLED_ShowNum(60,40,high_see,4,8,1);
OLED_Refresh();
}
LED2=!LED2;
xReturn = xSemaphoreGive( MuxSem_Handle );//给出互斥信号量
vTaskDelay(500);
}
}
8-FreeRTOS事件实验
/******************************2023年10月17日*************************************
这是一个事件实验,LED2任务需要事件触发,KEY任务可以通过按键计数创建对应的事件,
当事件满足时LED2任务才可以执行一次,执行完之后由于xEventGroupWaitBits某个参数
设置为pdTRUE,所以触发后会自动删除标志位,自动清除。这个函数返回值为事件的计算值。
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
#include "event_groups.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define LED2_TASK_PRIO 3
//任务堆栈大小
#define LED2_STK_SIZE 50
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);
//任务优先级
#define KEY_TASK_PRIO 4
//任务堆栈大小
#define KEY_STK_SIZE 512
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);
//创建句柄
EventGroupHandle_t Event_Handle =NULL;
#define KEY1_EVENT (0x01 << 0)//设置事件掩码的位0
#define KEY2_EVENT (0x01 << 1)//设置事件掩码的位1
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
/* 创建 Event_Handle */
Event_Handle = xEventGroupCreate();
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
//创建KEY任务
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//LED2任务函数
void led2_task(void *pvParameters)
{
EventBits_t r_event; /* 定义一个事件接收变量 */
while(1)
{
r_event = xEventGroupWaitBits(Event_Handle, /* 事件对象句柄 */
KEY1_EVENT|KEY2_EVENT,/* 接收线程感兴趣的事件 */
pdTRUE, /* 退出时清除事件位 */
pdTRUE, /* 满足感兴趣的所有事件 */
portMAX_DELAY);/* 指定超时事件,一直等 */
if((r_event & (KEY1_EVENT|KEY2_EVENT)) == (KEY1_EVENT|KEY2_EVENT))
{
OLED_ShowString(3,50 ,"get!",8,1);
LED2=!LED2;
}
else
OLED_ShowString(3,50 ,"err!",8,1);
OLED_Refresh();
}
}
//KEY任务函数
void key_task(void *pvParameters)
{
static uint32_t KEY_DOWN=0;
while(1)
{
if(KEY==1)
{
KEY_DOWN++;
if(KEY_DOWN%2==0)
{
xEventGroupSetBits(Event_Handle,KEY1_EVENT); //偶数创建事件1
OLED_ShowString(3,0 ,"event1 created!",8,1);
}
else
{
xEventGroupSetBits(Event_Handle,KEY2_EVENT); //奇数创建事件2
OLED_ShowString(3,20 ,"event2 created!",8,1);
}
while(KEY==1);
}
OLED_ShowNum(3,40,KEY_DOWN,2,8,1);
OLED_Refresh();
vTaskDelay(20);
}
}
9-FreeRTOS软件定时器实验
/******************************2023年10月17日*************************************
这是一个软件定时器实验,创建了两个软件定时器,定时器1可以一直定时,定时时间1秒;
定时器2只能定时一次,定时时间5秒。通过OLED屏幕显示来观察定时情况。
1 tick为 1 ms
需要修改宏定义中
//启用软件定时器
#define configUSE_TIMERS 1
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
/**************************************************************************************/
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/**************************************************************************************/
//创建句柄
TimerHandle_t Swtmr1_Handle =NULL;
TimerHandle_t Swtmr2_Handle =NULL;
static uint32_t TmrCb_Count1 = 0; /* 记录软件定时器1回调函数执行次数 */
static uint32_t TmrCb_Count2 = 0; /* 记录软件定时器2回调函数执行次数 */
//声明回调函数
static void Swtmr1_Callback(void* parameter);
static void Swtmr2_Callback(void* parameter);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建定时器1
Swtmr1_Handle=xTimerCreate((const char* )"AutoReloadTimer",
(TickType_t )1000,/* 定时器周期 1000(tick) */
(UBaseType_t )pdTRUE,/* 周期模式 */
(void* )1,/* 为每个计时器分配一个索引的唯一ID */
(TimerCallbackFunction_t)Swtmr1_Callback); /*回调函数名称*/
if(Swtmr1_Handle != NULL)
{
xTimerStart(Swtmr1_Handle,0); //开启周期定时器
}
//创建定时器2
Swtmr2_Handle=xTimerCreate((const char* )"OneShotTimer",
(TickType_t )5000,/* 定时器周期 5000(tick) */
(UBaseType_t )pdFALSE,/* 单次模式 */
(void* )2,/* 为每个计时器分配一个索引的唯一ID */
(TimerCallbackFunction_t)Swtmr2_Callback); /*回调函数名称*/
if(Swtmr2_Handle != NULL)
{
xTimerStart(Swtmr2_Handle,0); //开启周期定时器
}
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//定时器1回调函数
//软件定时器不要调用阻塞函数,也不要进行死循环,应快进快出
void Swtmr1_Callback(void* parameter)
{
TickType_t tick_num1;
TmrCb_Count1++; /* 每回调一次加一 */
tick_num1 = xTaskGetTickCount(); /* 获取滴答定时器的计数值 */
LED2=!LED2;
OLED_ShowNum(3,0,tick_num1,5,8,1); //滴答定时器值
OLED_ShowNum(3,20,TmrCb_Count1,5,8,1); //软件定时器1值
OLED_Refresh();
}
//定时器2回调函数
//软件定时器不要调用阻塞函数,也不要进行死循环,应快进快出
void Swtmr2_Callback(void* parameter)
{
TickType_t tick_num2;
TmrCb_Count2++; /* 每回调一次加一 */
tick_num2 = xTaskGetTickCount(); /* 获取滴答定时器的计数值 */
OLED_ShowNum(3,40,TmrCb_Count2,5,8,1); //软件定时器2值
OLED_ShowNum(3,0,tick_num2,5,8,1); //滴答定时器值
OLED_Refresh();
}
10-FreeRTOS任务通知代替消息队列实验
/******************************2023年10月18日*************************************
这是一个任务通知代替消息队列的实验,通过OLED与KEY观察现象。
判断KEY按下的次数来判断发送哪一个通知,奇数通知接收任务1,偶数通知接收任务2
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define Receive1_TASK_PRIO 3
//任务堆栈大小
#define Receive1_STK_SIZE 512
//任务句柄
TaskHandle_t Receive1Task_Handler;
//任务函数
void Receive1_task(void *pvParameters);
//任务优先级
#define Receive2_TASK_PRIO 4
//任务堆栈大小
#define Receive2_STK_SIZE 512
//任务句柄
TaskHandle_t Receive2Task_Handler;
//任务函数
void Receive2_task(void *pvParameters);
//任务优先级
#define Send_TASK_PRIO 5
//任务堆栈大小
#define Send_STK_SIZE 512
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void Send_task(void *pvParameters);
#define USE_CHAR 0 /* 测试字符串的时候配置为 1 ,测试变量配置为 0 */
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建Receive1任务
xTaskCreate((TaskFunction_t )Receive1_task,
(const char* )"Receive1_task",
(uint16_t )Receive1_STK_SIZE,
(void* )NULL,
(UBaseType_t )Receive1_TASK_PRIO,
(TaskHandle_t* )&Receive1Task_Handler);
//创建Receive2任务
xTaskCreate((TaskFunction_t )Receive2_task,
(const char* )"Receive2_task",
(uint16_t )Receive2_STK_SIZE,
(void* )NULL,
(UBaseType_t )Receive2_TASK_PRIO,
(TaskHandle_t* )&Receive2Task_Handler);
//创建Send任务
xTaskCreate((TaskFunction_t )Send_task,
(const char* )"Send_task",
(uint16_t )Send_STK_SIZE,
(void* )NULL,
(UBaseType_t )Send_TASK_PRIO,
(TaskHandle_t* )&SendTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//Receive1任务函数
void Receive1_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
#if USE_CHAR
char *r_char;
#else
uint32_t r_num;
#endif
while(1)
{
//获取任务通知 ,没获取到则一直等待
xReturn=xTaskNotifyWait(0x0, //进入函数的时候不清除任务bit
ULONG_MAX, //退出函数的时候清除所有的bit
#if USE_CHAR
(uint32_t *)&r_char, //保存任务通知值
#else
&r_num, //保存任务通知值
#endif
portMAX_DELAY); //阻塞时间
if( pdTRUE == xReturn )
#if USE_CHAR
printf("Receive1_Task 任务通知消息为 %s \n",r_char);
#else
{
OLED_ShowString(3,0,"receive1:",8,1);
OLED_ShowNum(70,0,r_num,1,8,1);
OLED_Refresh();
}
#endif
}
}
//Receive2任务函数
void Receive2_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
#if USE_CHAR
char *r_char;
#else
uint32_t r_num;
#endif
while(1)
{
//获取任务通知 ,没获取到则一直等待
xReturn=xTaskNotifyWait(0x0, //进入函数的时候不清除任务bit
ULONG_MAX, //退出函数的时候清除所有的bit
#if USE_CHAR
(uint32_t *)&r_char, //保存任务通知值
#else
&r_num, //保存任务通知值
#endif
portMAX_DELAY); //阻塞时间
if( pdTRUE == xReturn )
#if USE_CHAR
printf("Receive2_Task 任务通知消息为 %s \n",r_char);
#else
{
OLED_ShowString(3,20,"receive2:",8,1);
OLED_ShowNum(70,20,r_num,1,8,1);
OLED_Refresh();
}
#endif
}
}
//Send任务函数
void Send_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;
u8 PRESS=0;
#if USE_CHAR
char test_str1[] = "this is a mail test 1";/* 邮箱消息test1 */
char test_str2[] = "this is a mail test 2";/* 邮箱消息test2 */
#else
uint32_t send1 = 1;
uint32_t send2 = 2;
#endif
while(1)
{
if(KEY==1)
{
PRESS++;
while(KEY==1);
/**************************************奇数发送Receive1*****************************************/
if(PRESS%2!=0)
{ xReturn = xTaskNotify(Receive1Task_Handler, /*任务句柄*/
#if USE_CHAR
(uint32_t)&test_str1, /* 发送的数据,最大为4字节 */
#else
send1, /* 发送的数据,最大为4字节 */
#endif
eSetValueWithOverwrite );/*覆盖当前通知*/
if( xReturn == pdPASS )
{
OLED_ShowString(3,40,"receive1 send!",8,1);
OLED_Refresh();
}
}
/***************************************偶数发送Receive2**************************************/
else
{
xReturn = xTaskNotify(Receive2Task_Handler, /*任务句柄*/
#if USE_CHAR
(uint32_t)&test_str2, /* 发送的数据,最大为4字节 */
#else
send2, /* 发送的数据,最大为4字节 */
#endif
eSetValueWithOverwrite );/*覆盖当前通知*/
if( xReturn == pdPASS )
{
OLED_ShowString(3,40,"receive2 send!",8,1);
OLED_Refresh();
}
}
/*****************************************************************************/
}
vTaskDelay(20);
}
}
11-FreeRTOS任务通知代替二值信号量实验
/******************************2023年10月18日*************************************
这是一个任务通知代替二值信号量的实验,通过OLED与KEY观察现象。
判断KEY按下的次数来判断发送哪一个通知,奇数通知接收任务1,偶数通知接收任务2
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define Receive1_TASK_PRIO 3
//任务堆栈大小
#define Receive1_STK_SIZE 512
//任务句柄
TaskHandle_t Receive1Task_Handler;
//任务函数
void Receive1_task(void *pvParameters);
//任务优先级
#define Receive2_TASK_PRIO 4
//任务堆栈大小
#define Receive2_STK_SIZE 512
//任务句柄
TaskHandle_t Receive2Task_Handler;
//任务函数
void Receive2_task(void *pvParameters);
//任务优先级
#define Send_TASK_PRIO 5
//任务堆栈大小
#define Send_STK_SIZE 512
//任务句柄
TaskHandle_t SendTask_Handler;
//任务函数
void Send_task(void *pvParameters);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建Receive1任务
xTaskCreate((TaskFunction_t )Receive1_task,
(const char* )"Receive1_task",
(uint16_t )Receive1_STK_SIZE,
(void* )NULL,
(UBaseType_t )Receive1_TASK_PRIO,
(TaskHandle_t* )&Receive1Task_Handler);
//创建Receive2任务
xTaskCreate((TaskFunction_t )Receive2_task,
(const char* )"Receive2_task",
(uint16_t )Receive2_STK_SIZE,
(void* )NULL,
(UBaseType_t )Receive2_TASK_PRIO,
(TaskHandle_t* )&Receive2Task_Handler);
//创建Send任务
xTaskCreate((TaskFunction_t )Send_task,
(const char* )"Send_task",
(uint16_t )Send_STK_SIZE,
(void* )NULL,
(UBaseType_t )Send_TASK_PRIO,
(TaskHandle_t* )&SendTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//Receive1任务函数
void Receive1_task(void *pvParameters)
{
while(1)
{
//获取任务通知 ,没获取到则一直等待
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
OLED_ShowString(3,0,"task1 received!",8,1);
OLED_Refresh();
}
}
//Receive2任务函数
void Receive2_task(void *pvParameters)
{
while(1)
{
//获取任务通知 ,没获取到则一直等待
ulTaskNotifyTake(pdTRUE,portMAX_DELAY);
OLED_ShowString(3,20,"task2 received!",8,1);
OLED_Refresh();
}
}
//Send任务函数
void Send_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;
u8 PRESS=0;
while(1)
{
if(KEY==1)
{
PRESS++;
while(KEY==1);
/**************************************奇数发送Receive1*****************************************/
if(PRESS%2!=0)
{
xReturn = xTaskNotifyGive(Receive1Task_Handler);
if( xReturn == pdTRUE )
{
OLED_ShowString(3,40,"task1 send!",8,1);
OLED_Refresh();
}
}
/***************************************偶数发送Receive2**************************************/
else
{
xReturn = xTaskNotifyGive(Receive2Task_Handler);
if( xReturn == pdTRUE )
{
OLED_ShowString(3,40,"task2 send!",8,1);
OLED_Refresh();
}
}
/*****************************************************************************/
}
vTaskDelay(20);
}
}
12-FreeRTOS任务通知代替计数信号量实验
/******************************2023年10月18日*************************************
这是一个任务通知代替计数信号量的实验,通过OLED与KEY观察现象。
KEY按下释放信号量,长按可一直释放信号量
take任务会一直获取信号量
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define Take_TASK_PRIO 3
//任务堆栈大小
#define Take_STK_SIZE 512
//任务句柄
TaskHandle_t TakeTask_Handler;
//任务函数
void Take_task(void *pvParameters);
//任务优先级
#define Give_TASK_PRIO 4
//任务堆栈大小
#define Give_STK_SIZE 512
//任务句柄
TaskHandle_t GiveTask_Handler;
//任务函数
void Give_task(void *pvParameters);
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建Take任务
xTaskCreate((TaskFunction_t )Take_task,
(const char* )"Take_task",
(uint16_t )Take_STK_SIZE,
(void* )NULL,
(UBaseType_t )Take_TASK_PRIO,
(TaskHandle_t* )&TakeTask_Handler);
//创建Give任务
xTaskCreate((TaskFunction_t )Give_task,
(const char* )"Give_task",
(uint16_t )Give_STK_SIZE,
(void* )NULL,
(UBaseType_t )Give_TASK_PRIO,
(TaskHandle_t* )&GiveTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//Give任务函数
void Give_task(void *pvParameters)
{
BaseType_t xReturn = pdPASS;
while(1)
{
if(KEY==1)
{
xReturn=xTaskNotifyGive(TakeTask_Handler);//发送任务通知
if ( pdPASS == xReturn )
{
OLED_ShowString(3,0,"release one!",8,1);
OLED_Refresh();
}
}
vTaskDelay(20);
}
}
//Take任务函数
void Take_task(void *pvParameters)
{
uint32_t take_num = pdTRUE;
while(1)
{
take_num=ulTaskNotifyTake(pdFALSE,0);
if(take_num > 0)
OLED_ShowNum(3,20,take_num,4,8,1);
else
OLED_ShowString(3,40,"wait",8,1);
OLED_Refresh();
vTaskDelay(20);
}
}
13-FreeRTOS任务通知代替事件组实验
/******************************2023年10月18日*************************************
这是一个任务通知代替事件组的实验,通过OLED与KEY观察现象。
KEY按下计数,通过计数的奇偶值来判断产生哪一个事件
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define LED2_TASK_PRIO 3
//任务堆栈大小
#define LED2_STK_SIZE 50
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);
//任务优先级
#define KEY_TASK_PRIO 4
//任务堆栈大小
#define KEY_STK_SIZE 512
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);
#define KEY1_EVENT (0x01 << 0)//设置事件掩码的位0
#define KEY2_EVENT (0x01 << 1)//设置事件掩码的位1
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
//创建KEY任务
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//LED2任务函数
void led2_task(void *pvParameters)
{
BaseType_t xReturn = pdTRUE;
uint32_t r_event = 0; /* 定义一个事件接收变量 */
uint32_t last_event = 0;/* 定义一个保存事件的变量 */
while(1)
{
//获取任务通知 ,没获取到则一直等待
xReturn = xTaskNotifyWait(0x0, //进入函数的时候不清除任务bit
ULONG_MAX, //退出函数的时候清除所有的bitR
&r_event, //保存任务通知值
portMAX_DELAY); //阻塞时间
if( pdTRUE == xReturn )
{
last_event |= r_event;
if(last_event == (KEY1_EVENT|KEY2_EVENT))
{
last_event=0;
LED2=!LED2;
}
else
last_event = r_event;
}
}
}
//KEY任务函数
void key_task(void *pvParameters)
{
u8 PRESS=0;
while(1)
{
if(KEY==1)
{
PRESS++;
while(KEY==1);
if(PRESS%2!=0)
{
OLED_ShowString(3,0,"KEY1_EVENT!",8,1);
/* 触发一个事件1 */
xTaskNotify((TaskHandle_t )LED2Task_Handler,//接收任务通知的任务句柄
(uint32_t )KEY1_EVENT,//要触发的事件
(eNotifyAction)eSetBits);//设置任务通知值中的位
}
else
{
OLED_ShowString(3,20,"KEY2_EVENT!",8,1);
/* 触发一个事件2 */
xTaskNotify((TaskHandle_t )LED2Task_Handler,//接收任务通知的任务句柄
(uint32_t )KEY2_EVENT,//要触发的事件
(eNotifyAction)eSetBits);//设置任务通知值中的位
}
}
OLED_Refresh();
vTaskDelay(20);
}
}
14-FreeRTOS内存管理实验
/******************************2023年10月18日*************************************
这是一个内存管理实验,通过OLED与KEY观察现象。
KEY按下计数,通过计数的奇偶值来判断产生申请内存还是释放内存
显示申请到的内存地址,以及申请内存后的剩余空间,以及系统运行时间
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
/******************************************************************************/
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/******************************************************************************/
//任务优先级
#define KEY_TASK_PRIO 4
//任务堆栈大小
#define KEY_STK_SIZE 512
//任务句柄
TaskHandle_t KEYTask_Handler;
//任务函数
void key_task(void *pvParameters);
uint8_t *Test_Ptr = NULL;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建KEY任务
xTaskCreate((TaskFunction_t )key_task,
(const char* )"key_task",
(uint16_t )KEY_STK_SIZE,
(void* )NULL,
(UBaseType_t )KEY_TASK_PRIO,
(TaskHandle_t* )&KEYTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
LED1=1;
vTaskDelay(800);
}
}
//KEY任务函数
void key_task(void *pvParameters)
{
u8 PRESS=0;
uint32_t g_memsize;
while(1)
{
if(KEY==1)
{
while(KEY==1);
PRESS++;
if(PRESS%2!=0)
{
if(NULL == Test_Ptr)
{
/* 获取当前内存大小 */
g_memsize = xPortGetFreeHeapSize();
OLED_ShowString(3,0,"rest ram:",8,1);
OLED_ShowNum(60,0,g_memsize,9,8,1);
Test_Ptr = pvPortMalloc(1024); //申请1k内存
if(NULL != Test_Ptr)
{
OLED_ShowString(3,20,"get ram:",8,1);
sprintf((char*)Test_Ptr," %#x \n",Test_Ptr); //转变为16进制数据
OLED_ShowString(60,20,(char*)Test_Ptr,8,1); //显示地址
/* 获取当前内剩余存大小 */
g_memsize = xPortGetFreeHeapSize();
OLED_ShowString(3,40,"rest ram:",8,1);
OLED_ShowNum(60,40,g_memsize,9,8,1);
//向Test_Ptr中写入当数据:当前系统时间
sprintf((char*)Test_Ptr,"TickCount = %d \n",xTaskGetTickCount());
// printf("写入的数据是 %s \n",(char*)Test_Ptr);
OLED_ShowString(3,50,(char*)Test_Ptr,8,1);
}
}
else
printf("请先按下KEY2释放内存再申请\n");
}
else
{
if(NULL != Test_Ptr)
{
OLED_Clear();
OLED_ShowString(3,0,"clear ram",8,1);
vPortFree(Test_Ptr);//释放内存
Test_Ptr=NULL;
/* 获取当前内剩余存大小 */
g_memsize = xPortGetFreeHeapSize();
OLED_ShowString(3,20,"rest ram:",8,1);
OLED_ShowNum(60,20,g_memsize,9,8,1);
}
else
printf("请先按下KEY1申请内存再释放\n");
}
}
OLED_Refresh();
vTaskDelay(20);
}
}
15-FreeRTOS-CPU利用率实验
/******************************2023年10月18日*************************************
这是一个CPU利用率实验,通过USART1与XCOM观察现象。
串口会不断的打印CPU利用情况
本次需要使用硬件定时器来统计CPU运行时间,频率为10000HZ
需修改配置文件如下内容
/********************************************************************
FreeRTOS与运行时间和任务状态收集有关的配置选项
**********************************************************************/
//启用运行时间统计功能
//#define configGENERATE_RUN_TIME_STATS 1
//启用可视化跟踪调试
//#define configUSE_TRACE_FACILITY 1
/* 与宏configUSE_TRACE_FACILITY同时为1时会编译下面3个函数
* prvWriteNameToBuffer()
* vTaskList(),
* vTaskGetRunTimeStats()
*/
//#define configUSE_STATS_FORMATTING_FUNCTIONS 1
//
// extern volatile uint32_t CPU_RunTime;
//#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() (CPU_RunTime = 0ul)
//#define portGET_RUN_TIME_COUNTER_VALUE() CPU_RunTime
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
#include "timer.h"
#include "string.h"
/************************************************************/
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
/************************************************************/
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 50
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
/************************************************************/
//任务优先级
#define LED2_TASK_PRIO 3
//任务堆栈大小
#define LED2_STK_SIZE 50
//任务句柄
TaskHandle_t LED2Task_Handler;
//任务函数
void led2_task(void *pvParameters);
/************************************************************/
//任务优先级
#define CPU_TASK_PRIO 4
//任务堆栈大小
#define CPU_STK_SIZE 512
//任务句柄
TaskHandle_t CPUTask_Handler;
//任务函数
void CPU_task(void *pvParameters);
/************************************************************/
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
TIM2_Int_Init(100-1,72-1);
printf("Freertos CPU利用率实验\r\n");
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建LED2任务
xTaskCreate((TaskFunction_t )led2_task,
(const char* )"led2_task",
(uint16_t )LED2_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED2_TASK_PRIO,
(TaskHandle_t* )&LED2Task_Handler);
//创建CPU任务
xTaskCreate((TaskFunction_t )CPU_task,
(const char* )"CPU_task",
(uint16_t )CPU_STK_SIZE,
(void* )NULL,
(UBaseType_t )CPU_TASK_PRIO,
(TaskHandle_t* )&CPUTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
LED1=0;
vTaskDelay(200);
printf("LED1_Task Running,LED2_ON\r\n");
LED1=1;
vTaskDelay(800);
printf("LED1_Task Running,LED2_OFF\r\n");
}
}
//LED2任务函数
void led2_task(void *pvParameters)
{
while(1)
{
LED2=0;
vTaskDelay(800);
printf("LED2_Task Running,LED2_ON\r\n");
LED2=1;
vTaskDelay(200);
printf("LED2_Task Running,LED2_OFF\r\n");
}
}
//CPU任务函数
void CPU_task(void *pvParameters)
{
uint8_t CPU_RunInfo[400];//保存任务运行时间信息
while(1)
{
memset(CPU_RunInfo,0,400);//信息缓冲区清零
vTaskList((char *)&CPU_RunInfo); //获取任务运行时间信息
printf("---------------------------------------------\r\n");
printf("任务名 任务状态 优先级 剩余栈 任务序号\r\n");
printf("%s", CPU_RunInfo);
printf("---------------------------------------------\r\n");
memset(CPU_RunInfo,0,400); //信息缓冲区清零
vTaskGetRunTimeStats((char *)&CPU_RunInfo);
printf("任务名 运行计数 利用率\r\n");
printf("%s", CPU_RunInfo);
printf("---------------------------------------------\r\n\n");
vTaskDelay(1000); /* 延时1000个tick */
}
}
16-FreeRTOS中断管理实验
/******************************2023年10月18日*************************************
这是一个中断管理实验,通过设置中断优先级来起到控制作用。
freertos中断开关管理可以管理优先级低的
中断优先级数值越小,优先级越高。
默认中断管理阈值为5,优先级数值高于或等于5的中断可以被管理
任务优先级数值小于5的中断不会被管理,因为优先级更高。
*********************************************************************************/
#include "system.h"
#include "SysTick.h"
#include "led.h"
#include "key.h"
#include "oled.h"
#include "usart.h"
#include "FreeRTOS.h"
#include "task.h"
#include "limits.h"
#include "timer.h"
#include "string.h"
/************************************************************/
//任务优先级
#define START_TASK_PRIO 1
//任务堆栈大小
#define START_STK_SIZE 128
//任务句柄
TaskHandle_t StartTask_Handler;
//任务函数
void start_task(void *pvParameters);
//任务优先级
#define LED1_TASK_PRIO 2
//任务堆栈大小
#define LED1_STK_SIZE 512
//任务句柄
TaskHandle_t LED1Task_Handler;
//任务函数
void led1_task(void *pvParameters);
//任务优先级
#define Interrupt_TASK_PRIO 4
//任务堆栈大小
#define Interrupt_STK_SIZE 512
//任务句柄
TaskHandle_t InterruptTask_Handler;
//任务函数
void Interrupt_task(void *pvParameters);
extern volatile uint32_t TIME2_RUN;
extern volatile uint32_t TIME3_RUN;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);//设置系统中断优先级分组4
USART1_Init(115200);
KEY_Init();
LED_Init();
OLED_Init();
OLED_ColorTurn(0);//0正常显示,1 反色显示
OLED_DisplayTurn(0);
OLED_Clear();
TIM2_Int_Init(10000-1,7200-1); //1s中断
TIM3_Int_Init(10000-1,7200-1); //1s中断
printf("Freertos CPU利用率实验\r\n");
//创建开始任务
xTaskCreate((TaskFunction_t )start_task, //任务函数
(const char* )"start_task", //任务名称
(uint16_t )START_STK_SIZE, //任务堆栈大小
(void* )NULL, //传递给任务函数的参数
(UBaseType_t )START_TASK_PRIO, //任务优先级
(TaskHandle_t* )&StartTask_Handler); //任务句柄
vTaskStartScheduler(); //开启任务调度
}
//开始任务任务函数
void start_task(void *pvParameters)
{
taskENTER_CRITICAL(); //进入临界区
//创建LED1任务
xTaskCreate((TaskFunction_t )led1_task,
(const char* )"led1_task",
(uint16_t )LED1_STK_SIZE,
(void* )NULL,
(UBaseType_t )LED1_TASK_PRIO,
(TaskHandle_t* )&LED1Task_Handler);
//创建Interrupt任务
xTaskCreate((TaskFunction_t )Interrupt_task,
(const char* )"Interrupt_task",
(uint16_t )Interrupt_STK_SIZE,
(void* )NULL,
(UBaseType_t )Interrupt_TASK_PRIO,
(TaskHandle_t* )&InterruptTask_Handler);
vTaskDelete(StartTask_Handler); //删除开始任务
taskEXIT_CRITICAL(); //退出临界区
}
//LED1任务函数
void led1_task(void *pvParameters)
{
while(1)
{
OLED_ShowNum(3,0,TIME3_RUN,4,8,1);
OLED_ShowNum(3,20,TIME2_RUN,4,8,1);
OLED_Refresh();
vTaskDelay(200);
}
}
//Interrupt任务函数
void Interrupt_task(void *pvParameters)
{
static u32 total_num=0;
while(1)
{
total_num+=1;
if(total_num==5)
{
printf("关闭中断.............\r\n");
portDISABLE_INTERRUPTS(); //关闭中断
delay_xms(6000); //延时6s,使用不影响任务调度的延时
printf("打开中断.............\r\n"); //打开中断
portENABLE_INTERRUPTS();
}
LED2=!LED2;
vTaskDelay(1000);
}
}