英飞凌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

五、性能优化建议

  1. 缓存机制

    #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];
    }
    
  2. 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);
    }
    
  3. 低功耗模式

    // 进入Standby模式
    void eeprom_standby() {
        eeprom_send_command(AT25DF081A_CMD_STANDBY);
        IfxGtm_setPinOutput(AT25DF081A_CS_PIN, IfxPort_OutputState_high);
    }
    

posted @ 2025-11-13 11:25  小前端攻城狮  阅读(4)  评论(0)    收藏  举报