You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tiva TM4C123GXL I2C连接EEPROM读取返回0xFF问题求助

Tiva TM4C123GXL I2C读取EEPROM返回0xFF问题排查与修复

你当前的代码在I2C初始化、EEPROM读写流程上存在多处错误,导致通信失败,读取返回0xFF(通常表示未正确接收到数据)。以下是具体问题分析和修正方案:

问题代码

void write_i2c(unsigned int data) {
int i;
I2C3_MSA_R = 0xA0;
I2C3_MDR_R = 0x00000000;
I2C3_MCS_R = 0b00000011;

while((I2C3_MCS_R & BIT_0) != 0);

I2C3_MDR_R = 0x00000000;
I2C3_MCS_R = 0b00000001;
while((I2C3_MCS_R & BIT_0) != 0);

I2C3_MDR_R = data;
I2C3_MCS_R = 0b00000101;

while((I2C3_MCS_R & BIT_0) != 0);
for(i = 0; i < 10000; i++);
}

unsigned int read_i2c() {
I2C3_MSA_R = 0xA0;
I2C3_MDR_R = 0x00000000;
I2C3_MCS_R = 0b00000011;
while((I2C3_MCS_R & BIT_0) != 0);
I2C3_MDR_R = 0x00000000;
I2C3_MCS_R = 0b00000001;

I2C3_MSA_R = 0xA1;
unsigned int data;
// 0xA0 is EEPROM address shifted by 1
I2C3_MCS_R = 0b00000101;

// I2C3_MCS_R = 0b00000101;
while((I2C3_MCS_R & BIT_0) != 0);

data = I2C3_MDR_R;
return data;
}

void init_i2c() {
//address of eeprom is 1010000
// A0 is PB0, A1 is PB1, A2 is PB2
SYSCTL_RCGCI2C_R = BIT_3;

GPIO_PORTD_PUR_R |= BIT_0 | BIT_1;

// Port D Alternate Function
// PD0 is SCL, PD1 is SDA
GPIO_PORTD_AFSEL_R |= BIT_0 | BIT_1;
GPIO_PORTD_PCTL_R |= 0x33;
GPIO_PORTD_ODR_R |= BIT_1;
GPIO_PORTD_DEN_R |= BIT_0 | BIT_1;

// Enable I2C3 Master
I2C3_MCR_R = BIT_4;
I2C3_MTPR_R = 0x64;
}

关键问题分析

  1. GPIO时钟未使能:初始化时只开启了I2C3的时钟,但未开启Port D的GPIO时钟,导致引脚功能无法正常工作,需添加Port D时钟使能。
  2. GPIO_PCTL_R赋值错误:当前0x33仅设置了PD0/PD1的低2位,正确应使用0x00000033,避免干扰其他引脚的PCTL配置。
  3. I2C时钟速率配置错误:I2C3_MTPR_R = 0x64会导致I2C速率远低于标准100kHz(假设系统时钟为16MHz,正确值应为0x4F)。
  4. 写入流程错误:EEPROM写入需遵循「设备写地址 → 内存地址 → 数据 → 停止」的流程,当前代码重复发送两次0x00,时序逻辑混乱。
  5. 读取流程错误:EEPROM读取需先通过写操作指定内存地址,再发送重启信号切换到读地址,当前代码未发送重启信号,直接切换地址导致通信中断。

修正后的代码

// 假设使用1字节内存地址的EEPROM(如24LC02),系统时钟为16MHz
#define EEPROM_DEV_ADDR 0xA0  // 设备写地址,A0/A1/A2接地时为0xA0
#define EEPROM_READ_ADDR 0xA1 // 设备读地址

void init_i2c() {
    // 开启I2C3和Port D的时钟
    SYSCTL_RCGCI2C_R |= BIT_3;
    SYSCTL_RCGCGPIO_R |= BIT_3;
    
    // 配置PD0(SCL)、PD1(SDA)为I2C功能
    GPIO_PORTD_AFSEL_R |= BIT_0 | BIT_1;
    GPIO_PORTD_PCTL_R |= 0x00000033; // PD0/PD1的PCTL设置为I2C功能
    GPIO_PORTD_ODR_R |= BIT_1;       // SDA引脚开漏输出
    GPIO_PORTD_DEN_R |= BIT_0 | BIT_1;
    GPIO_PORTD_PUR_R |= BIT_0 | BIT_1; // 上拉电阻增强信号
    
    // 初始化I2C3为主模式
    I2C3_MCR_R = BIT_4; // 使能主模式
    // 16MHz系统时钟下,100kHz I2C速率对应的MTPR值
    I2C3_MTPR_R = 0x4F; // (16000000/(2*100000)) -1 = 79 = 0x4F
}

// 向EEPROM指定内存地址写入1字节数据
void write_i2c(unsigned char mem_addr, unsigned char data) {
    // 1. 发送起始信号+设备写地址+内存地址
    I2C3_MSA_R = EEPROM_DEV_ADDR;
    I2C3_MDR_R = mem_addr;
    I2C3_MCS_R = 0x03; // START + RUN
    
    // 等待传输完成
    while((I2C3_MCS_R & BIT_0) == 0);
    // 检查NACK错误
    if(I2C3_MCS_R & BIT_2) {
        I2C3_MCS_R = 0x04; // 发送STOP终止
        return;
    }
    
    // 2. 发送数据+停止信号
    I2C3_MDR_R = data;
    I2C3_MCS_R = 0x05; // RUN + STOP
    
    while((I2C3_MCS_R & BIT_0) == 0);
    if(I2C3_MCS_R & BIT_2) {
        I2C3_MCS_R = 0x04;
        return;
    }
    
    // EEPROM写入后需要等待写入周期(根据型号调整时长)
    for(int i=0; i<50000; i++);
}

// 从EEPROM指定内存地址读取1字节数据
unsigned char read_i2c(unsigned char mem_addr) {
    unsigned char data;
    
    // 1. 先发送写操作指定内存地址
    I2C3_MSA_R = EEPROM_DEV_ADDR;
    I2C3_MDR_R = mem_addr;
    I2C3_MCS_R = 0x03; // START + RUN
    
    while((I2C3_MCS_R & BIT_0) == 0);
    if(I2C3_MCS_R & BIT_2) {
        I2C3_MCS_R = 0x04;
        return 0xFF;
    }
    
    // 2. 发送重启信号+设备读地址
    I2C3_MSA_R = EEPROM_READ_ADDR;
    I2C3_MCS_R = 0x0B; // RESTART + RUN
    
    while((I2C3_MCS_R & BIT_0) == 0);
    if(I2C3_MCS_R & BIT_2) {
        I2C3_MCS_R = 0x04;
        return 0xFF;
    }
    
    // 3. 读取数据并发送停止信号
    I2C3_MCS_R = 0x05; // RUN + STOP
    while((I2C3_MCS_R & BIT_0) == 0);
    
    data = I2C3_MDR_R;
    return data;
}

额外注意事项

  • 确认EEPROM的A0/A1/A2引脚连接是否与代码中的设备地址匹配(若引脚接VCC,需调整EEPROM_DEV_ADDR的对应位)。
  • 若使用2字节内存地址的EEPROM(如24LC256),需分两次发送内存地址的高字节和低字节。
  • 每次读写后建议检查I2C状态寄存器的错误位(如NACK、BUSERROR),便于快速排查问题。

内容的提问来源于stack exchange,提问作者Lemon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 02:21:03