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

对于STM32F407硬件开发指引,以下是一些基本的步骤和注意事项: 1. 硬件选型:了解STM32F407微控制器的特性和功能,确定其是否适合你的应用需求。 2. 电源设计:确保为芯片提供稳定可靠的电源,包括主要电源和备份电源,以满足不同工作模式和外设的需求。 3. 外设连接:根据你的应用需求,确定需要连接的外设接口,如UART、SPI、I2C、GPIO等,并进行合理的电路设计。 4. PCB布局:进行良好的PCB布局设计,确保信号完整性和最小的电磁干扰。尽量减少信号线长度、交叉和回路。 5. 时钟设置:根据你的应用需求,选择适当的时钟源和时钟分频配置,并确保时钟信号的稳定和精确性。 6. 外部存储器:如果需要扩展存储空间,可以考虑使用外部存储器如Flash、SD卡等,并进行相应的接口设计。 7. 调试接口:为了方便调试和程序下载,可以添加调试接口如SWD/JTAG,并进行相应的连接。 8. 地线和供电:确保良好的地线和供电,防止电源噪声和地线回流对系统性能的影响。 9. 信号完整性:使用合适的阻抗匹配、终端电阻等措施,保证信号的完整性和稳定性。 10. EMI/EMC设计:考虑到系统在工作时可能产生的电磁干扰和抗扰性,进行相应的设计来提高抗干扰能力。 这些是硬件开发中的一些基本指引,具体的开发流程还需要根据你的应用需求和具体芯片的技术文档进行详细研究和调整。同时,建议参考ST官方的技术文档、应用笔记和开发板设计参考等资源,以获取更多关于STM32F407硬件开发的指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

桂北研猛男

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值