当前位置: 首页 > news >正文

ARM I2C通信

1.概念

	I2C总线是PHLIPS公司在八十年代初推出的一种串行的半双工同步总线,主要用于连接整体电路

2.IIC总线硬件连接

在这里插入图片描述

1.IIC总线支持多主机多从机,但是在实际开发过程中,大多数采用单主机多从机模式
2.挂接到IIC总线上,每个从机设备都有自己的7bit从机地址
3.在总线上,发送数据的叫做发送器,接收数据叫做接收器
4.主动发起数据的叫做主机,只能被动接收数据的叫做从机
5.时钟信号由主机产生,作用:给从机,为了IIC总线上传输数据同步

3.IIC总线时序

3.1起始信号

在这里插入图片描述

在SCL为高电平期间,SDA从高到低的变化(下降沿),属于起始信号
起始信号由主机产生,起始信号产生之后,总线占用状态

3.2停止信号

在这里插入图片描述

在SCL为高电平期间,SDA从低到高的变化(上升沿),属于终止信号
停止信号由主机产生,停止信号产生之后,总线空闲状态

3.3数据传输信号(读写)

在这里插入图片描述

1.在SCL为高电平期间,数据线上的数据保持稳定,接收器从数据线上读取数据
2.在SCL为低电平期间,数据线上的数据允许变化,发送器向数据线上写入数据

3.4应答信号

在这里插入图片描述

1.每一个字节必须保证是8位长度。数据传送时,先传送高位,在发送低位,每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位)
2.发送器在发送完8位数据位之后,接收器在第9个时钟周期,返回一个应答信号(0),或者非应答信号(1)在第9个时钟周期,接收器向数据线上写入数据在第9个时钟周期,发送器从数据线上读取数据如果读取到0,代表应答信号如果读取到1,代表非应答信号

3.5寻址

在这里插入图片描述

1.IIC总线上传输数据是广义的,可以传输地址信号,也可以传输数据信号
2.主机在产生起始信号之后,必须传送7位从机地址,加上读写位
3.用0表示写,用1表示读

4.IIC框图

在这里插入图片描述

5.IIC总线协议

5.1主机给从机发送一个字节

在这里插入图片描述

5.2主机给从机发送多个连续字节

在这里插入图片描述

5.3主机从从机读一个字节

在这里插入图片描述

5.4主机从从机读多个连续字节

在这里插入图片描述

6.GPIO模拟IIC协议

在这里插入图片描述

7.分析SI7006芯片手册

7.1思路

1.分析SI7006芯片手册内部实现框图
2.分析SI7006从机地址
3.分析SI7006芯片通信协议
4.分析找到采集温湿度传感器命令码
5.找到将采集的模拟量转换为数字量的公式
6.分析SI7006初始化的值

7.2从机地址

在这里插入图片描述

通过以上分析可知,si7006芯片从机地址0x40
从机地址 + 读:0x40 << 1 | 1
从机地址 + 写:0x40 << 1 | 0

7.3分析命令码

在这里插入图片描述

7.4协议

在这里插入图片描述

7.5公式

在这里插入图片描述
在这里插入图片描述

7.6初始化值

在这里插入图片描述

8.代码

// si7006.h
#ifndef __SI7006_H__
#define __SI7006_H__#include "iic.h"
#define SI7006_SLAVE 0x40void si7006_init(void);unsigned short si7006_read_hum_data(unsigned char slave_addr, unsigned char cmd_code);
short si7006_read_temp_data(unsigned char slave_addr, unsigned char cmd_code);#endif //__SI7006_H__
// si7006.c
#include "iic.h"
#include "si7006.h"
/** 函数名:si7006_init* 函数功能:SI7006芯片的初始化* 函数参数:无* 函数返回值:无*/
extern void delay(int ms);
// 往SI7006芯片0XE6写入0X3A
void si7006_init(void)
{// I2初始化i2c_init();// 发送起始信号i2c_start();// 主机发送7位从机地址+1位写位i2c_write_byte(0X40 << 1 | 0);// 等待从机回应i2c_wait_ack();// 发送寄存器地址i2c_write_byte(0XE6);// 等待从机回应i2c_wait_ack();// 发送要写的数据i2c_write_byte(0X3A);// 等待从机回应i2c_wait_ack();// 发送终止信号i2c_stop();
}
/** 函数名:si7006_read_hum_data* 函数功能:读取SI7006的湿度转换结果* 函数参数:*     slave_addr : 从机地址*     cmd_code : 命令码* 函数返回值:湿度测量的数字量*/
unsigned short si7006_read_hum_data(unsigned char slave_addr,unsigned char cmd_code)
{unsigned short dat;			// 保存读取到的湿度数据unsigned char dat_h, dat_l; // 保存读取到的数据的高八位和低八位// 发送起始信号i2c_start();// 主机发送7位从机地址+1位写位i2c_write_byte(slave_addr << 1 | 0);// 等待从机回应i2c_wait_ack();// 发送寄存器地址i2c_write_byte(cmd_code);// 等待从机回应i2c_wait_ack();// 发送第二次起始信号i2c_start();// 主机发送7位从机地址+1位写位i2c_write_byte(slave_addr << 1 | 1);// 等待从机回应i2c_wait_ack();// 延时等待从机测量数据delay(100);// 读取数据的高8位dat_h = i2c_read_byte(0); // 读取完毕发送应答信号// 读取数据的低8位dat_l = i2c_read_byte(1); // 读取完毕发送非应答信号// 发送停止信号i2c_stop();// 将读取到的数据整合到一起dat = (dat_h << 8) | dat_l;return dat;
}
/** 函数名:si7006_read_temp_data* 函数功能:读取SI7006的温度转换结果* 函数参数:*     slave_addr : 从机地址*     cmd_code : 命令码* 函数返回值:温度测量的数字量*/
short si7006_read_temp_data(unsigned char slave_addr,unsigned char cmd_code)
{short dat;		   // 保存读取到的温度数据char dat_h, dat_l; // 保存读取到的数据的高八位和低八位// 发送起始信号i2c_start();// 主机发送7位从机地址+1位写位i2c_write_byte(slave_addr << 1 | 0);// 等待从机回应i2c_wait_ack();// 发送寄存器地址i2c_write_byte(cmd_code);// 等待从机回应i2c_wait_ack();// 发送第二次起始信号i2c_start();// 主机发送7位从机地址+1位写位i2c_write_byte(slave_addr << 1 | 1);// 等待从机回应i2c_wait_ack();// 延时等待从机测量数据delay(100);// 读取数据的高8位dat_h = i2c_read_byte(0); // 读取完毕发送应答信号// 读取数据的低8位dat_l = i2c_read_byte(1); // 读取完毕发送非应答信号// 发送停止信号i2c_stop();// 将读取到的数据整合到一起dat = (dat_h << 8) | dat_l;return dat;
}
// iic.h
#ifndef __IIC_H__
#define __IIC_H__
#include "stm32mp1xx_gpio.h"
#include "stm32mp1xx_rcc.h"
// #include "gpio.h"
/* 通过程序模拟实现I2C总线的时序和协议* GPIOF ---> AHB4* I2C1_SCL ---> PF14* I2C1_SDA ---> PF15** */#define SET_SDA_OUT                     \do                                  \{                                   \GPIOF->MODER &= (~(0x3 << 30)); \GPIOF->MODER |= (0x1 << 30);    \} while (0)
#define SET_SDA_IN                      \do                                  \{                                   \GPIOF->MODER &= (~(0x3 << 30)); \} while (0)#define I2C_SCL_H                   \do                              \{                               \GPIOF->BSRR |= (0x1 << 14); \} while (0)
#define I2C_SCL_L                  \do                             \{                              \GPIOF->BRR |= (0x1 << 14); \} while (0)#define I2C_SDA_H                   \do                              \{                               \GPIOF->BSRR |= (0x1 << 15); \} while (0)
#define I2C_SDA_L                  \do                             \{                              \GPIOF->BRR |= (0x1 << 15); \} while (0)#define I2C_SDA_READ (GPIOF->IDR & (0x1 << 15))void delay_us(void);
void i2c_init(void);
void i2c_start(void);
void i2c_stop(void);
void i2c_write_byte(unsigned char dat);
unsigned char i2c_read_byte(unsigned char ack);
unsigned char i2c_wait_ack(void);
void i2c_ack(void);
void i2c_nack(void);#endif
// icc.h
#include "iic.h"extern void printf(const char *fmt, ...);
/** 函数名 : delay_us* 函数功能:延时函数* 函数参数:无* 函数返回值:无* */
void delay_us(void)
{unsigned int i = 2000;while (i--);
}
/** 函数名 : i2c_init* 函数功能: i2C总线引脚的初始化, 通用输出,推挽输出,输出速度,* 函数参数:无* 函数返回值:无* */
void i2c_init(void)
{// 使能GPIOF端口的时钟RCC->MP_AHB4ENSETR |= (0x1 << 5);// 设置PF14,PF15引脚为通用的输出功能GPIOF->MODER &= (~(0xF << 28));GPIOF->MODER |= (0x5 << 28);// 设置PF14, PF15引脚为推挽输出GPIOF->OTYPER &= (~(0x3 << 14));// 设置PF14, PF15引脚为高速输出GPIOF->OSPEEDR |= (0xF << 28);// 设置PF14, PF15引脚的禁止上拉和下拉GPIOF->PUPDR &= (~(0xF << 28));// 空闲状态SDA和SCL拉高I2C_SCL_H;I2C_SDA_H;
}/** 函数名:i2c_start* 函数功能:模拟i2c开始信号的时序* 函数参数:无* 函数返回值:无* */
void i2c_start(void)
{/** 开始信号:时钟在高电平期间,数据线从高到低的变化*     --------* SCL         \*              --------*     ----* SDA     \*          --------* */// 确保SDA是输出状态 PF15输出SET_SDA_OUT;// 空闲状态SDA和SCL拉高I2C_SCL_H;I2C_SDA_H;delay_us(); // 延时等待一段时间I2C_SDA_L;	// 数据线拉低delay_us(); // 延时等待一段时间I2C_SCL_L;	// 时钟线拉低,让总线处于占用状态
}/** 函数名:i2c_stop* 函数功能:模拟i2c停止信号的时序* 函数参数:无* 函数返回值:无* */void i2c_stop(void)
{/** 停止信号 : 时钟在高电平期间,数据线从低到高的变化*             ----------* SCL        /*    --------*    ---         -------* SDA   X       /*    --- -------* */// 确保SDA是输出状态 PF15输出SET_SDA_OUT;// 时钟线拉低I2C_SCL_L;delay_us(); // 延时等待一段时间I2C_SDA_L;	// 数据线拉低delay_us(); // 延时等待一段时间// 时钟线拉高I2C_SCL_H;delay_us(); // 延时等待一段时间I2C_SDA_H;	// 数据线拉高
}/** 函数名: i2c_write_byte* 函数功能:主机向i2c总线上的从设备写8bits数据* 函数参数:dat : 等待发送的字节数据* 函数返回值: 无* */void i2c_write_byte(unsigned char dat)
{/** 数据信号:时钟在低电平期间,发送器向数据线上写入数据*          时钟在高电平期间,接收器从数据线上读取数据*      ----          --------*  SCL     \        /        \*           --------          --------*      -------- ------------------ ---*  SDA         X                  X*      -------- ------------------ ---**      先发送高位在发送低位* */// 确保SDA是输出状态 PF15输出SET_SDA_OUT;unsigned int i;for (i = 0; i < 8; i++){// 时钟线拉低I2C_SCL_L;delay_us(); // 延时// 0X3A->0011 1010   0X80->10000000if (dat & 0X80) // 最高位为1{// 发送1I2C_SDA_H;}else // 最高位为0{I2C_SDA_L; // 发送0}delay_us(); // 延时// 时钟线拉高,接收器接收I2C_SCL_H;delay_us(); // 延时,用于等待接收器接收数据delay_us(); // 延时// 将数据左移一位,让原来第6位变为第7位dat = dat << 1;}
}/** 函数名:i2c_read_byte* 函数功能: 主机从i2c总线上的从设备读8bits数据,*          主机发送一个应答或者非应答信号* 函数参数: 0 : 应答信号   1 : 非应答信号* 函数返回值:读到的有效数据** */
unsigned char i2c_read_byte(unsigned char ack)
{/** 数据信号:时钟在低电平期间,发送器向数据线上写入数据*          时钟在高电平期间,接收器从数据线上读取数据*      ----          --------*  SCL     \        /        \*           --------          --------*      -------- ------------------ ---*  SDA         X                  X*      -------- ------------------ ---**      先接收高位, 在接收低位* */unsigned int i;unsigned char dat; // 保存接受的数据// 将数据线设置为输入SET_SDA_IN;for (i = 0; i < 8; i++){// 先把时钟线拉低,等一段时间,保证发送器发送完毕数据I2C_SCL_L;delay_us();delay_us(); // 保证发送器发送完数据// 时钟线拉高,读取数据I2C_SCL_H;delay_us();dat = dat << 1;	  // 数值左移  0000 0000if (I2C_SDA_READ) // pf15管脚得到了一个高电平输入{dat |= 1; // 0000 0110}else{dat &= (~0X1);}delay_us();}if (ack){i2c_nack(); // 发送非应答信号,不再接收下一次数据}else{i2c_ack(); // 发送应答信号}return dat;
}
/** 函数名: i2c_wait_ack* 函数功能: 主机作为发送器时,等待接收器返回的应答信号* 函数参数:无* 函数返回值:*                  0:接收到的应答信号*                  1:接收到的非应答信号* */
unsigned char i2c_wait_ack(void)
{/** 主机发送一个字节之后,从机给主机返回一个应答信号**                   -----------* SCL              /   M:读    \*     -------------             --------*     --- ---- --------------------* SDA    X    X*     ---      --------------------*     主  释   从机    主机*     机  放   向数据  读数据线*         总   线写    上的数据*         线   数据* */// 时钟线拉低,接收器可以发送信号I2C_SCL_L;I2C_SDA_H; // 先把数据线拉高,当接收器回应应答信号时,数据线会拉低delay_us();SET_SDA_IN; // 设置数据线为输入delay_us();delay_us();I2C_SCL_H;		  // 用于读取数据线数据if (I2C_SDA_READ) // PF15得到一个高电平输入,收到非应答信号return 1;I2C_SCL_L; // 时钟线拉低,让数据线处于占用状态return 0;
}
/** 函数名: iic_ack* 函数功能: 主机作为接收器时,给发送器发送应答信号* 函数参数:无* 函数返回值:无* */
void i2c_ack(void)
{/*            --------* SCL       /        \*    -------          ------*    ---* SDA   X*    --- -------------* */// 保证数据线是输出SET_SDA_OUT;I2C_SCL_L; // 拉低时钟线delay_us();I2C_SDA_L; // 数据线拉低,表示应答信号delay_us();I2C_SCL_H; // 时钟线拉高,等待发送器读取应答信号delay_us();delay_us();I2C_SCL_L; // 数据线处于占用状态,发送器发送下一次数据
}
/** 函数名: iic_nack* 函数功能: 主机作为接收器时,给发送器发送非应答信号* 函数参数:无* 函数返回值:无* */
void i2c_nack(void)
{/*            --------* SCL       /        \*    -------          ------*    --- ---------------* SDA   X*    ---* */// 保证数据线是输出SET_SDA_OUT;I2C_SCL_L; // 拉低时钟线delay_us();I2C_SDA_H; // 数据线拉高,表示非应答信号delay_us();I2C_SCL_H; // 时钟线拉高,等待发送器读取应答信号delay_us();delay_us();I2C_SCL_L; // 数据线处于占用状态,发送器发送下一次数据
}
// main.c
#include "si7006.h"void delay(int ms)
{int i, j;for (i = 0; i < ms; i++){for (j = 0; j < 2000; j++);}
}
int main()
{unsigned short hum;short tem;// 进行si7006的初始化si7006_init();while (1){// 读取湿度hum = si7006_read_hum_data(0X40, 0XE5);// 读取温度tem = si7006_read_temp_data(0X40, 0XE3);// 将温度数据和湿度数据按照转换公式进行转换hum = 125 * hum / 65536 - 6;tem = 175.72 * tem / 65536 - 46.85;delay(1000); // 延时打印// 将获取到的数据打印到串口printf("hum:%d\n", hum);printf("tem:%d\n", tem);}return 0;
}

相关文章:

ARM I2C通信

1.概念 I2C总线是PHLIPS公司在八十年代初推出的一种串行的半双工同步总线&#xff0c;主要用于连接整体电路2.IIC总线硬件连接 1.IIC总线支持多主机多从机&#xff0c;但是在实际开发过程中&#xff0c;大多数采用单主机多从机模式 2.挂接到IIC总线上&#xff0c;每个从机设备都…...

Cent OS7 磁盘挂载:扩展存储空间和自动挂载

文章目录 &#xff08;1&#xff09;概述&#xff08;2&#xff09;查看磁盘使用情况&#xff08;3&#xff09;VMware虚拟机挂载磁盘&#xff08;4&#xff09;物理机磁盘挂载&#xff08;5&#xff09;ntfs硬盘处理 &#xff08;1&#xff09;概述 在Linux系统中&#xff0c…...

《使用ThinkPHP6开发项目》 - 创建应用

《使用ThinkPHP6开发项目》 - 安装ThinkPHP框架-CSDN博客 《使用ThinkPHP6开发项目》 - 设置项目环境变量-CSDN博客 《使用ThinkPHP6开发项目》 - 项目使用多应用开发-CSDN博客 根据前面的步骤&#xff0c;我们现在就可以开发我们的项目开发了&#xff0c;根据项目开发的需要…...

SpringBoot进行自然语言处理,利用Hanlp进行文本情感分析

. # &#x1f4d1;前言 本文主要是SpringBoot进行自然语言处理&#xff0c;利用Hanlp进行文本情感分析&#xff0c;如果有什么需要改进的地方还请大佬指出⛺️ &#x1f3ac;作者简介&#xff1a;大家好&#xff0c;我是青衿&#x1f947; ☁️博客首页&#xff1a;CSDN主页放风…...

MySQL 报错 You can‘t specify target table for update in FROM clause解决办法

You can’t specify target table for update in FROM clause 其含义是&#xff1a;不能在同一表中查询的数据作为同一表的更新数 单独执行复合查询是正常的&#xff0c;如下&#xff1a; 但是当执行子查询删除命令时&#xff0c;报如下错误 DELETE FROM abpusers WHERE Id I…...

Linux中使用podman管理容器

本章主要介绍使用podman管理容器 了解什么是容器&#xff0c;容器和镜像的关系安装和配置podman拉取和删除镜像给镜像打标签导出和导入镜像创建和删除镜像数据卷的使用管理容器的命令使用普通用户管理容器 对于初学者来说&#xff0c;不太容易理解什么是容器&#xff0c;这里…...

飞天使-linux操作的一些技巧与知识点3-http的工作原理

文章目录 http工作原理nginx的正向代理和反向代理的区别一个小技巧dig 命令巧用 http工作原理 http1.0 协议 使用的是短连接&#xff0c;建立一次tcp连接&#xff0c;发起一次http的请求&#xff0c;结束&#xff0c;tcp断开 http1.1 协议使用的是长连接&#xff0c;建立一次tc…...

微搭低代码实现登录注册功能

目录 1 创建用户数据源2 实现登录逻辑3 搭建登录页面4 设置登录框5 实现登录的逻辑6 用户注册总结 原来产品在创建应用的时候可以创建模型应用&#xff0c;模型应用对应我们小程序的后端。最新的更新已经将模型应用的能力下线&#xff0c;那我们不得不自己实现一下后端的逻辑。…...

使用Cobalt Srike制作钓鱼文件

钓鱼 钓鱼文件是一种常见的网络攻击手段&#xff0c;旨在欺骗用户&#xff0c;诱使他们点击恶意链接、下载恶意附件或提供敏感信息。钓鱼文件的概念是通过伪装成合法、可信的文件或链接来欺骗受害者&#xff0c;使其相信文件或链接的来源是可信的&#xff0c;从而促使他们采取…...

任意文件读取漏洞

使用方法php://filter/readconvert.base64-encode/resourcexxx 任意文件读取漏洞 php://filter/readconvert.base64-encode/resourceflag 在url后边接上 以base64的编码形式 读取flag里面的内容 php://filter/readconvert.base64encode/resourceflag 用kali来解码 创建一个文…...

一个文件下png,jpg,jpeg,bmp,xml,json,txt文件名称排序命名

#utf-8 #authors 会飞的渔WZH #time:2023-12-13 import os# 要修改的图像所在的文件夹路径 root_path rD:\images\lines2\3 # 要修改的图像所在的文件夹路径filelist os.listdir(root_path) #遍历文件夹 print(len(filelist)) i0for item in filelist:if item.endswith(.…...

phpstudy小皮(PHP集成环境)下载及使用

下载 https://www.xp.cn/download.html直接官网下载即可&#xff0c;下载完解压是个.exe程序&#xff0c;直接点击安装就可以&#xff0c;它会自动在D盘目录为D:\phpstudy_pro 使用 phpMyAdmin是集成的数据库可视化&#xff0c;这里需要下载一下&#xff0c;在软件管理-》网站程…...

[BUG记录]UART占用CPUload过高问题

目录 关键词平台说明一、背景二、根本原因三、措施 关键词 嵌入式、C语言、autosar、TDA4 平台说明 项目ValueOSautosar OSautosar厂商vector芯片厂商TI编程语言C&#xff0c;C编译器HighTec (GCC) 一、背景 在基于TDA4开发的域控中使用到了UART打印debug信息&#xff0c;不…...

Flutter常用命令

一、环境安装 flutter --version 查看当前安装的flutter 版本 flutter upgrade 升级当前的flutter 版本 flutter doctor 检查环境安装是否完成 二、项目编译运行 flutter clean 清空build目录 flutter pub get 获取pub插件包 flutter run --设备名称 运行项目到指定设…...

【C++】POCO学习总结(十四):引用计数、共享指针、缓冲区管理

【C】郭老二博文之&#xff1a;C目录 1、Poco::AutoPtr 智能指针 1.1 说明 Poco::AutoPtr是一个含有引用计数的“智能”指针模版。 Poco::AutoPtr用于支持引用计数的类实例化。支持引用计数的类需要有以下要求&#xff1a; 维护一个引用计数(在创建时初始化为1)实现void du…...

Python之禅

import this 这是 Python 社区中著名的 "The Zen of Python"&#xff08;Python之禅&#xff09;文档&#xff0c;由 Python 创始人之一的 Tim Peters 撰写。这个文档包含了一系列关于编程和代码设计哲学的原则&#xff0c;以指导 Python 社区的开发者。以下是这些原…...

RocketMQ源码 Broker-SubscriptionGroupManager 订阅组管理组件源码分析

前言 SubscriptionGroupManager 继承了ConfigManager配置管理组件&#xff0c;拥有将内存数据持久化到磁盘文件subscriptionGroup.json的能力。它主要负责维护所有消费组在内存中的订阅数据。 源码版本&#xff1a;4.9.3 源码架构图 核心数据结构 主要的数据结构比较简单&am…...

go-zero开发入门-API网关鉴权开发示例

本文是go-zero开发入门-API网关开发示例一文的延伸&#xff0c;继续之前请先阅读此文。 在项目根目录下创建子目录 middleware&#xff0c;在此目录下创建文件 auth.go&#xff0c;内容如下&#xff1a; // 鉴权中间件 package middlewareimport ("context""e…...

[LLM]nanoGPT---训练一个写唐诗的GPT

karpathy/nanoGPT: The simplest, fastest repository for training/finetuning medium-sized GPTs. (github.com) 原有模型使用的莎士比亚的戏剧数据集, 如果需要一个写唐诗机器人&#xff0c;需要使用唐诗的文本数据&#xff0c; 一个不错的唐诗&#xff0c;宋词数据的下载…...

docker compose部署wordpress

准备机器&#xff1a; 192.168.58.151 &#xff08;关闭防火墙和selinux&#xff09; 安装好docker服务 &#xff08;详细参照&#xff1a;http://t.csdnimg.cn/usG0s 中的国内源安装docker&#xff09; 部署wordpress: 创建目录&#xff1a; [rootdocker ~]# mkdir…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)

文章目录 1.什么是Redis&#xff1f;2.为什么要使用redis作为mysql的缓存&#xff1f;3.什么是缓存雪崩、缓存穿透、缓存击穿&#xff1f;3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...

相机Camera日志实例分析之二:相机Camx【专业模式开启直方图拍照】单帧流程日志详解

【关注我&#xff0c;后续持续新增专题博文&#xff0c;谢谢&#xff01;&#xff01;&#xff01;】 上一篇我们讲了&#xff1a; 这一篇我们开始讲&#xff1a; 目录 一、场景操作步骤 二、日志基础关键字分级如下 三、场景日志如下&#xff1a; 一、场景操作步骤 操作步…...

c++ 面试题(1)-----深度优先搜索(DFS)实现

操作系统&#xff1a;ubuntu22.04 IDE:Visual Studio Code 编程语言&#xff1a;C11 题目描述 地上有一个 m 行 n 列的方格&#xff0c;从坐标 [0,0] 起始。一个机器人可以从某一格移动到上下左右四个格子&#xff0c;但不能进入行坐标和列坐标的数位之和大于 k 的格子。 例…...

Neo4j 集群管理:原理、技术与最佳实践深度解析

Neo4j 的集群技术是其企业级高可用性、可扩展性和容错能力的核心。通过深入分析官方文档,本文将系统阐述其集群管理的核心原理、关键技术、实用技巧和行业最佳实践。 Neo4j 的 Causal Clustering 架构提供了一个强大而灵活的基石,用于构建高可用、可扩展且一致的图数据库服务…...

Spring Boot面试题精选汇总

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot面试题精选汇总⚙️ **一、核心概…...

Android15默认授权浮窗权限

我们经常有那种需求&#xff0c;客户需要定制的apk集成在ROM中&#xff0c;并且默认授予其【显示在其他应用的上层】权限&#xff0c;也就是我们常说的浮窗权限&#xff0c;那么我们就可以通过以下方法在wms、ams等系统服务的systemReady()方法中调用即可实现预置应用默认授权浮…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库&#xff0c;专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性&#xff0c;并提供了一个通用的框架&…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...

python爬虫——气象数据爬取

一、导入库与全局配置 python 运行 import json import datetime import time import requests from sqlalchemy import create_engine import csv import pandas as pd作用&#xff1a; 引入数据解析、网络请求、时间处理、数据库操作等所需库。requests&#xff1a;发送 …...