一、I2C介绍
I2C总线是由Philips公司开发的一种简单、双向二线制同步串行总线。它只需要两根线即可在连接于总线上的器件之间传送信息,SDA数据线和SCL时钟信号线。
主器件用于启动总线传送数据,并产生时钟以开放传送的器件,此时任何被寻址的器件均被认为是从器件.在总线上主和从、发和收的关系不是恒定的,而取决于此时数据传送方向。
- 如果主机要发送数据给从器件,则主机首先寻址从器件,然后主动发送数据至从器件,最后由主机终止数据传送;
- 如果主机要接收从器件的数据,首先由主器件寻址从器件.然后主机接收从器件发送的数据,最后由主机终止接收过程。在这种情况下.主机负责产生定时时钟和终止数据传送。
二、I2C的通信状态
-
总线空闲—SDA和SCL都为高电平
-
数据的有效位规定
SCL为高电平期间,数据线SDA上必须保持稳定
只有SCL为低电平期间,数据线SDA才允许变化
-
I2C的起始和终止信号
SCL线为高电平期间,SDA线由高电平—>低电平,表示起始信号
SCL线为高电平期间,SDA线由低电平—>高电平,表示终止信号
3.I2C字节的传送与应答
每一个字节是8位,先传最高位(MSB),每传一个字节后面必须跟随一个应答位(即一帧有9位)。
三、须知
下面代码用到了串口返回读取的数据信息,此处用到了串口一
用到的库函数
主发送器通讯过程
主接收器
四、程序部分
bsp_i2c_eeprom.h
#ifndef __BSP_I2C_EEPROM_H
#define __BSP_I2C_EEPROM_H
#include "stm32f4xx.h"
#define I2C_OWN_ADDR 0x77 /*主机的八位地址,只要不和从机重复*/
#define I2C_SPEED 400000 /*快速模式最高400khz*/
#define EEPROM_ADDR (0x50<<1) //0xA0,
//引脚定义,移植时修改此处即可,野火的I2C口为PB6和PB7
/*******************************************************/
#define EEPROM_I2C I2C1
#define EEPROM_I2C_CLK RCC_APB1Periph_I2C1
#define EEPROM_SCL_GPIO_PORT GPIOB
#define EEPROM_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
#define EEPROM_SCL_PIN GPIO_Pin_6
#define EEPROM_SCL_AF GPIO_AF_I2C1
#define EEPROM_SCL_SOURCE GPIO_PinSource6
#define EEPROM_SDA_GPIO_PORT GPIOB
#define EEPROM_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
#define EEPROM_SDA_PIN GPIO_Pin_7
#define EEPROM_SDA_AF GPIO_AF_I2C1
#define EEPROM_SDA_SOURCE GPIO_PinSource7
/************************************************************/
void EEPROM_GPIO_Config(void);
void EEPROM_I2C_ModeConfig(void);
void EEPROM_Byte_Write(uint8_t* pData,uint8_t addr);
uint8_t EEPROM_Byte_Read(uint8_t addr);
#endif /* __BSP_I2C_EEPROM_H */
bsp_i2c_eeprom.c
#include "./i2c/bsp_i2c_eeprom.h"
void Wait_for_EEPROM(void);
//1.初始化GPIO
void EEPROM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(EEPROM_SCL_GPIO_CLK|EEPROM_SDA_GPIO_CLK,ENABLE);
/* 连接SCL*/
GPIO_PinAFConfig(EEPROM_SCL_GPIO_PORT,EEPROM_SCL_SOURCE,EEPROM_SCL_AF);
/* 连接 SDA*/
GPIO_PinAFConfig(EEPROM_SDA_GPIO_PORT,EEPROM_SDA_SOURCE,EEPROM_SDA_AF);
/* GPIO初始化 */
GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/* 配置SCL引脚为复用功能 */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_Pin = EEPROM_SCL_PIN ;
GPIO_Init(EEPROM_SCL_GPIO_PORT, &GPIO_InitStructure);
/* 配置SDA引脚为复用功能 */
GPIO_InitStructure.GPIO_Pin = EEPROM_SDA_PIN;
GPIO_Init(EEPROM_SDA_GPIO_PORT,