STM32-IIC 配置解说(原创)STM32 - I2C 简介 :I2C 总线接口连接微控制器和串行 I2C 总线。它提供多主机功能,控制所有 I2C总线特定的时序、协议、仲裁和定时。支持标准和快速两种模式,另外 STM32的 I2C 可以使用 DMA 方式操作。本文主要以一个实例来介绍 STM32-I2C 的配置方式和具体在工程中通过调用哪些库函数来实现 I2C 器件的通信。实例:写入数据到器件 AT24C02 并将存入的数据读出好,我们先来讲讲 STM32 I2C 模块的端口基本配置,由 STM32 中文参考手册可以查到在使用 I2C 时对应的引脚要配置成哪种模式。 SCL 和 SDA 引脚都配置成开漏复用输出

本人用的是 STM32F103VET6,它有 2 个 I2C 接口。 I/O 口定义为 PB6-I2C_SCL,
PCB7-I2C1_SDA; PB10-I2C_SCL, PB11-I2C_SDA,由手册可以查出对应的端口。
图文如下:
调用库函数将 I2C 端口配置好(本文使用的是 PB6、 PB7 端口):
程序代码如下:
/*I2C-IO 口配置*/
void I2C_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure; //GPIO 结构体定义
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//使能 I2C 的 IO 口
/* PB6-I2C1_SCL、 PB7-I2C1_SDA*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD; // 开漏输出
GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化结构体配置
}
/* I2C 工作模式配置 */
void I2C_Mode_config(void)
{
/* 使能与 I2C1 有关的时钟 */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1,ENABLE);
/*定义 I2C 结构体*/
I2C_InitTypeDef I2C_InitStructure;
/*配置为 I2C 模式*/
I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
/*该参数只有在 I2C 工作在快速模式(时钟工作频率高于 100KHz)下才有意义。 */
I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
/*设置第一个设备自身地址*/
I2C_InitStructure.I2C_OwnAddress1 =0x0A;
/*使能应答*/
I2C_InitStructure.I2C_Ack = I2C_Ack_Enable ;
/*AT24C02 地址为 7 位所以设置 7 位就行了*/
I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
/*时钟速率,以 HZ 为单位的,最高为 400khz*/
I2C_InitStructure.I2C_ClockSpeed = 400000;
/* 使能 I2C1 */
I2C_Cmd(I2C1, ENABLE);
/* I2C1 初始化 */
I2C_Init(I2C1, &I2C_InitStructure);
}
好了, STM32 内部的 I2C 模块工作模式就这样被设好了,接下来需要完成与外部器件
AT24C02( EEPROM)进行通信。将分两部分进行代码解析,第一部分是:对 AT24C02 进
行写操作,第二部分:对 AT24C02 进行读操作。
第一部分(写):
备注: I2C_PageSize 为宏定义 #define I2C_PageSize 8 ;
/*
* 函数名: I2C_EE_BufferWrite
* 描述 :将缓冲区中的数据写到 I2C EEPROM 中
* 输入 : -pBuffer 缓冲区指针
* -WriteAddr 接收数据的 EEPROM 的地址
* -NumByteToWrite 要写入 EEPROM 的字节数
* 输出 :无
* 返回 :无
* 调用 :外部调用
*/
void I2C_EE_BufferWrite(u8* pBuffer, u8 WriteAddr, u16 NumByteToWrite)
{
u8 NumOfPage = 0, NumOfSingle = 0, Addr = 0, count = 0;
Addr = WriteAddr % I2C_PageSize;//查看输入的地址是不是 8 的整数倍
count = I2C_PageSize - Addr;//表示距离下一页页首地址的距离(步伐数)
NumOfPage = NumByteToWrite / I2C_PageSize;//算出一共有多少页
NumOfSingle = NumByteToWrite % I2C_PageSize;//算出不够一页的数据的余数
if(Addr == 0) //如果输入的地址是首页地址
{
if(NumOfPage == 0) //如果不足一页数据
{
I2C_EE_PageWrite(pBuffer, WriteAddr, NumOfSingle);//调用写函数, NumOfSingle 不
够一页的余数作为实参
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成内部操作
}
/* If NumByteToWrite > I2C_PageSize */
else //如果数据有一页以上
{
while(NumOfPage--)//用一个 while 循环,执行页写循环操作,有多少页就写多少次
{
I2C_EE_PageWrite(pBuffer, WriteAddr, I2C_PageSize); //调用写函数,将
I2C_PageSize 变量作为实
参执行页写
I2C_EE_WaitEepromStandbyState();//等待 EEPROM 器件完成内部操作
WriteAddr += I2C_PageSize;//每执行完一次页写对应的地址也需要移 8 个位
pBuffer += I2C_PageSize;//数据指针移 8 个位
}
if(NumOfSingle!=0)//如果有不足一页的数据余数则执行
{