M5ATOMS3基础02传感器MPU6886

news2024/11/25 1:31:18

M5ATOMS3基础01按键


简洁版本

MPU6886是一款6轴IMU单元,具有3轴重力加速度计和3轴陀螺仪。它采用16位ADC,内置可编程数字滤波器和片上温度传感器,并通过I2C接口(地址为0x68)与上位机通信。MPU6886支持低功耗模式,并具有高性能规格,包括陀螺仪灵敏度误差±1%、陀螺仪噪声±4 mdps/√Hz、加速度计噪声100 μg/√Hz等。此外,它还支持EIS同步,可以应用于可穿戴设备、运动跟踪、无人机姿态确定、智能手机和平板电脑、物联网应用、基于运动的游戏控制器,以及用于互联网连接的DTV和机顶盒、3D鼠标等领域。

详细介绍:

(MPU6886)6轴IMU单元是带有3轴重力加速度计和3轴陀螺仪的6轴姿态传感器,可以实时计算倾斜角度和加速度。该芯片采用mpu6886,具有16位ADC,内置可编程数字滤波器和片上温度传感器,采用I2C接口(addr:0x68)与上位机通信,并支持低功耗模式。

产品特性

  • 3轴重力加速度计和3轴陀螺仪
  • 片上温度传感器
  • 1KB 先进先出
  • 支持低功耗

开发平台:Arduino,uiflow(块状,python)

-高性能规格:

  • 陀螺仪灵敏度误差:±1%
  • 陀螺仪噪声:±4 mdps/√Hz
  • 加速度计噪声:100 μg/√Hz
  • 支持 EIS 同步

-产品应用

  • 可穿戴设备
  • 运动跟踪
  • 无人机姿态确定
  • 智能手机和平板电脑
  • 物联网应用
  • 基于运动的游戏控制器
  • 用于互联网连接 DTV 和机顶盒,3D鼠标

M5AtomS3官方示例代码:

/*
*******************************************************************************
* Copyright (c) 2021 by M5Stack
*                  Equipped with AtomS3 sample source code
*                          配套  AtomS3 示例源代码
* Visit for more information: https://docs.m5stack.com/en/core/AtomS3
* 获取更多资料请访问:https://docs.m5stack.com/zh_CN/core/AtomS3
*
* Describe: MPU6886.  姿态传感器示例
* Date: 2022/12/19
*******************************************************************************
*/
#include "M5AtomS3.h"

/* After AtomS3 is started or reset the program in the setUp ()
function will be run, and this part will only be run once.
在 AtomS3 启动或者复位后,即会开始执行setup()函数中的程序,该部分只会执行一次。
*/
void setup() {
    M5.begin(true, true, true,
             false);  // Init AtomS3(Initialize LCD, serial port).
                      // 初始化 AtomS3(初始化LCD、串口)
    M5.IMU.begin();   // Init IMU sensor.  初始化姿态传感器
    USBSerial.printf("whoAmI() = 0x%02x\n", M5.IMU.whoAmI());
}

/* After the program in setup() runs, it runs the program in loop()
The loop() function is an infinite loop in which the program runs repeatedly
在setup()函数中的程序执行完后,会接着执行loop()函数中的程序
loop()函数是一个死循环,其中的程序会不断的重复运行 */
float ax, ay, az, gx, gy, gz, t;
void loop() {
    M5.Lcd.setCursor(0, 40);
    M5.Lcd.clear();                  // Delay 100ms 延迟100ms
    M5.IMU.getAccel(&ax, &ay, &az);  // Read tri-axial accel 读取三轴加速度
    M5.IMU.getGyro(&gx, &gy, &gz);  // Read gyroscope data 读取陀螺仪数据
    M5.IMU.getTemp(&t);             // Read temperature data 读取温度数据
    USBSerial.printf("%f,%f,%f,%f,%f,%f,%f\n", ax, ay, az, gx, gy, gz,
                     t);  // serial port output the formatted string.  串口输出
    M5.Lcd.printf("IMU:\r\n");
    M5.Lcd.printf("%0.2f %0.2f %0.2f\r\n", ax, ay, az);
    M5.Lcd.printf("%0.2f %0.2f %0.2f\r\n", gx, gy, gz);
    delay(500);
}

arduino中获取MPU6886常规代码如下:

#include <Wire.h>  
  
#define MPU6886_ADDRESS 0x68  
  
byte int16_array[14] ;  
float posture[3] ;  
  
void setup() {  
  Wire.begin();  
  Wire.beginTransmission(MPU6886_ADDRESS);  
  Wire.write(0x6B); // PWR_MGMT_1 register  
  Wire.write(0); // set to zero (reset)  
  Wire.endTransmission(false);  
  Serial.begin(9600);  
}  
  
void loop() {  
  Wire.beginTransmission(MPU6886_ADDRESS);  
  Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)  
  Wire.endTransmission(false);  
  
  Wire.requestFrom(MPU6886_ADDRESS, 14, true); // request 14 bytes of data  
  
  for (int i = 0; i < 14; i++) { // read data into array  
    int16_array[i] = Wire.read() << 8 | Wire.read();  
  }  
  
  posture[0] = (float)int16_array[0] / 16384.0; // convert x-axis acceleration data to float  
  posture[1] = (float)int16_array[1] / 16384.0; // convert y-axis acceleration data to float  
  posture[2] = (float)int16_array[2] / 16384.0; // convert z-axis acceleration data to float  
  
  Serial.print("Posture X: ");  
  Serial.print(posture[0]);  
  Serial.print(" | Y: ");  
  Serial.print(posture[1]);  
  Serial.print(" | Z: ");  
  Serial.println(posture[2]);  
  
  delay(100);  
}

这个示例代码通过I2C接口与MPU6886通信,并读取加速度和角速度数据,然后将其转换为浮点数并输出到串口监视器中。在设置中,通过Wire.beginTransmission()和Wire.endTransmission()函数设置MPU6886的地址,并将其重置为默认设置。在循环中,通过Wire.requestFrom()函数从MPU6886请求数据,并将其读取到一个字节数组中。然后,将加速度数据转换为浮点数,并将其存储在一个浮点数数组中,最后将数据输出到串口监视器中。在示例代码中,延迟100毫秒,以便以适当的速率读取传感器数据。  


简要解析:

IMU

新代码如下:

    M5.IMU.getAccel(&ax, &ay, &az);  // Read tri-axial accel 读取三轴加速度
    M5.IMU.getGyro(&gx, &gy, &gz);  // Read gyroscope data 读取陀螺仪数据
    M5.IMU.getTemp(&t);             // Read temperature data 读取温度数据

具体如何实现?

MPU6886.h

#ifndef __MPU6886_H__
#define __MPU6886_H__

#include <Wire.h>

#define MPU6886_DEFAULT_ADDRESS 0x68

class MPU6886 {
   public:
    MPU6886(uint8_t deviceAddress = MPU6886_DEFAULT_ADDRESS,
            TwoWire& i2cPort      = Wire1);

    int begin(void);

    uint8_t whoAmI();

    void getAccel(float* ax, float* ay, float* az);
    void getGyro(float* gx, float* gy, float* gz);
    void getTemp(float* t);

   private:
    uint8_t readByte(uint8_t address);
    void writeByte(uint8_t address, uint8_t data);
    void bitOn(uint8_t address, uint8_t bit);
    void bitOff(uint8_t address, uint8_t bit);

    TwoWire* _i2cPort;
    int _deviceAddress;
};

#endif

MPU6886.c

#include "MPU6886.h"

MPU6886::MPU6886(uint8_t deviceAddress, TwoWire& i2cPort) {
    _deviceAddress = deviceAddress;
    _i2cPort       = &i2cPort;
}

uint8_t MPU6886::readByte(uint8_t address) {
    _i2cPort->beginTransmission(_deviceAddress);
    _i2cPort->write(address);
    _i2cPort->endTransmission();
    _i2cPort->requestFrom(_deviceAddress, 1);
    uint8_t val = _i2cPort->read();

    ESP_LOGD("MPU6886", "readByte(%02X) = %02X", address, val);
    return val;
}

void MPU6886::writeByte(uint8_t address, uint8_t data) {
    _i2cPort->beginTransmission(_deviceAddress);
    _i2cPort->write(address);
    _i2cPort->write(data);
    _i2cPort->endTransmission();
    ESP_LOGD("MPU6886", "writeByte(%02X) = %02X", address, data);
}

void MPU6886::bitOn(uint8_t address, uint8_t bit) {
    uint8_t add = address;
    uint8_t val = readByte(add) | bit;
    writeByte(add, val);
}

void MPU6886::bitOff(uint8_t address, uint8_t bit) {
    uint8_t add = address;
    uint8_t val = readByte(add) & ~bit;
    writeByte(add, val);
}

int MPU6886::begin(void) {
    // WHO_AM_I : IMU Check
    if (whoAmI() != 0x19) {
        return -1;
    }
    delay(1);

    // PWR_MGMT_1(0x6b)
    writeByte(0x6b, 0x00);
    delay(10);

    // PWR_MGMT_1(0x6b)
    writeByte(0x6b, 1 << 7);
    delay(10);

    // PWR_MGMT_1(0x6b)
    writeByte(0x6b, 1 << 0);
    delay(10);

    // ACCEL_CONFIG(0x1c) : +-8G
    writeByte(0x1c, 0x10);
    delay(1);

    // GYRO_CONFIG(0x1b) : +-2000dps
    writeByte(0x1b, 0x18);
    delay(1);

    // CONFIG(0x1a)
    writeByte(0x1a, 0x01);
    delay(1);

    // SMPLRT_DIV(0x19)
    writeByte(0x19, 0x05);
    delay(1);

    // INT_ENABLE(0x38)
    writeByte(0x38, 0x00);
    delay(1);

    // ACCEL_CONFIG 2(0x1d)
    writeByte(0x1d, 0x00);
    delay(1);

    // USER_CTRL(0x6a)
    writeByte(0x6a, 0x00);
    delay(1);

    // FIFO_EN(0x23)
    writeByte(0x23, 0x00);
    delay(1);

    // INT_PIN_CFG(0x37)
    writeByte(0x37, 0x22);
    delay(1);

    // INT_ENABLE(0x38)
    writeByte(0x38, 0x01);
    delay(100);

    return 0;
}

uint8_t MPU6886::whoAmI(void) {
    return readByte(0x75);
}

void MPU6886::getAccel(float* ax, float* ay, float* az) {
    float aRes = 8.0 / 32768.0;
    *ax        = (int16_t)((readByte(0x3b) << 8) | readByte(0x3c)) * aRes;
    *ay        = (int16_t)((readByte(0x3d) << 8) | readByte(0x3e)) * aRes;
    *az        = (int16_t)((readByte(0x3f) << 8) | readByte(0x40)) * aRes;
}

void MPU6886::getGyro(float* gx, float* gy, float* gz) {
    float gRes = 2000.0 / 32768.0;
    *gx        = (int16_t)((readByte(0x43) << 8) | readByte(0x44)) * gRes;
    *gy        = (int16_t)((readByte(0x45) << 8) | readByte(0x46)) * gRes;
    *gz        = (int16_t)((readByte(0x47) << 8) | readByte(0x48)) * gRes;
}

void MPU6886::getTemp(float* t) {
    *t = 25.0 + ((readByte(0x41) << 8) | readByte(0x42)) / 326.8;
}

都是一些固定流程。底层代码类似驱动,规范性是很重要的。 


修改:

下段代码是一个使用ESP32-S3开发板的程序,通过连接M5AtomS3库来进行传感器数据的读取和显示。

代码主要包括两个函数:setup()loop()

setup()函数是程序启动后首先执行的函数,它进行一些初始化的操作,包括初始化AtomS3(LCD和串口)和IMU传感器,然后延迟100毫秒,最后通过USB串口输出IMU传感器的信息。

loop()函数是一个死循环,其中的程序会不断的重复运行。在每次循环中,程序通过M5AtomS3库的函数读取IMU传感器的数据,包括三轴加速度、陀螺仪数据和温度数据。然后通过USB串口输出这些数据,并在LCD屏幕上显示IMU传感器的信息,包括加速度、陀螺仪和温度。每次循环后,程序会延迟20毫秒。

整体来说,这段代码的功能是不断读取并显示IMU传感器的数据,包括加速度、陀螺仪和温度,并通过串口输出。同时,它还在LCD屏幕上显示了IMU传感器的信息。

#include "M5AtomS3.h"

/* After AtomS3 is started or reset the program in the setUp ()
function will be run, and this part will only be run once.
在 AtomS3 启动或者复位后,即会开始执行setup()函数中的程序,该部分只会执行一次。
*/
void setup() {
    M5.begin(true, true, true,
             false);  // Init AtomS3(Initialize LCD, serial port).
                      // 初始化 AtomS3(初始化LCD、串口)
    M5.IMU.begin();   // Init IMU sensor.  初始化姿态传感器
    M5.Lcd.clear();                  // Delay 100ms 延迟100ms
    USBSerial.printf("whoAmI() = 0x%02x\n", M5.IMU.whoAmI());
}

/* After the program in setup() runs, it runs the program in loop()
The loop() function is an infinite loop in which the program runs repeatedly
在setup()函数中的程序执行完后,会接着执行loop()函数中的程序
loop()函数是一个死循环,其中的程序会不断的重复运行 */
float ax, ay, az, gx, gy, gz, t;
void loop() {
    M5.Lcd.setCursor(0, 40);
    M5.IMU.getAccel(&ax, &ay, &az);  // Read tri-axial accel 读取三轴加速度
    M5.IMU.getGyro(&gx, &gy, &gz);  // Read gyroscope data 读取陀螺仪数据
    M5.IMU.getTemp(&t);             // Read temperature data 读取温度数据
    USBSerial.printf("%f,%f,%f,%f,%f,%f,%f\n", ax, ay, az, gx, gy, gz,
                     t);  // serial port output the formatted string.  串口输出
    M5.Lcd.printf("IMU:Accel\r\n");
    M5.Lcd.printf("%0.2f %0.2f %0.2f\r\n", ax, ay, az);
    M5.Lcd.printf("IMU:Gyro\r\n");
    M5.Lcd.printf("%0.2f %0.2f %0.2f\r\n", gx, gy, gz);
    M5.Lcd.printf("IMU:Temp\r\n");
    M5.Lcd.printf("%0.2f \r\n", t);
    delay(20);
}

为何做这样的修改呢?其实串口部分代码也可以去掉。


调试结果:

很明显温度等不太合适嘛?

AI给出注意事项如下:

在使用MPU6886传感器连接到ESP32单片机时,需要注意以下事项:

  1. 硬件连接:确保将MPU6886正确连接到ESP32单片机。这涉及到正确连接电源、I2C总线和地线。
  2. I2C通信:确认MPU6886的I2C地址正确设置,并在ESP32单片机的程序中正确配置I2C总线。
  3. 供电要求:MPU6886的电压范围为2.5V至5.5V。确保提供适当的电源,并注意电源稳定性。
  4. 数据处理:对于读取的数据,需要正确解释和校正。例如,加速度数据需要进行温度补偿和偏移校正,以获得更准确的结果。
  5. 休眠模式:ESP32单片机可以通过将MPU6886的电源引脚拉低来将其置于休眠模式,以降低功耗。
  6. 数据输出:确认MPU6886的数据输出格式,例如16位或32位,并根据需要对其进行处理。
  7. 温度补偿:使用MPU6886时,需要注意温度对加速度计和陀螺仪的影响。需要进行温度补偿以获得更准确的数据。
  8. 陀螺仪校准:在使用MPU6886之前,需要对陀螺仪进行校准。这可以通过在静态条件下运行陀螺仪一段时间来进行。
  9. 数据滤波:为了减少噪声和干扰,可以在数据读取和处理过程中应用滤波技术,例如低通滤波或卡尔曼滤波。
  10. 更新频率:根据应用需要,可以设置MPU6886的更新频率。例如,对于需要高频率数据的应用,可以增加更新频率。

以上是使用MPU6886连接到ESP32单片机时的一些注意事项。根据具体应用和硬件配置,可能还有其他需要注意的事项。建议参考相关文档和资料,以确保正确和可靠的使用。


背景知识点:

MPU6886和MPU6050都是六轴惯性测量单元(IMU),用于测量姿态、加速度和角速度等运动参数。它们的主要区别在于芯片结构和连接方式。

MPU6886采用I2C接口,内置了3轴加速度计和3轴陀螺仪,并提供了数字运动处理器(DMP)和可编程数字滤波器。它采用2.5V至5.5V的电源供应,具有低功耗模式,并支持快速唤醒。MPU6886的主要特点包括高精度、低功耗、快速启动和低噪声。

MPU6050是一个整合感应器,内含3轴加速度计和3轴陀螺仪,采用I2C接口。它具有131 LSBs/°的角速度全格感测范围,并内置了数字运动处理器(DMP)。MPU6050的工作电压为2.5V至5.5V,具有低功耗模式,并能唤醒快速。主要特点包括高精度、低功耗、快速启动和低噪声。

总体而言,MPU6886和MPU6050在功能和性能上非常相似,都具有高精度、低功耗、快速启动和低噪声等特点。主要区别在于连接方式和芯片结构。具体选择哪个取决于具体应用的需求和预算。

ESP32-S3是一款基于Xtensa LX7架构的32位Wi-Fi SoC,具有高性能和低功耗的特点。它集成了2.4 GHz Wi-Fi、蓝牙和NFC功能,并提供了丰富的外设接口,如SD卡接口、ADC、DAC、SPI、I2C、UART等。ESP32-S3还支持神经网络加速器和TensorFlow Lite,可用于机器学习和人工智能应用。

以下是ESP32-S3的一些主要特点:

  1. Xtensa LX7 32位处理器,最高主频可达240 MHz。
  2. 2.4 GHz Wi-Fi和蓝牙双模芯片,支持802.11 b/g/n和蓝牙5.0。
  3. 内置NFC功能,可实现近场通信。
  4. 低功耗设计,可支持多种电源供电方式,包括1.8V、3.3V和1.2V。
  5. 集成了32 KB SRAM和32 KB ROM。
  6. 支持SD卡接口,可用于存储和读取数据。
  7. 提供丰富的外设接口,如ADC、DAC、SPI、I2C、UART等。
  8. 支持神经网络加速器和TensorFlow Lite,可用于机器学习和人工智能应用。

ESP32-S3适用于各种物联网应用,如智能家居、智能城市、智能医疗、工业自动化等。它具有高性能、低功耗和丰富的外设接口,可为各种应用提供可靠的解决方案。


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

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

相关文章

Linux系统MySQL中用户的权限管理

本节主要学习用户权限管理的概述&#xff0c;用户权限类型&#xff0c;用户赋权&#xff0c;权限删除&#xff0c;用户删除等。 目录 一、概述 二、用户权限类型 三、用户赋权 四、权限删除 五、用户删除 一、概述 数据库用户权限管理是数据库系统中非常重要的一个方面&am…

如何理解 SpringBoot 的生命周期

生命周期&#xff0c;就是从诞生到死亡的一个过程。Spring 中 bean 也是如此。在 Spring 中的 ConfigurableApplicationContext 的 refresh 开始直到一个 bean 可以被正常使用&#xff0c;中间经历了一系列初始化操作&#xff1b;而在其 close 后又经历了一系列销毁操作&#x…

(八九)如何与InfluxDB交互InfluxDB HTTP API

以下内容来自 尚硅谷&#xff0c;写这一系列的文章&#xff0c;主要是为了方便后续自己的查看&#xff0c;不用带着个PDF找来找去的&#xff0c;太麻烦&#xff01; 第 8 章 前言&#xff1a;如何与InfluxDB交互 1、InfluxDB启动后&#xff0c;会向外提供一套HTTP API。外部程…

配置代理——解决跨域问题(详解)

之前写项目的时候总会遇到配置代理的问题&#xff0c;可是配置了之后有时有用&#xff0c;有时就没有用&#xff0c;自己之前学的也是懵懵懂懂&#xff0c;于是专门花了一个小时去了解了如何配置代理跨域&#xff0c;然后在此记录一下&#xff0c;方便自己以后查阅。 一、 常用…

自守数 C语言实现

自守数 描述 自守数是指一个数的平方的尾数等于该数自身的自然数。例如&#xff1a;25^2 625&#xff0c;76^2 5776&#xff0c;9376^2 87909376。请求出n(包括n)以内的自守数的个数 数据范围&#xff1a; 1≤n≤10000 输入描述&#xff1a; int型整数 输出描述&#xf…

重学C++系列之多态

一、什么是多态 多态是类的三大特性之一&#xff08;封装&#xff0c;继承&#xff0c;多态&#xff09;。多态是指由继承而产生的相关不同的类&#xff0c;其派生类对象对同一个消息会作出不同响应。 二、引入多态的目的 能增加程序的灵活性&#xff0c;可以减轻系统升级和维…

EC200U-CN学习(三)

EC200U系列内置丰富的网络协议&#xff0c;集成多个工业标准接口&#xff0c;并支持多种驱动和软件功能&#xff08;适用于Windows 7/8/8.1/10、Linux和Android等操作系统下的USB驱动&#xff09;&#xff0c;极大地拓展了其在M2M领域的应用范围&#xff0c;如POS、POC、ETC、共…

TCP协议如何实现可靠传输

TCP最主要的特点 TCP是面向连接的运输层协议&#xff0c;在无连接的、不可靠的IP网络服务基础之上提供可靠交付的服务。为此&#xff0c;在IP的数据报服务基础之上&#xff0c;增加了保证可靠性的一系列措施。 TCP最主要的特点&#xff1a; TCP是面向连接的输出层协议 每一条…

vue3.2 + elementPlus + Windi CSS + ts创建一个好用的可兼容不同宽高的login页面

1.效果预览 2. 代码准备 导入windiCSS&#xff1a; npm i -D vite-plugin-windicss windicss windiCSS官网&#xff1a; https://cn.windicss.org/integrations/vite.html 使用vite创建好你的vue工程 sass版本为&#xff1a; 1.49.9 3.Windi CSS在页面中使用 apply 二次定义类名…

ACwing 1081. 度的数量

文章目录 题意思路代码 题意 给你一段区间[x, y]求其中满足一个数恰好等于K个互不相等的B的整数次幂之和的数的个数。 例如&#xff1a;x 15, y 20, k 2, b 2&#xff0c;那么对于这个区间有且仅有三个数满足题意&#xff1a; 17 2 4 2 0 10001 17 2^42^0 10001 1724…

行为型设计模式之策略模式【设计模式系列】

系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 设计模式系列 期待你的关注哦&#xff01;&#xff01;&#xff01; 现在的一切都是为将来的梦想编织翅膀&#xff0c;让梦想在现实中展翅高飞。 Now everythi…

OpenCV实现高斯模糊加水印

# coding:utf-8 # Email: wangguisendonews.com # Time: 2023/4/21 10:07 # File: utils.pyimport cv2 import PIL from PIL import Image import numpy as np from watermarker.marker import add_mark, im_add_mark import matplotlib.pyplot as plt# PIL Image转换成OpenCV格…

Docker 全栈体系(六)

Docker 体系&#xff08;高级篇&#xff09; 三、Docker微服务实战 1. 通过IDEA新建一个普通微服务模块 建Module docker_boot 改POM <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" …

【C#】医学实验室云LIS检验信息系统源码 采用B/S架构

基于B/S架构的医学实验室云LIS检验信息系统&#xff0c;整个系统的运行基于WEB层面&#xff0c;只需要在对应的工作台安装一个浏览器软件有外网即可访问&#xff0c;技术架构&#xff1a;Asp.NET CORE 3.1 MVC SQLserver Redis等。 一、系统概况 本系统是将各种生化、免疫、…

当ChatGPT应用在汽车行业,具体有哪些场景?

​ ChatGPT有潜力彻底改变汽车行业并将其提升到新的高度。在ChatGPT的加持下&#xff0c;该行业的多个领域都将取得重大变化。 利用ChatGPT作更高级的虚拟助理 你可能用过现有的虚拟助理&#xff0c;它们一系列的回复有时候让人不得不感叹一句“人工智障”&#xff01;然而&a…

【12】STM32·HAL库开发-STM32时钟系统 | F1/F4/F7时钟树 | 配置系统时钟

目录 1.认识时钟树&#xff08;掌握&#xff09;1.1什么是时钟&#xff1f;1.2认识时钟树&#xff08;F1&#xff09;1.2.1STM32F103时钟树简图1.2.2STM32CubeMX时钟树&#xff08;F103&#xff09; 1.3认识时钟树&#xff08;F4&#xff09;1.3.1F407时钟树1.3.2F429时钟树1.3…

【C++】解决菱形继承而产生的虚基表(偏移量表)

文章目录 继承概念切片和重定义派生类的默认成员函数菱形虚拟继承 继承概念 继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段&#xff0c;它允许程序员在保持原有类特性的基础上进行扩展&#xff0c;增加功能&#xff0c;这样产生新的类&#xff0c;称派…

LeetCode91.Decode-Ways<解码方法>

题目&#xff1a; 思路&#xff1a; 关键在于有没有0,其次能不能二位.二位的要求是在 1-- 26的范围内.所以动态规划的时候需要限制. 代码是&#xff1a; //codeclass Solution { public:int numDecodings(string s) {int n s.size();vector<int> dp(n1, 0); // 定义状…

java使用htmlunit + jsoup 爬网站图片案例(爬虫学习)

申明 该文章用于自己学习爬虫使用 案例分析 目的: 从百度图片中搜索"风景"并下载图片到本地 思路: 使用htmlunit进行模拟用户操作, 并使用jsoup对数据进行解析,获取到需要的数据后,再下载到本地保存 htmlunit官网 jsoup官网 操作步骤 使用谷歌浏览器打开百度图片…

用html+javascript打造公文一键排版系统8:附件及标题排版

最近工作有点忙&#xff0c;所 以没能及时完善公文一键排版系统&#xff0c;现在只好熬夜更新一下。 有时公文有包括附件&#xff0c;招照公文排版规范&#xff1a; 附件应当另面编排&#xff0c;并在版记之前&#xff0c;与公文正文一起装订。“附件”二字及附件顺序号用3号黑…