STM32F407系列硬件I2C详解及笔记分享

STM32F407系列有3个硬件I2C:

I2C1:该接口位于GPIOB引脚上,包括PB6(I2C1_SCL)和PB7(I2C1_SDA)。

I2C2:该接口位于GPIOB引脚上,包括PB10(I2C2_SCL)和PB11(I2C2_SDA)。

I2C3:该接口位于GPIOA和GPIOC引脚上,包括PA8(I2C3_SCL)和PC9(I2C3_SDA)。
 

硬件I2C的速度比软件I2C更快,硬件I2C通常可以达到几百kHz甚至更高的速度,软件I2C几十kHz

I2C1.C文件

#include "I2C1.h"


// I2C1初始化函数
void I2C1_Init(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;
    
    // 使能GPIOB和I2C1时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C1, ENABLE);
    
    // 配置GPIOB的引脚为复用模式
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    // 配置引脚复用映射
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource6, GPIO_AF_I2C1);  // SCL
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource7, GPIO_AF_I2C1);  // SDA
    
    // 配置I2C1
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;  // 设置自身设备地址
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_InitStructure.I2C_ClockSpeed = 100000;  // 设置通信速度,这里为100kHz
    
    I2C_Init(I2C1, &I2C_InitStructure);
    I2C_Cmd(I2C1, ENABLE);
}




void I2C1_Start(void)
{
    I2C_GenerateSTART(I2C1, ENABLE);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT));
}

void I2C1_Stop(void)
{
    I2C_GenerateSTOP(I2C1, ENABLE);
    while (I2C_GetFlagStatus(I2C1, I2C_FLAG_STOPF));
}

void I2C1_SendData(uint8_t slaveAddr, uint8_t* data, uint8_t len)
{
    I2C1_Start();
    I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED));

    for (uint8_t i = 0; i < len; i++)
    {
        I2C_SendData(I2C1, data[i]);
        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED));
    }

    I2C1_Stop();
}

void I2C1_ReceiveData(uint8_t slaveAddr, uint8_t* data, uint8_t len)
{
    I2C1_Start();
    I2C_Send7bitAddress(I2C1, slaveAddr, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED));

    for (uint8_t i = 0; i < len; i++)
    {
        if (i == len - 1)
            I2C_AcknowledgeConfig(I2C1, DISABLE);

        while (!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED));
        data[i] = I2C_ReceiveData(I2C1);
    }

    I2C1_Stop();
}


I2C1.H文件

#ifndef __I2C1_H
#define __I2C1_H
#include "sys.h" 


void I2C1_Init(void);// I2C1初始化函数
void I2C1_Start(void);
void I2C1_Stop(void);
void I2C1_SendData(uint8_t slaveAddr, uint8_t* data, uint8_t len);
void I2C1_ReceiveData(uint8_t slaveAddr, uint8_t* data, uint8_t len);


#endif



I2C2.C文件

#include "I2C2.h"



// I2C2初始化函数
void I2C2_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;

    // 打开I2C2和GPIOB的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C2, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

    // 配置GPIOB的引脚为I2C2功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 配置GPIO引脚复用功能
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_I2C2);
    GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_I2C2);

    // I2C2配置
    I2C_InitStructure.I2C_ClockSpeed = 100000;  // 设置时钟速度为100kHz
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C2, &I2C_InitStructure);

    // 使能I2C2
    I2C_Cmd(I2C2, ENABLE);
}

// I2C2发送数据函数
void I2C2_WriteData(uint8_t address, uint8_t reg, uint8_t data)
{
    // 等待I2C2处于空闲状态
    while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))
        ;

    // 发送START信号
    I2C_GenerateSTART(I2C2, ENABLE);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和写指令
    I2C_Send7bitAddress(I2C2, address, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        ;

    // 发送寄存器地址
    I2C_SendData(I2C2, reg);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 发送数据
    I2C_SendData(I2C2, data);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 发送STOP信号
    I2C_GenerateSTOP(I2C2, ENABLE);
}

// I2C2接收数据函数
uint8_t I2C2_ReadData(uint8_t address, uint8_t reg)
{
    uint8_t data;

    // 等待I2C2处于空闲状态
    while (I2C_GetFlagStatus(I2C2, I2C_FLAG_BUSY))
        ;

    // 发送START信号
    I2C_GenerateSTART(I2C2, ENABLE);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和写指令
    I2C_Send7bitAddress(I2C2, address, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        ;

    // 发送寄存器地址
    I2C_SendData(I2C2, reg);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 重新发送START信号,切换到接收模式
    I2C_GenerateSTART(I2C2, ENABLE);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和读指令
    I2C_Send7bitAddress(I2C2, address, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
        ;

    // 开启ACK
    I2C_AcknowledgeConfig(I2C2, ENABLE);

    // 接收数据
    while (!I2C_CheckEvent(I2C2, I2C_EVENT_MASTER_BYTE_RECEIVED))
        ;
    data = I2C_ReceiveData(I2C2);

    // 发送STOP信号
    I2C_GenerateSTOP(I2C2, ENABLE);

    return data;
}




I2C2.h文件

#ifndef __I2C2_H
#define __I2C2_H
#include "sys.h" 


// I2C2初始化函数
void I2C2_Init(void);

// I2C2发送数据函数
// 参数:
//   address: 目标设备地址
//   reg: 寄存器地址
//   data: 要发送的数据
void I2C2_WriteData(uint8_t address, uint8_t reg, uint8_t data);

// I2C2接收数据函数
// 参数:
//   address: 目标设备地址
//   reg: 寄存器地址
// 返回值:
//   读取到的数据
uint8_t I2C2_ReadData(uint8_t address, uint8_t reg);




#endif


I2C3.C文件

#include "I2C3.h"

// I2C3初始化函数
void I2C3_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    I2C_InitTypeDef I2C_InitStructure;

    // 打开I2C3和GPIOA的时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_I2C3, ENABLE);
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    // 配置GPIOA的引脚为I2C3功能
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;
    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 配置GPIO引脚复用功能
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource8, GPIO_AF_I2C3);
    GPIO_PinAFConfig(GPIOA, GPIO_PinSource9, GPIO_AF_I2C3);

    // I2C3配置
    I2C_InitStructure.I2C_ClockSpeed = 100000;  // 设置时钟速度为100kHz
    I2C_InitStructure.I2C_Mode = I2C_Mode_I2C;
    I2C_InitStructure.I2C_DutyCycle = I2C_DutyCycle_2;
    I2C_InitStructure.I2C_OwnAddress1 = 0x00;
    I2C_InitStructure.I2C_Ack = I2C_Ack_Enable;
    I2C_InitStructure.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit;
    I2C_Init(I2C3, &I2C_InitStructure);

    // 使能I2C3
    I2C_Cmd(I2C3, ENABLE);
}

// I2C3发送数据函数
void I2C3_WriteData(uint8_t address, uint8_t reg, uint8_t data)
{
    // 等待I2C3处于空闲状态
    while (I2C_GetFlagStatus(I2C3, I2C_FLAG_BUSY))
        ;

    // 发送START信号
    I2C_GenerateSTART(I2C3, ENABLE);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和写指令
    I2C_Send7bitAddress(I2C3, address, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        ;

    // 发送寄存器地址
    I2C_SendData(I2C3, reg);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 发送数据
    I2C_SendData(I2C3, data);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 发送STOP信号
    I2C_GenerateSTOP(I2C3, ENABLE);
}

// I2C3接收数据函数
uint8_t I2C3_ReadData(uint8_t address, uint8_t reg)
{
    uint8_t data;

    // 等待I2C3处于空闲状态
    while (I2C_GetFlagStatus(I2C3, I2C_FLAG_BUSY))
        ;

    // 发送START信号
    I2C_GenerateSTART(I2C3, ENABLE);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和写指令
    I2C_Send7bitAddress(I2C3, address, I2C_Direction_Transmitter);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED))
        ;

    // 发送寄存器地址
    I2C_SendData(I2C3, reg);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_BYTE_TRANSMITTED))
        ;

    // 重新发送START信号,切换到接收模式
    I2C_GenerateSTART(I2C3, ENABLE);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_MODE_SELECT))
        ;

    // 发送目标设备地址和读指令
    I2C_Send7bitAddress(I2C3, address, I2C_Direction_Receiver);
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED))
        ;

    // 开启ACK
    I2C_AcknowledgeConfig(I2C3, ENABLE);

    // 接收数据
    while (!I2C_CheckEvent(I2C3, I2C_EVENT_MASTER_BYTE_RECEIVED))
        ;
    data = I2C_ReceiveData(I2C3);

    // 发送STOP信号
    I2C_GenerateSTOP(I2C3, ENABLE);

    return data;
}

I2C3.h文件

#ifndef __I2C3_H
#define __I2C3_H
#include "sys.h" 


// I2C3初始化函数
void I2C3_Init(void);

// I2C3发送数据函数
// 参数:
//   address: 目标设备地址
//   reg: 寄存器地址
//   data: 要发送的数据
void I2C3_WriteData(uint8_t address, uint8_t reg, uint8_t data);

// I2C3接收数据函数
// 参数:
//   address: 目标设备地址
//   reg: 寄存器地址
// 返回值:
//   读取到的数据
uint8_t I2C3_ReadData(uint8_t address, uint8_t reg);



#endif

物联沃分享整理
物联沃-IOTWORD物联网 » STM32F407系列硬件I2C详解及笔记分享

发表评论