手把手教你用TMS320F280049的硬件I2C读写EEPROM(CAT24C02),附完整代码
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的单字节写入需要严格遵守器件手册规定的时序:
- 起始条件(START)
- 发送设备地址 + 写标志(0xA0)
- 等待ACK
- 发送目标地址(1字节)
- 等待ACK
- 发送数据(1字节)
- 等待ACK
- 停止条件(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的地址自动递增特性。典型操作时序:
- 发送起始条件 + 设备地址(写)
- 发送目标起始地址
- 重新发送起始条件 + 设备地址(读)
- 连续读取数据(最后字节发送NACK)
- 发送停止条件
优化后的代码实现:
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通信中,某些特定位置必须插入延时:
-
启动延时 :START信号后至少等待4.7μs
#define I2C_START_DELAY 5 // 单位μs -
字节间隔延时 :每个字节传输后至少等待1.2μs
#define I2C_BYTE_DELAY 2 // 单位μs -
停止延时 :STOP信号后至少等待4μs
#define I2C_STOP_DELAY 5 // 单位μs
这些延时补偿了以下硬件特性:
- 信号传播时间
- 总线电容充电时间
- 器件内部状态切换时间
3.2 典型时序问题排查
当通信失败时,按以下步骤排查:
-
信号完整性检查
- 用示波器观察SCL/SDA波形
- 确认上升时间符合规格(标准模式<1μs)
-
ACK检测流程
if(I2C_getACKStatus(I2C_MODULE) == I2C_ACK_RECEIVED) { // 正常处理 } else { // 错误处理 } -
常见错误代码 :
- 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模式下数据传输流程:
-
设置总传输字节数
I2C_setDataCount(I2C_MODULE, totalBytes); -
填充TX FIFO
while(bytesRemaining && !I2C_isFIFOFull(I2C_MODULE)) { I2C_putData(I2C_MODULE, *data++); bytesRemaining--; } -
处理传输完成中断
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字节为一页),否则会导致数据回卷。
更多推荐

所有评论(0)