【STM32单片机】#11 I2C通信(软件读写)

主要参考学习资料:

B站@江协科技

STM32入门教程-2023版 细致讲解 中文字幕

开发资料下载链接:https://pan.baidu.com/s/1h_UjuQKDX9IpP-U1Effbsw?pwd=dspb

单片机套装:STM32F103C8T6开发板单片机C6T6核心板 实验板最小系统板套件科协

实验:

  • 软件I2C读写MPU6050

目录

  • I2C通信
    • 硬件电路
    • I2C时序基本单元
    • I2C时序
  • MPU6050简介
    • MPU6050参数
    • 硬件电路
    • MPU6050框图
    • MPU6050寄存器
  • 实验24 软件I2C读写MPU6050
    • 接线图
    • I2C协议层
    • MPU6050驱动层
    • 主程序应用层

I2C通信

  • I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线。
  • 两根通信线:SCL(Serial Clock)、SDA(Serial Data)
  • 同步半双工通信:同步时序降低对硬件的依赖,时序稳定性更高;半双工一根线兼具发送与接收,最大化利用资源。
  • 带数据应答
  • 支持总线挂载多设备(一主多从,多主多从)

硬件电路

左图为I2C典型的一主多从电路模型,CPU(单片机)为主机。主机完全掌控SCL,且在空闲状态可以主动发起对SDA的控制。只有在从机发送数据和应答时,主机才会转交SDA控制权给主机。被控IC为从机,可以是姿态传感器、OLED、存储器、时钟模块等。从机对于SCL在任何时刻只能被动读取,并不允许主动发起对SDA的控制。只有在主机发送读取从机的命令后或从机应答时,从机才能短暂地取得SDA的控制权。

所有I2C设备的SCL连在一起,SDA连在一起。由于SDA对于不同设备会在输入和输出之间反复切换,如果总线时序协调不当,极有可能出现两个引脚同时输出的状态,若一个输出高电平,另一个输出低电平,会引起电源短路。为了避免该问题,I2C禁止所有设备输出强上拉的高电平,采用外置弱上拉电阻加开漏输出的结构,设备的SCL和SDA均须配置成开漏输出模式。右图为设备的引脚内部结构图,输入正常,输出去掉强上拉开关管,输出低电平时下管导通为强下拉,输出高电平时下管断开为浮空状态,由外置电阻弱上拉为高电平。此时一旦有一个设备输出低电平,则线路为低电平,只有所有设备均输出高电平或空闲时,线路才为高电平。

I2C时序基本单元

  • 起始条件:SCL高电平期间,SDA从高电平切换到低电平。
  • 终止条件:SCL高电平期间,SDA从低电平切换到高电平。

起始条件和终止条件相当于串口通信的起始位和停止位,由主机发出作为数据传输的开始和结束。起始信号产生之后总线处于占用状态,终止信号产生之后总线处于空闲状态。

  • 发送一个字节:SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL。从机将在SCL高电平期间读取数据位,因此SCL高电平期间SDA不允许有数据变化。依次循环上述过程8次即可发送一个字节。

由于有时钟线进行同步,因此即使数据传输中断,SCL和SDA电平都暂停变化,时序会在中断的位置保持不变,中断结束后继续传输也不会出现问题。

  • 接收一个字节:SCL低电平期间,从机将数据位依次放到SDA线上(高位先行)。然后主机释放SCL,在SCL高电平期间读取数据位,因此SCL高电平期间SDA不允许有数据变化。依次循环上述过程8次即可接收一个字节(主机在接收之前需要释放SDA)。

  • 发送应答:主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答。如果从机得到应答,则会继续发送数据。
  • 接收应答:主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前需要释放SDA)。如果主机得到应答,则说明从机接收到数据并回应。

I2C时序

I2C通过给每个从设备确定一个唯一的设备地址来实现一主多从。主机在起始条件之后会先发送一个字节的从机地址,所有的从机都会收到第一个字节与自己的地址比较,如果一样则响应主机后续读写操作。在同一条I2C总线中,挂载的每个设备地址必须不一样。从机设备地址在I2C协议标准中分为7位地址和10位地址,本文只讲7位地址模式,因为7位地址比较简单且应用范围最广。

每个I2C设备出厂时,厂商都会为其分配一个7位地址,可以在芯片手册中找到。一般设备地址的最后几位可以通过指定引脚的高低电平在电路中改变,以应对相同的芯片挂载在同一条总线的情况。

  • 指定地址写:对于指定设备(Slave Address,从设备地址)在指定地址(Reg Address,从设备内部寄存器地址)下写入指定数据(Data)。
  • 起始条件→7位地址位+1位读写位(写为0)→应答位(主机释放,从机应答)→寄存器地址/指令控制字(由从设备定义)→应答位→写入到寄存器的数据→应答位→停止位

  • 当前地址读:对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)。
  • 起始条件→7位地址位+1位读写位(读为1)→应答位→主机释放,从机在SCL低电平期间写入,主机在SCL高电平期间读取→非应答位(主机不释放,从机得到非应答后交还控制权,否则会继续发送下一个数据影响停止位的生成)→停止位
  • 地址指针:I2C在读写标志位给1后立马转为读时序,主机没有时间指定寄存器地址。在从机中,所有寄存器会被分配到一个线性区域中,并且有一个单独的指针变量指示其中一个寄存器。该指针一般上电默认指向0地址,在对应寄存器每写入或读出一个字节后会自动自增一次,移动到下一个位置,从机返回当前指针指向的寄存器的值。

  • 指定地址读:对于指定设备(Slave Address)在指定地址(Reg Address)下读取从机数据(Data)。
  • 起始条件→7位地址位+1位读写位(写)→应答位→寄存器地址→应答位→(终止条件可选)重复起始条件(切换读写方向)→7位地址位+1位读写位(读)→应答位→读取数据→非应答位→停止位
  • 相当于指定地址写(只指定地址,不写数据)→当前地址读

如需一次性写入多字节数据,则在指定地址写的终止条件前继续重复写入数据、应答位的过程,但寄存器地址会随着指针自增,因此该功能为从指定的位置开始,按顺序连续写入多个字节。读取多字节数据同理。

MPU6050简介

  • MPU6050是一个六轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合可进一步得到姿态角,常应用于平衡车、飞行器等需要检测自身姿态的场景。
  • 三轴加速度计(Accelerometer):测量X、Y、Z轴的加速度。
  • 三轴陀螺仪传感器(Gyroscope):测量X、Y、Z轴的角速度。
  • 另外,若芯片再集成一个三轴磁场传感器则为九轴姿态传感器,再集成一个气压传感器(海拔)则为十轴姿态传感器。

MPU6050参数

  • 16位ADC采集传感器的模拟信号,量化范围:-32768~32767
  • 加速度计满量程选择:±2/4/8/16(g)
  • 陀螺仪满量程选择:±250/500/1000/2000( ∘ ^\circ /sec)
  • 满量程越大,测量范围越广;满量程越小,测量精度越高。
  • 可配置的数字低通滤波器/时钟源/采样分频
  • I2C从机地址:1101000(AD0=0)或1101001(AD0=1)

硬件电路

MPU6050芯片中有很多引脚我们用不到,还有一些引脚为芯片最小系统的固定连接。芯片引出的排针中,XCL和XDA用于扩展芯片功能,通常外接磁力计或气压计,此时MPU6050的主机接口可以直接访问并读取这些扩展芯片的数据,由其中的DMP单元进行数据融合和姿态解算。AD0在悬空状态下默认弱下拉为低电平。INT可以通过配置芯片内部的一些事件触发其跳变产生中断信号,例如数据准备完成、I2C主机错误等,以及芯片内置的自由落体\运动\零运动检测功能。低压差线性稳压器LDO为芯片的供电逻辑,将芯片3.3V供电限制扩展到3.3~5V供电,LED为电源指示灯。

本实验只用到VCC和GND供电,SCL和SDA接上I2C通信的GPIO口。

MPU6050框图

框图左上角为时钟系统(CLOCK),灰色部分为芯片内部加速度和陀螺仪传感器,还内置了一个温度传感器(Temp Sensor)。传感器通过分压输出模拟电压,并通过ADC进行模数转换,转换完成后的数据通过DMA统一转移到数据寄存器(Sensor Registers)中,读取数据寄存器即可得到传感器测量的值。最左侧的自测单元(Self test)用于验证芯片好坏,启动自测时,芯片内部会向传感器施加模拟外力使值偏大,将其与关闭自测时的值相减得到的数据为自测响应。如果自测响应在芯片手册给出的范围内则芯片完好。电荷泵(Charge Pump)和CPOUT引脚外接电容组成升压电路支持陀螺仪运行,其原理是先将电池与电容并联为其充电,再将电池与电容串联得到两倍电压,通过串并联的高频切换和电源滤波实现平稳升压。

右侧中断状态寄存器(Interrupt Status Register)控制内部连接中断引脚输出的事件,先入先出寄存器(FIFO)对数据流进行缓存,配置寄存器(Config Registers)对内部的各个电路进行配置,工厂校准(Factory Calibratior)对内部传感器件进行校准,数字运动处理器(DMP)为芯片内部自带的姿态解算硬件算法。帧同步(FSYNC)暂时用不到,其上方为通信接口部分,分为从机I2C通信接口和主机I2C通信接口,接口旁路选择器(Serial Interface Bypass Mux)可以将两路总线合并,此时STM32可以控制包括扩展功能在内的所有设备。框图右下角为供电部分。

MPU6050寄存器

表格列1为地址,列3为寄存器名称,列4为读写权限,后8列为每位功能。

功能介绍时已标明实验所用配置。

电源管理寄存器1(默认)

765432/1/0
设备复位
(不需要)
睡眠模式
(不需要)
循环模式
(不需要)
温度传感器失能
(不需要)
内部时钟000
陀螺仪时钟001(官方推荐)

电源管理寄存器2

7/65~0
循环模式唤醒频率
(不需要)
每个轴的待机位
(不需要)

采样率分频:决定数据输出快慢,值越小越快。

配置寄存器

7/65/4/32/1/0
外部同步
(不需要)
数字低通滤波器
(110最平滑)

陀螺仪配置寄存器

7/6/54/32/1/0
自测使能
(不需要)
满量程
(11最大)
高通滤波器
(不需要)

加速度计配置寄存器

7/6/54/32/1/0
自测使能
(不需要)
满量程
(11最大)

每个轴的数据寄存器均分为高八位H和低八位L。

实验24 软件I2C读写MPU6050

接线图

I2C协议层

MyI2C.h

#ifndef __MYI2C_H
#define __MYI2C_Hvoid MyI2C_Init(void);
void MyI2C_Start(void);
void MyI2C_Stop(void);
void MyI2C_SendByte(uint8_t Byte);
uint8_t MyI2C_ReceiveByte(void);
void MyI2C_SendAck(uint8_t AckBit);
uint8_t MyI2C_ReceiveAck(void);#endif

MyI2C.c

#include "stm32f10x.h"
#include "Delay.h"//封装释放/拉低SCL函数
void MyI2C_W_SCL(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);//若单片机主频过高,需要延时以满足芯片时序性能Delay_us(10);
}//封装释放/拉低SDA函数
void MyI2C_W_SDA(uint8_t BitValue)
{GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);Delay_us(10);
}//封装读SDA函数
uint8_t MyI2C_R_SDA(void)
{uint8_t BitValue;BitValue = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_11);Delay_us(10);return BitValue;
}void MyI2C_Init(void)
{//配置模拟SCL、SDA的GPIO口RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;//开漏输出GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//释放总线GPIO_SetBits(GPIOB, GPIO_Pin_10 | GPIO_Pin_11);
}//起始条件
void MyI2C_Start(void)
{MyI2C_W_SDA(1);MyI2C_W_SCL(1);MyI2C_W_SDA(0);MyI2C_W_SCL(0);
}//终止条件
void MyI2C_Stop(void)
{//SCL在应答位后默认低电平无需拉低MyI2C_W_SDA(0);MyI2C_W_SCL(1);MyI2C_W_SDA(1);
}//除了终止条件,其余时序单元SCL都以低电平结束
//除了起始条件,其余时序单元SCL都以高电平开始
//便于拼接//发送单字节
void MyI2C_SendByte(uint8_t Byte)
{uint8_t i;for(i = 0;i < 8;i++){//与运算和右移提取从高到低的第i位MyI2C_W_SDA(Byte & (0x80 >> i));//驱动SCL走一个脉冲MyI2C_W_SCL(1);MyI2C_W_SCL(0);}
}//接收单字节
uint8_t MyI2C_ReceiveByte(void)
{uint8_t i, Byte = 0x00;//释放SDAMyI2C_W_SDA(1);for(i = 0;i < 8;i++){MyI2C_W_SCL(1);if(MyI2C_R_SDA())//或运算和右移将1写入从高到低的第i位Byte |= (0x80 >> i);MyI2C_W_SCL(0);}return Byte;
}//发送应答(相当于发送一位)
void MyI2C_SendAck(uint8_t AckBit)
{MyI2C_W_SDA(AckBit);MyI2C_W_SCL(1);MyI2C_W_SCL(0);
}//接收应答(相当于接收一位)
uint8_t MyI2C_ReceiveAck(void)
{uint8_t AckBit;MyI2C_W_SDA(1);MyI2C_W_SCL(1);AckBit = MyI2C_R_SDA();MyI2C_W_SCL(0);return AckBit;
}

MPU6050驱动层

MPU6050.h

#ifndef __MPU6050_H
#define __MPU6050_Hvoid MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data);
uint8_t MPU6050_ReadReg(uint8_t RegAddress);
void MPU6050_Init(void);
uint8_t MPU6050_GetID(void);
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ);#endif

MPU6050.c

#include "stm32f10x.h"
#include "MyI2C.h"
#include "MPU6050_Reg.h"//宏定义从机地址(写地址)
#define MPU6050_ADDRESS 0xD0//指定地址写
void MPU6050_WriteReg(uint8_t RegAddress, uint8_t Data)
{MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveAck();MyI2C_SendByte(RegAddress);MyI2C_ReceiveAck();MyI2C_SendByte(Data);MyI2C_ReceiveAck();MyI2C_Stop();
}//指定地址读
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{uint8_t Data;MyI2C_Start();MyI2C_SendByte(MPU6050_ADDRESS);MyI2C_ReceiveAck();MyI2C_SendByte(RegAddress);MyI2C_ReceiveAck();MyI2C_Start();//变为读地址MyI2C_SendByte(MPU6050_ADDRESS | 0x01);MyI2C_ReceiveAck();Data = MyI2C_ReceiveByte();//读取最后一个字节后给非应答MyI2C_SendAck(1);MyI2C_Stop();return Data;
}void MPU6050_Init(void)
{MyI2C_Init();//配置MPU6050寄存器,详见其介绍部分MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);MPU6050_WriteReg(MPU6050_CONFIG, 0x06);MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);
}//获取芯片ID
uint8_t MPU6050_GetID(void)
{return MPU6050_ReadReg(MPU6050_WHO_AM_I);
}//获取数据寄存器
//使用指针传递地址实现多参数返回
void MPU6050_GetData(int16_t *AccX, int16_t *AccY, int16_t *AccZ,int16_t *GyroX, int16_t *GyroY, int16_t *GyroZ)
{//高八位和低八位分开读取uint8_t DataH, DataL;DataH = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_H);DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//高八位左移八位与低八位合并*AccX = (DataH << 8) | DataL;DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);*AccY = (DataH << 8) | DataL;DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);*AccZ = (DataH << 8) | DataL;DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);*GyroX = (DataH << 8) | DataL;DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);*GyroY = (DataH << 8) | DataL;DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);*GyroZ = (DataH << 8) | DataL;
}

主程序应用层

#include "stm32f10x.h" 
#include "Delay.h"
#include "OLED.h"
#include "MPU6050.h"uint8_t ID;
int16_t AX, AY, AZ, GX, GY, GZ;int main(void)
{OLED_Init();MPU6050_Init();OLED_ShowString(1, 1, "ID:");ID = MPU6050_GetID();OLED_ShowHexNum(1, 4, ID, 2);while(1){MPU6050_GetData(&AX, &AY, &AZ, &GX, &GY, &GZ);OLED_ShowSignedNum(2, 1, AX, 5);OLED_ShowSignedNum(3, 1, AY, 5);OLED_ShowSignedNum(4, 1, AZ, 5);OLED_ShowSignedNum(2, 8, GX, 5);OLED_ShowSignedNum(3, 8, GY, 5);OLED_ShowSignedNum(4, 8, GZ, 5);}
}

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

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

相关文章

每天一道面试题@第一天

1&#xff1a;TCP和UDP的区别&#xff0c;TCP为什么是三次握手&#xff0c;不是两次&#xff1f; 因为TCP是全双工协议&#xff0c;区别在于TCP可靠&#xff0c;UDP不可靠&#xff0c;效率更高。 详解&#xff1a; TCP&#xff08;传输控制协议&#xff09;和 UDP&#xff08;…

一款强大的实时协作Markdown工具 | CodiMD 9.6K ⭐

CodiMD 介绍 CodiMD 是一个开源的实时协作 Markdown 笔记工具&#xff0c;它允许用户在任何平台上共同编辑 Markdown 文档。核心功能是实时协作&#xff0c;它允许多个用户同时编辑同一个文档&#xff0c;并实时看到彼此的更改。支持实时渲染预览&#xff0c;支持超多的富文本格…

若依如何切换 tab 不刷新

方法 如上图配置 菜单中选是否缓存&#xff1a;缓存 资料 前端手册 |RuoYi:

【浙江大学DeepSeek公开课】回望AI三大主义与加强通识教育

回望AI三大主义与加强通识教育 一、人工智能三大主义二、人工智能发展历程三、从 ChatGPT 到 DeepSeek四、人工智能通识教育五、人工智能的挑战与未来 一、人工智能三大主义 符号主义 &#xff1a;逻辑推理&#xff0c;将推理视为计算过程。如苏格拉底三段论&#xff0c;通过前…

边缘计算全透视:架构、应用与未来图景

边缘计算全透视&#xff1a;架构、应用与未来图景 一、产生背景二、本质三、特点&#xff08;一&#xff09;位置靠近数据源&#xff08;二&#xff09;分布式架构&#xff08;三&#xff09;实时性要求高 四、关键技术&#xff08;一&#xff09;硬件技术&#xff08;二&#…

C++——多态、抽象类和接口

目录 多态的基本概念 如何实现多态 在C中&#xff0c;派生类对象可以被当作基类对象使用 编程示例 关键概念总结 抽象类 一、抽象类的定义 基本语法 二、抽象类的核心特性 1. 不能直接实例化 2. 派生类必须实现所有纯虚函数才能成为具体类 3. 可以包含普通成员函数和…

初级达梦dba的技能水准

在x86环境&#xff08;windows、linux&#xff09;安装单机软件&#xff0c;安装客户端创建过至少20套数据库&#xff0c;优化参数并更新过正式许可会用逻辑导出导入以及dmrman备份了解manager工具的使用配置sqllog日志&#xff0c;并能解释输出内容能够分析因磁盘空间不足、内…

监控页面卡顿PerformanceObserver

监控页面卡顿PerformanceObserver 性能观察器掘金 const observer new PerformanceObserver((list) > {}); observer.observe({entryTypes: [longtask], })

智能座舱测试内容与步骤

智能座舱的测试步骤通常包括以下环节&#xff1a; 1.测试环境搭建与准备 • 硬件需求分析&#xff1a;准备测试车辆、服务器与工作站、网络设备以及传感器和执行器模拟器等硬件设备。 • 软件需求分析&#xff1a;选择测试管理软件、自动化测试工具、模拟软件和开发调试工具等。…

Redis——网络模型

目录 前言 1.用户空间和内核空间 1.2用户空间和内核空间的切换 1.3切换过程 2.阻塞IO 3.非阻塞IO 4.IO多路复用 4.1.IO多路复用过程 4.2.IO多路复用监听方式 4.3.IO多路复用-select 4.4.IO多路复用-poll 4.5.IO多路复用-epoll 4.6.select poll epoll总结 4.7.IO多…

电力系统中为什么采用三相交流电?

电力系统中为什么采用三相交流电 电力系统中采用三相交流电&#xff0c;主要是因为它在输电效率、设备使用、能量传输平稳性等方面相比单相交流或直流电具有显著优势。下面我详细解释一下原因&#xff1a; &#x1f31f; 1. 提高输电效率&#xff08;节省电缆材料&#xff09;…

python简介与入门

目录 python初始 python的优势 python的特性 python的应用领域 Linux环境中安装python 下载python3.11.6 安装依赖包 解压python压缩包 安装python 编译及安装 建立软连接 测试python3运行 设置国内pip更新源 更新pip版本&#xff08;必须更新&#xff09; wind…

Web内网渗透知识大全

内网渗透 端口转发 需要三个主机&#xff0c;Windows7、Windows2016、kali Windows7为内网主机 Windows2016为跳板机 kali为攻击机 使用到的工具 netsh、MSF 我们先在Windows7上开启一个80服务&#xff0c;而这个80服务只能由Windows2016访问&#xff0c;kali不能访问 我们…

ffmpeg av_buffer_unref的逻辑实现; av_freep 和 av_freep函数的区别

av_buffer_unref 是 FFmpeg 中用于管理引用计数和内存释放的核心函数&#xff0c;其内部实现机制如下&#xff1a; ‌一、核心流程‌ ‌引用计数递减‌ 函数首先对 AVBufferRef 的 buffer->refcount 进行原子递减操作&#xff08;通过 atomic_fetch_add_explicit 等机制保证…

从 GPS 数据中捕捉城市休闲热点:空间异质性视角下的新框架

从 GPS 数据中捕捉城市休闲热点&#xff1a;空间异质性视角下的新框架 原文&#xff1a;Capturing urban recreational hotspots from GPS data: A new framework in the lens of spatial heterogeneity 1. 背景与意义 城市娱乐活动的重要性&#xff1a; 娱乐活动是城市生活…

rk3568main.cc解析

rk3568main.cc解析 前言解析前言 正点原子rk3568学习,rk官方RKNN_MODEL_ZOO文件中 rknn_model_zoo-main/examples/mobilenet/cpp/main.cc 从执行命令:./build-linux.sh -t rk3568 -a aarch64 -d mobilenet 到: cmake ../../examples/mobilenet/cpp \-DTARGET_SOC=rk356x\…

【实验数据处理matlab程序】程序1:绘制figure文件中曲线的RMS值

立意 在本课题所涉及的实验中&#xff0c;需要将2个拉线式位移传感器中的数据收集并处理&#xff0c;在此基础上求解相应的速度 主要功能 针对一个figure文件中仅包含一个plot&#xff0c;且该plot中包含指定数目的曲线&#xff0c;求这些曲线的RMS值&#xff1b;针对一个fi…

kotlin的kmp编程中遇到Unresolved reference ‘java‘问题

解决办法 打开 File → Project Structure → Project 确保 Project SDK 是 与你的 jvmToolchain 保持一致 如果没有&#xff0c;点击右上角 Add SDK 添加 JDK 路径 同步Sync 然后就正常了。 package org.example.projectimport androidx.compose.animation.AnimatedVi…

静电放电测试中垂直和水平耦合板的作用

在静电放电&#xff08;ESD&#xff0c;Electrostatic Discharge&#xff09;测试中&#xff0c;垂直耦合板&#xff08;Vertical Coupling Plane, VCP&#xff09;和水平耦合板&#xff08;Horizontal Coupling Plane, HCP&#xff09;是模拟设备在实际环境中因静电放电产生的…

Web开发-JavaEE应用JNDI注入RMI服务LDAP服务DNS服务高版本限制绕过

知识点&#xff1a; 1、安全开发-JavaEE-JNDI注入-LADP&RMI&DNS等 2、安全开发-JavaEE-JNDI注入-项目工具&手工原理等 演示案例-WEB开发-JavaEE-JNDI注入&LDAP&RMI服务&DNS服务&高版本限制绕过 JNDI全称为 Java Naming and DirectoryInterface&am…