了解I2C协议,并能够使用I2C将数据写入和读出,
I2C协议
I2C协议和摩托罗拉公司的SPI协议一样,是一种通讯协议。串行外围设备接口,是一种高速全双工的通信总线,是由 Phiilps 公司开发的。
由于它引脚少,硬件 实现简单,可扩展性强,不需要 USART、CAN 等通讯协议的外部收发设备,现在被广泛 地使用在系统内多个集成电路(IC)间的通讯。
物理层
- 它是一个支持设备的总线
- 一个 I2C 总线只使用两条总线线路,一条双向串行数据线(SDA) ,一条串行时钟线 (SCL)。数据线即用来表示数据,时钟线用于数据收发同步。
- 写数据
若配置的方向传输位为“写数据”方向,广播完地址,接收到应 答信号后,主机开始正式向从机传输数据(DATA),数据包的大小为 8 位,主机每发送完一 个字节数据,都要等待从机的应答信号(ACK),重复这个过程,可以向从机传输 N 个数据, 这个 N 没有大小限制。当数据传输结束时,主机向从机发送一个停止传输信号§,表示不 再传输数据。 - 读数据
若配置的方向传输位为“读数据”方向,广播完地址,接收到应 答信号后,从机开始向主机返回数据(DATA),数据包大小也为 8 位,从机每发送完一个数 据,都会等待主机的应答信号(ACK),重复这个过程,可以返回 N 个数据,这个 N 也没有 大小限制。当主机希望停止接收数据时,就向从机返回一个非应答信号(NACK),则从机自动停止数据传输。
I2C总线读写EEPROM
Address为器件内部存储器地址,00-0XFF。连续写入时,器件内部地址会自动加1(地址低3位),一次写入数据超过8个会覆盖原来数据
字节写(1次连续写入8个字节)
读出:当前地址读、随机地址读和连续读
硬件电路
当 R/W 位为 0 时,表示写方向,所以加上 7 位地址,其值为“0xA0”,称 I2C 设备 的“写地址”;
当 R/W位为 1时,表示读方向,加上 7 位地址,其值为“0xA1”,称为“读地址”。
使用CubeMx配置
使用 CubeMX 生成工程(初始化)
- 首先设置RCC;外部晶振8M,STM32F103x的最高主频是72M;
- 使能 I2C2,在 Pinout 上选择 I2C2;
- 配置 I2C2 的两个引脚,PB10、PB11为开漏模式;
- 配置 I2C2参数,地址模式为 7 位,时钟标准模式(Standard Mode,100000Hz)\ 时钟快速模式(Fast Mode,400000Hz)、占空比为2;
- 生成源代码,在设置界面中输入工程名,保存路径。文件bsp_EEPROM.h和bsp_EEPROM.c
编写代码
首先在main.c文件前面声明两个输出存储读写数据,宏定义EEPROM读写地址以及缓存数据长度。
#define ADDR_AT24C02_Write 0xA0//写地址
#define ADDR_AT24C02_Read 0xA1//读地址
#define BufferSize 0x100
uint8_t I2C_Buffer_Write[BufferSize];
uint8_t I2C_Buffer_Read[BufferSize];
uint16_t i;
(参考函数)
HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
含义如下:
I2C_HandleTypeDef *hi2c --IIC的句柄,本例使用芯片有2个I2C接口,可以选择参数:&hi2c1,&hi2c2
uint16_t DevAddress – IIC设备的外部地址,本例可以选择:写地址0xA0,读地址0xA1
uint16_t MemAddress --IIC设备的内部地址,本例可以选择:0x00—0xFF
uint16_t MemAddSize --读写内部地址的方式,只有两种选择:I2C_MEMADD_SIZE_8BIT 或者 I2C_MEMADD_SIZE_16BIT
uint8_t *pData --写入的数组或者指针
uint16_t Size --写入的字节数
uint32_t Timeout – 超时时间
使用如下函数对24C02进行写入
HAL_I2C_Mem_Write(&hi2c2, ADDR_AT24C02_Write, i, I2C_MEMADD_SIZE_8BIT,&(I2C_Buffer_Write[i]),8, 1000)
读取就没有页的限制,我们可以一次全部读取256个字节。读取使用如下函数:
HAL_I2C_Mem_Read(&hi2c2, ADDR_AT24C02_Read, 0, I2C_MEMADD_SIZE_8BIT,I2C_Buffer_Read,256, 1000);
举例
写入和读取三个参数函数
int8_t params[3]={25,20,15};
uint8_t WriteParam(void)
{
return(HAL_I2C_Mem_Write(&hi2c2, ADDR_AT24C02_Write,16,I2C_MEMADD_SIZE_8BIT,(uint8_t *)params,3,10000)==HAL_OK);
}
uint8_t ReadParam(void)
{
return(HAL_I2C_Mem_Read(&hi2c2, ADDR_AT24C02_Read,16,I2C_MEMADD_SIZE_8BIT,(uint8_t *)params,3,10000)==HAL_OK);
}

编译 烧入就可以了 最好加上写验证代码 确定是否读取 和写入成功
应用
下面一篇文章 以一个实际应用
联合 数码管 键盘 串口通信 和I2C的应用。