I2C协议概述

I2C(Inter-Integrated Circuit)是一种同步、半双工的串行通信总线协议,由飞利浦(现恩智浦)开发,用于连接低速外设与微控制器。其核心特点包括两线制(SDA数据线、SCL时钟线)、多主多从架构和地址寻址机制。

物理层特性

  • 双线设计:SDA(Serial Data)传输数据,SCL(Serial Clock)提供同步时钟。
  • 开漏输出:需外接上拉电阻,支持线与逻辑,允许总线冲突检测。
  • 速率标准
    • 标准模式(100 kbps)
    • 快速模式(400 kbps)
    • 高速模式(3.4 Mbps)

协议帧结构

  1. 起始条件:SCL高电平时SDA由高变低。
  2. 地址帧:7位或10位从机地址 + 1位读写方向(0写,1读)。
  3. 数据帧:每8位数据后跟随1位ACK/NACK应答。
  4. 停止条件:SCL高电平时SDA由低变高。

典型通信流程

  • 主机发送起始信号后,传输从机地址和读写位。
  • 从机应答后,主机发送或接收数据,每字节需应答确认。
  • 通信结束时主机发送停止信号。

应用场景

  • 传感器(如温度、加速度计)
  • EEPROM存储器
  • 实时时钟(RTC)模块
  • 显示器控制(如OLED)

优势与局限

  • 优势:引脚占用少、支持多设备、协议简单。
  • 局限:速率较低、总线长度受限(通常<1米)。

EEPROM的定义

EEPROM(Electrically Erasable Programmable Read-Only Memory)是一种非易失性存储器,可通过电信号擦除和重编程。与EPROM(需紫外线擦除)不同,EEPROM支持单字节或块级擦写,无需物理移除芯片。

EEPROM的特点

  • 非易失性:断电后数据保留。
  • 可重复擦写:典型寿命为10万到100万次。
  • 按字节操作:支持精细数据修改,无需整片擦除。
  • 低功耗:适合嵌入式系统。

应用场景

  • 存储设备配置参数(如路由器设置)。
  • 保存用户数据(如家电使用记录)。
  • 微控制器(如Arduino、STM32)的固件存储。

与Flash的区别

  • 擦写粒度:EEPROM支持字节级,Flash需块级擦除。
  • 寿命:EEPROM擦写次数更高。
  • 容量与成本:Flash容量更大,成本更低,适合大容量存储。

注意事项

  • 避免频繁写入同一地址以延长寿命。
  • 部分芯片需延时等待擦写完成。
  • 数据备份建议结合校验机制(如CRC)。

I^2的初始化:

我们这里提供 I^2 的初始化文件将其添加到KEIL中(操作和LCD一样),这里我们任然使用LCD所以也要添加里面。

在stm32cubemx创建工程无变化;我们直接在keil进行代码的书写;

需要先进行几个函数的声明和定义;

1. X24C02 写入函数
void X24C02_Write(uint8_t adress, uint8_t info)
{
    I2CStart();
    I2CSendByte(0xA0); // 设备地址,写入模式
    I2CWaitAck();
    I2CSendByte(adress); // 地址
    I2CWaitAck();
    I2CSendByte(info); // 写入信息
    I2CWaitAck();
    I2CStop();
}
2. X24C02 读取函数
uint8_t X24C02_Read(uint8_t adress)
{
    unsigned char val;
    
    I2CStart();
    I2CSendByte(0xA0); // 设备地址,写入模式
    I2CWaitAck();
    I2CSendByte(adress); // 地址
    I2CWaitAck();
    I2CStop(); // 停止条件

    I2CStart();
    I2CSendByte(0xA1); // 设备地址,读取模式
    I2CWaitAck();
    val = I2CReceiveByte(); // 接收数据
    I2CStop();
    
    return(val);
}

为什么写入是0XA0;读取是0XAI?

前面根据图可知为:101000  ,只需要控制最后一位即可控制功能:

写入:                                                   读取:

                          

3. MCP4017 读取函数
uint8_t MCP4017_Read(void)
{
    unsigned char val;
    
    I2CStart();
    I2CSendByte(0x5F); // 设备地址
    I2CWaitAck();
    
    val = I2CReceiveByte(); // 接收数据
    I2CStop();
    
    return(val);
}
功能:读取 MCP4017 的状态。
4. MCP4017 写入函数
void MCP4017_Write(unsigned char info)
{
    I2CStart();
    I2CSendByte(0x5F); // 设备地址
    I2CWaitAck();
    
    I2CSendByte(0x5E); // 要写入的信息
    I2CWaitAck();
    I2CStop();
}

实验目的:

  1. 编写EEPROM的IIC读写的用户函数,完成开机次数存储实验;
  2. 编写MCP4017的IIC读写的用户函数,编写用户功能函数,以实现调节数字电位器;

我们一切准备工程完毕;现在书写使用函数完成实验目的即可:

1:初始化LCD和 I^2;
2:将定义的函数存放在正确位置;
3:在主函数套用函数:

(1):在循环外书写;因为

  • 非易失性:断电后数据保留。
  • 可重复擦写:典型寿命为10万到100万次。
  • 多次循环可能出错
	EEPROM=x24c02_read (0X02);
	x24c02_write (0X02,++EEPROM);
	sprintf ((char*)str," Value:%d :",EEPROM);	
    LCD_DisplayStringLine (Line8 ,str);

完善代码功能:

	if(STATR==0)
		{
			STATR=1;
			EEPROM=X24C02_Read(0X77);
			HAL_Delay(10);
			X24C02_Write (0X77,++EEPROM );
			sprintf((char*)str ," Value:%d ",EEPROM);
			LCD_DisplayStringLine (Line3,str);
			HAL_Delay (100);
		}
		  MCP4017_Write (mcp);
			HAL_Delay (1000);
			mcp=mcp+5;
			if(mcp>0X7F)mcp=0X00;
			sprintf((char*)str ," Value:%d ",mcp);
			LCD_DisplayStringLine (Line4,str);

断电后EEPROM保存上电次数,通过MCP改变电阻值;使电压表数值改变。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐