I2C与EEPROM通信

我用I2C0与一款EEPROM收发,用的PB6和PB7可以正常通信,当换成PB8和PB9作为SCL和SDA发现就一直卡在Busy为1的死循环里。PB6与PB8的区别如下,

img

所以在PB8/9 GPIO配置时加了rcu_periph_clock_enable(RCU_AF),请问如何用PB8/9正常与EEPROM通信起来?

对于使用PB8和PB9作为I2C通信引脚时,您需要进行以下步骤来确保与EEPROM正常通信:

确认硬件连接:请确保PB8与PB9正确连接到EEPROM的SCL和SDA引脚,并且没有连接错误或者电气问题。

配置GPIO引脚:在使用PB8和PB9作为I2C通信引脚时,您需要将这两个引脚配置为复用功能,并且开启AF(Alternate Function)功能。可以使用以下代码进行配置:

// 使能GPIOB时钟
rcu_periph_clock_enable(RCU_GPIOB);

// 配置PB8和PB9为复用功能
gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_8 | GPIO_PIN_9);

// 配置PB8和PB9的复用功能为I2C0
gpio_pin_remap_config(GPIO_B8_B9_REMAP, ENABLE);


这里使用了 gpio_pin_remap_config() 函数来配置PB8和PB9的复用功能为I2C0,这是因为在STM32F10x系列的芯片中,PB8和PB9的复用功能默认映射到了其他引脚,需要通过这个函数来重新映射。

初始化I2C:在初始化I2C时,您需要指定正确的SCL和SDA引脚,即PB8和PB9,并且使用正确的时钟频率和通信模式。例如,以下是初始化I2C0的示例代码:

// 使能I2C0时钟
rcu_periph_clock_enable(RCU_I2C0);

// 配置I2C0参数
i2c_init(I2C0);
i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, I2C_ADDFORMAT_7BITS, MY_OWN_ADDR);
i2c_ack_config(I2C0, I2C_ACK_ENABLE);
i2c_speed_config(I2C0, I2C_SPEED_STANDARD, 0x2D, 0x04);
i2c_enable(I2C0);


这里 MY_OWN_ADDR 是您的EEPROM的地址,根据您的实际应用进行配置。

确保EEPROM配置正确:请确保您的EEPROM的配置是正确的,包括地址设置、通信速率、通信模式等参数都与您的实际硬件连接和应用需求相匹配。

检查错误处理:如果您的代码中仍然无法正常通信,您可以添加错误处理机制,例如检查I2C的状态寄存器,查看是否出现错误标志位,进一步调试和定位问题。

I2C通讯与EEPROM

可以借鉴下
https://blog.csdn.net/weixin_44922452/article/details/105057169

以下内容引用CHATGPT:

首先,需要确认PB8和PB9的GPIO配置是否正确,包括AF配置、速度配置等。

其次,需要确认使用的EEPROM是否支持标准的I2C通信协议,包括地址位数、读写命令等,以及时钟频率是否在EEPROM的规格范围内。

最后,可以尝试使用示波器等工具对I2C信号进行观察和分析,以确定具体的通信问题。可以检查时钟信号是否正确、数据线是否被占用等。

以下是一个简单的I2C通信示例代码,可以根据实际情况进行修改:

#include "gd32f10x.h"

#define EEPROM_ADDRESS 0xA0

void i2c_init(void)
{
    /* enable GPIOB clock */
    rcu_periph_clock_enable(RCU_GPIOB);
    /* enable I2C0 clock */
    rcu_periph_clock_enable(RCU_I2C0);

    /* configure PB6 and PB7 as I2C0 pins */
    gpio_init(GPIOB, GPIO_MODE_AF_OD, GPIO_OSPEED_50MHZ, GPIO_PIN_6 | GPIO_PIN_7);
    gpio_pin_remap_config(GPIO_I2C0_REMAP, ENABLE);

    /* configure I2C0 parameters */
    i2c_clock_config(I2C0, 100000, I2C_DTCY_2);
    i2c_mode_addr_config(I2C0, I2C_I2CMODE_ENABLE, EEPROM_ADDRESS, I2C_ADDFORMAT_7BITS, I2C_I2CDEVADDR_DISABLE);
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    i2c_enable(I2C0);
}

void i2c_write_byte(uint8_t addr, uint8_t data)
{
    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
    /* send start bit */
    i2c_start_on_bus(I2C0);
    /* wait until start bit is sent */
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
    /* send device address */
    i2c_master_addressing(I2C0, addr, I2C_TRANSMITTER);
    /* wait until device address is sent */
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
    /* send data */
    i2c_data_transmit(I2C0, data);
    /* wait until data is sent */
    while(!i2c_flag_get(I2C0, I2C_FLAG_TBE));
    /* send stop bit */
    i2c_stop_on_bus(I2C0);
}

uint8_t i2c_read_byte(uint8_t addr)
{
    uint8_t data;
    /* wait until I2C bus is idle */
    while(i2c_flag_get(I2C0, I2C_FLAG_I2CBSY));
    /* send start bit */
    i2c_start_on_bus(I2C0);
    /* wait until start bit is sent */
    while(!i2c_flag_get(I2C0, I2C_FLAG_SBSEND));
    /* send device address */
    i2c_master_addressing(I2C0, addr, I2C_RECEIVER);
    /* wait until device address is sent */
    while(!i2c_flag_get(I2C0, I2C_FLAG_ADDSEND));
    /* enable ACK */
    i2c_ack_config(I2C0, I2C_ACK_ENABLE);
    /* wait until data is received */
    while(!i2c_flag_get(I2C0, I2C_FLAG_RBNE));
    /* read data */
    data = i2c_data_receive(I2C0);
    /* send stop bit */
    i2c_stop_on_bus(I2C0);
    return data;
}

int main(void)
{
    uint8_t data = 0x55;
    i2c_init();
    i2c_write_byte(EEPROM_ADDRESS, data);
    data = i2c_read_byte(EEPROM_ADDRESS);
    return 0;
}