YTM32B1ME0x芯片深度解读系列(八):通信接口

引言

在现代汽车电子系统中,各种ECU(电子控制单元)、传感器、执行器之间需要进行大量的数据交换。YTM32B1ME0x提供了丰富的串行通信接口,包括UART、SPI、I2C等,满足不同应用场景的通信需求。这些接口不仅支持标准协议,还针对汽车应用进行了优化,具备高可靠性、低功耗和强抗干扰能力。

通信接口系统概览

接口配置总览

YTM32B1ME0x集成了多种串行通信接口:

接口类型数量主要特性典型应用
UART4个异步串行,支持LIN调试、传感器通信
SPI3个同步串行,主从模式Flash、显示屏
I2C2个两线制,多主机EEPROM、传感器
LIN1个汽车网络,单线车身控制

通信接口架构

                    ┌─────────────────────────────────────┐
                    │           通信接口控制器             │
                    │     UART×4 + SPI×3 + I2C×2        │
                    └─────────────────┬───────────────────┘
                                      │
        ┌─────────────────────────────┼─────────────────────────────┐
        │                             │                             │
        ▼                             ▼                             ▼
   ┌─────────┐                  ┌─────────┐                  ┌─────────┐
   │  UART   │                  │   SPI   │                  │   I2C   │
   │ 控制器  │                  │ 控制器  │                  │ 控制器  │
   └─────────┘                  └─────────┘                  └─────────┘
        │                             │                             │
        ▼                             ▼                             ▼
   ┌─────────┐                  ┌─────────┐                  ┌─────────┐
   │ TX/RX   │                  │MOSI/MISO│                  │ SDA/SCL │
   │ FIFO    │                  │ SCLK/CS │                  │  总线   │
   │ 16×8bit │                  │ 16×8bit │                  │ 16×8bit │
   └─────────┘                  └─────────┘                  └─────────┘
        │                             │                             │
        ▼                             ▼                             ▼
   ┌─────────┐                  ┌─────────┐                  ┌─────────┐
   │ 中断/   │                  │ 中断/   │                  │ 中断/   │
   │ DMA     │                  │ DMA     │                  │ DMA     │
   │ 控制    │                  │ 控制    │                  │ 控制    │
   └─────────┘                  └─────────┘                  └─────────┘

UART通信系统

UART核心特性

YTM32B1ME0x的UART具有以下特性:

技术规格:

  • 数据位: 5-9位可配置

  • 停止位: 1、1.5、2位可选

  • 校验位: 无、奇校验、偶校验

  • 波特率: 最高2Mbps(在80MHz系统时钟下)

  • FIFO深度: 发送和接收各16字节

  • 流控制: 硬件RTS/CTS流控

  • 中断源: 多种中断事件

  • DMA支持: 发送和接收DMA传输

UART配置与初始化

// UART配置结构
typedef struct {
    uint32_t baudrate;           // 波特率
    uint32_t data_bits;          // 数据位
    uint32_t stop_bits;          // 停止位
    uint32_t parity;             // 校验位
    bool flow_control;           // 流控制
    bool dma_tx_enable;          // 发送DMA使能
    bool dma_rx_enable;          // 接收DMA使能
    uint32_t tx_fifo_threshold;  // 发送FIFO阈值
    uint32_t rx_fifo_threshold;  // 接收FIFO阈值
} uart_config_t;
​
// UART初始化
void uart_init(UART_Type *uart, uart_config_t *config) {
    // 使能UART时钟
    enable_uart_clock(uart);
    
    // 禁用UART
    uart->CR1 &= ~UART_CR1_UE;
    
    // 配置数据格式
    uart->CR1 = (uart->CR1 & ~UART_CR1_M_MASK) |
                UART_CR1_M(config->data_bits - 5);
    
    // 配置停止位
    uart->CR2 = (uart->CR2 & ~UART_CR2_STOP_MASK) |
                UART_CR2_STOP(config->stop_bits);
    
    // 配置校验位
    if (config->parity != UART_PARITY_NONE) {
        uart->CR1 |= UART_CR1_PCE;
        if (config->parity == UART_PARITY_ODD) {
            uart->CR1 |= UART_CR1_PS;
        }
    }
    
    // 配置波特率
    uint32_t uart_clock = get_uart_clock_frequency(uart);
    uint32_t brr_value = uart_clock / config->baudrate;
    uart->BRR = brr_value;
    
    // 配置FIFO阈值
    uart->CR3 = (uart->CR3 & ~UART_CR3_TXFTCFG_MASK) |
                UART_CR3_TXFTCFG(config->tx_fifo_threshold);
    uart->CR3 = (uart->CR3 & ~UART_CR3_RXFTCFG_MASK) |
                UART_CR3_RXFTCFG(config->rx_fifo_threshold);
    
    // 配置流控制
    if (config->flow_control) {
        uart->CR3 |= UART_CR3_RTSE | UART_CR3_CTSE;
    }
    
    // 配置DMA
    if (config->dma_tx_enable) {
        uart->CR3 |= UART_CR3_DMAT;
    }
    if (config->dma_rx_enable) {
        uart->CR3 |= UART_CR3_DMAR;
    }
    
    // 使能发送和接收
    uart->CR1 |= UART_CR1_TE | UART_CR1_RE;
    
    // 使能UART
    uart->CR1 |= UART_CR1_UE;
}
​
// UART发送数据
uart_status_t uart_send_data(UART_Type *uart, const uint8_t *data, uint32_t length) {
    for (uint32_t i = 0; i < length; i++) {
        // 等待发送FIFO不满
        while (!(uart->ISR & UART_ISR_TXE));
        
        // 发送数据
        uart->TDR = data[i];
    }
    
    // 等待发送完成
    while (!(uart->ISR & UART_ISR_TC));
    
    return UART_STATUS_OK;
}
​
// UART接收数据
uart_status_t uart_receive_data(UART_Type *uart, uint8_t *data, uint32_t length, uint32_t timeout) {
    uint32_t received = 0;
    uint32_t start_time = get_system_time_ms();
    
    while (received < length) {
        // 检查超时
        if (get_system_time_ms() - start_time > timeout) {
            return UART_STATUS_TIMEOUT;
        }
        
        // 检查接收FIFO
        if (uart->ISR & UART_ISR_RXNE) {
            data[received++] = uart->RDR;
        }
        
        // 检查错误
        if (uart->ISR & (UART_ISR_PE | UART_ISR_FE | UART_ISR_NE | UART_ISR_ORE)) {
            return UART_STATUS_ERROR;
        }
    }
    
    return UART_STATUS_OK;
}

UART中断处理

// UART中断处理结构
typedef struct {
    uint8_t tx_buffer[256];      // 发送缓冲区
    uint8_t rx_buffer[256];      // 接收缓冲区
    uint32_t tx_head;            // 发送头指针
    uint32_t tx_tail;            // 发送尾指针
    uint32_t rx_head;            // 接收头指针
    uint32_t rx_tail;            // 接收尾指针
    bool tx_busy;                // 发送忙标志
    uart_callback_t tx_callback; // 发送完成回调
    uart_callback_t rx_callback; // 接收完成回调
} uart_handle_t;
​
// 配置UART中断
void uart_configure_interrupts(UART_Type *uart, uart_handle_t *handle) {
    // 使能接收中断
    uart->CR1 |= UART_CR1_RXNEIE;
    
    // 使能错误中断
    uart->CR3 |= UART_CR3_EIE;
    
    // 使能FIFO阈值中断
    uart->CR3 |= UART_CR3_RXFTIE;
    
    // 配置NVIC
    NVIC_EnableIRQ(get_uart_irq_number(uart));
}
​
// UART中断处理函数
void UART1_IRQHandler(void) {
    uart_handle_t *handle = get_uart_handle(UART1);
    
    // 处理接收中断
    if (UART1->ISR & UART_ISR_RXNE) {
        uint8_t data = UART1->RDR;
        
        // 存储到环形缓冲区
        uint32_t next_head = (handle->rx_head + 1) % sizeof(handle->rx_buffer);
        if (next_head != handle->rx_tail) {
            handle->rx_buffer[handle->rx_head] = data;
            handle->rx_head = next_head;
        }
        
        // 调用接收回调
        if (handle->rx_callback) {
            handle->rx_callback(data);
        }
    }
    
    // 处理发送中断
    if (UART1->ISR & UART_ISR_TXE) {
        if (handle->tx_head != handle->tx_tail) {
            // 发送下一个字节
            UART1->TDR = handle->tx_buffer[handle->tx_tail];
            handle->tx_tail = (handle->tx_tail + 1) % sizeof(handle->tx_buffer);
        } else {
            // 发送完成,禁用发送中断
            UART1->CR1 &= ~UART_CR1_TXEIE;
            handle->tx_busy = false;
            
            if (handle->tx_callback) {
                handle->tx_callback(0);
            }
        }
    }
    
    // 处理错误中断
    if (UART1->ISR & (UART_ISR_PE | UART_ISR_FE | UART_ISR_NE | UART_ISR_ORE)) {
        // 清除错误标志
        UART1->ICR = UART_ICR_PECF | UART_ICR_FECF | UART_ICR_NECF | UART_ICR_ORECF;
        
        // 处理错误
        handle_uart_error(UART1);
    }
}
​
// 异步发送数据
uart_status_t uart_send_async(UART_Type *uart, const uint8_t *data, uint32_t length) {
    uart_handle_t *handle = get_uart_handle(uart);
    
    if (handle->tx_busy) {
        return UART_STATUS_BUSY;
    }
    
    // 复制数据到发送缓冲区
    for (uint32_t i = 0; i < length; i++) {
        uint32_t next_head = (handle->tx_head + 1) % sizeof(handle->tx_buffer);
        if (next_head == handle->tx_tail) {
            return UART_STATUS_BUFFER_FULL;
        }
        
        handle->tx_buffer[handle->tx_head] = data[i];
        handle->tx_head = next_head;
    }
    
    // 启动发送
    handle->tx_busy = true;
    uart->CR1 |= UART_CR1_TXEIE;
    
    return UART_STATUS_OK;
}

UART DMA传输

// UART DMA配置
typedef struct {
    DMA_Channel_TypeDef *tx_channel;  // 发送DMA通道
    DMA_Channel_TypeDef *rx_channel;  // 接收DMA通道
    uint8_t *tx_buffer;               // 发送缓冲区
    uint8_t *rx_buffer;               // 接收缓冲区
    uint32_t tx_size;                 // 发送大小
    uint32_t rx_size;                 // 接收大小
    bool tx_complete;                 // 发送完成标志
    bool rx_complete;                 // 接收完成标志
} uart_dma_t;
​
void uart_configure_dma(UART_Type *uart, uart_dma_t *dma_config) {
    // 配置发送DMA
    dma_config->tx_channel->CPAR = (uint32_t)&uart->TDR;
    dma_config->tx_channel->CMAR = (uint32_t)dma_config->tx_buffer;
    dma_config->tx_channel->CNDTR = dma_config->tx_size;
    dma_config->tx_channel->CCR = DMA_CCR_DIR |           // 内存到外设
                                  DMA_CCR_MINC |          // 内存地址递增
                                  DMA_CCR_TCIE |          // 传输完成中断
                                  DMA_CCR_TEIE;           // 传输错误中断
    
    // 配置接收DMA
    dma_config->rx_channel->CPAR = (uint32_t)&uart->RDR;
    dma_config->rx_channel->CMAR = (uint32_t)dma_config->rx_buffer;
    dma_config->rx_channel->CNDTR = dma_config->rx_size;
    dma_config->rx_channel->CCR = DMA_CCR_MINC |          // 内存地址递增
                                  DMA_CCR_TCIE |          // 传输完成中断
                                  DMA_CCR_TEIE |          // 传输错误中断
                                  DMA_CCR_CIRC;           // 循环模式
    
    // 使能DMA通道
    dma_config->tx_channel->CCR |= DMA_CCR_EN;
    dma_config->rx_channel->CCR |= DMA_CCR_EN;
    
    // 使能UART DMA请求
    uart->CR3 |= UART_CR3_DMAT | UART_CR3_DMAR;
}
​
// DMA发送数据
uart_status_t uart_send_dma(UART_Type *uart, const uint8_t *data, uint32_t length) {
    uart_dma_t *dma_config = get_uart_dma_config(uart);
    
    if (dma_config->tx_channel->CCR & DMA_CCR_EN) {
        return UART_STATUS_BUSY;
    }
    
    // 配置DMA传输
    dma_config->tx_channel->CMAR = (uint32_t)data;
    dma_config->tx_channel->CNDTR = length;
    dma_config->tx_complete = false;
    
    // 启动DMA传输
    dma_config->tx_channel->CCR |= DMA_CCR_EN;
    
    return UART_STATUS_OK;
}
​
// DMA中断处理
void DMA1_Channel4_IRQHandler(void) {  // UART1 TX DMA
    uart_dma_t *dma_config = get_uart_dma_config(UART1);
    
    if (DMA1->ISR & DMA_ISR_TCIF4) {
        // 传输完成
        DMA1->IFCR = DMA_IFCR_CTCIF4;
        dma_config->tx_complete = true;
        
        // 禁用DMA通道
        dma_config->tx_channel->CCR &= ~DMA_CCR_EN;
        
        // 调用完成回调
        if (dma_config->tx_callback) {
            dma_config->tx_callback();
        }
    }
    
    if (DMA1->ISR & DMA_ISR_TEIF4) {
        // 传输错误
        DMA1->IFCR = DMA_IFCR_CTEIF4;
        handle_uart_dma_error(UART1);
    }
}

SPI通信系统

SPI核心特性

YTM32B1ME0x的SPI具有以下特性:

技术规格:

  • 工作模式: 主机/从机模式

  • 数据宽度: 4-16位可配置

  • 时钟频率: 最高40MHz

  • 时钟极性: CPOL可配置

  • 时钟相位: CPHA可配置

  • NSS管理: 硬件/软件NSS

  • FIFO深度: 发送和接收各16字节

  • DMA支持: 全双工DMA传输

SPI配置与初始化

// SPI配置结构
typedef struct {
    uint32_t mode;               // 主机/从机模式
    uint32_t data_size;          // 数据位宽
    uint32_t clock_polarity;     // 时钟极性
    uint32_t clock_phase;        // 时钟相位
    uint32_t nss_mode;           // NSS管理模式
    uint32_t baudrate_prescaler; // 波特率分频
    uint32_t first_bit;          // 首位传输
    bool crc_enable;             // CRC使能
    uint32_t crc_polynomial;     // CRC多项式
} spi_config_t;
​
void spi_init(SPI_TypeDef *spi, spi_config_t *config) {
    // 使能SPI时钟
    enable_spi_clock(spi);
    
    // 禁用SPI
    spi->CR1 &= ~SPI_CR1_SPE;
    
    // 配置基本参数
    spi->CR1 = (spi->CR1 & ~SPI_CR1_MSTR) |
               (config->mode == SPI_MODE_MASTER ? SPI_CR1_MSTR : 0);
    
    spi->CR1 = (spi->CR1 & ~SPI_CR1_CPOL) |
               (config->clock_polarity == SPI_POLARITY_HIGH ? SPI_CR1_CPOL : 0);
    
    spi->CR1 = (spi->CR1 & ~SPI_CR1_CPHA) |
               (config->clock_phase == SPI_PHASE_2EDGE ? SPI_CR1_CPHA : 0);
    
    spi->CR1 = (spi->CR1 & ~SPI_CR1_LSBFIRST) |
               (config->first_bit == SPI_FIRSTBIT_LSB ? SPI_CR1_LSBFIRST : 0);
    
    // 配置波特率
    spi->CR1 = (spi->CR1 & ~SPI_CR1_BR_MASK) |
               SPI_CR1_BR(config->baudrate_prescaler);
    
    // 配置数据大小
    spi->CR2 = (spi->CR2 & ~SPI_CR2_DS_MASK) |
               SPI_CR2_DS(config->data_size - 1);
    
    // 配置NSS
    if (config->nss_mode == SPI_NSS_SOFT) {
        spi->CR1 |= SPI_CR1_SSM | SPI_CR1_SSI;
    } else {
        spi->CR2 |= SPI_CR2_SSOE;  // 硬件NSS输出使能
    }
    
    // 配置FIFO阈值
    spi->CR2 |= SPI_CR2_FRXTH;  // 8位FIFO阈值
    
    // 配置CRC
    if (config->crc_enable) {
        spi->CRCPR = config->crc_polynomial;
        spi->CR1 |= SPI_CR1_CRCEN;
    }
    
    // 使能SPI
    spi->CR1 |= SPI_CR1_SPE;
}
​
// SPI数据传输
spi_status_t spi_transmit_receive(SPI_TypeDef *spi, const uint8_t *tx_data, 
                                  uint8_t *rx_data, uint32_t length) {
    for (uint32_t i = 0; i < length; i++) {
        // 等待发送FIFO不满
        while (!(spi->SR & SPI_SR_TXE));
        
        // 发送数据
        *(volatile uint8_t*)&spi->DR = tx_data ? tx_data[i] : 0xFF;
        
        // 等待接收FIFO不空
        while (!(spi->SR & SPI_SR_RXNE));
        
        // 接收数据
        if (rx_data) {
            rx_data[i] = *(volatile uint8_t*)&spi->DR;
        } else {
            (void)*(volatile uint8_t*)&spi->DR;  // 丢弃数据
        }
    }
    
    // 等待传输完成
    while (spi->SR & SPI_SR_BSY);
    
    return SPI_STATUS_OK;
}

SPI DMA传输

// SPI DMA配置
typedef struct {
    DMA_Channel_TypeDef *tx_channel;  // 发送DMA通道
    DMA_Channel_TypeDef *rx_channel;  // 接收DMA通道
    bool tx_complete;                 // 发送完成标志
    bool rx_complete;                 // 接收完成标志
    spi_callback_t complete_callback; // 完成回调
} spi_dma_t;
​
void spi_configure_dma(SPI_TypeDef *spi, spi_dma_t *dma_config) {
    // 配置发送DMA
    dma_config->tx_channel->CPAR = (uint32_t)&spi->DR;
    dma_config->tx_channel->CCR = DMA_CCR_DIR |           // 内存到外设
                                  DMA_CCR_MINC |          // 内存地址递增
                                  DMA_CCR_TCIE;           // 传输完成中断
    
    // 配置接收DMA
    dma_config->rx_channel->CPAR = (uint32_t)&spi->DR;
    dma_config->rx_channel->CCR = DMA_CCR_MINC |          // 内存地址递增
                                  DMA_CCR_TCIE;           // 传输完成中断
    
    // 使能SPI DMA请求
    spi->CR2 |= SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN;
}
​
// SPI DMA传输
spi_status_t spi_transmit_receive_dma(SPI_TypeDef *spi, const uint8_t *tx_data,
                                      uint8_t *rx_data, uint32_t length) {
    spi_dma_t *dma_config = get_spi_dma_config(spi);
    
    // 配置接收DMA
    dma_config->rx_channel->CMAR = (uint32_t)rx_data;
    dma_config->rx_channel->CNDTR = length;
    dma_config->rx_complete = false;
    dma_config->rx_channel->CCR |= DMA_CCR_EN;
    
    // 配置发送DMA
    dma_config->tx_channel->CMAR = (uint32_t)tx_data;
    dma_config->tx_channel->CNDTR = length;
    dma_config->tx_complete = false;
    dma_config->tx_channel->CCR |= DMA_CCR_EN;
    
    return SPI_STATUS_OK;
}
​
// SPI Flash接口示例
typedef struct {
    SPI_TypeDef *spi;
    GPIO_TypeDef *cs_port;
    uint32_t cs_pin;
    spi_dma_t dma_config;
} spi_flash_t;
​
void spi_flash_init(spi_flash_t *flash) {
    // 配置SPI
    spi_config_t spi_config = {
        .mode = SPI_MODE_MASTER,
        .data_size = 8,
        .clock_polarity = SPI_POLARITY_LOW,
        .clock_phase = SPI_PHASE_1EDGE,
        .nss_mode = SPI_NSS_SOFT,
        .baudrate_prescaler = SPI_BAUDRATEPRESCALER_8,  // 10MHz
        .first_bit = SPI_FIRSTBIT_MSB,
        .crc_enable = false
    };
    
    spi_init(flash->spi, &spi_config);
    
    // 配置CS引脚
    gpio_config_t cs_config = {
        .mode = GPIO_MODE_OUTPUT,
        .pull = GPIO_NOPULL,
        .speed = GPIO_SPEED_HIGH
    };
    gpio_init(flash->cs_port, flash->cs_pin, &cs_config);
    gpio_write_pin(flash->cs_port, flash->cs_pin, GPIO_PIN_SET);  // CS高电平
    
    // 配置DMA
    spi_configure_dma(flash->spi, &flash->dma_config);
}
​
// Flash读取操作
spi_status_t spi_flash_read(spi_flash_t *flash, uint32_t address, 
                           uint8_t *data, uint32_t length) {
    uint8_t cmd[4] = {
        0x03,                    // 读命令
        (address >> 16) & 0xFF,  // 地址高字节
        (address >> 8) & 0xFF,   // 地址中字节
        address & 0xFF           // 地址低字节
    };
    
    // 拉低CS
    gpio_write_pin(flash->cs_port, flash->cs_pin, GPIO_PIN_RESET);
    
    // 发送命令和地址
    spi_transmit_receive(flash->spi, cmd, NULL, 4);
    
    // 读取数据
    spi_transmit_receive(flash->spi, NULL, data, length);
    
    // 拉高CS
    gpio_write_pin(flash->cs_port, flash->cs_pin, GPIO_PIN_SET);
    
    return SPI_STATUS_OK;
}

I2C通信系统

I2C核心特性

YTM32B1ME0x的I2C具有以下特性:

技术规格:

  • 工作模式: 主机/从机/多主机

  • 速度模式: 标准(100kHz)、快速(400kHz)、快速+(1MHz)

  • 地址模式: 7位/10位地址

  • 时钟拉伸: 支持时钟拉伸

  • SMBus支持: 兼容SMBus协议

  • DMA支持: 发送和接收DMA传输

  • 错误检测: 总线错误、仲裁丢失检测

I2C配置与初始化

// I2C配置结构
typedef struct {
    uint32_t clock_speed;        // 时钟速度
    uint32_t duty_cycle;         // 占空比
    uint32_t own_address1;       // 自身地址1
    uint32_t address_mode;       // 地址模式
    uint32_t dual_address_mode;  // 双地址模式
    uint32_t own_address2;       // 自身地址2
    uint32_t general_call_mode;  // 广播呼叫模式
    uint32_t no_stretch_mode;    // 时钟拉伸模式
} i2c_config_t;
​
void i2c_init(I2C_TypeDef *i2c, i2c_config_t *config) {
    // 使能I2C时钟
    enable_i2c_clock(i2c);
    
    // 禁用I2C
    i2c->CR1 &= ~I2C_CR1_PE;
    
    // 配置时钟
    uint32_t pclk1 = get_pclk1_frequency();
    i2c->CR2 = (i2c->CR2 & ~I2C_CR2_FREQ_MASK) | 
               I2C_CR2_FREQ(pclk1 / 1000000);  // MHz
    
    // 配置时钟控制寄存器
    if (config->clock_speed <= 100000) {
        // 标准模式
        uint32_t ccr_value = pclk1 / (config->clock_speed * 2);
        i2c->CCR = ccr_value;
        i2c->TRISE = (pclk1 / 1000000) + 1;
    } else {
        // 快速模式
        uint32_t ccr_value;
        if (config->duty_cycle == I2C_DUTYCYCLE_2) {
            ccr_value = pclk1 / (config->clock_speed * 3);
        } else {
            ccr_value = pclk1 / (config->clock_speed * 25);
            i2c->CCR |= I2C_CCR_DUTY;
        }
        i2c->CCR |= I2C_CCR_FS | ccr_value;
        i2c->TRISE = ((pclk1 * 300) / 1000000000) + 1;
    }
    
    // 配置自身地址
    i2c->OAR1 = (config->address_mode == I2C_ADDRESSINGMODE_7BIT) ?
                (config->own_address1 << 1) :
                (I2C_OAR1_ADDMODE | config->own_address1);
    
    // 配置双地址模式
    if (config->dual_address_mode == I2C_DUALADDRESS_ENABLE) {
        i2c->OAR2 = I2C_OAR2_ENDUAL | (config->own_address2 << 1);
    }
    
    // 配置广播呼叫
    if (config->general_call_mode == I2C_GENERALCALL_ENABLE) {
        i2c->CR1 |= I2C_CR1_ENGC;
    }
    
    // 配置时钟拉伸
    if (config->no_stretch_mode == I2C_NOSTRETCH_ENABLE) {
        i2c->CR1 |= I2C_CR1_NOSTRETCH;
    }
    
    // 使能I2C
    i2c->CR1 |= I2C_CR1_PE;
}
​
// I2C主机发送
i2c_status_t i2c_master_transmit(I2C_TypeDef *i2c, uint16_t dev_address,
                                 const uint8_t *data, uint32_t length) {
    // 等待总线空闲
    while (i2c->SR2 & I2C_SR2_BUSY);
    
    // 产生起始条件
    i2c->CR1 |= I2C_CR1_START;
    while (!(i2c->SR1 & I2C_SR1_SB));
    
    // 发送设备地址(写)
    i2c->DR = dev_address & 0xFE;
    while (!(i2c->SR1 & I2C_SR1_ADDR));
    
    // 清除ADDR标志
    (void)i2c->SR1;
    (void)i2c->SR2;
    
    // 发送数据
    for (uint32_t i = 0; i < length; i++) {
        while (!(i2c->SR1 & I2C_SR1_TXE));
        i2c->DR = data[i];
    }
    
    // 等待传输完成
    while (!(i2c->SR1 & I2C_SR1_BTF));
    
    // 产生停止条件
    i2c->CR1 |= I2C_CR1_STOP;
    
    return I2C_STATUS_OK;
}
​
// I2C主机接收
i2c_status_t i2c_master_receive(I2C_TypeDef *i2c, uint16_t dev_address,
                                uint8_t *data, uint32_t length) {
    // 等待总线空闲
    while (i2c->SR2 & I2C_SR2_BUSY);
    
    // 配置ACK
    if (length == 1) {
        i2c->CR1 &= ~I2C_CR1_ACK;
    } else {
        i2c->CR1 |= I2C_CR1_ACK;
    }
    
    // 产生起始条件
    i2c->CR1 |= I2C_CR1_START;
    while (!(i2c->SR1 & I2C_SR1_SB));
    
    // 发送设备地址(读)
    i2c->DR = dev_address | 0x01;
    while (!(i2c->SR1 & I2C_SR1_ADDR));
    
    if (length == 1) {
        // 清除ADDR标志
        (void)i2c->SR1;
        (void)i2c->SR2;
        
        // 产生停止条件
        i2c->CR1 |= I2C_CR1_STOP;
        
        // 接收数据
        while (!(i2c->SR1 & I2C_SR1_RXNE));
        data[0] = i2c->DR;
    } else {
        // 清除ADDR标志
        (void)i2c->SR1;
        (void)i2c->SR2;
        
        // 接收数据
        for (uint32_t i = 0; i < length; i++) {
            if (i == length - 2) {
                // 倒数第二个字节,清除ACK
                i2c->CR1 &= ~I2C_CR1_ACK;
            }
            if (i == length - 1) {
                // 最后一个字节,产生停止条件
                i2c->CR1 |= I2C_CR1_STOP;
            }
            
            while (!(i2c->SR1 & I2C_SR1_RXNE));
            data[i] = i2c->DR;
        }
    }
    
    return I2C_STATUS_OK;
}

I2C EEPROM接口示例

// I2C EEPROM驱动
typedef struct {
    I2C_TypeDef *i2c;
    uint16_t device_address;
    uint32_t page_size;
    uint32_t total_size;
    uint32_t address_size;  // 地址字节数
} i2c_eeprom_t;
​
void i2c_eeprom_init(i2c_eeprom_t *eeprom) {
    // 配置I2C
    i2c_config_t i2c_config = {
        .clock_speed = 400000,  // 400kHz
        .duty_cycle = I2C_DUTYCYCLE_2,
        .own_address1 = 0x00,
        .address_mode = I2C_ADDRESSINGMODE_7BIT,
        .dual_address_mode = I2C_DUALADDRESS_DISABLE,
        .general_call_mode = I2C_GENERALCALL_DISABLE,
        .no_stretch_mode = I2C_NOSTRETCH_DISABLE
    };
    
    i2c_init(eeprom->i2c, &i2c_config);
}
​
// EEPROM写入
i2c_status_t i2c_eeprom_write(i2c_eeprom_t *eeprom, uint32_t address,
                              const uint8_t *data, uint32_t length) {
    uint32_t bytes_written = 0;
    
    while (bytes_written < length) {
        uint32_t current_address = address + bytes_written;
        uint32_t page_offset = current_address % eeprom->page_size;
        uint32_t bytes_to_write = MIN(length - bytes_written,
                                      eeprom->page_size - page_offset);
        
        // 等待总线空闲
        while (eeprom->i2c->SR2 & I2C_SR2_BUSY);
        
        // 产生起始条件
        eeprom->i2c->CR1 |= I2C_CR1_START;
        while (!(eeprom->i2c->SR1 & I2C_SR1_SB));
        
        // 发送设备地址(写)
        eeprom->i2c->DR = eeprom->device_address & 0xFE;
        while (!(eeprom->i2c->SR1 & I2C_SR1_ADDR));
        
        // 清除ADDR标志
        (void)eeprom->i2c->SR1;
        (void)eeprom->i2c->SR2;
        
        // 发送内存地址
        if (eeprom->address_size == 2) {
            // 16位地址
            while (!(eeprom->i2c->SR1 & I2C_SR1_TXE));
            eeprom->i2c->DR = (current_address >> 8) & 0xFF;
        }
        while (!(eeprom->i2c->SR1 & I2C_SR1_TXE));
        eeprom->i2c->DR = current_address & 0xFF;
        
        // 发送数据
        for (uint32_t i = 0; i < bytes_to_write; i++) {
            while (!(eeprom->i2c->SR1 & I2C_SR1_TXE));
            eeprom->i2c->DR = data[bytes_written + i];
        }
        
        // 等待传输完成
        while (!(eeprom->i2c->SR1 & I2C_SR1_BTF));
        
        // 产生停止条件
        eeprom->i2c->CR1 |= I2C_CR1_STOP;
        
        // 等待写入完成
        delay_ms(5);  // 典型写入时间
        
        bytes_written += bytes_to_write;
    }
    
    return I2C_STATUS_OK;
}
​
// EEPROM读取
i2c_status_t i2c_eeprom_read(i2c_eeprom_t *eeprom, uint32_t address,
                             uint8_t *data, uint32_t length) {
    // 等待总线空闲
    while (eeprom->i2c->SR2 & I2C_SR2_BUSY);
    
    // 产生起始条件
    eeprom->i2c->CR1 |= I2C_CR1_START;
    while (!(eeprom->i2c->SR1 & I2C_SR1_SB));
    
    // 发送设备地址(写)
    eeprom->i2c->DR = eeprom->device_address & 0xFE;
    while (!(eeprom->i2c->SR1 & I2C_SR1_ADDR));
    
    // 清除ADDR标志
    (void)eeprom->i2c->SR1;
    (void)eeprom->i2c->SR2;
    
    // 发送内存地址
    if (eeprom->address_size == 2) {
        // 16位地址
        while (!(eeprom->i2c->SR1 & I2C_SR1_TXE));
        eeprom->i2c->DR = (address >> 8) & 0xFF;
    }
    while (!(eeprom->i2c->SR1 & I2C_SR1_TXE));
    eeprom->i2c->DR = address & 0xFF;
    
    // 重新产生起始条件
    eeprom->i2c->CR1 |= I2C_CR1_START;
    while (!(eeprom->i2c->SR1 & I2C_SR1_SB));
    
    // 发送设备地址(读)
    eeprom->i2c->DR = eeprom->device_address | 0x01;
    while (!(eeprom->i2c->SR1 & I2C_SR1_ADDR));
    
    // 接收数据
    if (length == 1) {
        // 单字节读取
        eeprom->i2c->CR1 &= ~I2C_CR1_ACK;
        
        // 清除ADDR标志
        (void)eeprom->i2c->SR1;
        (void)eeprom->i2c->SR2;
        
        // 产生停止条件
        eeprom->i2c->CR1 |= I2C_CR1_STOP;
        
        // 接收数据
        while (!(eeprom->i2c->SR1 & I2C_SR1_RXNE));
        data[0] = eeprom->i2c->DR;
    } else {
        // 多字节读取
        eeprom->i2c->CR1 |= I2C_CR1_ACK;
        
        // 清除ADDR标志
        (void)eeprom->i2c->SR1;
        (void)eeprom->i2c->SR2;
        
        for (uint32_t i = 0; i < length; i++) {
            if (i == length - 2) {
                // 倒数第二个字节,清除ACK
                eeprom->i2c->CR1 &= ~I2C_CR1_ACK;
            }
            if (i == length - 1) {
                // 最后一个字节,产生停止条件
                eeprom->i2c->CR1 |= I2C_CR1_STOP;
            }
            
            while (!(eeprom->i2c->SR1 & I2C_SR1_RXNE));
            data[i] = eeprom->i2c->DR;
        }
    }
    
    return I2C_STATUS_OK;
}
```## LIN通
信系统
​
### LIN协议特性
​
LIN(Local Interconnect Network)是专为汽车应用设计的低成本串行通信协议:
​
**技术规格:**
- **传输速率**: 1kbps - 20kbps
- **总线拓扑**: 单主机多从机
- **物理层**: 单线+地线
- **帧格式**: 标准LIN 2.1协议
- **错误检测**: 校验和、同步场检测
- **唤醒功能**: 支持总线唤醒
​
### LIN配置与实现
​
```c
// LIN配置结构
typedef struct {
    uint32_t baudrate;           // 波特率
    uint32_t break_length;       // 间隔场长度
    uint32_t node_type;          // 节点类型(主机/从机)
    bool checksum_enhanced;      // 增强校验和
    bool auto_baudrate;          // 自动波特率检测
    lin_callback_t frame_callback; // 帧处理回调
} lin_config_t;
​
// LIN帧结构
typedef struct {
    uint8_t id;                  // 帧ID
    uint8_t data[8];             // 数据
    uint8_t length;              // 数据长度
    uint8_t checksum;            // 校验和
    lin_frame_type_t type;       // 帧类型
} lin_frame_t;
​
void lin_init(UART_Type *uart, lin_config_t *config) {
    // 配置UART用于LIN
    uart_config_t uart_config = {
        .baudrate = config->baudrate,
        .data_bits = 8,
        .stop_bits = UART_STOPBITS_1,
        .parity = UART_PARITY_NONE,
        .flow_control = false,
        .dma_tx_enable = false,
        .dma_rx_enable = false,
        .tx_fifo_threshold = 1,
        .rx_fifo_threshold = 1
    };
    
    uart_init(uart, &uart_config);
    
    // 配置LIN特殊功能
    uart->CR2 |= UART_CR2_LINEN;  // 使能LIN模式
    
    if (config->break_length == LIN_BREAK_13BITS) {
        uart->CR2 |= UART_CR2_LBDL;
    }
    
    // 使能LIN中断
    uart->CR2 |= UART_CR2_LBDIE;  // 间隔检测中断
    
    // 配置自动波特率检测
    if (config->auto_baudrate) {
        uart->CR2 |= UART_CR2_ABREN;
    }
    
    NVIC_EnableIRQ(get_uart_irq_number(uart));
}
​
// LIN主机发送帧头
lin_status_t lin_master_send_header(UART_Type *uart, uint8_t frame_id) {
    // 发送间隔场(13位低电平)
    uart->CR1 |= UART_CR1_SBK;
    while (uart->CR1 & UART_CR1_SBK);
    
    // 发送同步场(0x55)
    while (!(uart->ISR & UART_ISR_TXE));
    uart->TDR = 0x55;
    
    // 发送受保护ID
    uint8_t protected_id = calculate_protected_id(frame_id);
    while (!(uart->ISR & UART_ISR_TXE));
    uart->TDR = protected_id;
    
    return LIN_STATUS_OK;
}
​
// 计算受保护ID
uint8_t calculate_protected_id(uint8_t frame_id) {
    uint8_t p0 = (frame_id ^ (frame_id >> 1) ^ (frame_id >> 2) ^ (frame_id >> 4)) & 0x01;
    uint8_t p1 = ~((frame_id >> 1) ^ (frame_id >> 3) ^ (frame_id >> 4) ^ (frame_id >> 5)) & 0x01;
    
    return frame_id | (p0 << 6) | (p1 << 7);
}
​
// LIN从机响应处理
void lin_slave_response_handler(UART_Type *uart, uint8_t frame_id) {
    lin_frame_t *frame = get_lin_frame_config(frame_id);
    
    if (frame->type == LIN_FRAME_TX) {
        // 发送响应
        for (uint8_t i = 0; i < frame->length; i++) {
            while (!(uart->ISR & UART_ISR_TXE));
            uart->TDR = frame->data[i];
        }
        
        // 发送校验和
        uint8_t checksum = calculate_lin_checksum(frame);
        while (!(uart->ISR & UART_ISR_TXE));
        uart->TDR = checksum;
        
    } else if (frame->type == LIN_FRAME_RX) {
        // 准备接收响应
        start_lin_reception(uart, frame);
    }
}
​
// 计算LIN校验和
uint8_t calculate_lin_checksum(lin_frame_t *frame) {
    uint16_t sum = 0;
    
    // 增强校验和包含受保护ID
    if (frame->checksum_enhanced) {
        sum += calculate_protected_id(frame->id);
    }
    
    // 累加数据字节
    for (uint8_t i = 0; i < frame->length; i++) {
        sum += frame->data[i];
        if (sum > 0xFF) {
            sum = (sum & 0xFF) + 1;  // 进位处理
        }
    }
    
    return (~sum) & 0xFF;  // 取反
}
​
// LIN中断处理
void UART2_IRQHandler(void) {  // 假设UART2用于LIN
    if (UART2->ISR & UART_ISR_LBDF) {
        // 检测到间隔场
        UART2->ICR |= UART_ICR_LBDCF;
        
        // 开始接收同步场和受保护ID
        start_lin_header_reception();
    }
    
    if (UART2->ISR & UART_ISR_RXNE) {
        uint8_t data = UART2->RDR;
        process_lin_byte(data);
    }
    
    // 处理其他中断...
}

多协议通信管理

// 通信协议管理器
typedef struct {
    struct {
        UART_Type *uart;
        uart_handle_t handle;
        bool active;
    } uart_channels[4];
    
    struct {
        SPI_TypeDef *spi;
        spi_dma_t dma_config;
        bool active;
    } spi_channels[3];
    
    struct {
        I2C_TypeDef *i2c;
        bool active;
    } i2c_channels[2];
    
    struct {
        UART_Type *uart;
        lin_config_t config;
        bool active;
    } lin_channel;
    
    // 通信统计
    struct {
        uint32_t uart_tx_count[4];
        uint32_t uart_rx_count[4];
        uint32_t spi_transfer_count[3];
        uint32_t i2c_transfer_count[2];
        uint32_t lin_frame_count;
        uint32_t error_count;
    } statistics;
    
} comm_manager_t;

void comm_manager_init(comm_manager_t *manager) {
    // 初始化所有通信接口
    for (int i = 0; i < 4; i++) {
        if (manager->uart_channels[i].active) {
            uart_config_t config = get_default_uart_config();
            uart_init(manager->uart_channels[i].uart, &config);
            uart_configure_interrupts(manager->uart_channels[i].uart,
                                    &manager->uart_channels[i].handle);
        }
    }
    
    for (int i = 0; i < 3; i++) {
        if (manager->spi_channels[i].active) {
            spi_config_t config = get_default_spi_config();
            spi_init(manager->spi_channels[i].spi, &config);
            spi_configure_dma(manager->spi_channels[i].spi,
                            &manager->spi_channels[i].dma_config);
        }
    }
    
    for (int i = 0; i < 2; i++) {
        if (manager->i2c_channels[i].active) {
            i2c_config_t config = get_default_i2c_config();
            i2c_init(manager->i2c_channels[i].i2c, &config);
        }
    }
    
    if (manager->lin_channel.active) {
        lin_init(manager->lin_channel.uart, &manager->lin_channel.config);
    }
    
    // 清零统计信息
    memset(&manager->statistics, 0, sizeof(manager->statistics));
}

// 通信任务调度
void comm_task_scheduler(void *param) {
    comm_manager_t *manager = (comm_manager_t*)param;
    
    while (1) {
        // 处理UART通信
        for (int i = 0; i < 4; i++) {
            if (manager->uart_channels[i].active) {
                process_uart_communication(i, manager);
            }
        }
        
        // 处理SPI通信
        for (int i = 0; i < 3; i++) {
            if (manager->spi_channels[i].active) {
                process_spi_communication(i, manager);
            }
        }
        
        // 处理I2C通信
        for (int i = 0; i < 2; i++) {
            if (manager->i2c_channels[i].active) {
                process_i2c_communication(i, manager);
            }
        }
        
        // 处理LIN通信
        if (manager->lin_channel.active) {
            process_lin_communication(manager);
        }
        
        // 更新统计信息
        update_communication_statistics(manager);
        
        vTaskDelay(pdMS_TO_TICKS(10));  // 10ms调度周期
    }
}

通信协议栈实现

自定义协议实现

// 自定义协议帧格式
typedef struct {
    uint8_t header[2];           // 帧头 0xAA, 0x55
    uint8_t length;              // 数据长度
    uint8_t command;             // 命令字
    uint8_t data[64];            // 数据
    uint16_t crc;                // CRC校验
} custom_protocol_frame_t;

// 协议状态机
typedef enum {
    PROTOCOL_STATE_IDLE,
    PROTOCOL_STATE_HEADER1,
    PROTOCOL_STATE_HEADER2,
    PROTOCOL_STATE_LENGTH,
    PROTOCOL_STATE_COMMAND,
    PROTOCOL_STATE_DATA,
    PROTOCOL_STATE_CRC_LOW,
    PROTOCOL_STATE_CRC_HIGH
} protocol_state_t;

// 协议处理器
typedef struct {
    protocol_state_t state;
    custom_protocol_frame_t rx_frame;
    uint32_t rx_index;
    uint32_t expected_length;
    uint16_t calculated_crc;
    protocol_callback_t frame_callback;
} protocol_handler_t;

void protocol_process_byte(protocol_handler_t *handler, uint8_t byte) {
    switch (handler->state) {
        case PROTOCOL_STATE_IDLE:
            if (byte == 0xAA) {
                handler->state = PROTOCOL_STATE_HEADER1;
                handler->rx_frame.header[0] = byte;
            }
            break;
            
        case PROTOCOL_STATE_HEADER1:
            if (byte == 0x55) {
                handler->state = PROTOCOL_STATE_HEADER2;
                handler->rx_frame.header[1] = byte;
            } else {
                handler->state = PROTOCOL_STATE_IDLE;
            }
            break;
            
        case PROTOCOL_STATE_HEADER2:
            handler->rx_frame.length = byte;
            handler->expected_length = byte;
            handler->state = PROTOCOL_STATE_LENGTH;
            break;
            
        case PROTOCOL_STATE_LENGTH:
            handler->rx_frame.command = byte;
            handler->rx_index = 0;
            if (handler->expected_length > 0) {
                handler->state = PROTOCOL_STATE_DATA;
            } else {
                handler->state = PROTOCOL_STATE_CRC_LOW;
            }
            break;
            
        case PROTOCOL_STATE_DATA:
            handler->rx_frame.data[handler->rx_index++] = byte;
            if (handler->rx_index >= handler->expected_length) {
                handler->state = PROTOCOL_STATE_CRC_LOW;
            }
            break;
            
        case PROTOCOL_STATE_CRC_LOW:
            handler->rx_frame.crc = byte;
            handler->state = PROTOCOL_STATE_CRC_HIGH;
            break;
            
        case PROTOCOL_STATE_CRC_HIGH:
            handler->rx_frame.crc |= (byte << 8);
            
            // 验证CRC
            handler->calculated_crc = calculate_frame_crc(&handler->rx_frame);
            if (handler->calculated_crc == handler->rx_frame.crc) {
                // 帧接收完成,调用回调
                if (handler->frame_callback) {
                    handler->frame_callback(&handler->rx_frame);
                }
            }
            
            handler->state = PROTOCOL_STATE_IDLE;
            break;
    }
}

// 发送协议帧
protocol_status_t protocol_send_frame(UART_Type *uart, uint8_t command,
                                     const uint8_t *data, uint8_t length) {
    custom_protocol_frame_t frame;
    
    // 构建帧
    frame.header[0] = 0xAA;
    frame.header[1] = 0x55;
    frame.length = length;
    frame.command = command;
    
    if (length > 0 && data != NULL) {
        memcpy(frame.data, data, length);
    }
    
    // 计算CRC
    frame.crc = calculate_frame_crc(&frame);
    
    // 发送帧
    uint8_t *frame_bytes = (uint8_t*)&frame;
    uint32_t frame_size = 4 + length + 2;  // 头+长度+命令+数据+CRC
    
    return uart_send_data(uart, frame_bytes, frame_size);
}

// CRC计算
uint16_t calculate_frame_crc(custom_protocol_frame_t *frame) {
    uint16_t crc = 0xFFFF;
    uint8_t *data = (uint8_t*)frame;
    uint32_t length = 4 + frame->length;  // 不包括CRC字段
    
    for (uint32_t i = 0; i < length; i++) {
        crc ^= data[i];
        for (int j = 0; j < 8; j++) {
            if (crc & 0x0001) {
                crc = (crc >> 1) ^ 0xA001;
            } else {
                crc >>= 1;
            }
        }
    }
    
    return crc;
}

通信性能优化

缓冲区管理

// 环形缓冲区实现
typedef struct {
    uint8_t *buffer;
    uint32_t size;
    volatile uint32_t head;
    volatile uint32_t tail;
    volatile uint32_t count;
} ring_buffer_t;

void ring_buffer_init(ring_buffer_t *rb, uint8_t *buffer, uint32_t size) {
    rb->buffer = buffer;
    rb->size = size;
    rb->head = 0;
    rb->tail = 0;
    rb->count = 0;
}

bool ring_buffer_put(ring_buffer_t *rb, uint8_t data) {
    if (rb->count >= rb->size) {
        return false;  // 缓冲区满
    }
    
    rb->buffer[rb->head] = data;
    rb->head = (rb->head + 1) % rb->size;
    rb->count++;
    
    return true;
}

bool ring_buffer_get(ring_buffer_t *rb, uint8_t *data) {
    if (rb->count == 0) {
        return false;  // 缓冲区空
    }
    
    *data = rb->buffer[rb->tail];
    rb->tail = (rb->tail + 1) % rb->size;
    rb->count--;
    
    return true;
}

uint32_t ring_buffer_available(ring_buffer_t *rb) {
    return rb->count;
}

uint32_t ring_buffer_free_space(ring_buffer_t *rb) {
    return rb->size - rb->count;
}

通信错误处理

// 错误处理系统
typedef struct {
    uint32_t uart_errors[4];
    uint32_t spi_errors[3];
    uint32_t i2c_errors[2];
    uint32_t lin_errors;
    uint32_t total_errors;
    
    // 错误恢复策略
    bool auto_recovery_enabled;
    uint32_t max_retry_count;
    uint32_t recovery_delay_ms;
} comm_error_handler_t;

void handle_uart_error(UART_Type *uart, uint32_t error_flags) {
    comm_error_handler_t *error_handler = get_error_handler();
    uint32_t uart_index = get_uart_index(uart);
    
    error_handler->uart_errors[uart_index]++;
    error_handler->total_errors++;
    
    if (error_flags & UART_ISR_ORE) {
        // 溢出错误
        uart->ICR |= UART_ICR_ORECF;
        
        // 清空接收FIFO
        while (uart->ISR & UART_ISR_RXNE) {
            (void)uart->RDR;
        }
    }
    
    if (error_flags & UART_ISR_FE) {
        // 帧错误
        uart->ICR |= UART_ICR_FECF;
    }
    
    if (error_flags & UART_ISR_PE) {
        // 校验错误
        uart->ICR |= UART_ICR_PECF;
    }
    
    if (error_flags & UART_ISR_NE) {
        // 噪声错误
        uart->ICR |= UART_ICR_NECF;
    }
    
    // 自动恢复
    if (error_handler->auto_recovery_enabled) {
        schedule_uart_recovery(uart);
    }
}

void handle_spi_error(SPI_TypeDef *spi, uint32_t error_flags) {
    comm_error_handler_t *error_handler = get_error_handler();
    uint32_t spi_index = get_spi_index(spi);
    
    error_handler->spi_errors[spi_index]++;
    error_handler->total_errors++;
    
    if (error_flags & SPI_SR_OVR) {
        // 溢出错误
        (void)spi->DR;  // 读取数据寄存器
        (void)spi->SR;  // 读取状态寄存器
    }
    
    if (error_flags & SPI_SR_MODF) {
        // 模式故障
        spi->CR1 &= ~SPI_CR1_SPE;  // 禁用SPI
        spi->CR1 |= SPI_CR1_SPE;   // 重新使能SPI
    }
    
    // 重置SPI
    if (error_handler->auto_recovery_enabled) {
        schedule_spi_recovery(spi);
    }
}

void handle_i2c_error(I2C_TypeDef *i2c, uint32_t error_flags) {
    comm_error_handler_t *error_handler = get_error_handler();
    uint32_t i2c_index = get_i2c_index(i2c);
    
    error_handler->i2c_errors[i2c_index]++;
    error_handler->total_errors++;
    
    if (error_flags & I2C_SR1_BERR) {
        // 总线错误
        i2c->SR1 &= ~I2C_SR1_BERR;
    }
    
    if (error_flags & I2C_SR1_ARLO) {
        // 仲裁丢失
        i2c->SR1 &= ~I2C_SR1_ARLO;
    }
    
    if (error_flags & I2C_SR1_AF) {
        // 应答失败
        i2c->SR1 &= ~I2C_SR1_AF;
        i2c->CR1 |= I2C_CR1_STOP;  // 产生停止条件
    }
    
    if (error_flags & I2C_SR1_OVR) {
        // 溢出/欠载
        i2c->SR1 &= ~I2C_SR1_OVR;
    }
    
    // 总线恢复
    if (error_handler->auto_recovery_enabled) {
        schedule_i2c_recovery(i2c);
    }
}

应用实例

汽车传感器网络

// 汽车传感器网络系统
typedef struct {
    // 通信接口
    struct {
        UART_Type *debug_uart;       // 调试串口
        UART_Type *lin_uart;         // LIN总线
        SPI_TypeDef *sensor_spi;     // 传感器SPI
        I2C_TypeDef *eeprom_i2c;     // EEPROM I2C
    } interfaces;
    
    // 传感器数据
    struct {
        float wheel_speed[4];        // 车轮转速
        float engine_rpm;            // 发动机转速
        float coolant_temp;          // 冷却液温度
        float oil_pressure;          // 机油压力
        bool door_status[4];         // 车门状态
        bool light_status[8];        // 灯光状态
    } sensor_data;
    
    // 通信状态
    struct {
        bool lin_online;
        bool spi_sensors_online;
        bool eeprom_accessible;
        uint32_t communication_errors;
    } status;
    
} automotive_comm_system_t;

void automotive_comm_init(automotive_comm_system_t *system) {
    // 初始化调试串口
    uart_config_t debug_config = {
        .baudrate = 115200,
        .data_bits = 8,
        .stop_bits = UART_STOPBITS_1,
        .parity = UART_PARITY_NONE,
        .flow_control = false,
        .dma_tx_enable = true,
        .dma_rx_enable = false,
        .tx_fifo_threshold = 8,
        .rx_fifo_threshold = 1
    };
    uart_init(system->interfaces.debug_uart, &debug_config);
    
    // 初始化LIN总线
    lin_config_t lin_config = {
        .baudrate = 19200,
        .break_length = LIN_BREAK_13BITS,
        .node_type = LIN_NODE_SLAVE,
        .checksum_enhanced = true,
        .auto_baudrate = false,
        .frame_callback = lin_frame_handler
    };
    lin_init(system->interfaces.lin_uart, &lin_config);
    
    // 初始化传感器SPI
    spi_config_t spi_config = {
        .mode = SPI_MODE_MASTER,
        .data_size = 8,
        .clock_polarity = SPI_POLARITY_LOW,
        .clock_phase = SPI_PHASE_1EDGE,
        .nss_mode = SPI_NSS_SOFT,
        .baudrate_prescaler = SPI_BAUDRATEPRESCALER_16,
        .first_bit = SPI_FIRSTBIT_MSB,
        .crc_enable = false
    };
    spi_init(system->interfaces.sensor_spi, &spi_config);
    
    // 初始化EEPROM I2C
    i2c_config_t i2c_config = {
        .clock_speed = 400000,
        .duty_cycle = I2C_DUTYCYCLE_2,
        .own_address1 = 0x00,
        .address_mode = I2C_ADDRESSINGMODE_7BIT,
        .dual_address_mode = I2C_DUALADDRESS_DISABLE,
        .general_call_mode = I2C_GENERALCALL_DISABLE,
        .no_stretch_mode = I2C_NOSTRETCH_DISABLE
    };
    i2c_init(system->interfaces.eeprom_i2c, &i2c_config);
    
    // 初始化传感器数据
    memset(&system->sensor_data, 0, sizeof(system->sensor_data));
    
    // 初始化状态
    system->status.lin_online = false;
    system->status.spi_sensors_online = false;
    system->status.eeprom_accessible = false;
    system->status.communication_errors = 0;
}

// 传感器数据采集任务
void sensor_data_task(void *param) {
    automotive_comm_system_t *system = (automotive_comm_system_t*)param;
    
    while (1) {
        // 读取SPI传感器
        if (read_spi_sensors(system)) {
            system->status.spi_sensors_online = true;
        } else {
            system->status.spi_sensors_online = false;
            system->status.communication_errors++;
        }
        
        // 处理LIN通信
        process_lin_communication(system);
        
        // 保存数据到EEPROM
        if (should_save_data()) {
            save_sensor_data_to_eeprom(system);
        }
        
        // 发送调试信息
        send_debug_info(system);
        
        vTaskDelay(pdMS_TO_TICKS(100));  // 100ms周期
    }
}

// 读取SPI传感器
bool read_spi_sensors(automotive_comm_system_t *system) {
    uint8_t tx_data[4] = {0x80, 0x00, 0x00, 0x00};  // 读命令
    uint8_t rx_data[4];
    
    // 读取车轮转速传感器
    for (int i = 0; i < 4; i++) {
        if (spi_transmit_receive(system->interfaces.sensor_spi, 
                               tx_data, rx_data, 4) == SPI_STATUS_OK) {
            uint16_t raw_speed = (rx_data[1] << 8) | rx_data[2];
            system->sensor_data.wheel_speed[i] = raw_speed * 0.1;  // 转换为实际值
        } else {
            return false;
        }
        
        delay_ms(1);  // 传感器间延时
    }
    
    return true;
}

// LIN帧处理
void lin_frame_handler(lin_frame_t *frame) {
    automotive_comm_system_t *system = get_automotive_system();
    
    switch (frame->id) {
        case 0x01:  // 车门状态
            for (int i = 0; i < 4; i++) {
                system->sensor_data.door_status[i] = (frame->data[0] >> i) & 0x01;
            }
            break;
            
        case 0x02:  // 灯光状态
            for (int i = 0; i < 8; i++) {
                system->sensor_data.light_status[i] = (frame->data[0] >> i) & 0x01;
            }
            break;
            
        case 0x03:  // 发动机数据
            system->sensor_data.engine_rpm = (frame->data[0] << 8) | frame->data[1];
            system->sensor_data.coolant_temp = frame->data[2] - 40;  // 偏移40度
            system->sensor_data.oil_pressure = frame->data[3] * 0.1;
            break;
            
        default:
            break;
    }
    
    system->status.lin_online = true;
}

// 保存数据到EEPROM
void save_sensor_data_to_eeprom(automotive_comm_system_t *system) {
    uint8_t data_buffer[64];
    uint32_t data_size = 0;
    
    // 序列化传感器数据
    memcpy(&data_buffer[data_size], &system->sensor_data.wheel_speed, 
           sizeof(system->sensor_data.wheel_speed));
    data_size += sizeof(system->sensor_data.wheel_speed);
    
    memcpy(&data_buffer[data_size], &system->sensor_data.engine_rpm, 
           sizeof(system->sensor_data.engine_rpm));
    data_size += sizeof(system->sensor_data.engine_rpm);
    
    // 写入EEPROM
    if (i2c_master_transmit(system->interfaces.eeprom_i2c, 0xA0, 
                           data_buffer, data_size) == I2C_STATUS_OK) {
        system->status.eeprom_accessible = true;
    } else {
        system->status.eeprom_accessible = false;
        system->status.communication_errors++;
    }
}

// 发送调试信息
void send_debug_info(automotive_comm_system_t *system) {
    char debug_msg[256];
    
    snprintf(debug_msg, sizeof(debug_msg),
             "Wheel Speed: %.1f %.1f %.1f %.1f RPM: %.0f Temp: %.1f\r\n",
             system->sensor_data.wheel_speed[0],
             system->sensor_data.wheel_speed[1],
             system->sensor_data.wheel_speed[2],
             system->sensor_data.wheel_speed[3],
             system->sensor_data.engine_rpm,
             system->sensor_data.coolant_temp);
    
    uart_send_data(system->interfaces.debug_uart, 
                   (uint8_t*)debug_msg, strlen(debug_msg));
}

总结

YTM32B1ME0x的通信接口系统为汽车电子应用提供了完整的串行通信解决方案。通过合理配置UART、SPI、I2C和LIN接口,可以实现与各种外设和网络的可靠通信。

关键特性总结:

  1. 丰富的接口资源: 4个UART、3个SPI、2个I2C,满足多样化通信需求

  2. 高性能传输: 支持DMA传输,减少CPU负载

  3. 灵活的配置: 多种工作模式、波特率、数据格式可配置

  4. 强大的错误处理: 完善的错误检测和恢复机制

  5. 汽车级可靠性: 支持LIN协议,适合汽车网络应用

  6. 协议栈支持: 可实现自定义协议和标准协议

CAN通信系统

CAN控制器特性

YTM32B1ME0x集成了符合CAN 2.0B标准的CAN控制器:

技术规格:

  • 协议支持: CAN 2.0A/2.0B

  • 波特率: 最高1Mbps

  • 消息缓冲区: 32个邮箱

  • 标识符: 11位标准/29位扩展

  • 过滤器: 28个过滤器组

  • FIFO深度: 3级接收FIFO

  • 时间戳: 16位时间戳计数器

CAN配置与初始化

// CAN配置结构
typedef struct {
    uint32_t mode;               // 工作模式
    uint32_t sjw;                // 同步跳转宽度
    uint32_t bs1;                // 时间段1
    uint32_t bs2;                // 时间段2
    uint32_t prescaler;          // 预分频器
    bool ttcm;                   // 时间触发通信模式
    bool abom;                   // 自动离线管理
    bool awum;                   // 自动唤醒模式
    bool nart;                   // 非自动重传
    bool rflm;                   // 接收FIFO锁定模式
    bool txfp;                   // 发送FIFO优先级
} can_config_t;

// CAN消息结构
typedef struct {
    uint32_t id;                 // 标识符
    uint8_t ide;                 // 标识符扩展位
    uint8_t rtr;                 // 远程传输请求
    uint8_t dlc;                 // 数据长度
    uint8_t data[8];             // 数据
    uint32_t timestamp;          // 时间戳
} can_message_t;

// CAN初始化
void can_init(CAN_TypeDef *can, can_config_t *config) {
    // 使能CAN时钟
    if (can == CAN1) {
        RCC->APB1ENR |= RCC_APB1ENR_CAN1EN;
    } else if (can == CAN2) {
        RCC->APB1ENR |= RCC_APB1ENR_CAN2EN;
    }
    
    // 进入初始化模式
    can->MCR |= CAN_MCR_INRQ;
    while (!(can->MSR & CAN_MSR_INAK));
    
    // 配置主控制寄存器
    can->MCR = CAN_MCR_INRQ;  // 保持初始化请求
    
    if (config->ttcm) can->MCR |= CAN_MCR_TTCM;
    if (config->abom) can->MCR |= CAN_MCR_ABOM;
    if (config->awum) can->MCR |= CAN_MCR_AWUM;
    if (config->nart) can->MCR |= CAN_MCR_NART;
    if (config->rflm) can->MCR |= CAN_MCR_RFLM;
    if (config->txfp) can->MCR |= CAN_MCR_TXFP;
    
    // 配置位时序寄存器
    can->BTR = (config->mode << 30) |
               ((config->sjw - 1) << 24) |
               ((config->bs1 - 1) << 16) |
               ((config->bs2 - 1) << 20) |
               (config->prescaler - 1);
    
    // 退出初始化模式
    can->MCR &= ~CAN_MCR_INRQ;
    while (can->MSR & CAN_MSR_INAK);
    
    // 配置中断
    can->IER = CAN_IER_FMPIE0 |   // FIFO0消息挂起中断
               CAN_IER_FMPIE1 |   // FIFO1消息挂起中断
               CAN_IER_TMEIE |    // 发送邮箱空中断
               CAN_IER_ERRIE;     // 错误中断
    
    NVIC_EnableIRQ(get_can_rx_irq(can));
    NVIC_EnableIRQ(get_can_tx_irq(can));
    NVIC_EnableIRQ(get_can_sce_irq(can));
}

// CAN消息发送
can_status_t can_transmit(CAN_TypeDef *can, can_message_t *message) {
    uint32_t transmit_mailbox;
    
    // 查找空的发送邮箱
    if (can->TSR & CAN_TSR_TME0) {
        transmit_mailbox = 0;
    } else if (can->TSR & CAN_TSR_TME1) {
        transmit_mailbox = 1;
    } else if (can->TSR & CAN_TSR_TME2) {
        transmit_mailbox = 2;
    } else {
        return CAN_STATUS_NO_MAILBOX;
    }
    
    // 配置标识符
    if (message->ide == CAN_ID_STD) {
        can->sTxMailBox[transmit_mailbox].TIR = (message->id << 21) |
                                               (message->rtr << 1);
    } else {
        can->sTxMailBox[transmit_mailbox].TIR = (message->id << 3) |
                                               CAN_TI0R_IDE |
                                               (message->rtr << 1);
    }
    
    // 配置数据长度
    can->sTxMailBox[transmit_mailbox].TDTR = message->dlc;
    
    // 配置数据
    can->sTxMailBox[transmit_mailbox].TDLR = (message->data[3] << 24) |
                                            (message->data[2] << 16) |
                                            (message->data[1] << 8) |
                                            message->data[0];
    
    can->sTxMailBox[transmit_mailbox].TDHR = (message->data[7] << 24) |
                                            (message->data[6] << 16) |
                                            (message->data[5] << 8) |
                                            message->data[4];
    
    // 请求发送
    can->sTxMailBox[transmit_mailbox].TIR |= CAN_TI0R_TXRQ;
    
    return CAN_STATUS_OK;
}

// CAN消息接收
can_status_t can_receive(CAN_TypeDef *can, uint32_t fifo, can_message_t *message) {
    // 检查FIFO是否有消息
    if ((fifo == CAN_FIFO0 && !(can->RF0R & CAN_RF0R_FMP0)) ||
        (fifo == CAN_FIFO1 && !(can->RF1R & CAN_RF1R_FMP1))) {
        return CAN_STATUS_NO_MESSAGE;
    }
    
    // 读取标识符
    uint32_t tir = can->sFIFOMailBox[fifo].RIR;
    if (tir & CAN_RI0R_IDE) {
        message->ide = CAN_ID_EXT;
        message->id = tir >> 3;
    } else {
        message->ide = CAN_ID_STD;
        message->id = tir >> 21;
    }
    
    message->rtr = (tir & CAN_RI0R_RTR) ? CAN_RTR_REMOTE : CAN_RTR_DATA;
    
    // 读取数据长度
    message->dlc = can->sFIFOMailBox[fifo].RDTR & 0x0F;
    
    // 读取时间戳
    message->timestamp = (can->sFIFOMailBox[fifo].RDTR >> 16) & 0xFFFF;
    
    // 读取数据
    uint32_t rdlr = can->sFIFOMailBox[fifo].RDLR;
    uint32_t rdhr = can->sFIFOMailBox[fifo].RDHR;
    
    message->data[0] = rdlr & 0xFF;
    message->data[1] = (rdlr >> 8) & 0xFF;
    message->data[2] = (rdlr >> 16) & 0xFF;
    message->data[3] = (rdlr >> 24) & 0xFF;
    message->data[4] = rdhr & 0xFF;
    message->data[5] = (rdhr >> 8) & 0xFF;
    message->data[6] = (rdhr >> 16) & 0xFF;
    message->data[7] = (rdhr >> 24) & 0xFF;
    
    // 释放FIFO
    if (fifo == CAN_FIFO0) {
        can->RF0R |= CAN_RF0R_RFOM0;
    } else {
        can->RF1R |= CAN_RF1R_RFOM1;
    }
    
    return CAN_STATUS_OK;
}

汽车网关应用实例

// 汽车网关系统
typedef struct {
    CAN_TypeDef *powertrain_can;     // 动力总成CAN
    CAN_TypeDef *body_can;           // 车身CAN
    UART_Type *diagnostic_uart;      // 诊断UART
    
    // 路由表
    can_route_entry_t route_table[MAX_ROUTE_ENTRIES];
    uint32_t route_count;
    
    // 统计信息
    gateway_statistics_t statistics;
} automotive_gateway_t;

// CAN路由条目
typedef struct {
    uint32_t source_id;          // 源CAN ID
    CAN_TypeDef *source_can;     // 源CAN总线
    uint32_t dest_id;            // 目标CAN ID
    CAN_TypeDef *dest_can;       // 目标CAN总线
    bool enable;                 // 路由使能
    uint32_t filter_mask;        // 过滤掩码
} can_route_entry_t;

// 网关初始化
void automotive_gateway_init(automotive_gateway_t *gateway) {
    // 初始化动力总成CAN (500kbps)
    can_config_t powertrain_config = {
        .mode = CAN_MODE_NORMAL,
        .sjw = 1,
        .bs1 = 6,
        .bs2 = 1,
        .prescaler = 10,  // 500kbps @ 40MHz
        .ttcm = false,
        .abom = true,
        .awum = false,
        .nart = false,
        .rflm = false,
        .txfp = false
    };
    can_init(gateway->powertrain_can, &powertrain_config);
    
    // 初始化车身CAN (125kbps)
    can_config_t body_config = powertrain_config;
    body_config.prescaler = 40;  // 125kbps @ 40MHz
    can_init(gateway->body_can, &body_config);
    
    // 配置路由表
    configure_routing_table(gateway);
    
    // 启动网关任务
    start_gateway_tasks(gateway);
}

// CAN消息路由处理
void process_can_routing(automotive_gateway_t *gateway, can_message_t *message,
                        CAN_TypeDef *source_can) {
    // 查找路由条目
    for (uint32_t i = 0; i < gateway->route_count; i++) {
        can_route_entry_t *entry = &gateway->route_table[i];
        
        if (entry->enable && entry->source_can == source_can) {
            // 检查ID匹配
            if ((message->id & entry->filter_mask) == 
                (entry->source_id & entry->filter_mask)) {
                
                // 创建路由消息
                can_message_t routed_message = *message;
                routed_message.id = entry->dest_id;
                
                // 发送到目标总线
                if (can_transmit(entry->dest_can, &routed_message) == CAN_STATUS_OK) {
                    gateway->statistics.messages_routed++;
                } else {
                    gateway->statistics.routing_errors++;
                }
                
                break;  // 找到匹配的路由条目,退出循环
            }
        }
    }
}

性能优化与调试

通信性能监控

// 通信性能监控
typedef struct {
    uint32_t uart_tx_count;      // UART发送计数
    uint32_t uart_rx_count;      // UART接收计数
    uint32_t can_tx_count;       // CAN发送计数
    uint32_t can_rx_count;       // CAN接收计数
    uint32_t can_error_count;    // CAN错误计数
    float can_bus_load;          // CAN总线负载
} comm_performance_t;

void monitor_communication_performance(void) {
    static comm_performance_t perf;
    static uint32_t last_update = 0;
    uint32_t current_time = get_system_time();
    
    if (current_time - last_update >= 1000) {  // 每秒更新
        // 计算CAN总线负载
        perf.can_bus_load = calculate_can_bus_load();
        
        // 输出性能信息
        printf("Communication Performance:\n");
        printf("  UART: TX=%lu, RX=%lu\n", perf.uart_tx_count, perf.uart_rx_count);
        printf("  CAN: TX=%lu, RX=%lu, Errors=%lu, Bus Load=%.1f%%\n",
               perf.can_tx_count, perf.can_rx_count, perf.can_error_count,
               perf.can_bus_load);
        
        // 重置计数器
        memset(&perf, 0, sizeof(comm_performance_t));
        last_update = current_time;
    }
}

总结

YTM32B1ME0x的通信接口系统为汽车电子应用提供了全面的连接解决方案。通过合理配置UART、SPI、I2C、LIN和CAN接口,可以实现高效可靠的数据通信。

关键特性总结:

  1. 丰富的接口类型: UART、SPI、I2C、LIN、CAN多种通信方式

  2. 高性能传输: 支持DMA、FIFO缓冲、中断处理

  3. 汽车级可靠性: 错误检测、故障恢复、总线监控

  4. 系统集成: 网关路由、多总线协调、性能监控

  5. 协议栈支持: 支持各种汽车通信协议

在下一篇文章中,我们将深入探讨YTM32B1ME0x的安全特性与功能安全,包括硬件安全模块、内存保护、故障检测等关键安全功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值