单片机——IIC协议与24C02
1、基础知识
1.1、IIC串行总线的组成及工作原理
I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。
1.2、I2C总线的数据传输
I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟线上的信号为低电平期间,数据线上的高电平或低电平状态才允许变化。 SCL线为高电平期间,SDA线由高电平向低电平的变化表示起始信号;SCL线为高电平期间,SDA线由低电平向高电平的变化表示终止信号。
1.3、模拟子程序
1.3.1、起始信号
实际上是严格按照时序进行编写的
Void I2CStart(void)
{ SDA = 1;//数据线为高电平SomeNop( );//保持一段时间SCL = 1;//时钟线为高电平SomeNop( );//保持一段时间SDA = 0;//数据线为低电平SomeNop( );//保持一段时间
}
1.3.2、终止信号
同上面原理一样
void I2cStop(void)
{SDA = 0;SomeNop( );SCL = 1;SomeNop( );SDA = 1;SomeNop( );
}
1.3.3应答I2C总线
void I2cACK(void)
{SDA = 0;SomeNop( );SCL = 1;SomeNop( );SCL = 0;SomeNop( );
}
1.3.4非应答I2C总线
void I2cNOACK(void)
{SDA = 1;SomeNop( );SCL = 1;SomeNop( );SCL = 0;SomeNop( );
}
2.程序
2.0、宏定义、头文件
#include<reg52.h>
#include<intrins.h> //_nop_
#define uchar unsigned char
#define uint unsigned intsbit SCL=P2^1;
sbit SDA=P2^0;
sbit RS=P1^0;
sbit RW=P1^1;
sbit E=P2^5;
sbit duan=P2^6;
sbit wei =P2^7;
sbit RST=P2^4;#define RS_data RS=1
#define RS_command RS=0
#define RW_read RW=1
#define RW_write RW=0
#define E_close E=0
#define E_open E=1
#define Data P0char string[]={"wuliwuli:"} ;
char string1[]={"clemmence:"};
uchar arr[8];
uchar arr1[8];
uchar dat[]={12,13,14,15};
2.1、延时部分
void delay(uint k)
{uint i,j;
for(i=0;i<k;i++){for(j=0;j<113;j++){;}}
}
关于延时部分的详细程序解释见
链接: 单片机控制一盏灯的亮与灭程序解释
2.2、IIC协议的起始与终止,24c02的应答与非应答
这一部分的详细解释见本篇文章第一节。主要是根据时隙写的。
//基本模块设置
//开始状态
void start()
{
SDA=1;
_nop_();
SCL=1;
_nop_();
SDA=0;
_nop_();
SCL=0;
_nop_();
}//结束状态
void end()
{
SDA=0;
_nop_();
SCL=1;
_nop_();
SDA=1;
_nop_();
}//应答
void ack()
{
SDA=0;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
}//非应答
void noack()
{
SDA=1;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
}
2.3、发送字节给2402
这个地方比较难理解,下面进行仔细讲解。
先逐行看程序
void sendbyte2402 (uchar dat )
定义含有返回值的函数,以及要发送的数据,为什么要有返回值呢。这是因为这段程序可能会发生错误,比如无法与设备通信或者写入数据出错等。通过设置返回值可以让调用者知道这段程序执行的结果,从而采取相应的措施或者纠正错误。
具体来说,在这段程序中,写入或读取数据时需要向设备发送一些命令,并检查设备是否回应了正确的应答信号,如果设备没有回应或者应答信号有误,程序就会出错。如果不设置返回值,调用者无法得知这段程序是否执行成功,也无法根据执行结果进行后续处理。因此,设置返回值可以提高程序的健壮性(鲁棒性)和可靠性。
uchar i;for(i=0;i<8;i++) //一字节等于8为二进制{}
进行循环传输字节,一字节是8为二进制
SCL=0;_nop_();
在前面的基础知识中讲过,当时钟线为1时,是进行保持的,不能改变状态,所以为了能够写入数据,这里将时钟置为0。延时的目的是,确定时钟线已经被拉高,可以正确写入数据。
SDA=dat>>7;_nop_();
dat 里面的8位2进制向右移动7位,赋值给SDA,那么SDA里面存的就是高位了。
延时的目的是以确保数据已经稳定传输。
SCL=1;
拉高时钟线,确保状态不再变化,数据存起来了。
dat=dat<<1;
dat进行左移,次高位变成了最高位,继续进行传输。
SCL=0;
关于为什么加 scl=0;:在这段代码中,每次发送完一位数据后,需要将时钟线 scl 置为0,以便下次发送数据。由于后续还需要使用 scl,因此需要在每次使用 scl 前将其置为0,以避免上次时钟信号的干扰。循环结束后,需要再次将 scl 置为0,以避免在后续操作中发生意外的时钟信号。
向24C02发送字节的完整程序为
void sendbyte2402 (uchar dat )
{uchar i;for(i=0;i<8;i++) //一字节等于8为二进制{SCL=0;_nop_();SDA=dat>>7;_nop_();SCL=1;dat=dat<<1;}SCL=0;//时钟重置
}
2.4、从24C02里面读取字节
有了发送数据知识的积累,现在我们来看从2402上读字节
uchar readbyte2402() //主体一个字节
{uchar i,dat=0;SDA=1;for (i=0;i<8;i++){SCL=1; // 数据稳定,方便读取_nop_(); dat<<=1; // 左移移位并赋值给dat _nop_(); dat=dat|SDA;_nop_(); SCL=0;_nop_(); }return bat;
}
详细解释
uchar readbyte2402(): 定义了一个名为readbyte2402的函数,它没有输入参数,返回类型为uchar,即一个字节的无符号整数。
uchar i,dat=0;: 定义了两个变量i和dat,i用于计数,dat用于存储读取的数据,初始值为0。
SDA=1;: 将SDA引脚设置为高电平,即输入模式,准备读取数据。
if(i=0;i<8;i++): 循环8次,依次读取8个位。
SCL=1;: 将SCL引脚设置为高电平,读取数据前先将时钟线拉高,确保数据稳定。
nop();: 空指令,延时一段时间。
dat<<=1;: 左移移位,将已经读取到的数据向左移一位,为下一个数据位腾出位置。
nop();: 空指令,延时一段时间。
dat=dat|SDA;: 将当前读取到的SDA数据位与dat变量进行或运算,将结果存储在dat中。
nop();: 空指令,延时一段时间。
SCL=0;: 将SCL引脚拉低,数据线上的数据位已经读取完毕,准备读取下一个数据位。
nop();: 空指令,延时一段时间。
return dat;: 返回已经读取到的8位数据,即一个字节的数据。
2.5、将数据写入到24C02
参数解释
uchar *ptr,uchar addr,uchar n
uchar *ptr:指向一个uchar类型的指针,该指针指向一块内存区域,用于存储要写入24C02的数据。
uchar addr:表示24C02内存的地址,指示从哪个地址开始写入数据。
uchar n:表示要写入的数据长度,即写入多少个字节的数据。
sendbyte2402(0xa0);
这行代码是向 24C02 发送一个写命令,并指定设备地址为 0xa0。在 I2C 协议中,设备地址的最高位是固定为 0 的,其余七位由硬件接线或软件设置。在这个代码中,设备地址为 0xa0,也就是二进制的 1010000,其中最高位为 0。这个地址是由厂商定义的,用来识别 24C02 存储器芯片。发送完这个命令后,接下来的操作就是向 24C02 写入数据。
之后就是根据数据长度进行循环,给地址和指针发送数据,并且产生应答,每经过一次循环,地址和指针自加1。
将数据写入到24C02的完整代码为
//将数据写入到24C02
void write2402(uchar *ptr,uchar add, uchar n) //指针,地址,写入长度
{
uchar i;
start();
_nop_();
sendbyte2402(0xa0);
_nop_();
ack();
_nop_(); //给2402发送写的命令 ,并应答for(i=0;i<n;i++)
{_nop_();
sendbyte2402(add);_nop_();ack();_nop_();
sendbyte2402( *ptr);
_nop_();ack();_nop_();add++;ptr++;
}
end();
delay(10);
}
这里面调用了许多空字节进行延时。那么自己定义的子程序delay和nop的区别在于:
delay指令是用于延时的,它可以在程序中让CPU暂停执行一段时间,等待一段时间后再继续执行后续的指令。延时的时间长度可以通过给delay指令传递参数来指定,一般以毫秒或微秒为单位。delay指令会消耗CPU资源,因此需要慎重使用,避免过度延时导致程序响应变慢或卡死。
nop指令是空操作指令,它的作用是让CPU执行一条空指令,不进行任何操作,只是等待一个时钟周期后继续执行下一条指令。nop指令通常用于占位或者空转,以便程序的执行时间满足特定的要求。相比delay指令,nop指令的执行速度更快,不会消耗过多的CPU资源,但是无法精确控制时间长度。
2.6、使用I2C协议从24C02芯片中读取n个字节的数据
sendbyte2402(add); //告诉地址
noack(); //不应答就开始读数据
不应答就开始读取数据的意思是。应答表示24C02正在接受数据,如果接收器返回非应答信号,就说明接收器不准备接收数据,可以开始读取数据了。
sendbyte2402(0xa1);
告诉芯片要读取命令
SCL=0;
在这个代码中,将时钟置0是为了防止在读完数据后,芯片还继续发送一些不必要的I2C命令。这个时候将时钟线拉低,芯片就无法再继续发送命令了,从而确保传输的安全性。
时钟线在正常的I2C通信过程中会有起伏和变化,但是在数据读取结束后,需要确保时钟线处于空闲状态(即没有起伏和变化),才能避免意外产生I2C命令。将时钟线拉低,就是让时钟线始终保持低电平,确保空闲状态。
I2C从24C02里面读数据的完整代码是
//使用I2C协议从24C02芯片中读取n个字节的数据void read2402(uchar *ptr,uchar add, uchar n){
start();
_nop_();
sendbyte2402(0xa0);
_nop_();
ack();
_nop_();while(n) //循环n次,每次读取一个字节
{
sendbyte2402(add); //告诉地址
noack(); //不应答就开始读数据
_nop_();start();
sendbyte2402(0xa1); //告诉24C02,读命令 告诉芯片要读取数据
ack();*ptr=readbyte2402();
ack();
ptr++;
add++;
n--;//循环计数器
}
SCL=0;
stop();}
上面比较细节的地方,在这一节里面已经详细说过,下面介绍该段代码的整体逻辑。这段代码实现的功能是读取数据。
在读取数据前需要向24C02发送一个写命令,告诉它要从哪个地址读取数据。所以在读命令的地方需要先执行写命令,然后再发送读命令,这样24C02才能正确地读取数据并发送给主控芯片。
接下来进入循环,读取数据
首先是告诉地址,没有应答,表明这一会没有数据写入,所以是可以读取数据的。告诉24C02,要读取数据,产生应答,代表可以读数据。指针、地址自加1,循环次数自减1,完成一次读取。
2.7、数码管锁存
void cmg()
{
duan=1;
P0=0x00;
duan=0;wei=1;
P0=0x00;
wei=0;RST=0; //关时钟DS1302
}
这一块解释见博文
链接: 单片机——数码管动态显示
2.8、LCD1602的写命令、读命令操作以及设置工作方式模块(初始化)
//LCD1602写命令void writecom(uchar command){delay(10);RS_command;RW_write;E_open;Data=command;_nop_();E_close;}//LCD1602写数据void writedata(uchar da){delay(10);RS_data;RW_write;E_open;Data=da;_nop_();E_close;}//LCD初始化void Init(){cmg();delay(15);writecom(0x38);//数据总线8位,显示两行。5×7writecom(0x38);writecom(0x38);writecom(0x0e); //显示功能开,有光标,光标闪烁writecom(0x06); // 光标右移,显示屏不移动writecom(0x01); //清屏}}
详细解释见博客
链接: 单片机——LCD1602
2.9、对数据进行处理
在程序的最开始我们定义了要显示的字符和要存储的数据。
char string[]={"wuliwuli:"} ;
char string1[]={"clemmence:"};
uchar arr[8];
uchar arr1[8];
uchar dat[]={12,13,14,15};
对bat数组里的四个元素进行处理,并放在arr中
void culi(){arr[0]='0'+dat[0]/10;arr[1]='0'+dat[0]%10;arr[2]='0'+dat[1]/10;arr[3]='0'+dat[1]%10;arr[4]='0'+dat[2]/10;arr[5]='0'+dat[2]%10;arr[6]='0'+dat[3]/10;arr[7]='0'+dat[3]%10;}}
函数culi()是将bat数组中四个元素(即bat[0]、bat[1]、bat[2]和bat[3])转换成对应的两位数字,保存在arr数组中。每个元素先除以10,得到十位上的数字,然后对10取余数,得到个位上的数字。这样就将四个数值分别处理成了两位数字,便于在1602液晶屏上显示。
arr[0]=‘0’+bat[0]/10;
在这个代码中, ‘0’ 是一个 ASCII 码值,表示字符 “0”。‘0’ + arr1[0]/10 将 arr1[0] 的值除以 10,得到十位上的数字,然后将其转换为字符 “0” 到 “9” 中的一个。由于字符在计算机中以 ASCII 码的形式表示,“0” 的 ASCII 码值是 48,所以可以用 ‘0’ 加上任何数字来获得相应的 ASCII 码字符。
void culi1(){arr[0]='0'+arr1[0]/10;arr[1]='0'+arr1[0]%10;arr[2]='0'+arr1[1]/10;arr[3]='0'+arr1[1]%10;arr[4]='0'+arr1[2]/10;arr[5]='0'+arr1[2]%10;arr[6]='0'+arr1[3]/10;arr[7]='0'+arr1[3]%10;}
arr1目前是一个空数组,待会会从24c02里面读数据,进行存储,所以同时也要将arr1处理并放置在arr数组中。
2.10、规定数据显示的位置显示的内容
2.10.1、规定显示的位置
lcdpos(uchar line ,p)
{
uchar pos;
if(line==0)
pos=0x80;//写在第一行
if(line==1)
pos=0xc0;//写在第二行
pos=p+pos;
writecom(pos);
}
这段代码是用于将数据显示在16x2字符LCD上的。首先,定义一个长度为4的数组dat,存储要显示的数据。接下来是两个函数,lcd_pos函数用于设置显示位置,其中参数line表示行数,p表示列数。因为1602显示器有两行,每行可以显示16个字符,所以第一行地址从0x80开始,第二行地址从0xc0开始,列数是在此基础上加上一个偏移量。例如,line=0,p=5时,pos的值为0x85,表示第一行第6个字符位置。
2.10.2、显示数据
lcddat(uchar n,uchar *ptr)
{
uchar i;
for(i=0;i<n;i++)
{
writedata (*(ptr+i));
}
}
n是数据长度。
*(ptr+i)是指针操作,表示取出指针ptr指向的内存中的值,加上偏移量i。这里的偏移量i实际上是循环变量,用来控制遍历的数据位置。
在函数lcddat中,ptr指向的是一个数组,通过遍历数组元素,将每个元素的值写入1602显示器中。使用指针的好处在于,可以避免数组在函数参数传递时的复制,节省内存空间。同时,通过传递指针,可以在函数内部修改调用者传递进来的数据。
2.11、主函数
void main()
{
uchar i;
Init(); //初始化,准备进行显示
delay(100);i=0;
lcdpos(0,0) ;//0行0列开始
lcddat(9,string+i); //wuliwuli:,是九个字符,显示dis里面的值i=0;
lcdpos(1,0) ;//1行0列开始
lcddat(9,string1+i); //写数据到24C02,给数据让1602显示,从2402里面读数据,再给1602显示while(1){i=0;write2402(dat+i,0,4);culi();i=0;lcdpos(0,10);lcddat(8,arr+i);i=0;read2402(arr1+i,0,4);i=0;culi1();lcdpos(1,10);lcddat(8,arr+i);}
}
主函数的主要功能是这段代码的主要作用是将数据写入24C02存储器,读取该存储器中的数据并将其显示在LCD1602液晶屏上。主要是对前面函数的调用。大体步骤:
初始化并准备显示。这里定义了一个uchar类型的变量i,然后调用了初始化函数Init()和延时函数delay(),以准备显示。
在LCD1602上显示字符串。这里设置了光标的初始位置,然后在LCD1602上显示了两个字符串。第一个字符串是从变量dis中取出来的,并在第0行第0列开始显示,显示长度为9个字符。第二个字符串是从变量dis1中取出来的,并在第1行第0列开始显示,显示长度为9个字符。
将数据写入24C02存储器。这里使用了一个无限循环,不断地将数据写入24C02存储器。使用函数write2402(),将变量dat中的数据写入存储器的地址0,写入4个字节。
读取24C02存储器中的数据,并在LCD1602上显示。这里调用了culi()和culi1()函数,用于控制延时时间。然后使用函数read2402()从24C02存储器中读取数据,将其存储在变量arr1中,从地址0开始读取4个字节。最后,在LCD1602上显示变量arr中的8个字符。
3.完整代码
#include<reg52.h>
#include<intrins.h> //_nop_
#define uchar unsigned char
#define uint unsigned intsbit SCL=P2^1;
sbit SDA=P2^0;
sbit RS=P1^0;
sbit RW=P1^1;
sbit E=P2^5;
sbit duan=P2^6;
sbit wei =P2^7;
sbit RST=P2^4;#define RS_data RS=1
#define RS_command RS=0
#define RW_read RW=1
#define RW_write RW=0
#define E_close E=0
#define E_open E=1
#define Data P0char string[]={"wuliwuli:"} ;
char string1[]={"clemence:"};
uchar arr[8];
uchar arr1[8];
uchar dat[]={12,13,14,15};// 延时部分
void delay(uint k)
{uint i,j;
for(i=0;i<k;i++){for(j=0;j<113;j++){;}}
}//基本模块设置
//开始状态
void start()
{
SDA=1;
_nop_();
SCL=1;
_nop_();
SDA=0;
_nop_();
SCL=0;
_nop_();
}//结束状态
void end()
{
SDA=0;
_nop_();
SCL=1;
_nop_();
SDA=1;
_nop_();
}//应答
void ack()
{
SDA=0;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
}//非应答
void noack()
{
SDA=1;
_nop_();
SCL=1;
_nop_();
SCL=0;
_nop_();
}//发送字节给2402
void sendbyte2402 (uchar dat )
{uchar i;for(i=0;i<8;i++) //一字节等于8为二进制{SCL=0;_nop_();SDA=dat>>7;_nop_();SCL=1;dat=dat<<1;}SCL=0;//时钟重置
}//从2402里面读取字节
uchar readbyte2402() //主体一个字节
{uchar i;uchar dat=0;SDA=1;for (i=0;i<8;i++){SCL=1; // 数据稳定,方便读取_nop_(); dat<<=1; // 左移移位并赋值给dat _nop_(); dat=dat|SDA;_nop_(); SCL=0;_nop_(); }return dat;
}//将数据写入到24C02
void write2402(uchar *ptr,uchar add, uchar n) //指针,地址,写入长度
{
uchar i;
start();
_nop_();
sendbyte2402(0xa0);
_nop_();
ack();
_nop_(); //给2402发送写的命令 ,并应答for(i=0;i<n;i++)
{_nop_();
sendbyte2402(add);_nop_();ack();_nop_();
sendbyte2402( *ptr);
_nop_();ack();_nop_();add++;ptr++;
}
end();
delay(10);
}//使用I2C协议从24C02芯片中读取n个字节的数据void read2402(uchar *ptr,uchar add, uchar n){
start();
_nop_();
sendbyte2402(0xa0);
_nop_();
ack();
_nop_();while(n) //循环n次,每次读取一个字节
{
sendbyte2402(add); //告诉地址
noack(); //不应答就开始读数据
_nop_();start();
sendbyte2402(0xa1); //告诉24C02,读命令 告诉芯片要读取数据
ack();*ptr=readbyte2402();
ack();
ptr++;
add++;
n--;//循环计数器
}
SCL=0;
end();}//数码管锁存
void cmg()
{
duan=1;
P0=0x00;
duan=0;wei=1;
P0=0x00;
wei=0;RST=0; //关时钟DS1302
}//LCD1602写命令void writecom(uchar command){delay(10);RS_command;RW_write;E_open;Data=command;_nop_();E_close;}//LCD1602写数据void writedata(uchar da){delay(10);RS_data;RW_write;E_open;Data=da;_nop_();E_close;}//LCD初始化void Init(){cmg();delay(15);writecom(0x38);//数据总线8位,显示两行。5×7writecom(0x38);writecom(0x38);writecom(0x0e); //显示功能开,有光标,光标闪烁writecom(0x06); // 光标右移,显示屏不移动writecom(0x01); //清屏}//对dat和arr1里面的数据进行处理void culi(){arr[0]='0'+dat[0]/10;arr[1]='0'+dat[0]%10;arr[2]='0'+dat[1]/10;arr[3]='0'+dat[1]%10;arr[4]='0'+dat[2]/10;arr[5]='0'+dat[2]%10;arr[6]='0'+dat[3]/10;arr[7]='0'+dat[3]%10;}void culi1(){arr[0]='0'+arr1[0]/10;arr[1]='0'+arr1[0]%10;arr[2]='0'+arr1[1]/10;arr[3]='0'+arr1[1]%10;arr[4]='0'+arr1[2]/10;arr[5]='0'+arr1[2]%10;arr[6]='0'+arr1[3]/10;arr[7]='0'+arr1[3]%10;}//显示位置lcdpos(uchar line ,p)
{
uchar pos;
if(line==0)
pos=0x80;//写在第一行
if(line==1)
pos=0xc0;//写在第二行
pos=p+pos;
writecom(pos);
}//显示数据
lcddat(uchar n,uchar *ptr)
{
uchar i;
for(i=0;i<n;i++)
{
writedata (*(ptr+i));
}
}void main()
{
uchar i;
Init(); //初始化,准备进行显示
delay(100);i=0;
lcdpos(0,0) ;//0行0列开始
lcddat(9,string+i); //wuliwuli:,是九个字符,显示dis里面的值i=0;
lcdpos(1,0) ;//1行0列开始
lcddat(10,string1+i); //写数据到24C02,给数据让1602显示,从2402里面读数据,再给1602显示while(1){i=0;write2402(dat+i,0,4);culi();i=0;lcdpos(0,10);lcddat(8,arr+i);i=0;read2402(arr1+i,0,4);i=0;culi1();lcdpos(1,10);lcddat(8,arr+i);}
}
4.运行结果
ps:这里解释一下,忘记它是1602了,15没地方显示了。由于程序和文章都是边做边写的,所以说修改的话,上面的子程序也要跟着修改,所以就不想修改了。然后子程序,就是第二板块内容是边做边写的,所以说子程序是在没有运行的情况下写的,部分地方可能存在问题,在运行完之后也对子程序进行了修改,但是难免还是有一些错误。但是完整的程序,就是第三部分一定是对的,在连线和我端口定义一样的情况下,一定是可以做出来的。(我自己做不出来就放在草稿箱里,改天继续看)
本次的24C02的部分有些难度,它是1602,IIC协议和24C02的综合。较之于之前新添加的部分就是IIC协议的使用和向24C02发数据,24C02写数据,读24C02里面的数据等。
好啦,24C02的部分就到这里啦。如有疑问,评论区留言,如能帮助到您,点个关注呗。
相关文章:
单片机——IIC协议与24C02
1、基础知识 1.1、IIC串行总线的组成及工作原理 I2C总线只有两根双向信号线。一根是数据线SDA,另一根是时钟线SCL。 1.2、I2C总线的数据传输 I2C总线进行数据传送时,时钟信号为高电平期间,数据线上的数据必须保持稳定,只有在时钟…...
案例05-将不必要的逻辑放到前端(发送调查问卷)
目录一:背景介绍背景二:思路&方案重大问题:解决办法优点:三:总结一:背景介绍 本篇博客书写的意义是警示大家不必把不必要的逻辑放到前端。 明确前后端分离的意义。 背景 下面的主要逻辑是࿱…...
【每日一题】——矩阵相等判定
🌏博客主页:PH_modest的博客主页 🚩当前专栏:每日一题 💌其他专栏: 🔴 每日反刍 🟢 读书笔记 🟡 C语言跬步积累 🌈座右铭:广积粮,缓称…...
Linux防火墙的关闭
查看防火墙的状态打开终端输入如下命令systemctl status firewalld如图所示:running表示防火墙目前处于打开状态输入命令进行关闭防火墙:systemctl stop firewalld如图所示正常的用户是没有权限的,需要输入管理员的密码才能够进行关闭防火墙。…...
Request和Response的概述
⭐作者介绍:大二本科网络工程专业在读,持续学习Java,输出优质文章⭐作者主页:︶ㄣ释然⭐如果觉得文章写的不错,欢迎点个关注😉有写的不好的地方也欢迎指正,一同进步😁Request和Respo…...
常见的Web安全漏洞:SYN攻击/CSRF/XSS
一、SYN攻击(属于DOS攻击) 什么情况下被动方出现SYN_RCVD状态?(flood攻击服务) 客户伪造 ip 端口, 向服务端发送SYN请求。完成2次握手,第三次服务端 等待客户端ACK确认,但由于客户不存在服务端一直未收到确认&#…...
【STC15单片机】 超声波模块的使用
目录 1 基于STC15F2K60S2的超声波测距代码 1.1 基本注意事项 1.1.1 跳线帽接法 1.1.2 晶振设置 1.2 板载超声波工作原理 1.2.1 原理总结 1.2.2 超声波代码思路 1.3 STC15单片机代码部分 1.3.1 定时器0&定时器1初始化 1.3.2 超声波ultrasonic.c ultrasonic.h文件配…...
SpringBoot 动态操作定时任务(启动、停止、修改执行周期)增强版
前段时间编写了一篇博客SpringBoot 动态操作定时任务(启动、停止、修改执行周期,该篇博客还是帮助了很多同学。 但是该篇博客中的方法有些不足的地方: 只能通过前端控制器controller手动注册任务。【具体的应该是我们提前配置好我们的任务&am…...
快排函数 -- qsort函数(Quick Sort)
文章目录🔎1.qsort函数简介💡1.1.函数原型💡1.2.参数含义🔎2.比较函数介绍🔎3.比较函数使用案例💡3.1.整型数组💡3.2.浮点型数组💡3.3.结构体类型 - 字符串🔎4.利用冒泡排…...
条形码和二维码
前言:需要的包的相关文档 1. Barcode:https://pypi.org/project/python-barcode/0.8.1/ 2. Qrcode:https://pypi.org/project/qrcode/ 3. Zbar: https://pypi.org/project/pyzbar/ 4. Opencv: https://docs.opencv.org/3.4.11/ 5. OpenC…...
大数据-学习实践-5企业级解决方案
大数据-学习实践-5企业级解决方案 (大数据系列) 文章目录大数据-学习实践-5企业级解决方案1知识点2具体内容2.1小文件问题2.1.1 SequenceFile2.1.2 MapFile2.1.3 小文件存储计算2.2数据倾斜2.3 YARN2.3.1 YARN架构2.3.2 YARN调度器2.3.2 YARN多资源队列配置和使用2.4Hadoop官方…...
破解吲哚花菁素IR-808 N3,IR-808 azide,IR-808叠氮,酯溶性染料修饰叠氮基团,相关知识
基础产品数据(Basic Product Data):CAS号:N/A中文名:IR-808叠氮英文名:IR-808 N3,IR-808 azideIR-808结构式(Structural):详细产品数据(Detailed …...
面试官:MQ的好处到底有哪些?
💗推荐阅读文章💗 🌸JavaSE系列🌸👉1️⃣《JavaSE系列教程》🌺MySQL系列🌺👉2️⃣《MySQL系列教程》🍀JavaWeb系列🍀👉3️⃣《JavaWeb系列教程》…...
事务机制:Redis能实现ACID属性吗?
ACID特性无需多言。我们知道关系数据库比如mysql可以实现事务的ACID特性,begin,commit,回滚实现。 那么redis可以实现ACID吗,结论是不能完全保证。 首先要知道redis通过MULTI关键字开启事务,中间一系列操作,加到操作队列中并不执…...
如何在 Apinto 实现 HTTP 与 gRPC 的协议转换(上)
什么是 gRPC 像 gRPC 是由 google 开发的一个高性能、通用的开源 RPC 框架,主要面向移动应用开发且基于 HTTP/2 协议标准而设计,同时支持大多数流行的编程语言。 gRPC 基于 HTTP/2 协议传输,而 HTTP/2 相比 HTTP1.x ,有以下优势:…...
3分钟看完-丄-Python自动化测试【项目实战解析】经验分享
目录:导读 引言 自动化测试 背景 测试团队 测试体系发展 测试平台 自动化测试现状 现状一: 现状二: 现状三: 现状四: 现状五: 现状六: 失败的背景 失败的经历 失败总结 引言 内…...
Web漏洞-命令执行和代码执行漏洞
命令执行原理就是指用户通过浏览器或其他辅助程序提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令。漏洞成因它所执行的命令会继承WebServer的权限,也就是说可以任意读取、修改、执行Web目录下的…...
Towards Unsupervised Text Classification Leveraging Experts and Word Embeddings
Towards Unsupervised Text Classification Leveraging Experts and Word Embeddings Abstract 该论文提出了一种无监督的方法,使用每个文档中相关单词之间的文本相似度以及每个类别的关键字字典将文档分为几类。所提出的方法通过人类专业知识和语言模型丰富了类别…...
linux进程管理
进程管理 进程是启动的可执行程序的一个指令 1、进程简介 (1)进程的组成部分 已分配内存的地址空间安全属性,包括所有权凭据和特权程序代码的一个或多个执行线程进程状态 (2)程序和进程的区别 程序是一个静态的二进制…...
【深度强化学习】(6) PPO 模型解析,附Pytorch完整代码
大家好,今天和各位分享一下深度强化学习中的近端策略优化算法(proximal policy optimization,PPO),并借助 OpenAI 的 gym 环境完成一个小案例,完整代码可以从我的 GitHub 中获得: https://gith…...
【数据结构】第二站:顺序表
目录 一、线性表 二、顺序表 1.顺序表的概念以及结构 2.顺序表的接口实现 3.顺序表完整代码 三、顺序表的经典题目 1.移除元素 2.删除有序数组中的重复项 3.合并两个有序数组 一、线性表 在了解顺序表前,我们得先了解线性表的概念 线性表(linear…...
嵌入式安防监控项目——实现真实数据的上传
目录 一、相关驱动开发 二、A9主框架 三、脚本及数据上传实验 https://www.yuque.com/uh1h8r/dqrma0/tx0fq08mw1ar1sor?singleDoc# 《常见问题》 上个笔记的相关问题 一、相关驱动开发 /* mpu6050六轴传感器 */ i2c138B0000 { /* #address-cells <1>…...
SAP 生成UUID
UUID含义是通用唯一识别码 (Universally Unique Identifier),这 是一个软件建构的标准,也是被开源软件基金会 (Open Software Foundation, OSF) 的组织应用在分布式计算环境 (Distributed Computing Environment, DCE) 领域的一部分。 UUID-Universally…...
DevOPs介绍,这一篇就足够了
一、什么是DevOps? DevOps是一种将软件开发和IT运维进行整合的文化和运动。它的目标是通过加强软件开发、测试和运维之间的协作和沟通,使整个软件开发和交付过程更加高效、快速、安全和可靠。DevOps涵盖了从计划和设计到开发、测试、交付和部署的全生命…...
libcurl库简介
一、libcurl简介libcurl是一个跨平台的网络协议库,支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传, HTTP基本表单上传,代理,cookies,和用户认证。…...
Spark SQL支持DataFrame操作的数据源
DataFrame提供统一接口加载和保存数据源中的数据,包括:结构化数据、Parquet文件、JSON文件、Hive表,以及通过JDBC连接外部数据源。一个DataFrame可以作为普通的RDD操作,也可以通过(registerTempTable)注册成…...
Java【归并排序】算法, 大白话式图文解析(附代码)
文章目录前言一、排序相关概念1, 什么是排序2, 什么是排序的稳定性3, 七大排序分类二、归并排序1, 图文解析2, 代码实现三、性能分析四、七大排序算法总体分析前言 各位读者好, 我是小陈, 这是我的个人主页 小陈还在持续努力学习编程, 努力通过博客输出所学知识 如果本篇对你有…...
【springboot】数据库访问
1、SQL 1、数据源的自动配置-HikariDataSource 1、导入JDBC场景 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-jdbc</artifactId></dependency>数据库驱动? 为什么导入JD…...
普通和hive兼容模式下sql的差异
–odps sql –– –author:宋文理 –create time:2023-03-08 15:23:52 –– – 差异分为三块 – 1.运算符的差异 – 2.类型转换的差异 – 3.内建函数的差异 – 以下是运算符的差异: – BITAND(&) – 当输入参数是BIGINT类型的时候&…...
github开源自己代码
接下来,我们需要先下载Git,的网址:https://git-scm.com/downloads,安装时如果没有特殊需求,一直下一步就可以了,安装完成之后,双击打开Git Bash 出现以下界面: 第一步:…...
湛江网站建设外包/seo专业实战培训
摘要:虚拟机Apache设置很多用户都遇到过,具体如何进行虚拟机Apache设置?怎样才能让虚拟机Apache设置达到最简单,最优化?本文为您讲解。Apache虚拟机设置有两种方法: 基于主机名的虚拟主机(一个IP地址&#…...
微信红包开发平台/百度seo优化方案
一、DLL文件常识DLL是Dynamic Link Library的缩写,意为动态链接库。在Windows中,许多应用程序并不是一个完整的可执行文件,它们被分割成一些相对独立的动态链接库,即DLL文件,放置于系统中。当我们执行某一个程序时&…...
网站建设应该注意哪些原则/短视频矩阵seo系统源码
第一步启用Ad Hoc Distributed Queries 在SQLserver执行以下的语句: exec sp_configure show advanced options,1 reconfigure exec sp_configure Ad Hoc Distributed Queries,1 reconfigure ----允许在进程中使用ACE.OLEDB.12 在安装了 ACE2010的驱动才可以执行…...
网站优化合同/南宁网站建设服务公司
在游戏中,我们都喜欢加一些描边效果,来凸显人物的边缘,提高识别度。美术一般都喜欢加。描边方式一般有两种,一种的模型边缘描边,一种的人物的转折点描边(这种需要用到卷轴) 在游戏中比较常用的…...
怎么做网站信息/全网关键词云查询
间隔了一周时间没写了,由于今年的股势行情貌似不错的样子,对于对股市完全不懂的我也在蠢蠢欲动,所以最近一周业余时间在“不务正业”-----学习炒股。发现学习它其实挺费神的,满脑子都是走势图,而且是神经有点受刺激的感…...
软件开发 网页设计网站/网站底部友情链接代码
容器是一个打包了应用和服务的环境,是一个轻量级的虚拟机,每一个容器都由一组特定的应用和必要的依赖库组成。 容器的管理操作 容器常见的命令:查看、创建、启动、终止和删除 创建容器 docker create docker run 二者的区别在于docker create…...