基于 rt-thread的I2C操作EEPROM(AT24C02)

news2024/12/23 7:02:58

一、AT24C02

The AT24C01A/02/04/08A/16A provides 1024/2048/4096/8192/16384 bits of serial electrically erasable and programmable read-only memory (EEPROM) organized as 128/256/512/1024/2048 words of 8 bits each.

AT24C01A/02/04/08A/16A提供1024/2048/4096/8192/16384位串行电可擦除和可编程只读存储器(EEPROM),以128/256/512/1024/2048 个字节的8位数据组成。

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

设备操作
1、数据有效性
在这里插入图片描述

2、开始停止
在这里插入图片描述
3、响应
在这里插入图片描述
4、软件复位
在这里插入图片描述
5、bus Timing
在这里插入图片描述
6、Write Cycle Timing
在这里插入图片描述
7、设备地址
在这里插入图片描述
8、
在这里插入图片描述
9、
在这里插入图片描述
10、
在这里插入图片描述
11、
在这里插入图片描述
12、
在这里插入图片描述

二、I2C 简介

来源 RT-Thread 标准文档 中 I2C 总线设备
https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/i2c/i2c?id=i2c-%e7%ae%80%e4%bb%8b

  I2C(Inter Integrated Circuit)总线是 PHILIPS 公司开发的一种半双工、双向二线制同步串行总线。I2C 总线传输数据时只需两根信号线,一根是双向数据线 SDA(serial data),另一根是双向时钟线 SCL(serial clock)。SPI 总线有两根线分别用于主从设备之间接收数据和发送数据,而 I2C 总线只使用一根线进行数据收发。
  I2C 和 SPI 一样以主从的方式工作,不同于 SPI 一主多从的结构,它允许同时有多个主设备存在,每个连接到总线上的器件都有唯一的地址,主设备启动数据传输并产生时钟信号,从设备被主设备寻址,同一时刻只允许有一个主设备。
在这里插入图片描述
I2C 总线主要的数据传输格式:
在这里插入图片描述
  当总线空闲时,SDA 和 SCL 都处于高电平状态,当主机要和某个从机通讯时,会先发送一个开始条件,然后发送从机地址和读写控制位,接下来传输数据(主机发送或者接收数据),数据传输结束时主机会发送停止条件。传输的每个字节为8位,高位在前,低位在后。数据传输过程中的不同名词详解如下所示:
1、开始条件: SCL 为高电平时,主机将 SDA 拉低,表示数据传输即将开始。
2、从机地址: 主机发送的第一个字节为从机地址,高 7 位为地址,最低位为 R/W 读写控制位,1 表示读操作,0 表示写操作。一般从机地址有 7 位地址模式和 10 位地址模式两种,如果是 10 位地址模式,第一个字节的头 7 位 是 11110XX 的组合,其中最后两位(XX)是 10 位地址的两个最高位,第二个字节为 10 位从机地址的剩下8位,如下图所示:
在这里插入图片描述
3、应答信号: 每传输完成一个字节的数据,接收方就需要回复一个 ACK(acknowledge)。写数据时由从机发送 ACK,读数据时由主机发送 ACK。当主机读到最后一个字节数据时,可发送 NACK(Not acknowledge)然后跟停止条件
4、数据: 从机地址发送完后可能会发送一些指令,依从机而定,然后开始传输数据,由主机或者从机发送,每个数据为 8 位,数据的字节数没有限制。
5、重复开始条件: 在一次通信过程中,主机可能需要和不同的从机传输数据或者需要切换读写操作时,主机可以再发送一个开始条件。
6、停止条件: 在 SDA 为低电平时,主机将 SCL 拉高并保持高电平,然后在将 SDA 拉高,表示传输结束。

三、代码

51代码来源
https://blog.csdn.net/weixin_43772810/article/details/122149151

//24C02的 A0、A1、A2 都接地,所以它的I2C设备地址为1010000,写地址为10100000(0xA0),读地址为10100001(0xA1)

#include <reg52.h>   //此文件中定义了单片机的一些特殊功能寄存器


sbit scl = P2^1;
sbit sda = P2^0;
unsigned char code coding[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
					0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0-F的值

					
#define LED_TUBE  P3 //P3的8个IO端口对应数码管的8个信号引脚
					
					
/******************************************************************************
 * @ 函数名  : Delay_10us
 * @ 功  能  : 10us粗略延时
 * @ 参  数  : 延时时间--单位10us
 * @ 返回值  : 无
 ******************************************************************************/
void Delay_10us(unsigned int time)
{
	while(time--);
}

/******************************************************************************
 * @ 函数名  : I2c_Delay
 * @ 功  能  : I2C延时函数
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_Delay()
{
	Delay_10us(1);
}

/******************************************************************************
 * @ 函数名  : I2c_Start
 * @ 功  能  : I2C起始信号
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_Start()
{
	sda = 1;
	scl = 1;
	I2c_Delay(); //起始信号建立时间
	sda = 0;     //SDA拉低,下降沿
	I2c_Delay(); //起始信号保持时间
	scl = 0;
}

/******************************************************************************
 * @ 函数名  : I2c_Stop
 * @ 功  能  : I2C停止信号
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_Stop()
{
	scl = 0;
	I2c_Delay(); //上一个时钟周期的低电平
	sda = 0;
	scl = 1;
	I2c_Delay(); //停止信号建立时间
	sda = 1;     //SDA拉高,上升沿
	I2c_Delay(); //总线空闲时间保持
}


/******************************************************************************
 * @ 函数名  : I2c_Ack
 * @ 功  能  : I2C应答信号
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_Ack()
{
	scl = 0;
	sda = 0;     //SDA拉低,发出应答信号
	I2c_Delay();
	scl = 1;
	I2c_Delay(); 
	scl = 0;
}


/******************************************************************************
 * @ 函数名  : I2c_No_Ack
 * @ 功  能  : I2C非应答信号
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_No_Ack()
{
	scl = 0;
	sda = 1;     //SDA拉高,发出非应答信号
	I2c_Delay();
	scl = 1;
	I2c_Delay(); 
	scl = 0;
}

/******************************************************************************
 * @ 函数名  : I2c_Wait_Ack
 * @ 功  能  : I2C等待应答信号
 * @ 参  数  : 无
 * @ 返回值  : 1:接收到应答信号,0:接收到非应答信号
 ******************************************************************************/
unsigned char I2c_Wait_Ack()
{
	unsigned char ack = 0;
	sda = 1;
	scl = 0;	    
	I2c_Delay();
	scl = 1;
	I2c_Delay(); 
	if(sda == 0) //检测数据线SDA是否被拉低
		ack = 1;
	else 
		ack = 0;
	scl = 0;
	return ack;
}



/******************************************************************************
 * @ 函数名  : I2c_Write_Byte
 * @ 功  能  : I2C写字节
 * @ 参  数  : dat 要写入的字节数据
 * @ 返回值  : 无
 ******************************************************************************/
void I2c_Write_Byte(unsigned char dat)
{
	unsigned char i = 0;
	
	
	for(i = 0; i < 8; i++) //读取8位
	{
		scl = 0;	
		I2c_Delay();
		if(dat & 0x80)  //发送最高位
			sda = 1;
		else 
			sda = 0;
		scl = 1; 
		I2c_Delay();		
		dat <<= 1;  //左移1位
	}
	scl = 0;
}


/******************************************************************************
 * @ 函数名  : I2c_Read_Byte
 * @ 功  能  : I2C读字节
 * @ 参  数  : 无
 * @ 返回值  : 读取的字节数据
 ******************************************************************************/
unsigned char I2c_Read_Byte()
{
	unsigned char dat = 0, i = 0;
    
	for(i = 0; i < 8; i++) //读取8位
	{
		dat <<= 1;   //左移1位
		scl = 0;	
		I2c_Delay();
		scl = 1;     //SCL高电平
		I2c_Delay();
		if(sda)      //读取SDA状态
			dat |= 0x1;
	}
	scl = 0;
	return dat;
}

/******************************************************************************
 * @ 函数名  : At24c02_Write
 * @ 功  能  : AT24C02写字节
 * @ 参  数  : 
 *              addr 要写数据的地址(存储空间)
 *              dat  要写入的字节数据
 * @ 返回值  : 无
 ******************************************************************************/
void At24c02_Write(unsigned char addr, unsigned char dat)
{
	I2c_Start();
	I2c_Write_Byte(0xA0); //发送I2C设备地址
	I2c_Wait_Ack();       //等待从机响应
	I2c_Write_Byte(addr); //发送要写入的内存地址
	I2c_Wait_Ack();
	I2c_Write_Byte(dat);  //写入数据
	I2c_Wait_Ack();
	I2c_Stop();
	Delay_10us(1000);     //写周期
}


/******************************************************************************
 * @ 函数名  : At24c02_Read
 * @ 功  能  : AT24C02读字节
 * @ 参  数  : addr 要读数据的地址(存储空间)
 * @ 返回值  : 读取的字节数据
 ******************************************************************************/
unsigned char At24c02_Read(unsigned char addr)
{
	unsigned char dat = 0, i = 0;
	I2c_Start();
	I2c_Write_Byte(0xA0); //发送I2C设备地址
	I2c_Wait_Ack();       //等待从机响应
	I2c_Write_Byte(addr); //发送要写入的内存地址
	I2c_Wait_Ack(); 
	I2c_Start();
	I2c_Write_Byte(0xA1); //发送I2C设备地址(读数据)
	I2c_Wait_Ack();       //等待从机响应
	dat = I2c_Read_Byte(); //读取数据
	I2c_Wait_Ack(); 
	I2c_Stop();
	return dat;
}


/******************************************************************************
 * @ 函数名  : main
 * @ 功  能  : 主函数
 * @ 参  数  : 无
 * @ 返回值  : 无
 ******************************************************************************/

int main()
{	
	unsigned char i = 0;
	Delay_10us(100);  //AT24C02上电时序
	
	while(1)
	{
		for(i = 0; i < 8; i++)
		{
			//向AT24C02前8个字节空间写8-i
			At24c02_Write(i, 8 - i);
			//读取该地址的数据,并显示到数码管
			LED_TUBE = coding[At24c02_Read(i)];
			//粗略延时500ms
			Delay_10us(50000);	 	
		}
		for(i = 0; i < 8; i++)
		{
			//向AT24C02前8个字节空间写i+1
			At24c02_Write(i, i + 1);
			//读取该地址的数据,并显示到数码管
			LED_TUBE = coding[At24c02_Read(i)];
			//粗略延时500ms
			Delay_10us(50000);			
		}	
	}
}

四、RT-Thread 操作配置

电路如下:
在这里插入图片描述
在这里插入图片描述

使用rt-thread studio IDE。
1、按照要求配置软件模拟I2C
在这里插入图片描述
2、添加软件包
在这里插入图片描述
3、直接编译,通过指令测试
在这里插入图片描述
在这里插入图片描述

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

代码测试1

/*
 * 程序清单:这是一个iic设备使用例程
 * 例程导出了i2c_test3命令到控制终端
 * 命令调用格式:i2c_test3
 * 实现功能:向eeprom写入16进制的HelloRTT,再重读eeprom并以字符输出。
 */
#include <rtthread.h>
#include <rtdevice.h>

static const char * i2c_bus_device_name = "i2c1";
static const rt_uint8_t eeprom_addr = 0x50;      // 1010A2A1A0 - R/W she bei di zhi

static  rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *data);

static rt_err_t read_regs(struct rt_i2c_bus_device *bus,  rt_uint8_t len,rt_uint8_t *buf);

rt_err_t i2c_test3(void)
{
    struct rt_i2c_bus_device * i2c_device;
    i2c_device = rt_i2c_bus_device_find(i2c_bus_device_name);
    if(i2c_device == RT_NULL)
    {
        rt_kprintf("i2c bus device %s not found!\n", i2c_bus_device_name);
        return -RT_ENOSYS;
    }
    rt_size_t i;
    rt_uint8_t send[8] = {0x48,0x65,0x6C,0x6C,0x6F,0x52,0x54,0x54};//HelloRTT
    rt_uint8_t recv[8] = {0};
    //step 1: write to eeprom.
    write_reg(i2c_device,8,send);
    //step 2: read out from eeprom.
    read_regs(i2c_device,8,recv);
    rt_kprintf("read eeprom at: 0x%02X\n", eeprom_addr);
    rt_kprintf("your data is: \n");
    for(i=0; i<sizeof(recv); i++)
    {
       rt_kprintf("%c", recv[i]);
    }
    rt_kprintf("\n");
    return RT_EOK;
}
MSH_CMD_EXPORT(i2c_test3, i2c_test3);

/* 写eeprom */
static rt_err_t write_reg(struct rt_i2c_bus_device *bus, rt_uint8_t len, rt_uint8_t *data)
{
    struct rt_i2c_msg msgs[2];
    rt_uint8_t buff[1] = {0x00};    //数据在EEPROM上的存储地址
    msgs[0].addr = eeprom_addr;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = buff;
    msgs[0].len = 1;
    msgs[1].addr = eeprom_addr;
    msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START;
    msgs[1].buf = data;
    msgs[1].len = len;
    if (rt_i2c_transfer(bus, msgs, 2) == 2)
    {
        rt_thread_delay(rt_tick_from_millisecond(10));
        return RT_EOK;
    }else{
        rt_kprintf("write eeprom fail!\n");
        return -RT_ERROR;
    }
}

/* 读eeprom数据 */
static rt_err_t read_regs(struct rt_i2c_bus_device *bus,rt_uint8_t len,rt_uint8_t *buf)
{
    struct rt_i2c_msg msgs[2];
    rt_uint8_t buff[1] = {0x00};   //数据在EEPROM上的存储地址
    msgs[0].addr = eeprom_addr;
    msgs[0].flags = RT_I2C_WR;
    msgs[0].buf = buff;
    msgs[0].len = 1;
    msgs[1].addr = eeprom_addr;
    msgs[1].flags = RT_I2C_RD;
    msgs[1].buf = buf;
    msgs[1].len = len;
    if (rt_i2c_transfer(bus, msgs, 2) == 2)// 调用I2C设备接口传输数据
    {
        return RT_EOK;
    }else{
        rt_kprintf("read eeprom fail!\n");
        return -RT_ERROR;
    }
}
//FINSH_FUNCTION_EXPORT(i2c_test3, i2c_test3);

代码测试2

#include <rtthread.h>
#include <rtdevice.h>
#include "at24cxx.h"


static const char * i2c_bus_device_name = "i2c1";
static const rt_uint8_t eeprom_addr = 0x50;      // 1010A2A1A0 - R/W she bei di zhi


rt_err_t i2c_test3(void)
{
    at24cxx_device_t dev = RT_NULL;
    dev = at24cxx_init(i2c_bus_device_name, 0);
    if(dev == RT_NULL)
    {
        rt_kprintf("i2c bus device %s not found!\n", i2c_bus_device_name);
        return -RT_ENOSYS;
    }
    rt_size_t i;
    uint8_t send[8] = {0x48,0x65,0x6C,0x6C,0x6F,0x52,0x54,0x54};//HelloRTT
    uint8_t recv[16] = {0};
    //step 1: write to eeprom.
    at24cxx_write(dev, 8, send, 8);
    rt_kprintf("write ok\n");
    //step 2: read out from eeprom.
    at24cxx_read(dev, 0, recv, 16);
    rt_kprintf("read eeprom at: 0x%02X\n", eeprom_addr);
    rt_kprintf("your data is: \n");
    for(i=0; i<sizeof(recv); i++)
    {
       rt_kprintf("%c", recv[i]);
    }
    rt_kprintf("\n");
    return RT_EOK;
}
MSH_CMD_EXPORT(i2c_test3, i2c_test3);

在这里插入图片描述

参考:
https://blog.csdn.net/weixin_43772810/article/details/122149151

https://www.rt-thread.org/document/site/#/rt-thread-version/rt-thread-standard/programming-manual/device/i2c/i2c?id=i2c-%e7%ae%80%e4%bb%8b

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Redis进阶(三)--Redis高性能底层原理

文章目录 第三章、Redis高性能底层原理一、持久化1、RDB&#xff08;1&#xff09;给哪些内存数据做快照?&#xff08;2&#xff09;RDB文件的生成是否会阻塞主线程&#xff08;3&#xff09;bgsave执的行流程&#xff08;4&#xff09;RDB文件&#xff08;5&#xff09;RDB的…

ios免签H5

1、windows下载mobileconfig文件制作工具&#xff0c;可在csdn搜索iPhone_Mobileconfig_Tool下载安装&#xff1b;IOS 从APP Store 下载Apple Configurator 2 2、用申请的域名SSL证书给mobieconfig文件签名&#xff0c;最好下载Apache证书&#xff0c;里面包含 AE86211.crt…

zabbix-高级应用(主被动监控、邮件告警、企业微信告警)

文章目录 zabbix-高级应用监控路由器交换机SNMP简单网络管理协议测试案例配置网络设备创建主机创建监控项测试监控项 自动发现什么是自动发现Discovery&#xff1f;配置自动发现1、创建自动发现规则2、创建Action动作&#xff08;发现主机后自动执行什么动作&#xff09;3、通过…

Python画笔案例-037 绘制彩色格子台阶

1、绘制彩色格子台阶 通过 python 的turtle 库绘制彩色格子台阶&#xff0c;如下图&#xff1a; 2、实现代码 绘制彩色格子台阶&#xff0c;以下为实现代码&#xff1a; """彩色格子台阶.py """ import turtle from random import randomturtle…

小杨做题c++

题目描述 为了准备考试&#xff0c;小杨每天都要做题。第1天&#xff0c;小杨做了a道题;第2天&#xff0c;小杨做了b道题;从第3天起&#xff0c;小杨每天做的题目数量是前两天的总和。 此外&#xff0c;小杨还规定&#xff0c;当自己某一天做了大于或等于m题时&#xff0c;接下…

KRTSt内嵌Lua脚本

KRTSt内嵌Lua脚本 Lua 简介 Lua是一门强大、高效、轻量、可嵌入的脚本语言。它支持多种编程架构&#xff1a;过程编程、面向对象编程&#xff08;OOP&#xff09;、函数式编程、数据驱动编程及数据描述。 Lua结合了简洁的过程语法和强大的数据描述结构&#xff08;基于关联数…

什么是网络准入控制系统?网络准入控制系统七大品牌介绍!

在当今信息化时代&#xff0c;企业网络安全面临着前所未有的挑战。网络准入控制系统&#xff08;NAC, Network Access Control&#xff09;作为一种重要的网络安全技术&#xff0c;扮演着守护企业网络安全大门的关键角色。网络准入控制系统通过对接入网络的设备进行身份验证、安…

为什么现在不建议去电力设计院?终于有人把电力设计院说清楚了!

作者&#xff1a;电气哥 最近电气哥收到了许多面临就业的同学特别是硕士同学有关于电力设计院的咨询&#xff0c;那么现在电力设计院到底还值不值得去&#xff1f;电气哥带你来分析一下电力设计院的前世今生。 01 电力设计院的前世今生 曾经&#xff0c;在我国的大基建时代&…

java设计模式--(行为型模式:策略模式、命令模式、责任链模式)

6&#xff0c;行为型模式 行为型模式用于描述程序在运行时复杂的流程控制&#xff0c;即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务&#xff0c;它涉及算法与对象间职责的分配。 行为型模式分为类行为模式和对象行为模式&#xff0c;前者采用继承…

keepalived和lvs高可用集群

keepavlied和lvs高可用集群搭建 主备模式&#xff1a; 关闭防火墙和selinux systemctl stop firewalld setenforce 0部署master负载调度服务器 zyj86 安装ipvsadm keepalived yum install -y keepalived ipvsadm修改主节点配置 vim /etc/keepalived/keepalived.conf! Conf…

鹰眼雾炮适合在哪些场合使用

朗观视觉鹰眼雾炮由于其独特的功能和优势&#xff0c;适合在多种场合使用&#xff0c;主要包括但不限于以下几个方面&#xff1a; 建筑工地&#xff1a;建筑工地是粉尘污染的主要来源之一。鹰眼雾炮可以有效降低施工过程中的扬尘&#xff0c;改善工地及周边空气质量&#xff0c…

南卡科技“满分之选”全新开放式耳机发布,打造超越Pro的极致体验!

在音频技术的不断革新中&#xff0c;南卡品牌以其深厚的声学底蕴和对创新的不懈追求&#xff0c;再次为市场带来惊喜。今天&#xff0c;我们自豪地宣布&#xff0c;南卡OE Pro2开放式蓝牙耳机正式亮相&#xff0c;它不仅代表了南卡在开放式耳机领域的技术巅峰&#xff0c;更是对…

基本和复合逻辑运算

目录 基本逻辑运算 与运算 或运算 非运算 复合逻辑运算 与非运算 或非运算 异或运算 同或运算 基本逻辑运算 与运算 两个都为1才为1&#xff0c;否则为0&#xff0c;类似于编程语言里的&。 有0出0&#xff0c;全1出1。 逻辑表达式就是AB,可以省略中间的点。 逻辑符…

TimescaleDB-3 超表的维护

数采系统上线半年多了&#xff0c;产生了大概2亿条记录&#xff0c;这些数据其实是有时效性的&#xff0c;用来生成的二次数据可以永久保存&#xff0c;这种时序数据没有多大价值&#xff0c;又非常占用空间&#xff0c;所以定期清理超表的trunk是必要的 --1、查看分区表以及…

好用的AI编程助手[豆包]

欢迎来到 Marscode 的世界&#xff01;这里将为你揭秘 Marscode&#xff0c;它的独特之处、应用领域等相关精彩内容等你来探索。 一、打开VS Code 二、选择 Extensions,搜索marscode 三、点击安装 四、点击使用 五、输入需要编写的代码 六、根据自己的需求修改代码 MarsCode 注…

Pytorch多GPU分布式训练代码编写

Pytorch多GPU分布式训练代码编写 一、数据并行 1.单机单卡 模型拷贝 model.cuda() 原地操作 数据拷贝&#xff08;每步&#xff09; datadata.cuda() 非原地操作 基于torch.cuda.is_available()来判断是否可用 模型保存与加载 torch.save 来保存模型、优化器、其他变量tor…

spring security 中的授权使用

一、认证 身份认证&#xff0c;就是判断一个用户是否为合法用户的处理过程。Spring Security 中支持多种不同方式的认证&#xff0c;但是无论开发者使用那种方式认证&#xff0c;都不会影响授权功能使用。因为 SpringSecurity 很好做到了认证和授权解耦。 二、授权 授权&#x…

红黑树的旋转

红黑树的基本性质 红黑树与普通的二叉搜索树不同&#xff0c;它在每个节点上附加了一个额外的属性——颜色&#xff0c;该颜色可以是红色或黑色。通过引入这些颜色&#xff0c;红黑树能够维持以下 5 个基本性质&#xff0c;以确保树的平衡性&#xff1a; 每个节点是红色或黑色…

C++入门10——stack与queue的使用

目录 1.什么是stack&#xff1f; stack的使用 2.什么是queue&#xff1f; queue的使用 3.priority_queue 3.1 什么是priority_queue? 3.2 priority_queue的使用 1.什么是stack&#xff1f; 在官网中&#xff0c;对stack有这样的介绍&#xff1a; Stacks are a type o…

一台电脑对应一个IP地址吗?‌探讨两台电脑共用IP的可能性

在当今数字化时代&#xff0c;‌IP地址作为网络世界中的“门牌号”&#xff0c;‌扮演着至关重要的角色。‌它负责在网络上唯一标识每一台设备&#xff0c;‌使得数据能够在庞大的互联网中准确无误地传输。‌然而&#xff0c;‌对于IP地址与电脑之间的对应关系&#xff0c;‌许…