引言
在现代汽车电子系统中,各种ECU(电子控制单元)、传感器、执行器之间需要进行大量的数据交换。YTM32B1ME0x提供了丰富的串行通信接口,包括UART、SPI、I2C等,满足不同应用场景的通信需求。这些接口不仅支持标准协议,还针对汽车应用进行了优化,具备高可靠性、低功耗和强抗干扰能力。
通信接口系统概览
接口配置总览
YTM32B1ME0x集成了多种串行通信接口:
接口类型 | 数量 | 主要特性 | 典型应用 |
---|---|---|---|
UART | 4个 | 异步串行,支持LIN | 调试、传感器通信 |
SPI | 3个 | 同步串行,主从模式 | Flash、显示屏 |
I2C | 2个 | 两线制,多主机 | EEPROM、传感器 |
LIN | 1个 | 汽车网络,单线 | 车身控制 |
通信接口架构
┌─────────────────────────────────────┐ │ 通信接口控制器 │ │ 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接口,可以实现与各种外设和网络的可靠通信。
关键特性总结:
-
丰富的接口资源: 4个UART、3个SPI、2个I2C,满足多样化通信需求
-
高性能传输: 支持DMA传输,减少CPU负载
-
灵活的配置: 多种工作模式、波特率、数据格式可配置
-
强大的错误处理: 完善的错误检测和恢复机制
-
汽车级可靠性: 支持LIN协议,适合汽车网络应用
-
协议栈支持: 可实现自定义协议和标准协议
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接口,可以实现高效可靠的数据通信。
关键特性总结:
-
丰富的接口类型: UART、SPI、I2C、LIN、CAN多种通信方式
-
高性能传输: 支持DMA、FIFO缓冲、中断处理
-
汽车级可靠性: 错误检测、故障恢复、总线监控
-
系统集成: 网关路由、多总线协调、性能监控
-
协议栈支持: 支持各种汽车通信协议
在下一篇文章中,我们将深入探讨YTM32B1ME0x的安全特性与功能安全,包括硬件安全模块、内存保护、故障检测等关键安全功能。