STM32 I2C

目录

I2C通信

 软件I2C读写MPU6050

I2C通信外设

硬件I2C读写MPU6050


I2C通信

R/W:0写1读

十轴:3轴加速度,3轴角速度,3轴磁场强度和一个气压强度

 软件I2C读写MPU6050

MyI2C.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"

/**
  * @brief  为I2C的SCL线写入数据
  * @param  BitValue:要写入的数据
  * @retval 无
  */
void MyI2C_W_SCL(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_10,(BitAction)BitValue);
    Delay_us(10);//防止引脚反转速度过快,外设跟不上
}

/**
  * @brief  为I2C的SDA线写入数据
  * @param  BitValue:要写入的数据
  * @retval 无
  */
void MyI2C_W_SDA(uint8_t BitValue)
{
    GPIO_WriteBit(GPIOB,GPIO_Pin_11,(BitAction)BitValue);
    Delay_us(10);//防止引脚反转速度过快,外设跟不上
}

/**
  * @brief  读取I2C的SDA线中的数据
  * @param  无
  * @retval SDA中的数据
  */
uint8_t MyI2C_R_SDA(void)
{
    uint8_t BitValue;
    BitValue = GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_11);
    Delay_us(10);
    return BitValue;
}

/**
  * @brief  初始化GPIO引脚
  * @param  无
  * @retval 无
  */
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);
    //将SCL与SDA初始置为高电平(空闲)

}

/**
  * @brief  开启I2C通信
  * @param  无
  * @retval 无
  */
void MyI2C_Start(void)
{
    MyI2C_W_SDA(1);
    MyI2C_W_SCL(1);
    //将两根线都置为高电平,准备开始时序
    
    MyI2C_W_SDA(0);
    MyI2C_W_SCL(0);
    //先将SDA拉低,再将SCL拉低形成起始条件
}

/**
  * @brief  终止I2C通信
  * @param  无
  * @retval 无
  */
void MyI2C_Stop(void)
{
    MyI2C_W_SDA(0);
    //确保SDA能产生上升沿,先进行拉低
    
    MyI2C_W_SCL(1);
    MyI2C_W_SDA(1);
    //在SCL处于高电平时,SDA产生上升沿形成终止条件
}

/**
  * @brief  使用I2C发送一个字节
  * @param  Byte:发送的字节数据
  * @retval 无
  */
void MyI2C_SendByte(uint8_t Byte)
{
    uint8_t i;
    for(i = 0;i<8;i++)
    {
        MyI2C_W_SDA(Byte & (0x80 >> i));//取出最高位
        //即使进行运算后结果为0x80,写入的还是只有1

        MyI2C_W_SCL(1);//释放SCL进行发送
        MyI2C_W_SCL(0);//结束一次发送
    }
}

/**
  * @brief  使用I2C接收一个字节
  * @param  无
  * @retval 接收到的字节数据
  */
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为高电平主机进行读取SDA上的数据
        if(MyI2C_R_SDA() == 1)//此时接收为1
        {
            Byte |= (0x80 >> i);//读到数据存入Byte
        }
        MyI2C_W_SCL(0);//拉低SCL完成一次读取
    }
    return Byte;
}

/**
  * @brief  主机接收完一个字节后发送应答
  * @param  AckBit:应答位,0为应答,1为不应答
  * @retval 无
  */
void MyI2C_SendAck(uint8_t AckBit)
{
    //接收完成时SCL为低电平
    MyI2C_W_SDA(AckBit);
    MyI2C_W_SCL(1);//释放SCL进行发送
    MyI2C_W_SCL(0);//结束一次发送
}

/**
  * @brief  从机发送完一个字节后接收主机应答
  * @param  无
  * @retval 从机的应答值
  */
uint8_t MyI2C_ReceiveAck(void)
{
    //发送完成时SCL为低电平
    uint8_t AckBit;
    MyI2C_W_SDA(1);//接收前先释放SDA
    //这里主机输出1,并不是强制SDA为高电平,而是释放SDA
    //进行通信时,主机释放SDA,从机会暂时获得控制权
    MyI2C_W_SCL(1);//释放SCL进行接收
    AckBit = MyI2C_R_SDA();//进行读取SDA
    MyI2C_W_SCL(0);//结束一次接收
    return AckBit;
}

MPU6050.c

#include "stm32f10x.h"                  // Device header
#include "MyI2C.h"
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS     0xD0

/**
  * @brief  MPU6050指定地址写数据进寄存器
  * @param  RegAddress:写入寄存器位置
  * @param  Data:写入寄存器数据
  * @retval 无
  */
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)//指定地址写寄存器
{
    MyI2C_Start();//开启I2C时序
    MyI2C_SendByte(MPU6050_ADDRESS);//从机地址加R(1)/W(0)
    MyI2C_ReceiveAck();//接收应答
    MyI2C_SendByte(RegAddress);//这个字节会存在MPU6050的当前地址指针中
    MyI2C_ReceiveAck();//接收应答
    MyI2C_SendByte(Data);//发送数据
    MyI2C_ReceiveAck();//接收应答
    MyI2C_Stop();//结束I2C时序
}

/**
  * @brief  MPU6050指定地址读寄存器数据
  * @param  RegAddress:寄存器位置
  * @retval 寄存器中存的数据
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    uint8_t Data;
    //写的时序
    MyI2C_Start();//开启I2C时序
    MyI2C_SendByte(MPU6050_ADDRESS);//从机地址加R(1)/W(0)
    MyI2C_ReceiveAck();//接收应答
    MyI2C_SendByte(RegAddress);//这个字节会存在MPU6050的当前地址指针中
    MyI2C_ReceiveAck();//接收应答
    
    //读的时序
    MyI2C_Start();//再次开启I2C时序
    MyI2C_SendByte(MPU6050_ADDRESS | 0x01);//从机地址+读
    MyI2C_ReceiveAck();//接收应答
    
    //此时控制权由从机控制(主机接收一个字节数据)
    Data = MyI2C_ReceiveByte();//主机接收一个字节数据
    MyI2C_SendAck(1);//发送应答(如果需要接收多个字节应答就给0,结束则给1)
    //主机收回总线控制权
    MyI2C_Stop();
    
    return Data;
}

/**
  * @brief  初始化MPU6050
  * @param  无
  * @retval 无
  */
void MPU6050_Init(void)
{
    MyI2C_Init();
    
    MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);//配置电源管理寄存器1
    //解除睡眠模式,并选择使用X轴陀螺仪时钟
    MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);//配置电源管理寄存器2
    //六个轴均不待机
    MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);//配置分频寄存器(值越小越快)
    //十分频
    MPU6050_WriteReg(MPU6050_CONFIG,0x06);//配置寄存器,(外部同步+数字低通滤波器)
    MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);//陀螺仪配置寄存器(自测使能+满量程选择)
    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);//加速度计配置寄存器(自测+满量程配置+高通滤波器)
}

/**
  * @brief  获得芯片ID号
  * @param  无
  * @retval 芯片ID
  */
uint8_t MPU6050_GetID(void)
{
    return MPU6050_ReadReg(MPU6050_WHO_AM_I);//读取芯片ID号
}

/**
  * @brief  读取加速度以及角速度数据
  * @param  AccX:X轴方向加速度
  * @param  AccY:Y轴方向加速度
  * @param  AccZ:Z轴方向加速度
  * @param  GyroX:X轴方向角速度
  * @param  GyroY:Y轴方向角速度
  * @param  GyroZ:Z轴方向角速度
  * @retval 无
  */
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);//加速度X轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低八位
    *AccX = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);//加速度Y轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);//低八位
    *AccY = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);//低八位
    *AccZ = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);//低八位
    *GyroX = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);//低八位
    *GyroY = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);//低八位
    *GyroZ = (DataH << 8) | DataL;
}

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 KeyNum;

int16_t AX,AY,AZ,GX,GY,GZ;

int main(void)
{
	OLED_Init();
   
    MPU6050_Init();
    
    OLED_ShowString(1,1,"ID:");
    OLED_ShowHexNum(1,4,MPU6050_GetID(),3);
    
	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);
	}
	
}

I2C通信外设

GPIO口需要配置为复用开漏输出模式。复用:就是GPIO的状态是交由片上外设来控制的,开漏输出,是I2C所规定的。

硬件I2C读写MPU6050

MPU6050.c

#include "stm32f10x.h"                  // Device header
#include "MPU6050_Reg.h"

#define MPU6050_ADDRESS     0xD0

/**
  * @brief  监控事件完成并延时退出
  * @param  I2Cx:选择的I2C资源
  * @param  I2C_EVENT:等待I2C完成的事件
  * @retval 无
  */
void MPU6050_WaitEvent(I2C_TypeDef* I2Cx, uint32_t I2C_EVENT)
{
    uint32_t TimeOut;
    TimeOut = 10000;
    while(I2C_CheckEvent(I2C2,I2C_EVENT) != SUCCESS)//等待Ev5事件完成
    {
        TimeOut -- ;
        if(TimeOut == 0)
        {
            break;
        }
    }
}

/**
  * @brief  MPU6050指定地址写数据进寄存器
  * @param  RegAddress:写入寄存器位置
  * @param  Data:写入寄存器数据
  * @retval 无
  */
void MPU6050_WriteReg(uint8_t RegAddress,uint8_t Data)//指定地址写寄存器
{
    
    I2C_GenerateSTART(I2C2,ENABLE);//生成起始条件(非阻塞式,需要标志位判断)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待Ev5事件完成
    
    I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);//发送从机地址(自带接收应答)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//等待发送Ev6事件完成
    
    I2C_SendData(I2C2,RegAddress);//发送写入地址
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTING);//等待Ev8事件完成
    
    I2C_SendData(I2C2,Data);//发送数据(只有一个字节,发完紧接结束)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待Ev8_2事件完成
    
    I2C_GenerateSTOP(I2C2,ENABLE);
}

/**
  * @brief  MPU6050指定地址读寄存器数据
  * @param  RegAddress:寄存器位置
  * @retval 寄存器中存的数据
  */
uint8_t MPU6050_ReadReg(uint8_t RegAddress)
{
    uint8_t Data;
    //写的时序
    I2C_GenerateSTART(I2C2,ENABLE);//生成起始条件(非阻塞式,需要标志位判断)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待Ev5事件完成
    
    I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Transmitter);//发送从机地址(自带接收应答)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED);//等待发送Ev6事件完成(发送)
    
    I2C_SendData(I2C2,RegAddress);//发送写入地址
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_TRANSMITTED);//等待Ev8事件完成
    
    //读的时序
    I2C_GenerateSTART(I2C2,ENABLE);//生成重复起始条件
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_MODE_SELECT);//等待发送Ev5事件完成
    I2C_Send7bitAddress(I2C2,MPU6050_ADDRESS,I2C_Direction_Receiver);//发送从机地址并改为接收方向(自带接收应答)
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED);//等待发送Ev6事件完成(接收)
    
    //清除响应和停止条件的产生位(在最后一个数据之前就要将Ack置零以及设置Stop终止条件)
    I2C_AcknowledgeConfig(I2C2,DISABLE);//设置Ack = 0,不给应答
    I2C_GenerateSTOP(I2C2,ENABLE);//配置停止位
    MPU6050_WaitEvent(I2C2,I2C_EVENT_MASTER_BYTE_RECEIVED);//等待发送Ev7事件完成
    //此时一个字节的数据以及存在DR中
    
    //读取DR即可获得字节
    Data = I2C_ReceiveData(I2C2);
    
    I2C_AcknowledgeConfig(I2C2,ENABLE);//方便接收多个字节
    
    return Data;
}

/**
  * @brief  初始化MPU6050
  * @param  无
  * @retval 无
  */
void MPU6050_Init(void)
{
    //开启对应时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2,ENABLE);
    
    //配置GPIO
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;//复用开漏
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB,&GPIO_InitStructure);
    
    //配置I2C
    I2C_InitTypeDef I2CInitStructure;
    I2CInitStructure.I2C_Mode = I2C_Mode_I2C;//I2C模式
    I2CInitStructure.I2C_ClockSpeed = 50000;//时钟速度(标准100 kHz,快速400 kHz)
    I2CInitStructure.I2C_DutyCycle = I2C_DutyCycle_2;//时钟占空比(>100kHz才有用)
    I2CInitStructure.I2C_Ack = I2C_Ack_Enable;//配置Ack位
    I2CInitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;//Stm32作为从机能响应几位地址
    I2CInitStructure.I2C_OwnAddress1 = 0x00;//指定stm32自身地址
    I2C_Init(I2C2,&I2CInitStructure);
    
    I2C_Cmd(I2C2,ENABLE);
    
    MPU6050_WriteReg(MPU6050_PWR_MGMT_1,0x01);//配置电源管理寄存器1
    //解除睡眠模式,并选择使用X轴陀螺仪时钟
    MPU6050_WriteReg(MPU6050_PWR_MGMT_2,0x00);//配置电源管理寄存器2
    //六个轴均不待机
    MPU6050_WriteReg(MPU6050_SMPLRT_DIV,0x09);//配置分频寄存器(值越小越快)
    //十分频
    MPU6050_WriteReg(MPU6050_CONFIG,0x06);//配置寄存器,(外部同步+数字低通滤波器)
    MPU6050_WriteReg(MPU6050_GYRO_CONFIG,0x18);//陀螺仪配置寄存器(自测使能+满量程选择)
    MPU6050_WriteReg(MPU6050_ACCEL_CONFIG,0x18);//加速度计配置寄存器(自测+满量程配置+高通滤波器)
}

/**
  * @brief  获得芯片ID号
  * @param  无
  * @retval 芯片ID
  */
uint8_t MPU6050_GetID(void)
{
    return MPU6050_ReadReg(MPU6050_WHO_AM_I);//读取芯片ID号
}

/**
  * @brief  读取加速度以及角速度数据
  * @param  AccX:X轴方向加速度
  * @param  AccY:Y轴方向加速度
  * @param  AccZ:Z轴方向加速度
  * @param  GyroX:X轴方向角速度
  * @param  GyroY:Y轴方向角速度
  * @param  GyroZ:Z轴方向角速度
  * @retval 无
  */
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);//加速度X轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_XOUT_L);//低八位
    *AccX = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_H);//加速度Y轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_YOUT_L);//低八位
    *AccY = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_ACCEL_ZOUT_L);//低八位
    *AccZ = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_XOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_XOUT_L);//低八位
    *GyroX = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_YOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_YOUT_L);//低八位
    *GyroY = (DataH << 8) | DataL;
    
    DataH = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_H);//加速度Z轴高八位
    DataL = MPU6050_ReadReg(MPU6050_GYRO_ZOUT_L);//低八位
    *GyroZ = (DataH << 8) | DataL;
}

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Java中抽象类和接口的区别

抽象类和接口都是 Java 中多态的常见使用方式. 都需要重点掌握. 同时又要认清两者的区别(重要!!! 常见面试题)。 核心区别: 抽象类中可以包含普通方法和普通字段, 这样的普通方法和字段可以被子类直接使用(不必重写而重写抽象方法), 而接口中不能包含普通方法&#xff08;接口…

大模型Layer normalization知识

Layer Norm 的计算公式 Layer Norm&#xff08;层归一化&#xff09;是一种用于神经网络中的归一化技术&#xff0c;用于提高模型的训练效果和泛化能力。 RMS Norm 的计算公式 RMS Norm 的作用是通过计算输入 X 的均方根&#xff0c;将每个样本的特征进行归一化&#xff0c;使…

蓝桥杯嵌入式第10届真题(完成) STM32G431

蓝桥杯嵌入式第10届真题(完成) STM32G431 题目 main.c /* USER CODE BEGIN Header */ /********************************************************************************* file : main.c* brief : Main program body********************************…

Linux---守护进程

运行的这个进程&#xff0c;它的pid和gpid(进程组ID)一样&#xff0c;它是自成一组的。 这就是一个进程组。 进程组和任务有什么关系&#xff1f; 将任务指派给进程组。任务都是由进程组去完成的。 可以发现&#xff0c;这三个进程的会话id1351都是一样的&#xff0c;多个任…

windows10|音视频剪辑|FFMPEG录屏和网络推流源初步的生成

前言&#xff1a; FFMPEG的功能强大是毋庸置疑的&#xff0c;那么录屏的需求大家在某些时候大家可能是非常需要的&#xff0c;例如&#xff0c;现有的项目需要演示&#xff0c;因此录制一段演示视频&#xff1b;亦或者做内容分发直播的&#xff0c;比如游戏主播&#xff0c;需…

使用word2vec+tensorflow自然语言处理NLP

目录 介绍&#xff1a; 搭建上下文或预测目标词来学习词向量 建模1&#xff1a; 建模2&#xff1a; 预测&#xff1a; 介绍&#xff1a; Word2Vec是一种用于将文本转换为向量表示的技术。它是由谷歌团队于2013年提出的一种神经网络模型。Word2Vec可以将单词表示为高维空间…

987. 二叉树的垂序遍历 - 力扣(LeetCode)

题目描述 给你二叉树的根结点 root &#xff0c;请你设计算法计算二叉树的 垂序遍历 序列。 对位于 (row, col) 的每个结点而言&#xff0c;其左右子结点分别位于 (row 1, col - 1) 和 (row 1, col 1) 。树的根结点位于 (0, 0) 。 二叉树的 垂序遍历 从最左边的列开始直到…

VM和Linux安装

VM和Linux安装 一、下载VM 1.官网地址&#xff1a;https://www.vmware.com/cn.html 2.其他地址&#xff1a;http://ww7.nocmd.com/windows/740.html 许可证这个&#xff0c;大家可以自己上网搜索&#xff0c;很容易就搜索到就可以使用了 上面内容就是安装VM的步骤 安…

LeetCode、1318. 或运算的最小翻转次数【中等,位运算】

文章目录 前言LeetCode、1318. 或运算的最小翻转次数【中等&#xff0c;位运算】题目链接与分类题解位运算 资料获取 前言 博主介绍&#xff1a;✌目前全网粉丝2W&#xff0c;csdn博客专家、Java领域优质创作者&#xff0c;博客之星、阿里云平台优质作者、专注于Java后端技术领…

线性代数的本质 2 线性组合、张成的空间、基

一种新的看待方式 对于一个向量&#xff0c;比如说&#xff0c;如何看待其中的3和-2&#xff1f; 一开始&#xff0c;我们往往将其看作长度&#xff08;从向量的首走到尾部&#xff0c;分别在x和y上走的长度&#xff09;。 在有了数乘后&#xff0c;我们可以将其视为对向量进行…

【心得】调试SPI+DMA的一点心得

由于项目需要&#xff0c;STM32F303跟STM32F405之间要用到DMASPI口来估大量数据传输&#xff0c;实现两边的数据收发。 开始只用到MISO&#xff0c;MOSI&#xff0c;跟CLK三个信号&#xff0c;STM32F303配置成主机&#xff0c;18M的波特率&#xff0c;用DMA发4K的Buffer的数据…

蓝牙BLE学习-安全

1.基本概念 蓝牙标准规定了5种基本的安全服务 身份验证:根据通信设备的蓝牙地址验证其身份。蓝牙不提供本地用户身份验证。保密性:确保只有授权的设备才能访问和查看传输的数据&#xff0c;防止窃听造成的信息泄露。授权(Authorization):在允许设备使用某项服务之前&#xff…

探索Gorm - Golang流行的数据库ORM框架

&#x1f3f7;️个人主页&#xff1a;鼠鼠我捏&#xff0c;要死了捏的主页 &#x1f3f7;️系列专栏&#xff1a;Golang全栈-专栏 &#x1f3f7;️个人学习笔记&#xff0c;若有缺误&#xff0c;欢迎评论区指正 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&…

Codeforces Round 303 (Div. 2)C. Kefa and Park(DFS、实现)

文章目录 题面链接题意题解代码总结 题面 链接 C. Kefa and Park 题意 求叶节点数量&#xff0c;叶节点满足&#xff0c;从根节点到叶节点的路径上最长连续1的长度小于m 题解 这道题目主要是实现&#xff0c;当不满足条件时直接返回。 到达叶节点后统计答案&#xff0c;用…

kali系统概述、nmap扫描应用、john破解密码、抓包概述、以太网帧结构、抓包应用、wireshark应用、nginx安全加固、Linux系统加固

目录 kali nmap扫描 使用john破解密码 抓包 封装与解封装 网络层数据包结构 TCP头部结构​编辑 UDP头部结构 实施抓包 安全加固 nginx安全 防止缓冲区溢出 Linux加固 kali 实际上它就是一个预安装了很多安全工具的Debian Linux [rootmyhost ~]# kali resetkali …

spring boot自动装配原理

spring boot自动装配是通过启动类SpringBootApplication默认扫描本包极其子包&#xff0c;要想扫描外部文件需要在启动类上加相应注解

【Spring MVC篇】Cookie和Session的获取 Header的获取

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【Spring MVC】 本专栏旨在分享学习Spring MVC的一点学习心得&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; Cookie是客户端保存用…

Vue--》深入学习Tailwind CSS掌握优雅而高效的前端样式开发

Tailwind CSS是一个非常强大且灵活的CSS框架&#xff0c;适用于开发者希望高度定制化界面样式的项目。今天博主就 Tailwind CSS 做一个简单介绍以及案例讲解&#xff0c;争取读者阅读文章后入门。 仅靠一篇文章博主也不可能将Tailwind CSS所有内容讲解的面面俱到&#xff0c;在…

算法学习——LeetCode力扣二叉树篇5

算法学习——LeetCode力扣二叉树篇5 513. 找树左下角的值 513. 找树左下角的值 - 力扣&#xff08;LeetCode&#xff09; 描述 给定一个二叉树的 根节点 root&#xff0c;请找出该二叉树的 最底层 最左边 节点的值。 假设二叉树中至少有一个节点。 示例 示例 1: 输入: r…

CorelDRAW2024国内专业个人免费版下载

CorelDRAW是一款屡获殊荣的图形和图像编辑软件&#xff0c;包含两个绘图应用程序&#xff1a;一个用于矢量图及页面设计&#xff0c;另一个用于图像编辑。自1989年进入中国市场以来&#xff0c;CorelDRAW不断推出新的版本和功能&#xff0c;以满足用户不断变化的需求。 CorelD…