STM-32:I2C通信协议—软件I2C读写MPU6050

news2025/1/19 23:23:28

目录

  • 一、I2C通信
  • 二、硬件电路
  • 三、I2C时序基本单元
    • 3.1起始和终止
      • 3.1.1起始条件
      • 3.1.2终止条件
    • 3.2发送一个字节
    • 3.3接收一个字节
    • 3.4发送应答
    • 3.5接收应答
  • 四、I2C时序
    • 4.1指定地址写
    • 4.2当前地址读
    • 4.2指定地址读
    • 4.3连续读与写
  • 五、MPU6050简介
  • 六、MPU6050参数
  • 七、硬件电路
  • 八、MPU6050框图
  • 九、应用实例:软件I2C读写MPU6050
    • 9.1接线图
    • 9.2程序代码

一、I2C通信

I2C总线(Inter IC BUS)是由Philips公司开发的一种通用数据总线

两根通信线:SCL(Serial Clock)、SDA(Serial Data)

同步【多一条时钟线,控制从机读写】,半双工【一根通信线】

带数据应答

支持总线挂载多设备(一主多从、多主多从)

控制原理和单片机cpu操作外设原理一样,单片机通过数据总线对寄存器进行读取和写入,而单片机需要通过协议来读写外部模块的寄存器,配置mpu6050的寄存器进而控制硬件电路。

异步通信对传输速率严格,且不能处理进入中断,必须完整发送一个字节,非常依赖硬件外设的支持,必须USART电路才能使用,同步时序比异步时序稳定性更加高,可以暂停传输(同时暂停时钟线)

软件模拟I2C通信:通过软件手动翻转电平实现通信,对硬件的依赖程度低
在这里插入图片描述

二、硬件电路

在这里插入图片描述
所有I2C设备的SCL连在一起,SDA连在一起

主机对SCL线是完全控制,对SDA线不是,在从机发送数据和从机应答的时候,主机才会转交SDA控制器给从机,从机的SCL线只能被动读取。

为了防止总线没有协调好导致电源短路问题,I2C禁止所有设备输出强上拉高电平【不能是推挽输出,会输出高电平】,采用外置弱上拉电阻+开漏输出的电路结构,可以同时兼具输入和输出功能。输入的时候先输出1,再读取输入数据寄存器

即设备的SCL和SDA均要配置成开漏输出模式【只有低电平和浮空两种状态】

SCL和SDA各添加一个上拉电阻,阻值一般为4.7KΩ左右【为了避免高电平造成的引脚浮空,加弱上拉电阻,类似于弹簧,配合开漏输出就是下拉的低电平或不拉的高电平】

CPU和外设内部的SCL和SDA设计如下图所示
在这里插入图片描述
有线与现象,一个从机是低电平,则SDA线就是低电平,只有所有设备输出高电平,SDA线才是高电平,利用这个特性可以实现多主机模式下的时钟同步和总线仲裁,这就是SCL也采用上拉电阻的原因。

三、I2C时序基本单元

在读写时,SCL低电平时,SDA写,SCL高电平时,SDA不变
在起始和结束时,SCL高电平,SDA变化

空闲状态,SCL和SDA由于外挂的上拉电阻拉高致高电平
起始和终止都是由主机产生的,从机始终不会去碰SCL和SDA线

3.1起始和终止

3.1.1起始条件

SCL高电平期间,SDA从高电平切换到低电平
在这里插入图片描述

3.1.2终止条件

SCL高电平期间,SDA从低电平切换到高电平
在这里插入图片描述

3.2发送一个字节

SCL低电平期间,主机将数据位依次放到SDA线上(高位先行),然后释放SCL,从机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可发送一个字节【在发送时,SCL和SDA都由主机进行控制】
在这里插入图片描述
由于有时钟线的控制,主机可以进入中断,此时传输会暂停,时序不会发送变化

3.3接收一个字节

SCL低电平期间,从机将数据位依次放到SDA线上(高位先行),然后释放SCL,主机将在SCL高电平期间读取数据位,所以SCL高电平期间SDA不允许有数据变化,依次循环上述过程8次,即可接收一个字节(主机在接收之前,需要释放SDA)此时从机获得SDA控制权,释放SDA就是主机切换成输入模式,“释放”可以理解为主机原本就是输入模式,在下拉为低电平时是输出模式
在这里插入图片描述

3.4发送应答

发送应答和接收应答就是发送数据的一位和接收数据的一位

主机在接收完一个字节之后,在下一个时钟发送一位数据,数据0表示应答,数据1表示非应答
在这里插入图片描述
发送应答逻辑:主机接收完一个字节数据后,主机会给从机发送一个发送应答,决定是否继续接收,不继续接收就会收回对SDA的控制权

3.5接收应答

主机在发送完一个字节之后,在下一个时钟接收一位数据,判断从机是否应答,数据0表示应答,数据1表示非应答(主机在接收之前,需要释放SDA)
在这里插入图片描述
接收应答逻辑:主机发送完一个字节数据后,发送一个接收应答,释放SDA控制权,若有从机拿到控制权并拉低电平,表示某个从机接收完毕。

四、I2C时序

从机设备地址分为7位和10位,一般相同型号的芯片地址是一样的
当相同型号的芯片挂载在同一总线上时,可以通过最后几位区分,例如mpu6050的最后一位可以由AD0引脚控制,接低电平时地址是1101000,接高电平时地址是1101001

4.1指定地址写

对于指定设备(Slave Address),在指定地址(Reg Address)下,写入指定数据(Data)
在这里插入图片描述
起始后,第一个字节内容必须是从机地址+读写位(0写1读)
接收应答:由于主机释放SDA之后立即就被从机拉低表示接收到该字节,根据线与的特性,此处就没有拉高的波形出现
在写操作时,第二个字节可以是指令控制字(如AD转换器)或寄存器地址(如MPU6050)
在这里插入图片描述

4.2当前地址读

对于指定设备(Slave Address),在当前地址指针指示的地址下,读取从机数据(Data)
在这里插入图片描述
由于读写标志位为1时,主机还来不及发送要读寄存器的地址
从机哪个寄存器的数据呢?取决于之前写入的地址+1,该时序不常用

4.2指定地址读

对于指定设备(Slave Address),在指定地址(Reg Address)下,读取从机数据(Data)
在这里插入图片描述
sr表示重复起始条件,在后面可以加停止时序,地址指针不会消失
在这里插入图片描述

4.3连续读与写

可以连续写入多个字节或读取多个字节,只需要在最后的时序写入多个字节,因为地址指针会在读写后自动加一,所以可以连续操作。读取时,还打算继续读就需要给应答,在结束的字节后给非应答,从机交出SDA控制权,也就是说从机的控制权从读写操作位1到发送应答位为1

五、MPU6050简介

MPU6050是一个6轴姿态传感器,可以测量芯片自身X、Y、Z轴的加速度、角速度参数,通过数据融合,可进一步得到姿态角(欧拉角),常应用于平衡车、飞行器等需要检测自身姿态的场景
MPU6050得出来的姿态角有三种:PITCH(俯仰角)、ROLL(横滚角)、YAW(航向角)【对应XYZ】
3轴加速度计(Accelerometer):测量X、Y、Z轴的加速度
3轴陀螺仪传感器(Gyroscope):测量X、Y、Z轴的角速度
9轴是多了3轴磁力计(磁场强度),补测得的航向角因为磁场和硬件问题造成的积分累积偏差
10轴是多了气压强度
常见的数据融合算法有卡尔曼滤波,互补滤波,互补滤波和卡尔曼滤波能够一定程度解决航向角偏移的问题,而且对于随机干扰也有更优秀的表现,但是是较为复杂的算法。

MPU6050内部有DMP单元,可以进行数据融合和姿态解算,避免了复杂的算法操作和外围电路。可以减轻外围微处理器的工作负担且避免了繁琐的滤波和数据融合,使用方便,只需要通过简单读取寄存器操作便可以获得小车的姿态信息。。
在这里插入图片描述
加速度计测量的是加速度(可以看做测力计,根据牛顿第二定律F=ma可以计算加速度),加速度计具有静态稳定性,不具有动态稳定性
在这里插入图片描述
MPU6050的陀螺仪测量的是角速度,角度可以通过角速度积分得到,具有动态稳定性,不具有静态稳定性
在这里插入图片描述

六、MPU6050参数

16位ADC采集传感器的模拟信号,量化范围:-32768~32767

加速度计满量程选择:±2、±4、±8、±16(g)【量化范围对应加速度计的量程范围,变化大则选大量程,测量范围越广,变化小则选小量程,精度更高】

陀螺仪满量程选择: ±250、±500、±1000、±2000(°/sec)

可配置的数字低通滤波器(平缓信号抖动)

可配置的时钟源

可配置的采样分频

I2C从机地址:
1101000(AD0=0)
关于从机地址的十六进制,有两种表示方法
将二进制转十六进制是0x68当做从机地址,在I2C通信时需要左移一位,按位或上读写位,读1写0
将左移1位的数0xD0作为从机地址,此时在I2C通信时0xD0是写地址,0xD1是读地址
1101001(AD0=1)

七、硬件电路

在这里插入图片描述
SCL和SDA在硬件电路中已经接上拉电阻
XCL和XDA是为了扩展芯片功能,通常是用于外接磁力计(偏航角)和气压计(高度),MPU6050的主机接口可以直接访问扩展芯片的数据,在芯片内部的DMP单元进行数据融合和姿态解算,解算出欧拉角
INT引脚可以设置电平跳变,用于输出芯片内部的中断事件
引脚功能图
在这里插入图片描述

八、MPU6050框图

在这里插入图片描述
灰色部分为传感器,本质上是可变电阻,通过串联分压后输出模拟电压,经过ADC转换后输出数据保存在寄存器中,不存在数据覆盖,每个传感器都有2个字节的寄存器,整个过程是硬件自动化完成
每个传感器都有自测单元self test,通过比较使能和失能后该寄存器的数据差是否在合理范围,进而判断传感器是否有问题
Charge Pump电荷泵,用于升压,电源与电容并联时充电,串联时放电,放电时电压就是放大2倍,由于电容的电压会放完,所以不断的充电放电就能升压,在MPU6050中陀螺仪需要高电压支持所以设计该升压电路
DMP:数字运动处理器是芯片内部自带的姿态解算的硬件算法
通信接口部分,上半部分显示MPU6050作为从机时,可以采用SPI通信,此时引脚的功能发送改变,也可以采用I2C通信。下半部分显示MPU6050作为主机时通过I2C协议与从机进行通信。Bypass Mux为开关,用于控制两路I2C是否为同一个通路,如果为同一个通路,则stm32既可以控制MPU6050又可以控制MPU6050的从设备。

九、应用实例:软件I2C读写MPU6050

9.1接线图

在这里插入图片描述

9.2程序代码

MyI2C.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
/*
封装三个函数操作相应的IO口便于移植
MyI2C_W_SCL
MyI2C_W_SDA
MyI2C_R_SDA
*/
void MyI2C_W_SCL(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_10, (BitAction)BitValue);
	Delay_us(10);
}

void MyI2C_W_SDA(uint8_t BitValue)
{
	GPIO_WriteBit(GPIOB, GPIO_Pin_11, (BitAction)BitValue);
	Delay_us(10);
}

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)
{
	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);//为了兼容sr重复起始条件,先释放sda后释放scl
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(0);
	MyI2C_W_SCL(0);
}

void MyI2C_Stop(void)
{
	MyI2C_W_SDA(0);//为了确保释放sda是高电平,先拉低sda
	MyI2C_W_SCL(1);
	MyI2C_W_SDA(1);
}

void MyI2C_SendByte(uint8_t Byte)
{
	uint8_t i;
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SDA(Byte & (0x80 >> i));//高位先行,按位与取出相应位数,右移得到相应的位
		MyI2C_W_SCL(1);//高位读取sda数据
		MyI2C_W_SCL(0);
	}
}

uint8_t MyI2C_ReceiveByte(void)
{
	uint8_t i, Byte = 0x00;//定义一个字节的数据
	MyI2C_W_SDA(1);//主机释放sda
	for (i = 0; i < 8; i ++)
	{
		MyI2C_W_SCL(1);//scl高电平时放入数据
		if (MyI2C_R_SDA() == 1){
			Byte |= (0x80 >> i);//输出寄存器为1则在该字节的相应位置写入1
		}
		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);//释放sda,而不是输出1
	MyI2C_W_SCL(1);
	AckBit = MyI2C_R_SDA();//读到0则表示从机应答
	MyI2C_W_SCL(0);
	return AckBit;
}


MyI2C.h

#ifndef __MYI2C_H
#define __MYI2C_H

void 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


MPU6050.c

#include "stm32f10x.h"                  // Device header
#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);//指定地址写,修改最低位为1
	MyI2C_ReceiveAck();
	Data = MyI2C_ReceiveByte();
	MyI2C_SendAck(1);//主机收回控制权
	MyI2C_Stop();
	
	return Data;
}
//指定地址写之前需要取消睡眠模式
void MPU6050_Init(void)
{
	MyI2C_Init();
	MPU6050_WriteReg(MPU6050_PWR_MGMT_1, 0x01);//最后三位选择时钟,0x01选择陀螺仪x轴的时钟
	MPU6050_WriteReg(MPU6050_PWR_MGMT_2, 0x00);//不需要待机
	MPU6050_WriteReg(MPU6050_SMPLRT_DIV, 0x09);//10分频
	MPU6050_WriteReg(MPU6050_CONFIG, 0x06);//后三位给110,低通滤波器
	MPU6050_WriteReg(MPU6050_GYRO_CONFIG, 0x18);//中间2位是满量程,给11是最大量程
	MPU6050_WriteReg(MPU6050_ACCEL_CONFIG, 0x18);//中间2位是满量程,给11是最大量程
}

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;//该变量为16位,有指针指向该地址
	
	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;
}
/*
多返回值设计:
1. 在该文件中定义全局变量,extern暴露出去,在main文件中使用
2. 用指针
3. 使用结构体打包


*/




MPU6050.h

#ifndef __MPU6050_H
#define __MPU6050_H

void 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_Reg.h
使用宏定义,将寄存器地址用一个字符串表示

#ifndef __MPU6050_REG_H
#define __MPU6050_REG_H

#define	MPU6050_SMPLRT_DIV		0x19
#define	MPU6050_CONFIG			0x1A
#define	MPU6050_GYRO_CONFIG		0x1B
#define	MPU6050_ACCEL_CONFIG	0x1C

#define	MPU6050_ACCEL_XOUT_H	0x3B
#define	MPU6050_ACCEL_XOUT_L	0x3C
#define	MPU6050_ACCEL_YOUT_H	0x3D
#define	MPU6050_ACCEL_YOUT_L	0x3E
#define	MPU6050_ACCEL_ZOUT_H	0x3F
#define	MPU6050_ACCEL_ZOUT_L	0x40
#define	MPU6050_TEMP_OUT_H		0x41
#define	MPU6050_TEMP_OUT_L		0x42
#define	MPU6050_GYRO_XOUT_H		0x43
#define	MPU6050_GYRO_XOUT_L		0x44
#define	MPU6050_GYRO_YOUT_H		0x45
#define	MPU6050_GYRO_YOUT_L		0x46
#define	MPU6050_GYRO_ZOUT_H		0x47
#define	MPU6050_GYRO_ZOUT_L		0x48

#define	MPU6050_PWR_MGMT_1		0x6B
#define	MPU6050_PWR_MGMT_2		0x6C
#define	MPU6050_WHO_AM_I		0x75

#endif


main.c

#include "stm32f10x.h"                  // Device header
#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.coloradmin.cn/o/414713.html

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

相关文章

用英语翻译中文-汉字英文翻译

中文转英语翻译 作为一款高效、准确的中文转英语翻译软件&#xff0c;我们的产品可以帮助全球用户更好地沟通和合作&#xff0c;实现跨文化交流。 在全球化的今天&#xff0c;中英文翻译已经成为商务、学术、娱乐等各个领域不可或缺的一部分。我们的中文转英语翻译软件是为了…

大学生必备神器

大学生要掌握的办公软件因专业和工作需求而异&#xff0c;但是以下是一些普遍适用于大学生的办公软件&#xff0c;可以帮助提高学习和工作效率&#xff0c;今天就给大家推荐几款大学生常用的软件。 1.OneDrive 这是微软出品的云存储产品&#xff0c;与百度网盘有些类似&#…

龙芯中科官方宣布,龙芯中科企业办公信息化平台全面完成国产化替代

4月4日&#xff0c;龙芯中科官方宣布&#xff0c;龙芯中科企业办公信息化平台全面完成国产化替代。龙芯 ERP 系统全系统使用国产化平台&#xff0c;私有化部署于基于龙芯 3C5000 服务器集群的虚拟化云平台上&#xff0c;使用自研 Loongnix 操作系统、自研 LoongDB 数据库及龙芯…

SpringBoot集成Milo库实现OPC UA客户端:连接、遍历节点、读取、写入、订阅与批量订阅

背景 前面我们搭建了一个本地的 PLC 仿真环境&#xff0c;并通过 KEPServerEX6 读取 PLC 上的数据&#xff0c;最后还使用 UAExpert 作为OPC客户端完成从 KEPServerEX6 这个OPC服务器的数据读取与订阅功能。在这篇文章中&#xff0c;我们将通过 SpringBoot 集成 Milo 库实现一…

idea右边找不到maven窗口不见了的多种解决方法

文章目录1. 文章引言2. 问题的多种解决方法3. 解决问题的其他方法4. 文末总结1. 文章引言 今天在从gitlab上克隆完Maven项目后&#xff0c;在idea中打开时&#xff0c;右边却不见了Maven窗口&#xff0c;如下图所示&#xff1a; 从上图中&#xff0c;你就会发现&#xff0c;明明…

JavaScript变量与基本数据类型

目录 一、声明变量 &#xff08;1&#xff09;let &#xff08;2&#xff09;const &#xff08;3&#xff09;var 二、基本类型 &#xff08;1&#xff09;undefined和null &#xff08;2&#xff09;string &#xff08;3&#xff09;number和bigin &#xff08;4&a…

C#基础复习--数组

数组 目录 数组 数组的类型 数组是对象 声明一维数组或矩形数组 实例化一维数组或矩形数组 访问数组元素 初始化数组 显式初始化一维数组 显式初始化矩形数组 快捷语法 隐式类型数组 交错数组 声明交错数组 快捷实例化 实例化交错数组 交错数组中的子数组 比较矩形数组和交…

【如何使用Arduino控制WS2812B可单独寻址的LED】

【如何使用Arduino控制WS2812B可单独寻址的LED】 1. 概述2. WS2812B 发光二极管的工作原理3. Arduino 和 WS2812B LED 示例3.1 例 13.2 例 24. 使用 WS2812B LED 的交互式 LED 咖啡桌4.1 原理图4.2 源代码在本教程中,我们将学习如何使用 Arduino 控制可单独寻址的 RGB LED 或 …

【数据结构】顺序表详解

本章要分享到内容是数据结构线性表的内容&#xff0c;那么学习他的主要内容就是对数据的增删查改的操作。 以下为目录方便阅读 目录 1.线性表中的顺序表和顺序表 2.顺序表 2.1概念和结构 2.2动态顺序表使用场景 比如我们看到的所显示出来的群成员的列表这样所展示出来的数…

Java——重建二叉树

题目链接 重建二叉树 题目描述 给定节点数为 n 的二叉树的前序遍历和中序遍历结果&#xff0c;请重建出该二叉树并返回它的头结点。 例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6}&#xff0c;则重建出如下图所示。 题目示例 示例1 输入&…

RK3568平台开发系列讲解(驱动基础篇)V4L2 用户空间 API 说明

🚀返回专栏总目录 文章目录 一、V4L2 用户空间 API二、打开视频设备三、查询设备功能沉淀、分享、成长,让自己和他人都能有所收获!😄 📢设备驱动的主要目的是控制和利用底层硬件,同时向用户展示功能。 这些用户可以是在用户空间或其他内核驱动中运行的应用。 本篇我们…

KIOPTRIX: LEVEL 5通关详解

环境配置 虚拟机网络适配器删了重新上一个就行 信息收集 漏洞发现 两个端口的web页面都没有显著的特征,尝试扫描路径,也没有扫到有价值的信息 8080端口访问被拒绝 在80端口的web页面源码中发现信息 访问 注意到title是pChart 尝试利用 可以知道有目录穿越和xss 我们可以尝…

Java实现根据利润提成发放的奖金,求1感叹号+2感叹号+……+20的和这两个程序的代码

目录 前言 一、根据利润提成发放的奖金 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 二、求1!2!3!……20的和 1.1运行流程&#xff08;思想&#xff09; 1.2代码段 1.3运行截图 前言 1.因多重原因&#xff0c;本博文有两个代码程序组成&#xff…

游戏工厂:AIGC/ChatGPT与流程式游戏开发(码客 卢益贵)

关键词&#xff1a;AI&#xff08;AIGC、ChatGPT、文心一言&#xff09;、流程式管理、好莱坞电影流程、电影工厂、游戏工厂、游戏开发流程、游戏架构、模块化开发 一、前言 开发周期长、人工成本高、成功率低等是游戏公司融资困难的罪因。所以有的公司凭一个爆款游戏一骑绝尘…

比GPT-4 Office还炸裂,阿里版GPT全家桶来袭

疯狂3月的那一天&#xff0c;一切还历历在目。 微软突然在发布会上放出大招&#xff0c;用Microsoft 365 Copilot掀起了办公软件革命。 而今天&#xff0c;阿里也放出一枚重磅炸弹——阿里版的Copilot也要来了&#xff01; 并且比微软更彻底的是&#xff0c;阿里全系产品也都…

“我用 ChatGPT 造了一个零日漏洞,成功逃脱了 69 家安全机构的检测!”

一周以前&#xff0c;图灵奖得主 Yoshua Bengio、伯克利计算机科学教授 Stuart Russell、特斯拉 CEO 埃隆马斯克、苹果联合创始人 Steve Wozniak 等在内的数千名 AI 学者、企业家联名发起一则公开信&#xff0c;建议全球 AI 实验室立即停止训练比 GPT-4 更强大的模型&#xff0…

Python高级编程 type、object、class的区别 python中常见的内置类型 魔法函数

python中一切皆对象 代码块&#xff1a; a 1 print(type(a)) print(type(int))控制台输出&#xff1a; <class int> <class type>也就是说在python中int类是由type类生成的&#xff0c;而数字1是由int类生成的。 代码块&#xff1a; b "abc" prin…

SHELL函数可课后作业

一、题目 1、编写函数&#xff0c;实现打印绿色OK和红色FAILED 判断是否有参数&#xff0c;存在为Ok&#xff0c;不存在为FAILED 2、编写函数&#xff0c;实现判断是否无位置参数&#xff0c;如无参数&#xff0c;提示错误 3、编写函数实现两个数字做为参数&#xff0c;返回最…

Window中,Visual Studio 2022(C++)环境下安装OpenCV教程(不用Cmake版本)

Window中&#xff0c;Visual Studio 2022(C)环境下安装OpenCV教程 本教程主要为了方便小白安装C版本的OpenCV。 1. 第一步&#xff1a;下载官方OpenCV 下载后&#xff0c;在本地安装即可&#xff0c;注意记住安装路径&#xff0c;后续需要&#xff01; 2. 配置系统环境变量…

人口普查数据集独热编码转换

人口普查数据集独热编码转换 描述 在机器学习中&#xff0c;数据的表示方式对于模型算法的性能影响很大&#xff0c;寻找数据最佳表示的过程被称为“特征工程”&#xff0c;在实际应用中许多特征并非连续的数值&#xff0c;比如国籍、学历、性别、肤色等&#xff0c;这些特征…