0 前言
学习视频:
【FreeRTOS入门与工程实践 --由浅入深带你学习FreeRTOS(FreeRTOS教程 基于STM32,以实际项目为导向)】 【精准空降到 03:20】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=33&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=200
参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》
https://rtos.100ask.net/zh/FreeRTOS/DShanMCU-F103/chapter11.html
1 任务
1.1 本节源码
在"03_参考的源码/DshanMCU-F103/02_nwatch_game_freertos.7z"的基础上
- “14_queue_game_multi_input”: 在"13_queue_game"的基础上,增加旋转编码控制功能
1.2实验目的
使用红外遥控器、旋转编码器玩游戏。
1.3实现方案
- 游戏任务:读取队列A获得控制信息,用来控制游戏
- 红外遥控器驱动:在中断函数里解析出按键后,写队列A
- 旋转编码器:
- 它的中断函数里解析出旋转编码器的状态,写队列B;
- 它的任务函数里,读取队列B,构造好数据后写队列A
2 code
2.1 创建队列
在game1.c的void game1_task(void *params)中添加
/* 创建队列:平台任务从里面读到旋转编码器数据,... */
g_xQueueRotary = xQueueCreateStatic(
10, // 长度 10 随意给的
sizeof(struct rotary_data), // 大小
g_ucQueueRotaryBuf, // 保存数据的buffer
&g_xQueueRotaryStaticStruct // 结构体的地址
);// 静态创建
定义结构体
struct rotary_data {
int32_t cnt; //设备
int32_t speed; //值
uint8_t dir; //方向
};
定义队列
QueueHandle_t g_xQueueRotary; /* 旋转编码器队列 */
static uint8_t g_ucQueueRotaryBuf[10*sizeof(struct rotary_data)]; //存放10个rotary_data结构体这么大小的buf
static StaticQueue_t g_xQueueRotaryStaticStruct; //队列的结构体
后面还需要创建旋转编码器的任务,这个任务就读取本队列,处理数据,再写队列
2.2 写队列
在旋转编码器的中断服务函数里写队列,写哪个队列? >>> g_xQueueRotary
在14_queue_game_multi_input\Drivers\DshanMCU-F103\driver_rotary_encoder.c路径下写
先添加头文件
#include "FreeRTOS.h"
#include "queue.h"
#include "typedefs.h"
再外部声明这个队列
extern QueueHandle_t g_xQueueRotary; /* 旋转编码器队列 */
在中断回调函数添加写队列的代码,后面注释了很多加号的就是新增的部分
/**********************************************************************
* 函数名称: RotaryEncoder_IRQ_Callback
* 功能描述: 旋转编码器的中断回调函数
* 输入参数: 无
* 输出参数: 无
* 返 回 值: 无
* 修改日期: 版本号 修改人 修改内容
* -----------------------------------------------
* 2023/08/04 V1.0 韦东山 创建
***********************************************************************/
void RotaryEncoder_IRQ_Callback(void)
{
uint64_t time;
static uint64_t pre_time = 0;
struct rotary_data rdata; //定义这个结构体++++++++++++++++++++++++++++++++++++++++++++++
/* 1. 记录中断发生的时刻 */
time = system_get_ns();
/* 上升沿触发: 必定是高电平
* 防抖
*/
mdelay(2);
if (!RotaryEncoder_Get_S1())
return;
/* S1上升沿触发中断
* S2为0表示逆时针转, 为1表示顺时针转
*/
g_speed = (uint64_t)1000000000/(time - pre_time);
if (RotaryEncoder_Get_S2())
{
g_count++;
}
else
{