任务B:
任务A中,LED端口15毫秒翻转一次
任务B中,LED端口10毫秒翻转一次
*注意:Delay_MS()是一个自定义的函数,用来模拟任务中处理其他东西浪费了5ms。
两个任务都是 TaskDelay(10毫秒) ,但是任务A中使用vTaskDelay(),在任务B中使用vTaskDelayUntil()。
在任务A中:vTaskDelay()是从调用的那一刻开始算,那么这个任务本身在Delay_MS中占用了5MS,LED翻转的时间忽略不计,那么加上vTaskDelay()的10MS,就是15MS。
在任务B中:vTaskDelayUntil()和任务本身执行时间无关,只要任务每次循环执行的总时间少于10ms,那么这个任务就是10ms执行一次了。
最后提一下xTaskAbortDelay()这个函数,根据描述,他能让正在阻塞状态等待延时的函数马上切出,进入就绪状态。但由于我的库版本比较旧,没有这个函数,所以就不作更多的介绍了。
四、开启调度器 4.1、函数简介:这个函数作用是开启调度器,调用这个函数后任务就会开始执行。所以在整个程序中只需要调用一次,一般在main函数中调用就可以了。开启成功的话,系统由调度器接管了,main函数中vTaskStartScheduler()后面的代码都不会被执行。
4.2、使用简介:官方的例子:
创建任务
开启调度器,开启后程序会跳转到vATask()任务中
五、任务的挂起和恢复 5.1、vTaskSuspend() 和 vTaskResume() 5.1.1、函数简介:
挂起/解除挂起单个任务:
vTaskSuspend的函数是让指定的任务进入挂起状态
xTaskResume的函数是让指定的任务从挂起状态换为就绪状态。
xTaskResumeFromISR()是xTaskResume()适合在中断中调用的版本
5.1.2、使用简介
使用很简单,当不需要用某个任务的时候用vTaskResume(句柄) 把那个任务挂起,需要用的时候再打开就行了,下面是官方的例程,实现了这三步:
使用xTaskCreate()创建任务
创建成功的话使用vTaskSuspend()把刚刚创建的任务转换为挂起状态(该任务将不会再得到执行)
使用vTaskResume()让刚刚挂起的任务转为就绪状态
5.2、vTaskSuspendAll()和vTaskResumeAll() 5.2.1、函数简介:
vTaskSuspendAll()挂起调度器 对应 xTaskResumeAll()解除挂起调度器:
• vTaskSuspendAll()挂起调度器后,只有当前任务在继续执行,不会发生任务切换了。
• xTaskResumeAll()对应vTaskSuspendAll()恢复调度器。
这个函数的作用之一在于,可以保证一些不能被分的程序执行,因为挂起调度器保证了不会被高优先级的任务强调(注意调度器挂起后中断还是可以运行的,如果要保证时效,还得把中断关闭)
注意:vTaskSuspendAll()是可以递归调用的,这意味着调用了多少次vTaskSuspendAll(),就必须有多少此vTaskResumeAll()的调用才能让调度器恢复。这个情况以下的例子中很好地体现了。
5.2.2、使用简介
在任务vTask1中第一此调用vTaskSuspendAll(),此时调度器被挂起,不会发生任务切换
调用另一个用作例子的vDemoFunction()
第二次调用vTaskSuspendAll(),此时调度器再次被挂起,而且挂起计数增加到2
第一次调用vTaskResumeAll(),此时调度器挂起计数减少为1,但是调度器仍然处于挂起状态
第二次调用vTaskResumeAll(),调度器计数为0,调度器恢复运行,后面会发生任务切换了