0 前言
学习视频:
【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 【精准空降到 00:34】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=32&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=34
参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》
1 队列集
1.1 创建队列集
函数原型如下:
QueueSetHandle_t xQueueCreateSet( const UBaseType_t uxEventQueueLength )
参数 | 说明 |
---|---|
uxQueueLength | 队列集长度,最多能存放多少个数据(队列句柄) |
返回值 | 非0:成功,返回句柄,以后使用句柄来操作队列NULL:失败,因为内存不足 |
1.2 把队列加入队列集
函数原型如下:
BaseType_t xQueueAddToSet( QueueSetMemberHandle_t xQueueOrSemaphore,
QueueSetHandle_t xQueueSet );
参数 | 说明 |
---|---|
xQueueOrSemaphore | 队列句柄,这个队列要加入队列集 |
xQueueSet | 队列集句柄 |
返回值 | pdTRUE:成功pdFALSE:失败 |
1.3 读取队列集
函数原型如下:
QueueSetMemberHandle_t xQueueSelectFromSet( QueueSetHandle_t xQueueSet,
TickType_t const xTicksToWait );
参数 | 说明 |
---|---|
xQueueSet | 队列集句柄 |
xTicksToWait | 如果队列集空则无法读出数据,可以让任务进入阻塞状态,xTicksToWait表示阻塞的最大时间(Tick Count)。如果被设为0,无法读出数据时函数会立刻返回;如果被设为portMAX_DELAY,则会一直阻塞直到有数据可写 |
返回值 | NULL:失败,队列句柄:成功 |
2 程序框架思路
2.1思路
来源:https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter11.html#_11-5-%E9%98%9F%E5%88%97%E9%9B%86
假设有2个输入设备:红外遥控器、旋转编码器,它们的驱动程序应该专注于“产生硬件数据”,不应该跟“业务有任何联系”。比如:红外遥控器驱动程序里,它只应该把键值记录下来、写入某个队列,它不应该把键值转换为游戏的控制键。在红外遥控器的驱动程序里,不应该有游戏相关的代码,这样,切换使用场景时,这个驱动程序还可以继续使用。
把红外遥控器的按键转换为游戏的控制键,应该在游戏的任务里实现。
假设我们增加一个MPU6050的输入,那就需要创建一个MPU6050的数据解析任务,每增加一个设备,就要增加这样的一个任务,如果很多设备,那就是很多任务,栈会不够用!怎么解决呢?
要支持多个输入设备时,我们需要实现一个“InputTask”,它读取各个设备的队列,得到数据后再分别转换为游戏的控制键。
这样操作好处就是,不管有多少设备,都只需要一个InputTask任务来读取队列,去处理数据
InputTask如何及时读取到多个队列的数据?要使用队列集。
- 轮询
- 队列集
2.2 轮询
读队列1,如果有数据就处理,读队列2,如果有数据就处理,读队列3,如果有数据就处理。
问题就来了!
当我读取队列1的时候,能否指定超时时间?
不可以指定超时时间,只能为0!
假设读取队列1时候没有数据,超时时间指定为30min,30min后没有数据,超时退出,才能读取队列2,队列3----这样导致读取队列2,队列3的时间被推迟,不够及时,使这个任务不断运行,一直没有阻塞状态,极大浪费CPU资源
2.3 队列集
队列集的本质也是队列,只不过里面存放的是队列句柄。使用过程如下:
- 创建队列A,它的长度是n1
- 创建队列B,它的长度是n2
- 创建队列集S,它的长度是“n1+n2”
- 把队列A、B加入队列集S
- 这样,写队列A的时候,会顺便把队列A的句柄写入队列集S
- 这样,写队列B的时候,会顺便把队列B的句柄写入队列集S
- InputTask先读取队列集S,它的返回值是一个队列句柄,这样就可以知道哪个队列有有数据了;然后InputTask再读取这个队列句柄得到数据。
有了这个队列集,我们在InputTask中的任务就简单了:
- 读队列集,得到队列句柄
- 读句柄,得到数据
- 处理数据,写入挡球板队列
思路就清晰明了了
3 示例: 使用队列集改善程序框架
本节代码为:15_queueset_game。