例子:创建一个任务,并在任务里面翻转LED 灯
1. 函数原型
BaseType_t xTaskCreate(TaskFunction_t pxTaskCode,const char * const pcName,const uint16_t usStackDepth,void * const pvParameters,UBaseType_t uxPriority,TaskHandle_t * const pxCreatedTask ) /*lint !e971 Unqualified char types are allowed for strings and single characters only. */
“ lint !e971 Unqualified char types are allowed for strings and single characters only” 告诉编译器在编译的时候不要报警告,这里把char类型和字符串类型混用了,编译器你不要报警告
1.1 参数1: pxTaskCode,创建的任务函数名,类似中断服务服务函数入口,函数的入口地址
1.2 参数2:pcName,也是创建的任务函数名称,只不过这个是没有实际意义的,只是方便记住创建的函数叫什么名字,FreeRTOS不会调用这个东东的,名称可随意写,长度有限制, configMAX_TASK_NAME_LEN 定义了名称的长度,包括 \0 字符,超过会自动截断
FreeRTOSConfig.h
#define configMAX_TASK_NAME_LEN (16)
1.3 参数3:usStackDepth,栈大小,每创建一个任务,系统就会为该任务分配一块内存(堆栈),单位是字(word),而不是字节(Byte),在32位机中 (STM32xx), 1 word = 4Byte,分配的空间就是stackSize = usStackDepth * 4,默认最小栈大小 configMINIMAL_STACK_SIZE
FreeRTOSConfig.h
#define configMINIMAL_STACK_SIZE ((unsigned short)130)
具体大小需要自己调试
1.4 pvParameters,创建的任务的实参,创建任务的时候,给他传进来的参数,万能指针 void *
1.5 uxPriority,任务的优先级
FreeRTOSConfig.h
#define configMAX_PRIORITIES (32)
优先级必须比这个宏要小,数字越小,优先级越高
configMAX_PRIORITIES 宏大小可随意,但最好使用实际需要的最小数值以避免内存浪费
如果优先级设置的比configMAX_PRIORITIES 大,会将优先级自动设置为最大优先级configMAX_PRIORITIES
1.6 pxCreatedTask 创建的任务的句柄,跟第一个参数类似,操作这个句柄就相当于操作这个任务,可以通过句柄改变任务的优先级、删除任务等,如果不需要使用句柄,就设为NULL
1.7 返回值
1.7.1 pdPASS,创建任务成功
1.7.2 errCOULD_NOT_ALLOCATE_REQUIRED_MEMORY, 内存堆空间不够,创建任务失败,也有可能是堆内存碎片化导致创建失败
2. 创建任务
// create task2
void vTask2( void *pvParameters )
{ // each task must be a endless loopfor( ;; ) { printf("task2 say: hello world");}
}// create task1
void vTask1( void *pvParameters )
{ // each task must be a endless loop, otherwise, the program will crashfor (;;) { printf("task1 say: hello world1");}
} int main( void )
{ // create task1xTaskCreate(vTask1, // create task1"Task 1", // task name128, // stack sizeNULL, // the task has no parameter1, // task priorityNULL ); // task handle // creat task2xTaskCreate(vTask2, // create task2"Task 2", // task name128, // stack sizeNULL,// the task has no parameter2, // task priority, the task priority can not be same as other task priorityNULL ); // The system start to schedulervTaskStartScheduler(); // the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idlefor (;;){}
}
3. 两个任务按照时间片轮转方式运行,系统调度,轮流来,一人一口饭,你一口,我一口
3. 在任务里面创建任务,创建任务1,然后在任务1 里面创建任务2
// create task2
void vTask2( void *pvParameters )
{ // each task must be a endless loopfor( ;; ) { printf("task2 say: hello world");}
}// create task1
void vTask1( void *pvParameters )
{ // creat task2xTaskCreate(vTask2, // create task2"Task 2", // task name128, // stack sizeNULL,// the task has no parameter2, // task priority, the task priority can not be same as other task priorityNULL ); // each task must be a endless loop, otherwise, the program will crashfor (;;) { printf("task1 say: hello world1");}
} int main( void )
{ // create task1xTaskCreate(vTask1, // create task1"Task 1", // task name128, // stack sizeNULL, // the task has no parameter1, // task priorityNULL ); // task handle // The system start to schedulervTaskStartScheduler(); // the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idlefor (;;){}
}
4. 使用任务参数,创建任务的同时传递一个参数进任务里面 vTaskFunction
// create task2
void vTask2(void *pvParameters)
{ char *pcTaskName;// (void *) forced conversion to string (char *)pcTaskName = (char *)pvParameters;// each task must be a endless loopfor( ;; ) { printf("task2, %s", pcTaskName );}
}// create task1
void vTask1( void *pvParameters )
{ char *pcTaskName;pcTaskName = (char *)pvParameters;// each task must be a endless loop, otherwise, the program will crashfor (;;) { printf("task1, %s", pcTaskName );}
} int main( void )
{ // create task1xTaskCreate(vTaskFunction, // create task1"Task 1", // task name128, // stack size“hello world”, // pass parameters to task11, // task priorityNULL); // task handle // creat task2xTaskCreate(vTaskFunction, // create task2"Task 2", // task name128, // stack size“hello world”, // pass parameters to task22, // task priority, the task priority can not be same as other task priorityNULL); // The system start to schedulervTaskStartScheduler(); // the program will not run here if there are no issues with the program, but if executed here, it is likely the memory heap space is insufficient resulting in idlefor (;;){}
}
与上面的第 2 步类似,只是在创建任务的同时传了一个字符串进任务里面了,然后在任务里面接收这个字符串,并打印出来
看起来写了一堆,很复杂,其实很简单,就一个函数调用,会使用就行了,调用函数的时候知道每个参数怎么填,怎么根据返回值判断创建结果就可以了
5. 在main 函数里面创建第一个任务
6. 在任务里面创建任务,理论上可以创建无数个,具体看系统,用的哪个操作系统,用的什么硬件平台,硬件资源够不够,内存够不够等等
7. 在任务的死循环里面执行任务操作,这个任务需要干些啥事都放在死循环里面写,死循环里面执行任务需要干的事,死循环前面基本都是一些初始化操作,STM32xx
8. 在死循环里面翻转LED灯,执行一遍该任务,LED1就会翻转一次,亮到灭到亮,反复亮灭