告别盲调!手把手教你用TMS320F280049C硬件I2C读写CAT24C02 EEPROM
TMS320F280049C硬件I2C驱动CAT24C02全流程实战解析
在嵌入式开发中,I2C总线因其简洁的两线制设计和多设备支持能力,成为传感器、存储器件等外设连接的常用接口。本文将基于TI的TMS320F280049C微控制器,深度解析如何通过硬件I2C接口实现对CAT24C02 EEPROM的可靠读写操作。不同于常见的Arduino平台简化实现,我们将从硬件原理层面对每个配置参数进行剖析,帮助开发者真正掌握工业级应用的实现要点。
1. 硬件架构与连接设计
1.1 I2C总线物理层特性
I2C总线由SDA(数据线)和SCL(时钟线)两条开漏输出线构成,必须通过上拉电阻连接到正电源。TMS320F280049C的I2C模块支持标准模式(100kHz)和快速模式(400kHz),CAT24C02兼容这两种速率。硬件连接时需注意:
- 上拉电阻选择 :典型值为4.7kΩ(3.3V系统),实际值需根据总线电容调整
- 信号完整性 :线长超过30cm时应考虑添加缓冲器或降低速率
- 地址配置 :CAT24C02的A2/A1/A0引脚决定器件地址,同一总线上地址不能冲突
开发板与EEPROM连接示意:
| TMS320F280049C引脚 | CAT24C02引脚 | 连接说明 |
|---|---|---|
| GPIO32 (I2CA_SDA) | SDA | 数据线,需上拉 |
| GPIO33 (I2CA_SCL) | SCL | 时钟线,需上拉 |
| 3.3V | VCC | 电源 |
| GND | GND | 地线 |
1.2 GPIO配置关键参数
TMS320F280049C的I2C引脚需要特殊配置才能正常工作。以下是使用Driverlib库进行初始化的核心代码:
// SDA线配置
GPIO_setDirectionMode(DEVICE_GPIO_PIN_SDAA, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(DEVICE_GPIO_PIN_SDAA, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(DEVICE_GPIO_PIN_SDAA, GPIO_QUAL_ASYNC);
// SCL线配置
GPIO_setDirectionMode(DEVICE_GPIO_PIN_SCLA, GPIO_DIR_MODE_OUT);
GPIO_setPadConfig(DEVICE_GPIO_PIN_SCLA, GPIO_PIN_TYPE_STD);
GPIO_setQualificationMode(DEVICE_GPIO_PIN_SCLA, GPIO_QUAL_ASYNC);
// 引脚功能映射
GPIO_setPinConfig(DEVICE_GPIO_CFG_SDAA);
GPIO_setPinConfig(DEVICE_GPIO_CFG_SCLA);
注意:虽然I2C总线需要上拉,但GPIO_setPadConfig使用了GPIO_PIN_TYPE_STD而非GPIO_PIN_TYPE_PULLUP。这是因为开发板已外接物理上拉电阻,内部上拉电阻值通常较大(约50kΩ),可能无法满足I2C的电流需求。
2. I2C主控制器初始化
2.1 时钟配置原理
I2C模块的时钟配置直接影响通信稳定性。TMS320F280049C要求I2C模块输入时钟在7-12MHz范围内,通过预分频器生成最终的SCL时钟。关键计算公式:
SCL频率 = 模块输入时钟 / (ICCL + ICCH)
其中ICCL和ICCH分别对应时钟低电平和高电平的计数周期。使用Driverlib初始化代码:
#define I2C_CLK_FREQ 100000 // 100kHz标准模式
I2C_initMaster(I2CA_BASE, DEVICE_SYSCLK_FREQ, I2C_CLK_FREQ, I2C_DUTYCYCLE_50);
参数解析:
DEVICE_SYSCLK_FREQ:系统时钟频率(如60MHz)I2C_CLK_FREQ:目标SCL频率I2C_DUTYCYCLE_50:时钟占空比50%
2.2 工作模式配置
TMS320F280049C的I2C模块支持四种基本模式,初始化时需要明确主从角色:
I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE); // 初始设置为发送模式
I2C_setAddressMode(I2CA_BASE, I2C_ADDR_MODE_7BITS); // 7位地址模式
I2C_setSlaveAddress(I2CA_BASE, 0x50); // CAT24C02默认地址
关键细节:CAT24C02的7位地址为0x50(A2=A1=A0=0),不同于常见的左移后地址(0xA0写/0xA1读)。TMS320F280049C的I2C模块会自动处理R/W位,开发者只需提供7位地址。
3. EEPROM读写操作实现
3.1 单字节写入时序
CAT24C02的单字节写入需要遵循特定时序:
- 发送起始条件(START)
- 发送器件地址(写模式)
- 发送要写入的内存地址
- 发送数据字节
- 发送停止条件(STOP)
对应代码实现:
int16_t EE_WriteByte(uint16_t addr, uint8_t data) {
I2C_setDataCount(I2CA_BASE, 2); // 准备发送2字节(地址+数据)
I2C_putData(I2CA_BASE, addr); // 写入地址
I2C_putData(I2CA_BASE, data); // 写入数据
I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
I2C_sendStartCondition(I2CA_BASE); // 启动传输
I2C_sendStopCondition(I2CA_BASE); // 结束传输
DEVICE_DELAY_US(1000); // 等待EEPROM完成内部写入
return 1;
}
3.2 多字节读取技巧
连续读取多个字节时,需要特别注意CAT24C02的地址自动递增特性:
uint16_t EE_ReadBytes(uint16_t addr, uint8_t *buffer, uint16_t count) {
// 发送目标地址
I2C_setDataCount(I2CA_BASE, 1);
I2C_putData(I2CA_BASE, addr);
I2C_setConfig(I2CA_BASE, I2C_MASTER_SEND_MODE);
I2C_sendStartCondition(I2CA_BASE);
DEVICE_DELAY_US(500);
// 切换为接收模式
I2C_setDataCount(I2CA_BASE, count);
I2C_setConfig(I2CA_BASE, I2C_MASTER_RECEIVE_MODE);
I2C_sendStartCondition(I2CA_BASE);
DEVICE_DELAY_US(500);
// 读取数据
for(uint16_t i = 0; i < count; i++) {
buffer[i] = I2C_getData(I2CA_BASE);
if(i == count-1) I2C_sendNACK(I2CA_BASE);
}
I2C_sendStopCondition(I2CA_BASE);
return count;
}
经验提示:当读取数据量超过16字节时,建议每16字节插入约1ms延时,避免因EEPROM内部页缓冲导致时序异常。
4. 调试技巧与性能优化
4.1 常见问题排查方法
I2C通信故障时,可通过以下步骤定位问题:
-
信号测量 :用示波器检查SCL/SDA波形,确认:
- 起始/停止条件是否正常
- 时钟频率是否符合预期
- 数据线在ACK时段是否有下拉
-
状态寄存器检查 :
uint16_t status = I2C_getStatus(I2CA_BASE); if(status & I2C_STAT_NACK) { // 从机未响应 } -
上拉电阻验证 :测量SDA/SCL高电平电压,应接近VCC
4.2 延时参数优化
TMS320F280049C与CAT24C02通信时,关键延时点包括:
| 操作环节 | 建议延时 | 作用说明 |
|---|---|---|
| 写入后等待 | 5ms | EEPROM内部编程周期 |
| 连续读取间隔 | 500μs | 保证数据稳定 |
| 起始条件建立时间 | 100μs | 满足t_HD;STA时序要求 |
实际项目中,这些参数应根据具体硬件调整:
#define EEPROM_WRITE_DELAY 5000 // 5ms
#define READ_INTERVAL_DELAY 500 // 500μs
void optimize_delays(uint32_t sysclk) {
if(sysclk > 100000000) {
// 高频系统适当减少延时
EEPROM_WRITE_DELAY = 3000;
}
}
4.3 FIFO模式进阶应用
启用FIFO可显著提升大数据量传输效率:
void enable_i2c_fifo(void) {
I2C_enableFIFO(I2CA_BASE);
I2C_setFIFOInterruptLevel(I2CA_BASE, I2C_FIFO_TX4, I2C_FIFO_RX4);
I2C_clearInterruptStatus(I2CA_BASE, I2C_INT_RXFF | I2C_INT_TXFF);
}
FIFO模式下数据传输示例:
void fifo_transfer(uint8_t *data, uint16_t len) {
I2C_setDataCount(I2CA_BASE, len);
for(uint16_t i = 0; i < len; i++) {
I2C_putData(I2CA_BASE, data[i]);
while(I2C_isTxFIFOFull(I2CA_BASE)) {
// 等待FIFO空间
}
}
}
通过合理配置FIFO触发深度,可以减少CPU中断开销,实现更高效率的数据传输。
更多推荐



所有评论(0)