本文目标:学习与使用FreeRTOS中的任务参数。
按照本文的描述,应该可以跑通实验并举一反三。
先决条件:拥有C语言基础,装有编译和集成的开发环境,比如:Keil uVision5
使用外设:USART1、GPIO、I2C
创建3个优先级相同的PrintTask任务,在任务中,使用OLED显示任务的执行次数。
在创建任务时,通过xTaskCreate或xTaskCreateStatic函数的pvParameters参数,将数据作为指针传递给任务函数。任务函数可以通过其入口参数pvParameters来获取数据。这种方法适用于传递静态或全局变量,或者只需要传递一次的数据。在我的这个场景中,使用xTaskCreate的动态的创建任务,相关代码片段如下:
struct TaskPrintInfo {
uint8_t x;
uint8_t y;
char name[16];
};
static struct TaskPrintInfo g_Task1Info = {0, 0, "Task1"};
static struct TaskPrintInfo g_Task2Info = {0, 16, "Task2"};
static struct TaskPrintInfo g_Task3Info = {0, 32, "Task3"};
/* 使用同一个函数创建不同的任务 */
xTaskCreate(PrintTask, "task1", 128, &g_Task1Info, osPriorityNormal, NULL);
xTaskCreate(PrintTask, "task2", 128, &g_Task2Info, osPriorityNormal, NULL);
xTaskCreate(PrintTask, "task3", 128, &g_Task3Info, osPriorityNormal, NULL);
我这里使用一个TaskPrintInfo结构体来传入一个坐标值和一个字符串,我的这个PrintTask中,最深的栈只有96字节,我这里创建任务时使用128的任务栈,也就是512字节,绰绰有余,不必但是死机等问题。
void PrintTask(void *params)
{
struct TaskPrintInfo *pInfo = params;
uint32_t cnt = 0;
OLED_Init();
while (1)
{
/* 打印信息 */
if (g_LCDCanUse)
{
g_LCDCanUse = 0;
OLED_ShowString(pInfo->x,pInfo->y,pInfo->name,16);
OLED_ShowNum((pInfo->x + 8 * 6),pInfo->y,cnt++,4,16);
OLED_Refresh(); // 刷新屏幕
g_LCDCanUse = 1;
}
mdelay(500); // 必要的延迟给任务让出资源,不然别的任务没机会执行
}
}
源码中,也就简单的显示一些字符和运行任务的次数。使用这个g_LCDCanUse全局变量,来进行简单的保护,因为OLED屏在刷新的屏幕的时候会用到i2c,等一个任务使用完了,另一个任务接着使用,这是简单粗暴的使用,仅供学习参考。
下载代码到板子上,发现,Task3先进行刷新,接着Task1跟着刷新,Task2最后刷新,这是因为优先级相同的任务,最后创建的任务先运行,然后按创建的任务顺序执行,在源码中也有体现:
在OLED屏幕上显示了不同的次数,其中Task1执行的最多(图片这里执行了291次),其次是Task3(237次),最后是Task2(233次),所以本次实验成功,成功使用任务的参数进行了实验。
https://download.csdn.net/download/weixin_44317448/88614406