引言
在现代汽车电子系统中,各种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的安全特性与功能安全,包括硬件安全模块、内存保护、故障检测等关键安全功能。
656

被折叠的 条评论
为什么被折叠?



