TMS320F280049硬件I2C驱动CAT24C02全流程实战指南

在嵌入式开发中,I2C总线因其简洁的两线制设计和多设备支持特性,成为传感器、存储芯片等外设的常用接口。德州仪器的TMS320F280049数字信号控制器内置硬件I2C模块,配合常见的CAT24C02 EEPROM芯片,可构建稳定可靠的非易失性存储解决方案。本文将彻底解析从硬件连接到软件实现的完整流程,提供经过实际验证的代码模块,并深入探讨那些容易被忽视但至关重要的时序细节。

1. 硬件准备与基础配置

1.1 硬件连接规范

TMS320F280049与CAT24C02的标准连接方式需要关注三个关键点:

  • 电源匹配 :确保两者工作电压相同(通常3.3V),CAT24C02的VCC引脚需连接100nF去耦电容
  • 上拉电阻 :SCL和SDA线必须接上拉电阻(典型值4.7kΩ),即使MCU内部已启用上拉
  • 地址配置 :CAT24C02的A0-A2引脚决定了设备地址,接地时7位地址为0x50

连接示意图如下:

TMS320F280049引脚 CAT24C02引脚 连接说明
GPIO32 (I2CA_SDA) SDA 数据线,需上拉
GPIO33 (I2CA_SCL) SCL 时钟线,需上拉
3.3V VCC 电源正极
GND GND 电源地

1.2 初始化硬件I2C模块

硬件I2C的正确初始化需要依次完成GPIO配置和模块参数设置:

// 硬件定义
#define I2C_SCL_PIN     33
#define I2C_SDA_PIN     32
#define I2C_MODULE      I2CA_BASE
#define I2C_CLK_FREQ    100000  // 100kHz标准模式

void I2C_InitMaster(void) {
    // 1. 配置GPIO为I2C功能
    GPIO_setPinConfig(DEVICE_GPIO_CFG_I2CA_SCL);
    GPIO_setPinConfig(DEVICE_GPIO_CFG_I2CA_SDA);
    
    // 2. 初始化I2C主模式
    I2C_disableModule(I2C_MODULE);
    I2C_initMaster(I2C_MODULE, DEVICE_SYSCLK_FREQ, I2C_CLK_FREQ, I2C_DUTYCYCLE_50);
    
    // 3. 设置数据格式
    I2C_setBitCount(I2C_MODULE, I2C_BITCOUNT_8);  // 8位数据
    I2C_setAddressMode(I2C_MODULE, I2C_ADDR_MODE_7BITS);  // 7位地址
    
    // 4. 使能模块
    I2C_enableModule(I2C_MODULE);
}

关键提示:I2C模块必须在禁用状态(IRS=0)下进行配置,修改后才重新使能。GPIO配置时务必关闭数字输入滤波(GPIO_QUAL_ASYNC),否则可能导致时序异常。

2. EEPROM读写操作精要

2.1 单字节写入时序剖析

CAT24C02的单字节写入需要严格遵守器件手册规定的时序:

  1. 起始条件(START)
  2. 发送设备地址 + 写标志(0xA0)
  3. 等待ACK
  4. 发送目标地址(1字节)
  5. 等待ACK
  6. 发送数据(1字节)
  7. 等待ACK
  8. 停止条件(STOP)

对应的代码实现:

void EEPROM_WriteByte(uint16_t addr, uint8_t data) {
    // 1. 设置传输数据量(地址+数据)
    I2C_setDataCount(I2C_MODULE, 2);
    
    // 2. 填充数据缓冲区
    I2C_putData(I2C_MODULE, (uint16_t)(addr & 0xFF));  // 地址低字节
    I2C_putData(I2C_MODULE, (uint16_t)data);          // 写入数据
    
    // 3. 配置为主发送模式
    I2C_setConfig(I2C_MODULE, I2C_MASTER_SEND_MODE);
    
    // 4. 启动传输
    I2C_sendStartCondition(I2C_MODULE);
    
    // 5. 等待传输完成
    while(I2C_isStopDetected(I2C_MODULE) == false);
    I2C_clearStopCondition(I2C_MODULE);
    
    // 6. 必须的写周期等待(典型值5ms)
    DEVICE_DELAY_US(5000);
}

时序关键点说明:

  • 地址对齐 :CAT24C02的地址为1字节,直接使用低8位
  • 写周期等待 :EEPROM内部写入需要时间,立即读取会导致失败
  • 错误处理 :实际应用中应添加ACK检测和超时判断

2.2 多字节读取高效实现

连续读取多个字节时,可以利用CAT24C02的地址自动递增特性。典型操作时序:

  1. 发送起始条件 + 设备地址(写)
  2. 发送目标起始地址
  3. 重新发送起始条件 + 设备地址(读)
  4. 连续读取数据(最后字节发送NACK)
  5. 发送停止条件

优化后的代码实现:

void EEPROM_ReadBuffer(uint16_t addr, uint8_t *buf, uint16_t len) {
    // 1. 发送目标地址(写模式)
    I2C_setDataCount(I2C_MODULE, 1);
    I2C_putData(I2C_MODULE, (uint16_t)(addr & 0xFF));
    I2C_setConfig(I2C_MODULE, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(I2C_MODULE);
    while(I2C_isStopDetected(I2C_MODULE) == false);
    I2C_clearStopCondition(I2C_MODULE);
    
    // 2. 重新启动为读模式
    I2C_setDataCount(I2C_MODULE, len);
    I2C_setConfig(I2C_MODULE, I2C_MASTER_RECEIVE_MODE);
    I2C_sendStartCondition(I2C_MODULE);
    
    // 3. 连续读取数据
    for(uint16_t i = 0; i < len; i++) {
        while(I2C_getDataCount(I2C_MODULE) > 0);
        buf[i] = (uint8_t)I2C_getData(I2C_MODULE);
        
        // 最后一个字节发送NACK
        if(i == len - 1) {
            I2C_sendNACK(I2C_MODULE);
        }
    }
    
    // 4. 结束传输
    I2C_sendStopCondition(I2C_MODULE);
    while(I2C_isStopDetected(I2C_MODULE) == false);
    I2C_clearStopCondition(I2C_MODULE);
}

性能提示:批量读取时,适当调整I2C时钟频率(最高400kHz)可显著提升速度,但需确保所有设备支持该速率。

3. 关键时序问题与解决方案

3.1 必须的延时及其原理

在I2C通信中,某些特定位置必须插入延时:

  1. 启动延时 :START信号后至少等待4.7μs

    #define I2C_START_DELAY  5  // 单位μs
    
  2. 字节间隔延时 :每个字节传输后至少等待1.2μs

    #define I2C_BYTE_DELAY   2  // 单位μs
    
  3. 停止延时 :STOP信号后至少等待4μs

    #define I2C_STOP_DELAY   5  // 单位μs
    

这些延时补偿了以下硬件特性:

  • 信号传播时间
  • 总线电容充电时间
  • 器件内部状态切换时间

3.2 典型时序问题排查

当通信失败时,按以下步骤排查:

  1. 信号完整性检查

    • 用示波器观察SCL/SDA波形
    • 确认上升时间符合规格(标准模式<1μs)
  2. ACK检测流程

    if(I2C_getACKStatus(I2C_MODULE) == I2C_ACK_RECEIVED) {
        // 正常处理
    } else {
        // 错误处理
    }
    
  3. 常见错误代码

    • 0x01: 总线忙(检查上拉和器件状态)
    • 0x02: 仲裁丢失(多主竞争)
    • 0x04: 无ACK响应(检查地址和连接)

4. 高级应用与性能优化

4.1 FIFO模式提升吞吐量

TMS320F280049的I2C模块支持16级FIFO,可显著减少CPU中断开销:

void I2C_EnableFIFO(void) {
    I2C_enableFIFO(I2C_MODULE);
    I2C_setFIFOInterruptLevel(I2C_MODULE, I2C_FIFO_TX4, I2C_FIFO_RX4);
    I2C_clearInterruptStatus(I2C_MODULE, I2C_INT_RXFF | I2C_INT_TXFF);
}

FIFO模式下数据传输流程:

  1. 设置总传输字节数

    I2C_setDataCount(I2C_MODULE, totalBytes);
    
  2. 填充TX FIFO

    while(bytesRemaining && !I2C_isFIFOFull(I2C_MODULE)) {
        I2C_putData(I2C_MODULE, *data++);
        bytesRemaining--;
    }
    
  3. 处理传输完成中断

    if(I2C_getInterruptStatus(I2C_MODULE) & I2C_INT_DATA_READY) {
        // 处理接收数据
    }
    

4.2 页写入加速策略

CAT24C02支持16字节页写入,比单字节写入效率提升16倍:

void EEPROM_PageWrite(uint16_t addr, uint8_t *data) {
    // 1. 确保地址页对齐
    addr = addr & 0xFFF0;
    
    // 2. 初始化传输
    I2C_setDataCount(I2C_MODULE, 17);  // 地址+16数据
    I2C_putData(I2C_MODULE, (uint16_t)(addr & 0xFF));
    
    // 3. 填充页数据
    for(int i=0; i<16; i++) {
        I2C_putData(I2C_MODULE, (uint16_t)data[i]);
    }
    
    // 4. 启动传输
    I2C_setConfig(I2C_MODULE, I2C_MASTER_SEND_MODE);
    I2C_sendStartCondition(I2C_MODULE);
    
    // 5. 等待完成
    while(I2C_isStopDetected(I2C_MODULE) == false);
    I2C_clearStopCondition(I2C_MODULE);
    DEVICE_DELAY_US(5000);  // 页写入需要更长时间
}

重要限制:页写入不能跨物理页边界(每16字节为一页),否则会导致数据回卷。

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐