I2C系列(三):软件模拟I2C读写24C04

一.目标

        PC 端的串口调试软件通过 RS-485 与单片机通信,控制单片机利用软件模拟 I2C 总线对 EEPROM(24C04) 进行任意读写。 

二.RS-485简述

        在工业控制领域,传输距离越长,要求抗干扰能力也越强。由于 RS-232 无法消除共模干扰,且传输距离只有 15m 左右,无法满足要求。
        工业标准组织提出了 RS-485 接口标准。 RS-485 标准采用差分信号传输方式,因此具有很强的抗共模干扰能力。 RS-485 接口芯片 SP485E 的封装及引脚说明如下图 1。

        RS-485 的逻辑电平为:

①当 A 的电位比 B 高 200mV 以上时, 为逻辑 1;

②当 B 的电位比 A 电位高200mA 以上时为逻辑 0,传输距离可达 1200m。由于是差分传输,因此无需公共地,在 RS-485 总线上仅需连接两根线 A 和 B。
       单片机与 RS-485 接口芯片的电路连接图如下图 2。

三.控制命令定义

        定义如下命令:

①c——串口接收数据函数初始化
②s——单片机将接收到的数据发送到串口调试终端显示,以确认单片机是否已正确接收数据
③w——将接收缓冲区 wbuf 中的数据写入 EEPROM 中
④r——将刚才写入 EEPROM 中的数据读出到缓冲区 rbuf 中,并发送到串口调试终端显示

四.C代码

        本代码注重功能实现,以期达到理解I2C协议和24C04读写方法的目的。实际项目还须考虑代码质量,如可读性、可维护性等。

4.1 I2C基础时序模拟

4.1.1 引脚初始化

void i2cinit(void)
{
	sdaout;/*引脚输出模式*/
	sclout;
	sda = 1; /*释放总线*/
	scl = 1;
}

4.1.2 延时函数

1.SCL 时序控制延时函数

        78K0指令的最短时钟周期为2个,一条NOP指令即为2个时钟周期,若使用内部8MHz时钟,则执行一条NOP指令需0.25us。

void delay(void)
{
	UCHAR i;
	for(i = 0;i < NOP_num;i++)
		NOP();
}

2.长延时函数

void delay_long(UINT a)
{
	UINT i,j;
	for(i = 0;i < a;i++)
	    for(j = 0;j < 100;j++);
}

4.1.3 起始信号模拟

        SCL 线为高电平期间, SDA 线由高电平向低电平的变化表示起始信号。

void i2cstart(void)
{
	sdaout;	
	sclout;
	/*1.初始化SDA为高电平:在SCL低电平期间拉高SDA*/
	scl = 0;
	delay();
	sda = 1;
	delay();
	
	/*2.模拟一个起始信号*/
	scl = 1;
	delay();
	sda = 0;
	delay();
}

4.1.4 停止信号模拟

        SCL 线为高电平期间, SDA 线由低电平向高电平的变化表示终止信号。

void i2cstop(void)
{
	sdaout;
	sclout;
	
	/*1.初始化SDA为低电平:在SCL低电平期间拉低SDA*/
	scl=0;
	delay();
	sda=0; 
	delay();
	
	/*2.模拟一个停止信号*/
	scl=1;
	delay();
	sda=1;
	delay();
} 

4.1.5 应答信号模拟

        每一个字节必须保证是 8 位长度。数据传送时,先传送最高位(MSB),每一个被传送的
字节后面都必须跟随一位应答位(即一帧共有 9 位)。

         在第 9 个时钟信号的高电平期间:若 SDA为 0,则为应答;若 SDA 为 1,则为非应答。

1.主机发送应答信号

void i2c_ack_write(UCHAR ack)
{
	sdaout;
	sclout;
	
	/*1.初始化SDA为应答信号/非应答电平:在SLC低电平期间改变SDA*/
	scl=0; /*sda 变化前,先将 scl 置 0,一个时钟周期的开始*/
	delay();
	if(ack == 1)
		sda = 1;/*1,不应答从机,通知从机释放 sda*/
	else 
		sda = 0;/*0,应答从机*/
	delay();
	
	/*2.scl 置高,通知从机读取SDA*/
	scl= 1;
	delay();
} 

2.读取从机的应答信号

UCHAR i2c_ack_read(void)
{
	UCHAR sack;
	sdaout;
	sclout;
	/*1.释放SDA,让从机控制:在SLC低电平期间拉高SDA*/
	scl=0;
	delay();
	sda=1;
	delay();
	sdain; /*sda 设置为输入模式,以检测从机的应答信号*/
	
	/*2.scl 置高,读取从机的应答信号*/
	scl=1
	delay();
	if(sda==1)
		sack=1;/*从机无应答*/
	else 
		sack=0;/*从机应答*/
	return sack; 
} 

4.1.6 写一个字节数据

        只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答。

void writebyte(UCHAR dat)
{
	UCHAR temp=0;
	UCHAR i;
	sdaout;
	sclout;
	for(i = 0;i < 8;i++)
	{
		/*1.在SCL低电平时,准备好SDA*/
		temp = dat&0x80;
		scl = 0; 
		delay();
		if(temp == 0)
			sda = 0;
		else 
			sda = 1; 
		delay();
		
		/*2.拉高SCL,通知从机读SDA*/
		scl = 1;
		delay();
		
		dat = dat << 1;
	}
	
	/*3.释放SDA总线*/
	scl = 0;
	delay();
	sda = 1;
	delay();
}

4.1.7 读一个字节数据

        只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答。

UCHAR readbyte(void)
{
	UCHAR i;
	UCHAR temp = 0;
	sdaout;
	sclout;
	/*1.主机释放SDA,并将SDA设为输入模式*/
	scl = 0;
	delay();
	sda = 1;
	delay();
	sdain; 
	
	for(i = 0;i < 8;i++)
	{
		/*1.拉低SCL,通知从机发送数据*/
		scl=0;
		delay();
		
		/*2.拉高SCL,读取SDA*/
		scl=1;
		delay();
		if(sda == 1)
			temp = (temp << 1) | 0x01;
		else
			temp = (temp << 1) | 0x00;
	}
	return temp;
}

4.2 I2C读写数据

4.2.1 向任意地址写单字节数据

        包括数据传送、应答信号(从机),但不包括开始和停止信号。

UCHAR writebyte_to_anyaddr(UCHAR addr,UCHAR dat)
{
	UCHAR sack;
	
	/*1.写器件地址*/
	writebyte(deviceaddr0);	
	sack = i2c_ack_read(); 
	if(sack	==	1)
		return 1;
	
	/*2.写存储单元地址*/
	writebyte(addr);
	sack = i2c_ack_read(); 
	if(sack == 1)
		return 1;
	
	/*3.发送数据*/
	writebyte(dat);	
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	else
		return 0;
} 

4.2.2 从任意地址读单字节数据

        包括数据传送、应答信号,但不包括开始和停止信号。

UCHAR readbyte_from_anyaddr(UCHAR addr)
{
	UCHAR temp = 0;
	UCHAR sack = 0;
	
	/*1.写器件地址*/
	writebyte(deviceaddr0);
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	
	/*2.写存储单元地址*/
	writebyte(addr);
	sack = i2c_ack_read();
	if(sack == 1)
		return 1;
	
	/*3.重置开始,改为读方向*/
	i2cstart();	
	writebyte(deviceaddr1);
	sack = i2c_ack_read();
	if(sack==1)
		return 1;
	
	/*4.读数据*/
	temp=readbyte();
	return temp; 
} 

4.2.3 写n字节数据到任意地址

UCHAR writenbytes_to_anyaddr(UCHAR addr,UCHAR* buf,UCHAR buflen)
{
	UCHAR i = 0;
	UCHAR sack = 0;
	i2cstart();
	writebyte_to_anyaddr(addr,buf[i]);/*向指定地址写一个数据*/
	for(i = 1;i < buflen;i++)
	{
		if(BYTES_PER_PAGE == 8)/*页边界处理:页内字节数为 8*/
		{
			if((addr & 0x07) == 0x07)/*地址的低 3 位为“111”时,主机须送下一页的起始地址*/
			{
				i2cstop(); /*到页边界时,主机须发停止信号,通知从机结束当前页的传送*/
				delay_long(1);/*结束信号与开始信号之间须延时*/
				i2cstart();/*开始*/
				writebyte(deviceaddr0); /*送器件地址,写*/
				sack = i2c_ack_read(); /*检测从机应答*/
				if(sack==1)
					return 1;/*无应答,返回 1*/
			
				writebyte(addr + 1);/*写数据地址,地址值加 1*/
				sack=i2c_ack_read();/*检测从机应答*/
				if(sack == 1)
					return 1;/*无应答,返回 1*/
			}
		}
		if(BYTES_PER_PAGE == 16)/*页边界处理:页内字节数为 16*/
		{
			if((addr&0x0f)==0x0f)/*地址的低 4 位为“1111”时,主机须送下一页的起始地址*/
			{
				i2cstop();
				delay_long(1);
				i2cstart();
				writebyte(deviceaddr0);
				i2c_ack_read();
				writebyte(addr+1);
				sack=i2c_ack_read();
				if(sack==1)
					return 1;
			}
		}
		writebyte(buf[i]); /*页内写字节,地址自动加 1*/
		sack=i2c_ack_read();
		if(sack==1)
			return 1;
	
		addr++;/*addr 始终等于当前写入数据的地址,以便进行页边界判断*/
	}
	return 0; /*返回 0,写成功*/
} 

4.2.4 从任意地址读n字节数据

UCHAR readnbytes_from_anyaddr(UCHAR addr,UCHAR* buf,UCHAR buflen)
{
	UCHAR i=0;
	UCHAR sack;
	i2cstart();/*开始*/
	writebyte(deviceaddr0);/*送器件地址,写*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	writebyte(addr);/*送数据地址*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	i2cstart();/*开始*/
	writebyte(deviceaddr1);/*送器件地址,读*/
	sack=i2c_ack_read();/*检测从机应答*/
	if(sack==1)
		return 1;
	
	for(i=0;i<buflen;i++)
	{
		buf[i]=readbyte(); /*读一字节数据到指定的缓冲区中*/
		if(i==(buflen-1))
			i2c_ack_write(M_NACK); /*读完后,主机不应答,通知从机释放 sda*/
		else
			i2c_ack_write(M_ACK); /*若未读完,主机应答,继续读*/
	}
	return 0;/*返回 0,读成功*/
}

4.3 串口中断服务函数

4.3.1 接收中断处理函数

__interrupt void MD_INTSR0(void)
{
	UCHAR err_type;
	UCHAR rx_data;
	err_type = ASIS0;
	rx_data = RXB0;
	P7=rx_data;
	if( err_type & 0x07 )
	{
		CALL_UART0_Error( err_type );
		return;
	}
	if(rx_data=='c') /*接收到 c 命令, flag 置 1*/
	{
		flag=1;
		return;
	}
	if(rx_data=='s') /*接收到 s 命令, flag 置 2*/
	{
		flag=2;
		return;
	}
	if(rx_data=='w') /*接收到 w 命令, flag 置 4*/
	{
		flag=4;
		return;
	}
	if(rx_data=='r')/*接收到 r 命令, flag 置 5*/
	{
		flag=5;
		return;
	}
	if(gUart0RxLen > gUart0RxCnt)/*正常接收数据,非命令*/
	{
		*gpUart0RxAddress = rx_data;
		gpUart0RxAddress++;
		gUart0RxCnt++;
	}
	else
		flag=3;/*接收缓冲区满, flag 置 3*/
} 

4.3.2 发送中断处理函数

__interrupt void MD_INTST0(void)/*发送中断处理函数*/
{
	if( gUart0TxCnt > 0 )
	{
		TXS0 = *gpUart0TxAddress;
		gpUart0TxAddress++;
		gUart0TxCnt--;
	}
	else /*发送完毕*/
	{
		P1.2=0;/*将 485 设置为接收模式*/
		SRMK0=0;/*开接收中断*/
	}
}

4.4 宏定义和声明

extern volatile USHORT gUart0RxCnt; /*接收数据统计*/
extern UCHAR flag;/*串口调试软件终端发送的命令标识*/

#define NOP_num 60/*延时函数中 NOP()指令的执行次数*/
#define scl P6.0 /*开漏输出引脚 P6.0 作为时钟引脚*/
#define sda P6.1 /*开漏输出引脚 P6.1 作为数据引脚*/
#define sclout PM6.0=0 /*时钟引脚输出模式*/
#define sdaout PM6.1=0 /*数据引脚输出模式*/
#define sclin PM6.0=1 /*时钟引脚输入模式*/
#define sdain PM6.1=1 /*数据引脚输入模式*/
#define deviceaddr0 0xa0 /*器件地址宏定义,输出*/
#define deviceaddr1 0xa1 /*器件地址宏定义,输入*/
#define M_NACK 1 /*主机无应答常量定义*/
#define M_ACK 0 /*主机应答常量定义*/
#define BYTES_PER_PAGE 16 /*EEPROM 页内字节数宏定义*/

void delay(void); /*SCL 时序控制延时函数*/
void delay_long(UINT a);/*长延时函数*/

void i2cinit(void);/*IIC 引脚初始化函数*/

void i2cstart(void);/*启动函数*/
void i2cstop(void);/*停止函数*/
void i2c_ack_write(UCHAR);/*主机应答处理函数*/
UCHAR i2c_ack_read(void);/*从机应答处理函数*/

void writebyte(UCHAR dat);/*写一个字节函数,只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答*/
UCHAR readbyte(void);/*读一个字节函数,只是数据段传送的操作,即开始与应答之间的操作,但不包括开始和应答*/

UCHAR writebyte_to_anyaddr(UCHAR addr,UCHAR dat);/*向任意地址写一个数,包括开始信号、数据传送、应答信号(从机),但不包括停止信号*/
UCHAR readbyte_from_anyaddr(UCHAR addr);/*从任意地址中读一个数,包括开始信号和数据传送,但不包括应答信号(主机)和停止信号*/

UCHAR writenbytes_to_anyaddr(UCHAR addr,UCHAR* buf,UCHAR buflen);/*向任一地址开始的连续多个储存单元写一串数据*/
UCHAR readnbytes_from_anyaddr(UCHAR addr,UCHAR* buf,UCHAR buflen);/*从任一地址开始的连续多个储存单元读出一串数据*/

4.5 主处理函数main

void main( void )
{
	UCHAR wbuf[256]={0};/*待写到 EEPROM 中的数据缓冲区*/
	UCHAR rbuf[256]={0};/*从 EEPROM 中读出的数据缓冲区*/
	UCHAR wend[10]={'w','r','i','t','e',' ','e','n','d','!'};/*写完成提示*/
	UCHAR temp=0;
	UCHAR i;
	UCHAR wnum=0;
	i2cinit();/*IIC 引脚初始化*/
	UART0_ReceiveData( wbuf,256);/*串口接收数据函数初始化*/
	P1.2=0;/*RS-485 使能引脚,设置为数据接收模式*/
	UART0_Start(); /*启动串口*/
	P7.0=0; /*程序运行 LED 指示*/
	while (1)
	{
		if(flag == 1)/*c 命令,串口接收数据函数初始化*/
		{
			UART0_ReceiveData( wbuf,256);
			flag=0;
		}
		if(flag == 2)/*s 命令,单片机将接收到的数据发送到串口调试终端显示*/
		{
			SRMK0=1;/*屏蔽接收中断*/
			P1.2=1; /*单片机设置为数据发送模式*/
			delay_long(1);
			flag=0;
			temp=(UCHAR)gUart0RxCnt;/*强制类型转换*/
			UART0_SendData(wbuf,temp);/*将接收的数据发送到串口调试终端*/
		}
		if(flag==3)/*接收缓冲区满,初始化串口接收函数,覆盖原来的数据*/
		{
			flag=0;
			UART0_ReceiveData( wbuf,256);
		}
		if(flag==4)/*w 命令,将 wbuf 中的数据写入 EEPROM 中*/
		{
			flag=0;
			DI();/*写过程,禁止中断*/
			temp=(UCHAR)gUart0RxCnt;
			writenbytes_to_anyaddr(0,wbuf,temp);
			i2cstop();
			delay_long(2);
			i2cstart();
			writebyte_to_anyaddr(250, temp);
			i2cstop();
			EI();/*开中断*/
			SRMK0=1;/*屏蔽接收中断*/
			P1.2=1; /*设置为发送模式*/
			UART0_SendData( wend,10);/*发送写结束字符串到串口调试终端显示*/
		}
		if(flag==5)/*r 命令,将刚才写入到 EEPROM 中的数据读出到 rbuf 中,并发送到串口调试终端显示*/
		{
			flag=0;
			DI();/*读过程中,禁止中断*/
			i2cstart();
			wnum=readbyte_from_anyaddr(250);
			i2cstop();
			delay_long(1);
			readnbytes_from_anyaddr(0,rbuf,wnum); /*读数据*/
			i2cstop();
			EI();/*开中断*/
			SRMK0=1;
			P1.2=1;
			delay_long(1);
			UART0_SendData(rbuf,wnum);
		}
	}
}

五.测试结果

        发送 “1,2,3....18” 共 18 个数给单片机,让单片机以页写的方式写入 24C04 中。

        结果如下:
1) 若不进行页边界处理,则 17 和 18 两个数覆盖 01 和 02,即为页上卷,且说明页内字节数为
16字节。(如下图 )

2)进行页边界处理后,结果如下图 :
 

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

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

相关文章

【复杂网络建模】——XGI库进阶学习:生成随机超图

目录 一、构建随机超图 二、绘制随机超图 三、其他功能 3.1 访问超图的最大阶 3.2 列出所有边尺寸 3.3 边大小的直方图 3.4 节点度直方图 一、构建随机超图 XGI&#xff08;eXtensible Graphs and Hypergraphs&#xff09;是一个Python库&#xff0c;专注于超图&#…

ARM CPU的总线发展

ARM架构是当今世界上最为广泛应用的嵌入式处理器架构之一&#xff0c;其CPU总线的发展对于系统性能和扩展性具有重要影响。本文将探讨ARM CPU总线的发展历程、关键技术和对系统性能的影响。 以下是我整理的关于嵌入式开发的一些入门级资料&#xff0c;免费分享给大家&#xff…

Flutter学习10 - Json解析与Model使用

对于网络请求返回的 Json 数据&#xff0c;一般会进行如下解析&#xff1a; 将 Json String 解析为 Map<String, dynamic>将 Json String 解析为 Dart Model 发起一个返回 Json String 的网络请求 import package:http/http.dart as http;void main() {_doGet(); }_do…

计算机网络——26通用转发和SDN

通用转发和SDN 网络层功能&#xff1a; 转发&#xff1a; 对于从某个端口 到来的分组转发到合适的 输出端口路由&#xff1a; 决定分组从源端 到目标端的路径 网络层 传统路由器的功能 每个路由器(Per Route)的控制平面 &#xff08;传统&#xff09; 每个路由器上都有实…

本地运行环境工具UPUPWANK(win)和Navicat数据库管理工具

UPUPWANK安装地址&#xff1a;https://www.upupw.net 1.进入UPUPWANK后点击一键开启 2.新增项目 这里请千万注意80端口&#xff0c;如果80端口被占用了&#xff0c;请记住去任务管理器关闭占用80端口的进程。不然就不会成功显示。&#xff08;笔者含泪警告&#xff0c;一晚上的…

2024年C语言最新经典面试题汇总(11-20)

C语言文章更新目录 C语言学习资源汇总&#xff0c;史上最全面总结&#xff0c;没有之一 C/C学习资源&#xff08;百度云盘链接&#xff09; 计算机二级资料&#xff08;过级专用&#xff09; C语言学习路线&#xff08;从入门到实战&#xff09; 编写C语言程序的7个步骤和编程…

Day44:WEB攻防-PHP应用SQL盲注布尔回显延时判断报错处理增删改查方式

目录 PHP-MYSQL-SQL操作-增删改查 PHP-MYSQL-注入函数-布尔&报错&延迟 基于布尔的SQL盲注-逻辑判断(需要有回显,没回显搞不了)跟union需要的条件差不多 基于时间的SQL盲注-延时判断(不需要任何回显) 基于报错的SQL盲注-报错回显(需要报错回显&#xff0c;没报错回…

算法系列--链表刷题(二)

&#x1f495;"轻舟已过万重山"&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;算法系列–链表刷题(二) 今天为大家带来的是算法系列--链表刷题(二),带来了几道经典的有关链表的面试题(合并K个有序列表) 1.两数相加 https://leetcode.cn/problems/a…

短视频素材网站去哪里找?

嘿&#xff0c;各位视频创作者们&#xff01;想知道短视频素材网站去哪里找&#xff1f;今天就来给大家介绍几个必备的视频素材网站&#xff0c;特别是对于入门新手和运营人员来说&#xff0c;这些网站可是必不可少的资源哦&#xff01; 首先&#xff0c;我们来看看那些提供可…

FreeRtos时间管理(一)

FreeRtos的时间管理包括相对延时vTaskDelay、绝对延时vTaskDelayUntil、系统时钟Systick 本篇主要分析相对延时vTaskDelay函数 调用vTaskDelay是一定会触发任务切换的&#xff0c;需要分析下PendSv中断触发的位置。 一、 函数流程 二 、prvAddCurrentTaskToDelayedList 注意&…

Redis中AOF、RDB和复制功能对过期键的处理

AOF、RDB和复制功能对过期键的处理 生成RDB文件 在执行SAVE命令或者BGSAVE命令创建一个新的RDB文件时&#xff0c;程序会对数据库中的键进行检查&#xff0c;已过期的键不会被保存到新创建的RDB文件中。 例子 举个例子&#xff0c;如果数据库中包含三个键k1、k2、k3&#x…

地宫取宝dfs

分析&#xff1a; 矩阵里的每一个位置都有标记&#xff0c;要求的问题是&#xff1a;有几种方法能完成这个规定。 那么&#xff0c;我们只需要计算从开始(1,1)到最后(n,m)的深度优先搜索中&#xff0c;有几个是满足要求的即为正确答案。 有个要求是&#xff0c;如果一个格子中…

删除单链表偶数节点

本题要求实现两个函数&#xff0c;分别将读入的数据存储为单链表、将链表中偶数值的结点删除。链表结点定义如下&#xff1a; struct ListNode {int data;struct ListNode *next; };函数接口定义&#xff1a; struct ListNode *createlist(); struct ListNode *deleteeven( s…

Linux hook系统调用使你文件无法删除

文章目录 前言一、什么是hook技术二、Linux hook种类三、系统调用表hook3.1 查看删除文件用到系统调用3.2 获取系统调用函数3.3 编写hook函数3.4 替换hook函数3.5 测试 参考资料 前言 hook技术在Linux系统安全领域有着广泛的应用&#xff0c;例如通过hook技术可以劫持删除文件…

xilinx的高速接口构成原理和连接结构

本文来源&#xff1a; V3学院 尤老师的培训班笔记【高速收发器】xilinx高速收发器学习记录Xilinx-7Series-FPGA高速收发器使用学习—概述与参考时钟GT Transceiver的总体架构梳理 文章目录 一、概述&#xff1a;二、高速收发器结构&#xff1a;2.1 QUAD2.1.1 时钟2.1.2 CHANNEL…

pytest之fixture结合conftest.py文件使用+断言实战

pytest之fixture结合conftest.py文件使用 conftest.py--存放固件固件的优先级pytest执行流程pytest之断言实战pytest结合allure-pytest插件生成美观的报告 conftest.py–存放固件 在一个项目的测试中&#xff0c;大多数情况下会有多个类、模块、或者包要使用相同的测试夹具。这…

【Node.js】全局变量和全局 API

node 环境中没有 dom 和 bom &#xff0c;此外 es 基本上都是可以正常使用的。 如果一定要使用 dom 和bom&#xff0c;可以借助第三方库 jsdom 帮助我们实现操作。npm i jsdom 实例&#xff1a; const fs require(node:fs) const {JSDOM} require(jsdom)const dom new JS…

命令执行漏洞

绕过技巧&#xff1a; cat 233.txt # 管道符号绕过 # 空格绕过 ${IFS} # %0a、%09 # 重定向绕过 < <> # 变量拼接绕过 kali:$ ac;bat;cfl;dag;$a$b $c$d # 单引号、双引号绕过 cat flag cat"" flag # 编码绕过 $(printf "\x63\x61\x74\x20\x2f\x…

前端学习之css 定位与浮动

定位 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>定位和浮动</title><style>*{/* 将模块紧紧贴着浏览器边框 */margin: 0;}.c{background-color: blueviolet;width: 100px;height: 1…

长安链团队论文入选国际顶会Usenix Security 2024

零知识证明是区块链扩容和隐私保护的关键前沿技术&#xff0c;其天然具备完备性、可靠性和零知识性的特点&#xff0c;是提升区块链交易吞吐量与可扩展性、在验证用户身份的同时保护用户数据隐私&#xff0c;实现复杂计算不可或缺的关键技术。基于零知识证明技术实现高兼容性、…