【FreeRTOS】队列集实验 MPU6050 更新中……

1 修改代码

1.1 创建队列A队列B

先删除红外部分

//    if (datas[2] == 0xe0) 删除红外部分,直接上报队列
//        idata.val = UPT_MOVE_LEFT;  //左移
//    else if (datas[2] == 0x90)
//        idata.val = UPT_MOVE_RIGHT; //右移
//    else
//        idata.val = UPT_MOVE_NONE;

定义一个结构体

struct ir_data {
	uint32_t dev;
	uint32_t val;
};

定义键值的宏

#define IR_KEY_POWER  0xa2
#define IR_KEY_MENU   0xe2
#define IR_KEY_TEST   0x22
#define IR_KEY_ADD    0x02
#define IR_KEY_RETURN 0xc2
#define IR_KEY_LEFT   0xe0
#define IR_KEY_PLAY   0xa8
#define IR_KEY_RIGHT  0x90
#define IR_KEY_0      0x68
#define IR_KEY_DEC    0x98
#define IR_KEY_C      0xb0
#define IR_KEY_1      0x30
#define IR_KEY_2      0x18
#define IR_KEY_3      0x7a
#define IR_KEY_4      0x10
#define IR_KEY_5      0x38
#define IR_KEY_6      0x5a
#define IR_KEY_7      0x42
#define IR_KEY_8      0x4a
#define IR_KEY_9      0x52
#define IR_KEY_REPEAT 0x00

修改解析数据的代码

static int IRReceiver_IRQTimes_Parse(void)
{
	uint64_t time;
	int i;
	int m, n;
	unsigned char datas[4];
	unsigned char data = 0;
	int bits = 0;
	int byte = 0;
	struct ir_data idata;   //修改成 ir_data

	/* 1. 判断前导码 : 9ms的低脉冲, 4.5ms高脉冲  */
	time = g_IRReceiverIRQ_Timers[1] - g_IRReceiverIRQ_Timers[0];
	if (time < 8000000 || time > 10000000)
	{
		return -1;
	}

	time = g_IRReceiverIRQ_Timers[2] - g_IRReceiverIRQ_Timers[1];
	if (time < 3500000 || time > 55000000)
	{
		return -1;
	}

	/* 2. 解析数据 */
	for (i = 0; i < 32; i++)
	{
		m = 3 + i*2;
		n = m+1;
		time = g_IRReceiverIRQ_Timers[n] - g_IRReceiverIRQ_Timers[m];
		data <<= 1;
		bits++;
		if (time > 1000000)
		{
			/* 得到了数据1 */
			data |= 1;
		}

		if (bits == 8)
		{
			datas[byte] = data;
			byte++;
			data = 0;
			bits = 0;
		}
	}

	/* 判断数据正误 */
	datas[1] = ~datas[1];
	datas[3] = ~datas[3];
	
	if ((datas[0] != datas[1]) || (datas[2] != datas[3]))
	{
        g_IRReceiverIRQ_Cnt = 0;
        return -1;
	}

	//PutKeyToBuf(datas[0]);    //写环形缓冲区
	//PutKeyToBuf(datas[2]);
    
    /* 写队列 */
    idata.dev = datas[0];
    idata.val = datas[2];
    
    xQueueSendToBackFromISR(g_xQueuePlatform, &idata, NULL);
    return 0;
}

在初始化时候,创建自己的队列

```c
void IRReceiver_Init(void)
{
    /* PA10在MX_GPIO_Init()中已经被配置为双边沿触发, 并使能了中断 */
#if 0
    /*Configure GPIO pin : PB10 */
    GPIO_InitStruct.Pin = GPIO_PIN_10;
    GPIO_InitStruct.Mode = GPIO_MODE_EVT_RISING_FALLING;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
#endif
    g_xQueueIR = xQueueCreate(10, sizeof(struct ir_data));	//创建队列
}

现在我们就实现了,解析出数据放到自己的队列里
在这里插入图片描述

1.2 创建队列集

在这里插入图片描述

static QueueHandle_t g_xQueueSetInput;  //输入设备的队列集

#define IR_QUEUE_LEN 10     	//队列长度
#define ROTARY_QUEUE_LEN 10     //队列长度

g_xQueueSetInput = xQueueCreateSet(IR_QUEUE_LEN + ROTARY_QUEUE_LEN);   //创建队列集

创建队列集之后,将队列加入队列集

	/* 创建队列,队列集,输入任务 InputTask */
	g_xQueuePlatform = xQueueCreate(10, sizeof(struct input_data)); // 动态创建
    g_xQueueSetInput = xQueueCreateSet(IR_QUEUE_LEN + ROTARY_QUEUE_LEN);   //创建队列集
    
    g_xQueueIR = GetQueueIR();          //获取这两个全局变量,句柄
    g_xQueueRotary = GetQueueRotary();
    
    xQueueAddToSet(g_xQueueIR, g_xQueueSetInput);       // g_xQueueIR 加入队列集
    xQueueAddToSet(g_xQueueRotary, g_xQueueSetInput);   // g_xQueueRotary 加入队列集

    /* 创建 InputTask 的任务 */
    xTaskCreate(InputTask, "InputTask", 128, NULL, osPriorityNormal, NULL);

1.3 InputTask

我们要实现一个框架,底层都写自己的队列,在InputTask读队列集,根据不同队列句柄,分别调用不同的处理函数,处理函数里,都会把原始的硬件数据,转换成游戏的控制数据,写入队列,写入队列之后,挡球板的任务就可以读到数据,就实现控制挡球板了。

在这里插入图片描述

函数的任务

  1. 读队列集,得到有数据的队列句柄
  2. 读队列句柄得到数据
  3. 处理红外/旋转编码器/…数据
  4. 写挡球板队列

编写这个函数:

/**********************************************************************
 * 函数名称: InputTask
 * 功能描述: 输入任务,检测多个输入设备并调用对应处理函数
 * 输入参数: params - 未使用
 * 输出参数: 无
 * 返 回 值: 无
 * 修改日期:      版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2024/08/20	     V1.0	  LoongFly	      创建
 ***********************************************************************/
static void InputTask(void *params)
{
    QueueSetMemberHandle_t xQueueHandle;    // 队列集
    
    while(1)
    {
        /* 1.读队列集,得到有数据的队列句柄 */
        xQueueHandle = xQueueSelectFromSet(g_xQueueSetInput, portMAX_DELAY); // portMAX_DELAY得不到数据就一直等待
        
        if (xQueueHandle)   // 如果读到了句柄
        {
            /* 2.读队列句柄得到数据 */
            if (xQueueHandle == g_xQueueIR)             //红外的句柄
            {
                /* 3.处理红外数据 */
                ProcessIRData();
            }
            else if (xQueueHandle == g_xQueueRotary)    //旋转编码器的句柄
            {
                /* 3.处理旋转编码器数据 */
                ProcessRotaryData();
            }
            /* 4.写挡球板队列 在函数里实现了*/
        }
    }
}

1.3.1 ProcessIRData 解析红外数据

/**********************************************************************
 * 函数名称: ProcessIRData
 * 功能描述: 读取红外遥控器键值并转换为游戏控制键,写入挡球板队列
 * 输入参数: 无
 * 输出参数: 无
 * 返 回 值: 无
 * 修改日期:      版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2024/08/20	     V1.0	  LoongFly	      创建
 ***********************************************************************/
static void ProcessIRData(void)
{
    struct ir_data irdata;
    static struct input_data input;
    
    xQueueReceive(g_xQueueIR, &irdata, 0);  //读队列,不阻塞
    
    if (irdata.val == IR_KEY_LEFT)              //左移
    {
        input.dev = irdata.dev;
        input.val = UPT_MOVE_LEFT;
    }
    else if (irdata.val == IR_KEY_RIGHT)        //右移
    {
        input.dev = irdata.dev;
        input.val = UPT_MOVE_RIGHT;
    }
    else if (irdata.val == IR_KEY_REPEAT)       //重复码
    {
        ;   //保持不变
    }
    else
    {
        input.dev = irdata.dev;
        input.val = UPT_MOVE_NONE;
    }
    /* 写挡球板队列 */
    xQueueSend(g_xQueuePlatform, &input, 0);
}

1.3.2 ProcessRotaryData 解析旋转编码器数据

/**********************************************************************
 * 函数名称: ProcessRotaryData
 * 功能描述: 读取旋转编码器数据并转换为游戏控制键,写入挡球板队列
 * 输入参数: 无
 * 输出参数: 无
 * 返 回 值: 无
 * 修改日期:      版本号     修改人	      修改内容
 * -----------------------------------------------
 * 2024/08/20	     V1.0	  LoongFly	      创建
 ***********************************************************************/
static void ProcessRotaryData(void)
{
    struct rotary_data rdata;
	struct input_data idata;
	int left;
	int i, cnt;
    
    /* 1.读取旋转编码器队列 */
    xQueueReceive(g_xQueueRotary,&rdata, 0);    //读到的数据保存到rdata结构体里,无需等待
    
    /* 2.处理队列 */
    /* 判断速度: 负数表示向左转动, 正数表示向右转动 */
    if (rdata.speed < 0)
    {
        left = 1;
        rdata.speed = 0 - rdata.speed;
    }
    else
    {
        left = 0;
    }

    if (rdata.speed > 50)
        cnt = 5;
    else if (rdata.speed > 40)
         cnt = 4;
    else if (rdata.speed > 30)
         cnt = 3;
    else if (rdata.speed > 20)
        cnt = 2;
    else
        cnt = 1;

    /* 3.写入挡球板队列 */
    idata.dev = 1;
    idata.val = left ? UPT_MOVE_RIGHT : UPT_MOVE_LEFT;      //+++++++++++++++++++++++
    for (i = 0; i < cnt; i ++)  //速度快就多写几遍
    {
        xQueueSend(g_xQueuePlatform, &idata, 0);    //这里要么成功\要么失败,不能阻塞
    }
}

包含需要的头文件,最后会报错
在这里插入图片描述

01_freertos_template\01_freertos_template.axf: Error: L6218E: Undefined symbol xQueueAddToSet (referred from game1.o).
01_freertos_template\01_freertos_template.axf: Error: L6218E: Undefined symbol xQueueCreateSet (referred from game1.o).
01_freertos_template\01_freertos_template.axf: Error: L6218E: Undefined symbol xQueueSelectFromSet (referred from game1.o).
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.

我们在15_queueset_game\Core\Inc\FreeRTOSConfig.h加一句

#define configUSE_QUEUE_SETS 1	//使用队列集

烧写程序之后,挡球板不见了

在这里插入图片描述

这里是内存不够用了

在这里插入图片描述
配置8000

在这里插入图片描述
我们现在就实现了用队列集改进程序框架

在这里插入图片描述

  • 8
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

北国无红豆

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值