FreeRTOS标准库例程代码
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);//设置系统中断优先级分组4LED_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);//设置系统中断优先级分组4LED_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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;}elseOLED_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); //偶数创建事件1OLED_ShowString(3,0 ,"event1 created!",8,1);}else{xEventGroupSetBits(Event_Handle,KEY2_EVENT); //奇数创建事件2OLED_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);//设置系统中断优先级分组4USART1_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(); //进入临界区//创建定时器1Swtmr1_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); //开启周期定时器}//创建定时器2Swtmr2_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);//设置系统中断优先级分组4USART1_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_CHARchar *r_char;
#elseuint32_t r_num;
#endifwhile(1){//获取任务通知 ,没获取到则一直等待xReturn=xTaskNotifyWait(0x0, //进入函数的时候不清除任务bitULONG_MAX, //退出函数的时候清除所有的bit
#if USE_CHAR(uint32_t *)&r_char, //保存任务通知值
#else&r_num, //保存任务通知值
#endif portMAX_DELAY); //阻塞时间if( pdTRUE == xReturn )
#if USE_CHARprintf("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_CHARchar *r_char;
#elseuint32_t r_num;
#endifwhile(1){//获取任务通知 ,没获取到则一直等待xReturn=xTaskNotifyWait(0x0, //进入函数的时候不清除任务bitULONG_MAX, //退出函数的时候清除所有的bit
#if USE_CHAR(uint32_t *)&r_char, //保存任务通知值
#else&r_num, //保存任务通知值
#endif portMAX_DELAY); //阻塞时间if( pdTRUE == xReturn )
#if USE_CHARprintf("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_CHARchar test_str1[] = "this is a mail test 1";/* 邮箱消息test1 */char test_str2[] = "this is a mail test 2";/* 邮箱消息test2 */
#elseuint32_t send1 = 1;uint32_t send2 = 2;
#endifwhile(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字节 */
#elsesend1, /* 发送的数据,最大为4字节 */
#endifeSetValueWithOverwrite );/*覆盖当前通知*/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字节 */
#elsesend2, /* 发送的数据,最大为4字节 */
#endifeSetValueWithOverwrite );/*覆盖当前通知*/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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);elseOLED_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);//设置系统中断优先级分组4USART1_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, //进入函数的时候不清除任务bitULONG_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;}elselast_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);//设置系统中断优先级分组4USART1_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);}}elseprintf("请先按下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);}elseprintf("请先按下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);//设置系统中断优先级分组4USART1_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);//设置系统中断优先级分组4USART1_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);}
}
相关文章:

FreeRTOS标准库例程代码
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 "…...

wandb: - 0.000 MB of 0.011 MB uploaded持续出现的解决方案
大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…...

分布式模式让业务更高效、更安全、更稳定
🌈 个人主页:danci_ 🔥 系列专栏:《设计模式》 💪🏻 制定明确可量化的目标,坚持默默的做事。 🚀 转载自热榜文章🔥:探索设计模式的魅力:分布式模…...

5.11学习记录
20长安杯部分 检材 1 的操作系统版本 CentOS Linux 7.6.1810 (Core) 检材 1 中,操作系统的内核版本是 3.10.0-957.el7.x86_64 检材 1 中磁盘包含一个 LVM 逻辑卷,该 LVM 开始的逻辑区块地址(LBA)是 2099200 物理卷ÿ…...

Java类加载器介绍
在Java中,类加载器是一种动态加载类的机制,它负责在运行时查找、加载和链接类文件。当Java应用程序需要创建某个类的对象时,类加载器会在运行时查找该类对应的.class文件,并将其加载到Java虚拟机中。Java类加载器通常分为三层&…...

VC++ PDH/性能计数器
例子: PID0,缺省为当前进程,但最好是获取当前进程ID传递进去,当然也可以选择其它进程的ID。 PerformanceCounter pc; pc.Open(0, "//Processor(_Total)//% Processor Time"); 源实现: #include <windo…...

C++ 类和对象:面向对象编程基础
目录标题 1. 什么是类?2. 什么是对象?3. 如何定义一个类?4. 如何创建对象?5. 类的构造函数6. 类的析构函数7. 数据封装和访问修饰符8. 示例:一个简单的BankAccount类9. 使用g编译10. 再来一个简单的C程序11. 定义书籍类…...

linux 基础命令使用
命令 su 用于切换到另一个用户身份,通常是超级用户(root)。su命令可以用来在命令行下切换用户,也可以在脚本中使用。 语法: su [选项] [用户名] 选项: - -c:执行完命令后,立即退出su命令;…...

eve 导入linux
mkdir /opt/unetlab/addons/qemu/linux-centos7 cd /opt/unetlab/addons/qemu/linux-centos7 上传hda.qcow2 /opt/unetlab/wrappers/unl_wrapper -a fixpermissions Linux images - (eve-ng.net) Due to very high demand of this section and problems with how to crea…...

vivado新版本兼容老版本,vitis classic兼容sdk教程
new version: vivado版本2023.2 和vitisv classic 2023.2 old version: vivado 2018.3以及之前的版本 打开工程 自动升级到当前版本,选择OK 点击Yes,合并当前的目录架构 点击OK 点击Report IP status 勾选要升级的IP核,点击升级 在项目工程文件夹…...

02.02.返回倒数第k个节点
实现一种算法,找出单向链表中倒数第 k 个节点。返回该节点的值。 注意:本题相对原题稍作改动 示例: 输入: 1->2->3->4->5 和 k 2 输出: 4 说明: 给定的 k 保证是有效的。 代码ÿ…...

MongoDB 从部署到掌握
一、docker部署MongoDB ## 通过docker安装MongoDB~~~shell #拉取镜像 docker pull mongo:4.0.3#创建容器 docker create --name mongodb-server -p 27017:27017 -v mongodb-data:/data/db mongo:4.0.3 --auth#启动容器 docker start mongodb-server#进入容器 docker exec -it …...

electron-vite工具打包后通过内置配置文件动态修改接口地址实现方法
系列文章目录 electronvitevue3 快速入门教程 文章目录 系列文章目录前言一、实现过程二、代码演示1.resources/env.json2.App.vue3.main/index.js4.request.js5.安装后修改 前言 使用electron-vite 工具开发项目打包完后每次要改接口地址都要重新打包,对于多环境…...

每日一练2024.5.9
题目: 给定一副牌,每张牌上都写着一个整数。 此时,你需要选定一个数字 X,使我们可以将整副牌按下述规则分成 1 组或更多组: 每组都有 X 张牌。组内所有的牌上都写着相同的整数。 仅当你可选的 X > 2 时返回 tru…...

P2622 关灯问题
小小注解: 1. vis:表示到达该状态的步数(min)1, 因为我们是从开始状态 穷举,所以每次到一个新状态(之前没有到过的状态)就是最小步数。 如何判断是否是一个新状态呢,…...

从头开始的建材类电商小程序开发指南
在当今数字化时代,小程序已经成为了许多企业推广和销售的重要渠道。对于建筑材料行业来说,开发一个属于自己的小程序商城不仅可以提升产品曝光度,还可以提供更好的用户购物体验。下面,我们将逐步教你如何开发建筑材料行业小程序。…...

数据结构中的栈(C语言版)
一.栈的概念 栈是一种常见的数据结构,它遵循后进先出的原则。栈可以看作是一种容器,其中的元素按照一种特定的顺序进行插入和删除操作。 压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 出栈:栈的删除操作叫做…...

(贪心05) 无重叠区间 划分字母区间 合并区间
一、无重叠区间 力扣第435题 第一种方法: 个人思路: 按照区间左边界排序,然后从左开始遍历,每遍历到一个区间就要保证该区间之前的集合为不重叠区间(贪心,局部最优解)。 难点在于如何把新遍历…...

简单网络管理协议(SNMP)入门
目录 概述 SMI(对象命名、数据类型、编码方法) 对象命名 数据类型 编码方法 MIB(版本、分组、对象定义、变量访问) 版本 分组 对象定义 变量访问 SNMP 实现机制与报文分析 协议操作 报文格式 实现机制 验证分析 SN…...

leetcode解题思路分析(一百五十七)1366 - 1372 题
通过投票对团队排名 现在有一个特殊的排名系统,依据参赛团队在投票人心中的次序进行排名,每个投票者都需要按从高到低的顺序对参与排名的所有团队进行排位。 排名规则如下: 参赛团队的排名次序依照其所获「排位第一」的票的多少决定。如果存在…...

药物代谢动力学学习笔记
一、基本概念 二、经典房室模型 三、非线性药物代谢动力学 四、非房室模型 五、药代动力学与药效动力学 六、生物等效性评价 七、生物样品分析方法 基本概念 生物样品:生物机体的全血、血浆、血清、粪便、尿液或其他组织的样品 特异性,specificity&…...

IDEA中git的常用操作(保姆级教学)
IDEA中git的常用操作(保姆级教学) 以下是git的工作原理,觉得繁琐的可以跳过不看 Workspace:工作区 (平时存放代码的地方) Index / Stage:暂存区(用于临时存放存放你的改动,事实上就是一个文件&…...

保研面试408复习 3——操作系统
文章目录 1、操作系统一、进程有哪几种状态,状态之间的转换、二、调度策略a.处理机调度分为三级:b.调度算法 标记文字记忆,加粗文字注意,普通文字理解。 为什么越写越少? 问就是在打瓦。(bushi) 1、操作系统 一、进程…...

【代码随想录37期】Day02 有序数组的平方、长度最小的子数组、螺旋矩阵Ⅱ(施工中)
有序数组的平方 977. 有序数组的平方 - 力扣(LeetCode) v1.0:直接暴力 4分半做出来,用sort api class Solution { public:vector<int> sortedSquares(vector<int>& nums) {vector<int> result;for(int i 0; i<…...

通俗的理解网关的概念的用途(三):你的数据包是如何到达下一层的
其实,这一章我写不好,因为这其中会涉及到一些计算和一些广播等概念,本人不善于此项。在此略述,可以参考。 每台设备的不同连接在获得有效的IP地址后,会根据IP地址的规则和掩码的规则,在操作系统和交换机&a…...

基于Springboot的校运会管理系统(有报告)。Javaee项目,springboot项目。
演示视频: 基于Springboot的校运会管理系统(有报告)。Javaee项目,springboot项目。 项目介绍: 采用M(model)V(view)C(controller)三层体系结构&a…...

USP技术提升大语言模型的零样本学习能力
大语言模型(LLMs)在零样本和少样本学习能力上取得了显著进展,这通常通过上下文学习(in-context learning, ICL)和提示(prompting)来实现。然而,零样本性能通常较弱,因为缺…...

前端安全防护实战:XSS、CSRF防御与同源策略详解(react 案例)
前端安全防护实战中,主要涉及三个方面:XSS (Cross-Site Scripting) 攻击的防御、CSRF (Cross-Site Request Forgery) 攻击的防御,以及浏览器的同源策略。以下是这三个方面的详细说明: XSS 防御详解 XSS 概述 XSS攻击是一种让攻…...

2024C题生物质和煤共热解问题的研究 详细思路
背景 随着全球能源需求的不断增长和对可再生能源的追求,生物质和煤共热解作为一种潜在的能源转化技术备受关注。生物质是指可再生能源,源自植物和动物的有机物质,而煤则是一种化石燃料。** 在共热解过程中,生物质和煤在高温和缺氧…...

智慧旅游引领未来风尚,科技助力旅行更精彩:科技的力量推动旅游业创新发展,为旅行者带来更加便捷、高效和智能的旅行服务
目录 一、引言 二、智慧旅游的概念与特点 (一)智慧旅游的概念 (二)智慧旅游的特点 三、科技推动旅游业创新发展 (一)大数据技术的应用 (二)人工智能技术的应用 (…...