[8-2-3] 队列实验_多设备玩游戏(旋转编码器)_重录

[8-2-3] 队列实验_多设备玩游戏(旋转编码器)_重录

在这节课中,我们将修改第十三个程序,增加旋转编码器控制的功能,使得你既可以用红外遥控器,也可以使用旋转编码器来控制游戏。旋转编码器可以提供比红外遥控器更快速的响应,因此它能够让游戏操作更流畅。我们将一步步讲解如何将旋转编码器添加到程序中,并通过队列优化数据传输。

1. 游戏控制的背景

之前的程序中,我们使用红外遥控器控制挡球板的左右移动,但响应较慢。为了提高游戏的控制精度,我们决定引入旋转编码器,旋转编码器通过旋转的速度来控制挡球板的移动。这个改进不仅使游戏操作更加精准,也避免了红外遥控器响应速度较慢的问题。

1.1 原始程序结构

原始的程序中,红外遥控器的数据通过一个队列传输到控制挡球板的任务。任务会根据队列中的数据来调整挡球板的位置。我们将在这个程序的基础上进行改造,加入旋转编码器的支持。

1.2 问题分析

  • 响应速度:红外遥控器的响应速度较慢,导致挡球板的控制不够流畅。
  • 精度问题:旋转编码器能够提供精确的速度控制,使得游戏操作更加精确。

2. 修改中断服务程序:写队列B

我们首先要修改旋转编码器的中断服务程序,将旋转编码器的数据写入队列B。这样,我们就能够通过队列将旋转编码器的数据传输到控制挡球板的任务。

2.1 创建旋转编码器的数据结构

为了存储旋转编码器的数据,我们定义了一个结构体,包含当前的旋转方向(增大或减小)和旋转速度。

typedef struct {
    int count;  // 当前旋转的计数,增加或减少
    int speed;  // 旋转速度
} EncoderData;

EncoderData encoderBuffer[10];  // 数据缓冲区

2.2 创建队列

接着,我们创建一个队列来存放旋转编码器的数据,方便后续任务读取和处理。

xQueueHandle encoderQueue;
encoderQueue = xQueueCreate(10, sizeof(EncoderData));  // 创建旋转编码器的队列

2.3 中断服务程序

在旋转编码器的中断服务程序中,我们读取旋转编码器的速度数据,并将其写入队列B。

void Encoder_ISR() {
    EncoderData data;
    data.count = read_encoder_count();
    data.speed = read_encoder_speed();
    xQueueSend(encoderQueue, &data, portMAX_DELAY);  // 写入队列B
}

3. 旋转编码器任务:读取队列B并处理数据

接下来,我们需要创建一个任务,读取队列B中的旋转编码器数据,并根据旋转编码器的速度调整挡球板的位置。

3.1 创建旋转编码器任务

旋转编码器的任务将从队列B读取数据,并根据速度来调整挡球板的移动。如果旋转编码器的速度较快,挡球板移动幅度更大,反之则移动幅度较小。

void encoder_task(void *pvParameters) {
    EncoderData data;
    while (1) {
        if (xQueueReceive(encoderQueue, &data, portMAX_DELAY)) {
            int move_count = data.speed / 10;  // 根据速度计算挡球板移动次数
            for (int i = 0; i < move_count; i++) {
                move_paddle(data.count > 0 ? 1 : -1);  // 根据旋转方向调整挡球板
            }
        }
    }
}

3.2 队列的阻塞与唤醒机制

通过使用队列,旋转编码器任务在读取数据时能够自动阻塞,直到队列中有新的数据可供读取。这种机制有效避免了CPU资源的浪费,提升了系统效率。

4. 数据处理:红外遥控器与旋转编码器的协同

红外遥控器和旋转编码器需要通过队列来协同工作。在此,我们分别处理两种输入设备的数据,并转换为控制挡球板的指令。通过将每个输入设备的数据格式统一,我们可以有效避免数据混淆。

4.1 数据转换:红外遥控器与旋转编码器的数据格式

我们首先需要转换红外遥控器和旋转编码器的输入数据,使得它们能够被统一处理。具体来说,我们把红外遥控器的数据(如左键和右键)转换为一个统一的控制格式,旋转编码器的数据则根据速度计算出控制幅度。

typedef struct {
    int value;  // 用于表示左、右或其他动作
} PaddleControl;

PaddleControl controlData;

4.2 将数据写入队列A

红外遥控器和旋转编码器的数据都会写入队列A,控制任务从队列A中读取数据并执行相应的动作。

xQueueSend(queueA, &controlData, portMAX_DELAY);  // 写入队列A

5. 改进后的程序效果

通过引入旋转编码器,游戏的控制变得更加精准和流畅。用户可以通过旋转编码器快速而精确地调整挡球板的位置,而不再依赖于反应较慢的红外遥控器。

5.1 流畅的控制

旋转编码器的控制响应速度更快,使得玩家可以根据需要快速或慢速地调整挡球板的位置,提升了游戏体验。

5.2 队列的优化

通过使用队列,我们避免了原始环形缓冲区的低效操作,确保了数据传输的同步性和高效性。队列的阻塞与唤醒机制有效地减少了CPU资源浪费,同时保证了任务间的协调。

6. 总结

通过引入旋转编码器并结合队列来优化游戏控制,我们成功提升了游戏的互动性和流畅度。旋转编码器通过提供更高精度和更快速的响应,使得玩家在控制挡球板时获得了更好的体验。同时,队列的使用使得数据传输更加高效,避免了原环形缓冲区中的一些问题。

希望通过这篇博客,你能够理解如何使用队列与旋转编码器优化嵌入式系统中的多设备协作,并为你的项目提供更高效的解决方案。

你可能感兴趣的:(玩游戏,网络)