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

I2C协议—读写EEPROM(24Cxx为例)

STM32 I2C协议详解与应用实践-CSDN博客

实际项目中移植IIC协议及读写EEprom代码:

/* AT24C08,写次数达100万次SOC ,2500次充放电次数,需要500万次记录,需存储均衡
每页*/#include "FreeRTOS.h"
#include "task.h"
#include "24C08.h"
#include "CortrolMain.h"//#define	OP_READ	0xa1		// ?÷?tμ??·ò??°?áè?2ù×÷,0xa1?′?a1010 0001B
#define	EE_ADDR 0xa0		// ?÷?tμ??·ò??°D′è?2ù×÷,0xa1?′?a1010 0000B#include "include.h"
#define EE_SCL_PIN  PTB2   //模拟IIC的SCL信号  1.修改引脚即可修改IIC接口
#define EE_SDA_PIN  PTC13   //模拟IIC的SDA信号#define EE_SDA_IN()   GPIO_PDDR_REG(GPIOX[EE_SDA_PIN>> 5]) &= ~(1 << (EE_SDA_PIN&0x1f));  //GPIO_PinSetDir(EE_SDA_PIN, 0);	//输入
#define EE_SDA_OUT()  GPIO_PDDR_REG(GPIOX[EE_SDA_PIN>> 5]) |= (1 << (EE_SDA_PIN&0x1f)); //GPIO_PinSetDir(EE_SDA_PIN, 1);	//输出#define EE_SCK_OUT()  GPIO_PDDR_REG(GPIOX[EE_SCL_PIN>> 5]) |= (1 << (EE_SCL_PIN&0x1f)); //GPIO_PinSetDir(EE_SDA_PIN, 1);	//输出#define EE_IIC_SCL    PTB2_OUT                   //SCL      2.修改引脚即可修改IIC接口        
#define EE_IIC_SDA    PTC13_OUT                   //SDA	 
#define EE_READ_SDA   PTC13_INT                    //输入SDA /******************************************************************************
*函  数:void EE_IIC_Delay(void)
*功 能:IIC延时
*参  数:无
*返回值:无
*备  注: 移植时只需要将EE_IIC_Delay()换成自己的延时即可
*******************************************************************************/	
void EE_IIC_Delay(uint8_t us)
{for(int i = 0; i < 20; i++)    {__asm("NOP");//core bus 160M  情况下大概IIC速率 400K}    
}
/******************************************************************************
*函  数:void IIC_Init(void)
*功 能:IIC初始化
*参  数:无
*返回值:无
*备  注:无
*******************************************************************************/void EE_IIC_Init(void)
{			gpio_init(EE_SCL_PIN,GPO,1) ;gpio_init(EE_SDA_PIN,GPO,1) ;EE_SCK_OUT();EE_SDA_OUT();EE_IIC_SCL=1;EE_IIC_SDA=1;        
}void EE_IIC_Start(void)
{EE_SDA_OUT(); //sda线输出 EE_IIC_SDA=1;	EE_IIC_SCL=1;EE_IIC_Delay(4);EE_IIC_SDA=0; //START:when CLK is high,DATA change form high to low EE_IIC_Delay(4);EE_IIC_SCL=0; //钳住I2C总线,准备发送或接收数据 
}void EE_IIC_Stop(void)
{EE_SDA_OUT(); //sda线输出EE_IIC_SCL=0;EE_IIC_SDA=0; //STOP:when CLK is high DATA change form low to highEE_IIC_Delay(4);EE_IIC_SCL=1; EE_IIC_SDA=1; //发送I2C总线结束信号EE_IIC_Delay(4);							   	
}uint8_t EE_IIC_WaitAck(void)
{uint8_t ucErrTime=0;EE_SDA_IN(); //SDA设置为输入  (从机给一个低电平做为应答) EE_IIC_SDA=1;EE_IIC_Delay(1);	   EE_IIC_SCL=1;EE_IIC_Delay(1);;	 while(EE_READ_SDA){ucErrTime++;if(ucErrTime>250){EE_IIC_Stop();return 1;}}EE_IIC_SCL=0; //时钟输出0 	   return 0;  
} void EE_IIC_Ack(void)
{EE_IIC_SCL=0;EE_SDA_OUT();EE_IIC_SDA=0;EE_IIC_Delay(1);EE_IIC_SCL=1;EE_IIC_Delay(2);EE_IIC_SCL=0;
}void EE_IIC_NAck(void)
{EE_IIC_SCL=0;EE_SDA_OUT();EE_IIC_SDA=1;EE_IIC_Delay(1);EE_IIC_SCL=1;EE_IIC_Delay(1);EE_IIC_SCL=0;
}					 				     void EE_IIC_SendByte(uint8_t data)
{                        uint8_t t;   EE_SDA_OUT(); 	    EE_IIC_SCL=0; //拉低时钟开始数据传输for(t=0;t<8;t++){              EE_IIC_SDA=(data&0x80)>>7;EE_IIC_Delay(1);			EE_IIC_SCL=1;data<<=1;EE_IIC_Delay(1);EE_IIC_SCL=0;	   }EE_IIC_Delay(1);
} 	void EE_IIC_PageSendByte(uint16_t data)
{                        uint8_t t,DataIn;   EE_SDA_OUT(); 	    EE_IIC_SCL=0; //拉低时钟开始数据传输DataIn=data&0xff;for(t=0;t<8;t++){              EE_IIC_SDA=(DataIn&0x80)>>7;EE_IIC_Delay(1);			EE_IIC_SCL=1;data<<=1;EE_IIC_Delay(1);EE_IIC_SCL=0;	   }DataIn=(data>>8)&0xff;for(t=0;t<8;t++){              EE_IIC_SDA=(DataIn&0x80)>>7;EE_IIC_Delay(1);			EE_IIC_SCL=1;data<<=1;EE_IIC_Delay(1);EE_IIC_SCL=0;	   }EE_IIC_Delay(1);
} uint8_t EE_IIC_ReadByte(uint8_t ack)
{uint8_t i,receive=0;EE_SDA_IN(); //SDA设置为输入模式 等待接收从机返回数据for(i=0;i<8;i++ ){EE_IIC_SCL=0; EE_IIC_Delay(1);EE_IIC_SCL=1;receive<<=1;if(EE_READ_SDA)receive++; //从机发送的电平EE_IIC_Delay(1); }					 if(ack)EE_IIC_Ack(); //发送ACK elseEE_IIC_NAck(); //发送nACK  return receive;
}uint8_t EE_IIC_ReadByteFromSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t *buf)
{EE_IIC_Start();	EE_IIC_SendByte(I2C_Addr);	 //发送从机地址if(EE_IIC_WaitAck()) //如果从机未应答则数据发送失败{EE_IIC_Stop();return 1;}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck();	  EE_IIC_Start();EE_IIC_SendByte(I2C_Addr+1); //进入接收模式			   EE_IIC_WaitAck();*buf=EE_IIC_ReadByte(0);	   EE_IIC_Stop(); //产生一个停止条件return 0;
}uint8_t EE_EE_IIC_SendByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{EE_IIC_Start();EE_IIC_SendByte(I2C_Addr); //发送从机地址if(EE_IIC_WaitAck()){EE_IIC_Stop();return 1; //从机地址写入失败}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck();	  EE_IIC_SendByte(data); if(EE_IIC_WaitAck()){EE_IIC_Stop(); return 1; //数据写入失败}EE_IIC_Stop(); //产生一个停止条件return 0;
}uint8_t EE_IIC_WriteByteToSlave(uint8_t I2C_Addr,uint8_t reg,uint8_t data)
{EE_IIC_Start();EE_IIC_SendByte(I2C_Addr); //发送从机地址if(EE_IIC_WaitAck()){EE_IIC_Stop();return 1; //从机地址写入失败}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck();	  EE_IIC_SendByte(data); if(EE_IIC_WaitAck()){EE_IIC_Stop(); return 1; //数据写入失败}EE_IIC_Stop(); //产生一个停止条件return 0;
}
uint8_t EE_IIC_ReadMultByteFromSlave(uint8_t dev, uint8_t reg, uint8_t length, uint8_t *data)
{uint8_t count = 0;uint8_t temp;EE_IIC_Start();EE_IIC_SendByte(dev); //发送从机地址if(EE_IIC_WaitAck()){EE_IIC_Stop(); return 1; //从机地址写入失败}EE_IIC_SendByte(reg); //发送寄存器地址EE_IIC_WaitAck();	  EE_IIC_Start();EE_IIC_SendByte(dev+1); //进入接收模式	EE_IIC_WaitAck();for(count=0;count<length;count++){if(count!=(length-1))temp = EE_IIC_ReadByte(1); //带ACK的读数据else  temp = EE_IIC_ReadByte(0); //最后一个字节NACKdata[count] = temp;}EE_IIC_Stop(); //产生一个停止条件return 0;
}/******************************************************************************
*函  数:uint8_t IICwriteBytes(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data)
*功 能:将多个字节写入指定设备 指定寄存器
*参  数:dev     目标设备地址
reg	   寄存器地址
length  要写的字节数
*data   要写入的数据将要存放的指针
*返回值:1成功 0失败
*备  注:无
*******************************************************************************/ 
uint8_t EE_IIC_WriteMultByteToSlave(uint8_t dev, uint8_t reg, uint8_t length, uint8_t* data)
{   uint8_t count = 0;EE_IIC_Start();EE_IIC_SendByte(dev); //发送从机地址if(EE_IIC_WaitAck()){EE_IIC_Stop();return 1; //从机地址写入失败}EE_IIC_SendByte(reg&0xff); //发送寄存器地址,就是页地址EE_IIC_WaitAck();	  for(count=0;count<length;count++){EE_IIC_SendByte(data[count]); if(EE_IIC_WaitAck()) //每一个字节都要等从机应答{EE_IIC_Stop();return 1; //数据写入失败}}EE_IIC_Stop(); //产生一个停止条件return 0;
}uint8_t EEPROM_PageWrite(uint8 PageNum, uint8_t length, uint8_t* data)
{uint8 Addr,PageAddr,i;uint16 j;//每页16个字节,24c08一共64页,页地址是页号*16/*if(PageNum<16)//0~15{PageAddr=16*PageNum;Addr=0xA0;EE_IIC_WriteMultByteToSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=16 && PageNum<=31){Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_WriteMultByteToSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=32 && PageNum<=47){Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_WriteMultByteToSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=48 && PageNum<=63){Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_WriteMultByteToSlave(Addr,PageAddr,length,data) ;}*///cht- eeprom进行写的时候,MP进行接地处理EEPROMMP(0);
//    vTaskDelay( 2/portTICK_RATE_MS );EE_IIC_Delay(20);DisableInterrupts;Addr=0xA0+((((PageNum*16)>>8)&0x07)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_WriteMultByteToSlave(Addr,PageAddr,length,data) ;EnableInterrupts;for(i=0;i<6;i++){for(j=0;j<500;j++){EE_IIC_Delay(1);}
//        vTaskDelay( 1/portTICK_RATE_MS );}EEPROMMP(1);//cht-恢复高电平,可以读return 1;
}uint8_t EEPROM_PageRead(uint8 PageNum, uint8_t length, uint8_t* data)
{uint8 Addr,PageAddr;//每页16个字节,24c08一共64页,页地址是页号*16/*if(PageNum<16)//0~15{PageAddr=16*PageNum;Addr=0xA0;EE_IIC_ReadMultByteFromSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=16 && PageNum<=31){// PageAddr=(16*PageNum)%256;Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_ReadMultByteFromSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=32 && PageNum<=47){Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_ReadMultByteFromSlave(Addr,PageAddr,length,data) ;}else if(PageNum>=48 && PageNum<=63){Addr=0xA0+((((PageNum*16)>>8)&0x03)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_ReadMultByteFromSlave(Addr,PageAddr,length,data) ;}*/Addr=0xA0+((((PageNum*16)>>8)&0x07)<<1);PageAddr=(PageNum*16)&0xff;EE_IIC_ReadMultByteFromSlave(Addr,PageAddr,length,data) ;return 1; }#define _24C08	        4
#define PAGE_SIZE		16
#define PAGE_SIZE_REM	0x0F
#define MEM_SIZE		0x03ff#define MAX_ADDR	( (MEM_SIZE+1)*DEV_24CXX_NUM-1 )
//芯片常量
#define DEV_24CXX_MAIN_ADDR	0xA0
#define DEV_24CXX_READ	    0x01
#define DEV_24CXX_WRITE	    0x00
#define IIC_SEND_ACK	    0x10
#define IIC_SEND_NOACK	    0x11#define IIC_STATE_NOACK	    0x20
#define IIC_STATE_ACK	    0x21uint16 HardAddr;
void _24CXXX_AddrProcess(unsigned int Addr)
{HardAddr = 0x00;
}void _24CXXX_WriteByte(unsigned int Addr,unsigned char Data)
{_24CXXX_AddrProcess(Addr);Addr &= MEM_SIZE;	EE_IIC_Start();EE_IIC_SendByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE);EE_IIC_SendByte( ((unsigned char)(Addr>>8)) );EE_IIC_SendByte( ((unsigned char)Addr) );EE_IIC_SendByte( Data );EE_IIC_Stop();}unsigned char _24CXXX_ReadByte(unsigned int Addr)
{unsigned char temp;_24CXXX_AddrProcess(Addr);Addr &= MEM_SIZE;EE_IIC_Start();EE_IIC_SendByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE);EE_IIC_SendByte( ((unsigned char)(Addr>>8)) );EE_IIC_SendByte( ((unsigned char)Addr) );EE_IIC_Start();EE_IIC_SendByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);temp = EE_IIC_ReadByte(IIC_SEND_NOACK);EE_IIC_Stop();return temp;
}void _24CXXX_WriteBytes(unsigned int StartAddr,unsigned char *Data,int DataNum)
{unsigned char Num;unsigned int i;unsigned int y;unsigned int yy;_24CXXX_AddrProcess(StartAddr);yy = StartAddr & MEM_SIZE;y = yy&PAGE_SIZE_REM;	//=StartAddr/PAGE_SIZEy = PAGE_SIZE - y;	    //要写的第一页中有多少个数据if( y <= PAGE_SIZE )	//写第一页(可能不到一页,以使页对齐){EE_IIC_Start();EE_IIC_SendByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );EE_IIC_SendByte( ((unsigned char)(yy>>8)) );EE_IIC_SendByte( ((unsigned char)yy) );for(i=0;i<y;i++){if( i>=DataNum ){break;}EE_IIC_SendByte( *(Data++) );			}}IIC_Stop();//DelayMs(10);vTaskDelay( 20/portTICK_RATE_MS );DataNum -= y;		//还有多少数据未写i = 0;Num = 0;			//用于记录已经写了多少页while( DataNum>0 )	//数据未写完{if( i == 0 ){yy = StartAddr+y+Num*PAGE_SIZE;_24CXXX_AddrProcess(yy);yy = yy & MEM_SIZE;EE_IIC_Start();EE_IIC_SendByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );EE_IIC_SendByte( ((unsigned char)(yy>>8)) );EE_IIC_SendByte( ((unsigned char)(yy)) );}EE_IIC_SendByte( *(Data++) );i++;if(i>=PAGE_SIZE )	//如果一页写完{i = 0;Num++;IIC_Stop();vTaskDelay( 20/portTICK_RATE_MS );}DataNum--;}if(i!=0x0000)	//如果写结束时,并未到达页的最后,则需要补上停止位{EE_IIC_Stop();vTaskDelay( 20/portTICK_RATE_MS );}	
}void _24CXXX_ReadBytes(unsigned int StartAddr,unsigned char *Data,int DataNum)
{unsigned char Num;unsigned int i;unsigned int y;unsigned int yy;_24CXXX_AddrProcess(StartAddr);yy = StartAddr & MEM_SIZE;y = yy&PAGE_SIZE_REM;	//=StartAddr/PAGE_SIZEy = PAGE_SIZE - y;				//要写的第一页中有多少个数据if( y <= PAGE_SIZE )	//写第一页(可能不到一页,以使页对齐){EE_IIC_Start();EE_IIC_SendByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );EE_IIC_SendByte( ((unsigned char)(StartAddr>>8)) );EE_IIC_SendByte( ((unsigned char)StartAddr) );EE_IIC_Start();EE_IIC_SendByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);for(i=0;i<y;i++){if( i>=DataNum ){break;}if( (i==DataNum-1)||(i==y-1) )	//如果是该页的最后一个数据,则NOACK*Data = EE_IIC_ReadByte(IIC_SEND_NOACK);else*Data = EE_IIC_ReadByte(IIC_SEND_ACK);Data++;			}}EE_IIC_Stop();//DelayUs(20);DataNum -= y;		//还有多少数据未写i = 0;Num = 0;			//用于记录已经写了多少页while( DataNum>0 )	//数据未写完{if( i == 0 ){yy = StartAddr+y+Num*PAGE_SIZE;_24CXXX_AddrProcess(yy);yy = yy & MEM_SIZE;EE_IIC_Start();EE_IIC_SendByte( DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_WRITE );EE_IIC_SendByte( (unsigned char)(yy>>8) );EE_IIC_SendByte( (unsigned char)(yy) );EE_IIC_Start();EE_IIC_SendByte(DEV_24CXX_MAIN_ADDR|(HardAddr<<1)|DEV_24CXX_READ);}if( (i==PAGE_SIZE-1)||(DataNum==1) )	//如果是该页或要读的最后一个数据,则NOACK*Data = EE_IIC_ReadByte(IIC_SEND_NOACK);else*Data = EE_IIC_ReadByte(IIC_SEND_ACK);Data++;i++;if(i>=PAGE_SIZE )	//如果一页写完{i = 0;Num++;EE_IIC_Stop();//DelayUs(20);}DataNum--;}if(i!=0x0000)	//如果写结束时,并未到达页的最后,则需要补上停止位{EE_IIC_Stop();}}

区分硬件IIC与软件IIC

一般使用软件模拟IIC,,可移植性高


一:模拟IIC与硬件IIC定义?


模拟I2C一般是用GPIO管脚,用软件控制管脚状态以模拟I2C通信波形。
硬件I2C对应芯片上的I2C外设,有相应I2C驱动电路,其所使用的I2C管脚也是专用。

二:优缺点


1.硬件I2C的效率要远高于软件的,而软件I2C由于不受管脚限制,接口比较灵活。
2.模拟I2C 是通过GPIO,软件模拟寄存器的工作方式,而硬件(固件)I2C是直接调用内部寄存器进行配置。如果要从具体硬件上来看,可以去看下芯片手册。因为固件I2C的端口是固定的,所以会有所区别。

三:如何区分它们

可以看底层配置,比如IO口配置,如果配置了IO口的功能(IIC功能)那就是固件IIC,否则就是模拟

可以看IIC写函数,看里面有木有调用现成的函数或者给某个寄存器赋值,如果有,则肯定是固件IIC功能,没有的话肯定是数据一个bit一个bit模拟发生送的,肯定用到了循环,则为模拟。

根据代码量判断,模拟的代码量肯定比固件的要大。

相关文章:

I2C协议—读写EEPROM(24Cxx为例)

STM32 I2C协议详解与应用实践-CSDN博客 实际项目中移植IIC协议及读写EEprom代码&#xff1a; /* AT24C08,写次数达100万次SOC ,2500次充放电次数&#xff0c;需要500万次记录&#xff0c;需存储均衡 每页*/#include "FreeRTOS.h" #include "task.h" #incl…...

示例:JAVA调用deepseek

近日&#xff0c;国产AI DeepSeek在中国、美国的科技圈受到广泛关注&#xff0c;甚至被认为是大模型行业的最大“黑马”。在外网&#xff0c;DeepSeek被不少人称为“神秘的东方力量”。1月27日&#xff0c;DeepSeek应用登顶苹果美国地区应用商店免费APP下载排行榜&#xff0c;在…...

Linux系统命令无法使用(glib库相关问题)

1.背景描述 Yum强制安装了一些软件&#xff0c;安装软件成功无报错&#xff0c;完成后不久突然发现系统出问题了&#xff0c;所有的命令无法使用了&#xff0c;如ls、mv、cat等基本命令报错。 relocation error&#xff1a; /lib64/libpthread.so.0: symbol_libc_dl_error_tsd …...

Java 一键将 Word 文档转为 PDF

嘿&#xff0c;朋友们&#xff01;在开发中&#xff0c;经常会碰到需要把 Word 文档转换成 PDF 格式的需求&#xff0c;像生成报告、合同啥的。Java 有不少好用的库能实现这个功能&#xff0c;下面就给大家介绍两种常见的方法&#xff0c;分别使用 Apache POI 和 Docx4J 结合 i…...

从基础到进阶:一文掌握排序、查找、动态规划与图算法的全面实现(C++代码实例解析)

引言 算法是计算机科学的核心&#xff0c;也是程序员解决复杂问题的利器。从基础的排序与查找到进阶的动态规划与图论算法&#xff0c;掌握这些技能不仅是提升编程能力的必经之路&#xff0c;更是解决实际问题的根本。本篇文章将通过 C 实现多个经典算法&#xff0c;包括排序、…...

Nginx反代Ollama接口跨域、无法逐字输出问题

场景 本地部署deepseek模型&#xff0c;用的Ollama管理&#xff0c;内网穿透到公网&#xff0c;在通过nginx反代ollama接口。 问题描述 跨域问题 nginx转发时请求头中需要加入origin&#xff0c;并且origin还要和ollama接口同源&#xff08;协议、ip、端口一致&#xff09;。…...

电脑黑屏按什么键恢复?电脑黑屏的解决办法

电脑黑屏的原因有很多&#xff0c;可能是硬件、软件、系统或者病毒等方面造成的。那么&#xff0c;当我们遇到电脑黑屏时&#xff0c;应该怎么做呢&#xff1f;有没有什么快捷的方法可以恢复正常呢&#xff1f;本文将为您介绍一些常见的电脑黑屏情况及其解决办法。 一、电脑开机…...

docker启动报错code=exited, status=1/FAILURE——问题排查

问题 在某台centos7机器上&#xff0c;启动docker服务 sudo systemctl start docker报下列错误&#xff1a; ● docker.service - Docker Application Container EngineLoaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)Active: …...

Kong故障转移参数配置

一、Passive Health Check Healthchecks.Passive.Unhealthy.HttpStatuses 含义&#xff1a; 列出了被认为是“不健康”的HTTP状态码。目的&#xff1a; 当健康检查&#xff08;Healthcheck&#xff09;返回这些状态码时&#xff0c;系统会认为服务不健康&#xff0c;并可能触…...

使用opencv解析视频,通过图片比对,筛选出每一帧视频的变化

记录瞬间 最近碰到一个问题&#xff0c;在客户端上操作时&#xff0c;存在背景判断的情况&#xff0c;对自动化实现此操作增加难度。 所以考虑到实际的使用&#xff0c;将一些计算机视觉技术加入到实际的使用中&#xff0c;来解决此问题。 import os import cv2 import numpy#…...

思翼遥控器疑问?

1.地面端与遥控端对频&#xff0c;地面端选择数传2为串口&#xff0c;天空端的UART2通过USB转TTL模块连接电脑&#xff0c;通过串口助手观察得有1Hz输出帧&#xff08;开启遥控器APP时间段为10Hz&#xff09;&#xff0c;共21字节&#xff0c;请问&#xff0c;这个是什么含义&a…...

anaconda中可以import cv2,但是notebook中cv2 module not found

一、问题 anaconda中成功import cv2 但是jupyter notebook中却无法导入cv2 二、排查 anaconda中使用python路径如下&#xff1a; jupyter notebook中使用python路径如下&#xff1a; 可以发现路径不一致。 三、解决 ①查看可用的kernel ②选中想要修改的kernel&#xff0c;打…...

如何解决 Linux 文件系统挂载失败的问题

当遇到Linux文件系统挂载失败的问题时&#xff0c;您可以通过以下步骤来解决问题&#xff1a; 解决方法&#xff1a; 检查挂载点&#xff1a; 确保要挂载的目标文件系统存在&#xff0c;并且挂载点是正确的。检查挂载点是否已经被其他文件系统占用。 检查文件系统状态&#x…...

PHP填表统计预约打卡表单系统小程序

&#x1f4cb; 填表统计预约打卡表单系统——专属定制&#xff0c;信息互动新纪元 &#x1f4ca; 填表统计预约打卡表单系统&#xff0c;一款专为现代快节奏生活量身打造的多元化自定义表单统计小程序&#xff0c;集信息填表、预约报名、签到打卡、活动通知、报名投票、班级统…...

PAT乙级( 1009 说反话 1010 一元多项式求导)C语言版本超详细解析

1009 说反话 给定一句英语&#xff0c;要求你编写程序&#xff0c;将句中所有单词的顺序颠倒输出。 输入格式&#xff1a; 测试输入包含一个测试用例&#xff0c;在一行内给出总长度不超过 80的字符串。字符串由若干单词和若干空格组成&#xff0c;其中单词是由英文字母&#x…...

LVSNAT服务搭建

LVSNAT实验环境搭建 在虚拟机上&#xff0c;我的NAT模式ip划分为&#xff1a;172.25.254.0 仅主机模式IP为&#xff1a;192.168.0.0 拓补图如下 配置服务&#xff1a;LVS服务端添加两个网卡&#xff0c;分别为NAT模式和仅主机模式 LVS服务端配置&#xff1a; systemctl st…...

websocket自动重连封装

websocket自动重连封装 前端代码封装 import { ref, onUnmounted } from vue;interface WebSocketOptions {url: string;protocols?: string | string[];reconnectTimeout?: number; }class WebSocketService {private ws: WebSocket | null null;private callbacks: { [k…...

2. Mellanox 网卡的参数调优-LINK_TYPE_P1(GPU-AI-大模型,底层调优-测试)

命令详细分析 echo yes | sudo mlxconfig -d $line set LINK_TYPE_P1=1 这个命令用于设置 Mellanox 网卡设备的 LINK_TYPE_P1 参数为 1。以下是该命令的详细解析: 各部分解释 echo yes |: 这个部分通过管道将字符串 yes 传递给后续命令,以自动确认任何需要用户输入确认的…...

apisix网关ip-restriction插件使用说明

ip-restriction插件可以在网关层进行客户端请求ip拦截。 当然了&#xff0c;一般不推荐使用该方法&#xff0c;专业的事专业工具做。建议有条件&#xff0c;还是上防火墙或者waf来做。 官方文档&#xff1a;ip-restriction | Apache APISIX -- Cloud-Native API Gateway whit…...

使用 Docker 和 PM2 构建高并发 Node.js API 网关

在现代 Web 开发中&#xff0c;构建高并发、高可用的 API 网关是一个常见的需求。本文将介绍如何结合 Docker 和 PM2 构建一个高性能的 Node.js API 网关&#xff0c;并深入探讨分布式限流器的原理与实现。 1. 背景与需求 1.1 高并发 API 网关的挑战 在高并发场景下&#xff…...

现代前端工程化实践:高效构建的秘密

一、前端工程化错误监控 这种监控可以帮助开发人员及时发现和解决问题&#xff0c;提高应用程序的稳定性和可靠性。 1. Sentry&#xff1a;Sentry是一款开源的错误监控平台&#xff0c;可以监控前端、后端以及移动端应用程序中的错误和异常。Sentry提供了实时错误报告、错误分…...

react高级面试题

以下是一些React高级面试题&#xff1a; 一、组件相关 React组件的生命周期有哪些&#xff08;类组件&#xff09;&#xff1f;在函数组件中如何实现类似功能&#xff1f; 答案&#xff1a; 类组件生命周期&#xff1a; componentDidMount&#xff1a;组件挂载后调用&#xff…...

html 列动态布局

样式说明&#xff1a; /* 列动态布局&#xff0c;列之间以空格填充 */ li {display: flex;/* flex-direction: column; */justify-content: space-between; }...

C++小等于的所有奇数和=最大奇数除2加1的平方。

缘由 三种思路解题&#xff1a;依据算术推导得到一个规律&#xff1a;小等于的所有奇数和等于最大奇数除以2加1的平方。将在后续发布&#xff0c;总计有十种推导出来的实现代码。 int a 0,aa 1,aaa 0;cin >> a; while (aa<a) aaa aa, aa 2;cout << aaa;i…...

政采云业务网关实践:使用 Higress 统一替代 APISIX/Kong/Istio Ingress

作者&#xff1a;政采云基础架构团队技术专家 朱海峰&#xff08;片风&#xff09; 业务网关项目背景 由于一些历史的背景&#xff0c;政采云平台在网关建设上遇到一些问题&#xff1a; 容器网关配置较多&#xff0c;配置方式多样&#xff0c;运维压力较大&#xff1a; 配置…...

【嵌入式 Linux 音视频+ AI 实战项目】瑞芯微 Rockchip 系列 RK3588-基于深度学习的人脸门禁+ IPC 智能安防监控系统

前言 本文主要介绍我最近开发的一个个人实战项目&#xff0c;“基于深度学习的人脸门禁 IPC 智能安防监控系统”&#xff0c;全程满帧流畅运行。这个项目我目前全网搜了一圈&#xff0c;还没发现有相关类型的开源项目。这个项目只要稍微改进下&#xff0c;就可以变成市面上目前…...

安卓7以上抓包证书安装

安卓7以上抓包证书安装 fiddler 用户可以直接试试这个文件 前提是要root过了&#xff0c;如果是模拟器就很容易开启 前提&#xff1a;要有openssl工具&#xff0c;在linux一个指令就可以下载了&#xff1a;sudo apt-get install openssl,windons则是在https://www.openssl.org/…...

【C#】任务调度的实现原理与组件应用Quartz.Net

Quartz 是一个流行的开源作业调度库&#xff0c;最初由 Terracotta 开发&#xff0c;现在由 Terracotta 的一部分 Oracle 所有。它主要用于在 Java 应用程序中调度作业的执行。Quartz 使用了一种复杂的底层算法来管理任务调度&#xff0c;其中包括任务触发、执行、持久化以及集…...

C语言:深入了解指针4(超级详细)

看之前必须得掌握有一定指针的知识&#xff0c;不然会看不懂&#xff0c;如果有不懂的可以看我博客 指针1&#xff0c;指针2&#xff0c;指针3 这三个讲了指针全部的基础知识超级详细&#xff0c;这篇只要是讲一些指针练习题也是非常详细 1. sizeof和strlen的对⽐ 1. 基本定义…...

C#+Redis接收数据并定时3秒钟频率异步保存到数据库

要在C#中实现从Redis接收数据,并以每3秒的频率异步保存到数据库,你可以使用System.Threading.Tasks.Task.Delay或System.Timers.Timer来创建一个定时任务。不过,对于更复杂的定时和调度需求,System.Threading.Tasks.Timer或Quartz.NET等库可能更合适。 在这个场景中,由于…...