【FreeRTOS】事件组实验-改进姿态控制

news2024/11/15 14:06:54

目录

  • 0 前言
  • 1 事件组实验_改进姿态控制
  • 2 改进思路
    • 2.1 创建事件
    • 2.2 等待事件
    • 2.3 设置事件
    • 2.4 Debug
    • 2.5 设置MPU6050寄存器
  • 3 总结


0 前言

学习视频:
【FreeRTOS 入门与工程实践 --由浅入深带你学习 FreeRTOS(FreeRTOS 教程 基于 STM32,以实际项目为导向)】 【精准空降到 00:28】 https://www.bilibili.com/video/BV1Jw411i7Fz/?p=43&share_source=copy_web&vd_source=8af85e60c2df9af1f0fd23935753a933&t=28

参考《FreeRTOS 入门与工程实践(基于 DshanMCU-103).pdf》

  • 《第 10 章 同步互斥与通信》
  • 《第 14 章 事件组(event group)》

1 事件组实验_改进姿态控制

本节源码:在"25_eventgroup_and"的基础上,改出:26_eventgroup_mpu6050

2 改进思路

以前的程序框图

在这里插入图片描述

  • 这里的思路不是使用中断来操作MPU6050,我们是创建了一个任务,读取I2C,但是读取I2C这个操作很耗时间,就需要放到任务里去完成,这没有问题的
  • 那我们怎么样让这个任务及时获得我们摇晃的动作呢?
  • 我们用的是vTaskDelay,使其50ms

改进思路如下:

  • 我们可以使用中断,在中断里唤醒任务,在任务里读取I2C,读到数据之后再写队列,把数据写到队列3去,这里会同时写队列集,这个InputTask就会获得队列3的句柄,然后读取队列3得到摇晃的数据,最后去控制游戏。
  • 现在我们需要增加一个中断在中断里怎么唤醒任务?
  • 我们可以用事件组来唤醒:在中断里设置事件,在读I2C之前等待事件(读不到事件就一直阻塞)

这样和之前的程序相比较,现在就少了很多无谓的操作了

在这里插入图片描述

2.1 创建事件

static EventGroupHandle_t g_xEventMPU6050;  //定义MPU6050事件


/* 然后再到MPU6050_Init创建事件 */
int MPU6050_Init(void)
{
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_1, 0x00);	//解除休眠状态
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteRegister(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteRegister(MPU6050_CONFIG, 0x06);
	MPU6050_WriteRegister(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteRegister(MPU6050_ACCEL_CONFIG, 0x18);

	g_xQueueMPU6050 = xQueueCreate(MPU6050_QUEUE_LEN, sizeof(struct mpu6050_data));
	g_xEventMPU6050 = xEventGroupCreate();	
	return 0;
}

2.2 等待事件

然后在任务里等待事件

void MPU6050_Task(void *params)
{	
    int16_t AccX;
	struct mpu6050_data result;
	int ret;

    extern void GetI2C(void);
    extern void PutI2C(void);
    while (1)
    {    
        
        /* 等待事件 */
        /* 等待bit0 and bit1事件 */
        xEventGroupWaitBits(g_xEventMPU6050, (1<<0),    // 等待bit0 and bit1事件
                            pdTRUE,                 //  pdTRUE: 清除uxBitsToWaitFor指定的位
                            pdTRUE,                 // 都为1才可以 
                            portMAX_DELAY);         // 一定等到成功才返回
        
		/* 读数据 */
        
        GetI2C();   // 使用LCD之前,先获得互斥量。会一直等待
        ret = MPU6050_ReadData(&AccX, NULL, NULL, NULL, NULL, NULL);
        PutI2C();   // 使用LCD之后,再释放互斥量
		
        if (0 == ret)
		{
			/* 解析数据 */
			MPU6050_ParseData(AccX, 0, 0, 0, 0, 0, &result);

			/* 写队列 */
			xQueueSend(g_xQueueMPU6050, &result, 0);
		}
		
		/* delay */
		vTaskDelay(50);
	}
}


加入必要的头文件

#include "FreeRTOS.h"                   // ARM.FreeRTOS::RTOS:Core
#include "task.h"                       // ARM.FreeRTOS::RTOS:Core
#include "event_groups.h"               // ARM.FreeRTOS::RTOS:Event Groups

2.3 设置事件

在这里插入图片描述
根据原理图,我们使用PB5的外部中断用来触发,设置事件。

MPU6050的INT引脚是外部中断引脚,触发中断是高电平信号,INT引脚静息状态为低电平。所以这里我们配置上升沿触发,上拉输入

在这里插入图片描述

在这里插入图片描述

void EXTI9_5_IRQHandler(void)
{
    /* 设置事件组:bit0 */
    xEventGroupSetBits(g_xEventMPU6050, (1<<0));
}

2.4 Debug

编译下载程序,发现不能运行,我们先来检查是否使能了中断,再检查是否进入了中断,打开CubeMX发现确实没使能中断,

在这里插入图片描述
然后就报错了,说我们重复定义了

01_freertos_template\01_freertos_template.axf:
 Error: L6200E: Symbol EXTI9_5_IRQHandler multiply defined 
 (by driver_mpu6050.o and stm32f1xx_it.o).

然后编写MPU6050的设置事件组的代码

void MPU6050_Callback(void)
{
    /* 设置事件组:bit0 */
    xEventGroupSetBitsFromISR(g_xEventMPU6050, (1<<0), NULL);   //在中断里设置事件
}

声明这个文件,并且在中断回调函数里添加 case GPIO_PIN_5的情况!

extern void MPU6050_Callback(void);


void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    switch (GPIO_Pin)
    {
        case GPIO_PIN_5:
        {
            MPU6050_Callback();
            break;
        }
        case GPIO_PIN_10:
        {
            IRReceiver_IRQ_Callback();
            break;
        }

        case GPIO_PIN_12:
        {
            RotaryEncoder_IRQ_Callback();
            break;
        }

        default:
        {
            break;
        }
    }
}

2.5 设置MPU6050寄存器

设置寄存器,做初始化工作:配置中断引脚使能中断

#define	MPU6050_INT_PIN_CFG		0x37    //引脚配置
#define	MPU6050_INT_ENABLE		0x38    //中断使能

int MPU6050_Init(void)
{
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_1, 0x00);	//解除休眠状态
	MPU6050_WriteRegister(MPU6050_PWR_MGMT_2, 0x00);
	MPU6050_WriteRegister(MPU6050_SMPLRT_DIV, 0x09);
	MPU6050_WriteRegister(MPU6050_CONFIG, 0x06);
	MPU6050_WriteRegister(MPU6050_GYRO_CONFIG, 0x18);
	MPU6050_WriteRegister(MPU6050_ACCEL_CONFIG, 0x18);
    
    /* 配置中断引脚 */
    MPU6050_WriteRegister(MPU6050_INT_PIN_CFG, 0);
    /* 使能中断 */
    MPU6050_WriteRegister(MPU6050_INT_ENABLE, 0xFF);

	g_xQueueMPU6050 = xQueueCreate(MPU6050_QUEUE_LEN, sizeof(struct mpu6050_data));
	g_xEventMPU6050 = xEventGroupCreate();	//创建事件
	return 0;
}

烧录程序,现在就能正常运行了,但是运行的特别快,我们在MPU6050_Task的最后取消注释vTaskDelay(50);
现在就很丝滑了

3 总结

我们实现了在中断里使用事件组改造这个程序,这个任务只有当中断写了事件之后,得到了事件,才会读取I2C,避免了一直读取I2C的数据,节省资源。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2108207.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pdf文件怎么编辑?6个pdf编辑方法学起来(图文教程)

pdf文件怎么编辑&#xff1f;现今的互联网时代&#xff0c;我们的办公也趋向于数字化办公。PDF文件已经成为我们日常工作和学习中不可或缺的格式文件。然而&#xff0c;编辑PDF文档不是一件容易的事。很多人会因为编辑pdf文档感到非常苦恼&#xff0c;尤其是当需要对PDF进行内容…

Linux内核编程(十五)网络设备驱动

本文目录 一、常见的网络协议二、传输介质三、RJ-45接口 对于网络知识不太熟悉的同学可以查看这篇文章&#xff1a;计算机网络知识点详情总结。 一、常见的网络协议 TCP、UDP协议&#xff1a;详情查看-TCP、UDP系统编程。DNS协议&#xff1a;是互联网中用于将域名&#xff08…

【刷题笔记】删除并获取最大点数粉刷房子

欢迎来到 破晓的历程的 博客 ⛺️不负时光&#xff0c;不负己✈️ 题目一 题目链接&#xff1a;删除并获取最大点数 思路&#xff1a; 预处理状态表示 状态转移方程 代码如下&#xff1a; class Solution { public:int deleteAndEarn(vector<int>& nums) {int N1…

八股(7)——Redis

八股&#xff08;7&#xff09;——Redis 4.3 RedisRedis 基础简单介绍一下 Redis!分布式缓存常见的技术选型方案有哪些&#xff1f;说一下 Redis 和 Memcached 的区别和共同点缓存数据的处理流程是怎样的&#xff1f;为什么要用 Redis/为什么要用缓存&#xff1f;Redis 除了做…

2024 年全国大学生数学建模竞赛(国赛)浅析

需要完整资料&#xff0c;请关注WX&#xff1a;“小何数模”&#xff01; &#xff08;需要完整B、C和E题资料请关注WX&#xff1a;“小何数模”&#xff0c;获取资料链接&#xff01;&#xff09; 本次万众瞩目的全国大学生数学建模赛题已正式出炉&#xff0c;无论是赛题难度…

Floorp Browser:开源自由,打造更个性化的浏览环境!

前言 "技术引领未来&#xff0c;创新改变世界。" 在这个日新月异的数字化时代&#xff0c;网络浏览器作为我们探索互联网世界的窗口&#xff0c;其重要性不言而喻。正是在这样的背景下&#xff0c;Floorp浏览器应运而生&#xff0c;它不仅继承了Mozilla Firefox的强…

基于SpringBoot的外卖点餐系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringBootJSP 工具&#xff1a;IDEA/Eclipse、Navicat、Maven、Tomcat 系统展示 首页 用户管理界…

超强台风“摩羯”来临:EasyCVR平台如何汇聚城市视频资源,构建应急监测网

一、背景概述 2024年第11号台风“摩羯”自生成以来&#xff0c;迅速加强为超强台风级别&#xff0c;预计将在海南琼海到广东电白一带沿海登陆&#xff0c;带来16-17级的强风和巨浪。我国作为自然灾害多发的国家&#xff0c;每年夏季都面临着山洪、泥石流、洪涝、飓风、地震等多…

摸鱼 | 图片转Excel单元格脚本

依赖安装 pip install Pillow tqdm源码&#xff1a; import argparse from PIL import Image import openpyxl from openpyxl.styles import PatternFill from tqdm import tqdmdef image_to_excel(image_path, excel_path, cell_size20, sample_ratio1, output_widthNone, o…

C++(十五)继承 part1

一、继承的概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许我们在保持原有类特性的基础上进行扩展&#xff0c;增加方法(成员函数)和属性(成员变量)&#xff0c;这样产生新的类&#xff0c;称子类。继承呈现了面向对象程序设计的…

Restful风格接口开发

一、项目搭建 安装nestjs脚手架 // 安装nestjs脚手架 npm i nestjs/cli// 新建 nest new [名字]//选择要用的工具 npm / yarn / pnpm 文件信息&#xff1a; 【main.ts】&#xff1a; 入口文件&#xff0c;通过NestFactory&#xff08;由nestjs/core库抛出的对象&#x…

【深度学习】softmax 回归的从零开始实现与简洁实现

前言 小时候听过一个小孩练琴的故事&#xff0c;老师让他先弹最简单的第一小节&#xff0c;小孩练了两天后弹不出。接着&#xff0c;老师让他直接去练更难的第二小节&#xff0c;小孩练习了几天后还是弹不出&#xff0c;开始感觉到挫败和烦躁了。 小孩以为老师之后会让他从简…

数据链路层认识以太网

我们前面学习到的传输层&#xff0c;网络层&#xff0c;传输层是保证数据可靠传输。而网络层是实现在复杂的网络环境中确定一个合适的路径。我们接下来所说的数据链路层其实就是用于两个设备(同一种数据链路节点)之间进行传递。其实也就是如数次的局域网中设备之间的转发过程。…

Pytest-@pytest.fixture夹具篇(一)

一、定义 在Python的pytest测试框架中&#xff0c;pytest.fixture是一个&#xff08;不是唯一&#xff09;装饰器&#xff0c;用于定义一个测试夹具。 二、简单实例 使用参数autouserTrue pytest.fixture(autouseTrue) def my_fixture():print("Setup: 准备测试环境&q…

华为软件测试笔试真题,抓紧收藏不然就看不到了

软件测试工程师笔试题目 一&#xff0e;填空 1、 系统测试使用&#xff08; C &#xff09;技术, 主要测试被测应用的高级互操作性需求, 而无需考虑被测试应用的内部结构。 A、 单元测试 B、 集成测试 C、 黑盒测试 D、白盒测试 2、单元测试主要的测试技术不包括&#xff08…

11. GIS三维建模工程师岗位职责、技术要求和常见面试题

本系列文章目录&#xff1a; 1. GIS开发工程师岗位职责、技术要求和常见面试题 2. GIS数据工程师岗位职责、技术要求和常见面试题 3. GIS后端工程师岗位职责、技术要求和常见面试题 4. GIS前端工程师岗位职责、技术要求和常见面试题 5. GIS工程师岗位职责、技术要求和常见面试…

CACTER直播预告:畅联海外,高效通邮——解锁海外通邮新路径

在全球化的今天&#xff0c;企业通信的无障碍至关重要。然而&#xff0c;随着企业业务的不断拓展&#xff0c;海外通信的挑战也随之增加。跨国邮件传输的延迟、丢件、甚至安全问题&#xff0c;都可能成为企业国际化道路上的绊脚石。如何确保邮件在全球范围内的高效、安全传输&a…

设计模式1:C#开发中使用创建型的工厂模式和行为型的策略模式

一、接口设计的好处 三大好处&#xff1a;解耦、可复用、可扩展。 二、简单工厂模式 【三要素】能创建具体产品的工厂、抽象产品&#xff08;接口&#xff09;、具体产品 【基本用法】字符串>创建对象>调用其方法 // 产品接口 public interface IProduct {void Opera…

【计组易混淆概念梳理助记】机器字长、指令字长、存储字长、数据通路宽度...各种字长大杂炖,应该如何区分?谁又应该等于谁?

苏泽 “弃工从研”的路上很孤独&#xff0c;于是我记下了些许笔记相伴&#xff0c;希望能够帮助到大家 所有学过计组的人几乎都有一个烦恼 就是里面的概念无法记住 经典“转头忘” 那究竟是为什么&#xff1f;很显然 因为名词之间没形成结构化 点与点之间无法建立联系 在…

学AI绘画必知!文生图与图生图的基本认知

​ 在AI绘画的学习与使用中&#xff0c;无论是入门小白还是进阶高手&#xff0c;都绕不开两个核心概念&#xff1a;文生图和图生图。 这是所有AI绘画工具的根本操作方法。掌握这两者的基本原理&#xff0c;你便能轻松驾驭大多数AI工具&#xff0c;无论是MidJourney、Stable Dif…