英飞凌TC1782微控制器实现SPI接口EEPROM读写
一、硬件
1. 芯片选型与连接
| 模块 | 型号 | 关键特性 |
|---|---|---|
| 主控芯片 | TC1782 | 32位TriCore™架构,支持SPI |
| EEPROM芯片 | AT25DF081A | 8Mb SPI接口,页尺寸64字节 |
| 时钟源 | 8MHz外部晶振 | SPI时钟分频配置基础 |
硬件连接示意图:
TC1782引脚 → AT25DF081A引脚
-----------------------------
SCLK → SCK
MOSI → SI
MISO → SO
SS → CS
GND → GND
3.3V → VCC
WP → 高电平(禁用写保护)
2. 电气特性要求
- SPI时钟频率 ≤ 20MHz(AT25DF081A最大支持)
- 电源滤波:100nF陶瓷电容 + 10μF电解电容并联
- 信号完整性:差分信号长度匹配 ≤ 50mil
二、软件驱动开发
1. SPI初始化配置
// SPI模式配置(CPOL=0, CPHA=0)
IfxSpi_SpiMasterConfig spiConfig = {
.baudrate = 16000000, // 16MHz
.clockPolarity = IfxSpi_ClockPolarity_idleLow,
.clockPhase = IfxSpi_ClockPhase_sampleLeading,
.wordLength = IfxSpi_WordLength_8bit,
.busFreeVal = 0xFF,
.ssPolarity = IfxSpi_SsPolarity_activeLow
};
// 初始化SPI主站
IfxSpi_SpiMaster spiMaster = IfxSpi_SpiMaster_init(&spiConfig);
2. EEPROM读写操作
// 发送SPI指令
void eeprom_send_command(uint8_t cmd) {
IfxSpi_SpiMaster_transmit(&spiMaster, &cmd, 1);
while(!IfxSpi_SpiMaster_isTransmitDone(&spiMaster));
}
// 读取状态寄存器
uint8_t eeprom_read_status() {
eeprom_send_command(AT25DF081A_CMD_RDSR);
uint8_t status;
IfxSpi_SpiMaster_receive(&spiMaster, &status, 1);
return status;
}
// 写入数据(带页缓冲)
void eeprom_page_write(uint16_t addr, uint8_t *data, uint16_t len) {
// 等待写完成
while(eeprom_read_status() & AT25DF081A_STATUS_BUSY);
// 发送写使能命令
eeprom_send_command(AT25DF081A_CMD_WREN);
// 发送页写指令
eeprom_send_command(AT25DF081A_CMD_PP);
eeprom_send_command((addr >> 8) & 0xFF); // 高字节地址
eeprom_send_command(addr & 0xFF); // 低字节地址
// 传输数据
IfxSpi_SpiMaster_transmit(&spiMaster, data, len);
while(!IfxSpi_SpiMaster_isTransmitDone(&spiMaster));
// 等待写入完成
while(eeprom_read_status() & AT25DF081A_STATUS_BUSY);
}
// 读取数据
void eeprom_read_data(uint16_t addr, uint8_t *buf, uint16_t len) {
eeprom_send_command(AT25DF081A_CMD_READ);
eeprom_send_command((addr >> 8) & 0xFF);
eeprom_send_command(addr & 0xFF);
IfxSpi_SpiMaster_receive(&spiMaster, buf, len);
}
3. 中断服务程序
// SPI中断处理函数
void Spi_IrqHandler(void) {
IfxSpi_SpiMaster_clearAllFlags(&spiMaster);
switch(IfxSpi_SpiMaster_getEvent(&spiMaster)) {
case IfxSpi_SpiMaster_Event_receive:
// 处理接收数据
break;
case IfxSpi_SpiMaster_Event_transmit:
// 处理发送完成
break;
default:
break;
}
}
// 初始化中断
void spi_irq_init() {
IfxSpi_enableInterrupt(&spiMaster, TRUE);
IfxGtm_setPinHandler(AT25DF081A_CS_PIN, Spi_IrqHandler);
}
三、工程实现要点
1. 写保护机制
// 启用写保护
void eeprom_enable_write_protect() {
IfxGtm_setPinOutput(AT25DF081A_WP_PIN, IfxPort_OutputState_low);
}
// 禁用写保护
void eeprom_disable_write_protect() {
IfxGtm_setPinOutput(AT25DF081A_WP_PIN, IfxPort_OutputState_high);
}
2. 错误处理策略
// 错误码定义
typedef enum {
EEPROM_OK = 0,
EEPROM_BUSY,
EEPROM_TIMEOUT,
EEPROM_CRC_ERROR
} EepromError;
// 带超时的写操作
EepromError eeprom_safe_write(uint16_t addr, uint8_t *data, uint16_t len) {
uint32_t timeout = 100000; // 100ms超时
while(--timeout && (eeprom_read_status() & AT25DF081A_STATUS_BUSY));
if(timeout == 0) return EEPROM_TIMEOUT;
// 执行写操作...
return EEPROM_OK;
}
3. DMA传输配置
// DMA通道配置
IfxDma_DmaChannelConfig dmaConfig = {
.requestMode = IfxDma_RequestMode_single,
.transferCount = len,
.sourceAddress = (uint32_t)data,
.destinationAddress = (uint32_t)&spiMaster.base.address,
.transferType = IfxDma_TransferType_incrementSource
};
IfxDma_DmaChannel dmaChannel = IfxDma_initChannel(&dmaConfig);
IfxDma_startChannelTransfer(dmaChannel);
四、调试与验证
1. 逻辑分析仪捕获
- 验证SPI时序是否符合AT25DF081A时序要求: 片选信号低电平保持 ≥ 100ns 时钟空闲电平与CPOL设置一致 数据在时钟上升沿稳定
2. 数据校验算法
// CRC-16校验
uint16_t eeprom_crc16(uint8_t *data, uint16_t len) {
uint16_t crc = 0xFFFF;
for(uint16_t i=0; i<len; i++) {
crc ^= (uint16_t)data[i] << 8;
for(uint8_t j=0; j<8; j++) {
if(crc & 0x8000) crc = (crc << 1) ^ 0x1021;
else crc <<= 1;
}
}
return crc;
}
3. 压力测试方案
// 寿命测试:循环写入10万次
void eeprom_lifetime_test() {
uint8_t test_data[256] = {0};
for(uint32_t i=0; i<100000; i++) {
eeprom_page_write(0x0000, test_data, sizeof(test_data));
eeprom_read_data(0x0000, test_data, sizeof(test_data));
if(memcmp(test_data, original_data, sizeof(test_data))) {
// 触发错误处理
break;
}
}
}
参考代码 英飞凌单片机TC1782,利用SPI读写EEPROM工程 www.youwenfan.com/contentcnl/72743.html
五、性能优化建议
-
缓存机制
#define EEPROM_CACHE_SIZE 256 static uint8_t eeprom_cache[EEPROM_CACHE_SIZE]; static uint16_t cache_addr = 0xFFFF; // 读取时优先使用缓存 uint8_t eeprom_cached_read(uint16_t addr) { if(addr/EEPROM_PAGE_SIZE != cache_addr/EEPROM_PAGE_SIZE) { eeprom_read_data(addr & 0xFFF0, eeprom_cache, EEPROM_CACHE_SIZE); cache_addr = addr & 0xFFF0; } return eeprom_cache[addr & 0x000F]; } -
DMA双缓冲
// 配置双缓冲区 uint8_t dma_buffer[2][256]; volatile uint8_t current_buffer = 0; // 中断中切换缓冲区 void Spi_IrqHandler() { IfxSpi_SpiMaster_clearAllFlags(&spiMaster); current_buffer ^= 1; IfxDma_startChannelTransfer(dmaChannel); } -
低功耗模式
// 进入Standby模式 void eeprom_standby() { eeprom_send_command(AT25DF081A_CMD_STANDBY); IfxGtm_setPinOutput(AT25DF081A_CS_PIN, IfxPort_OutputState_high); }
浙公网安备 33010602011771号