9. UART LIN
9.1. 概述
UART LIN 组件提供了基于 UART 外设实现 LIN 协议的功能。该组件支持:
主从模式通信
增强型校验和模式
支持轮询和中断两种传输方式
9.2. 功能特性
主机模式功能
发送/接收 LIN 帧
发送唤醒信号
支持同步间隔控制
支持增强型校验和
支持最大 8 字节数据传输
从机模式功能
响应主机请求
自动校验帧头格式
支持增强型校验和
支持最大 8 字节数据传输
传输模式
支持轮询方式传输
支持中断方式传输
支持 FIFO 触发等级配置
9.3. 数据结构
9.3.1. 主要结构体
uart_lin_master_config_t
主机配置结构体,包含以下字段:
ptr: UART 外设基地址id: LIN 帧 ID(6 位)data: LIN 数据配置(uart_lin_data_t 类型)pin_ctrl: 引脚控制配置(uart_lin_master_pin_ctrl_t 类型)
uart_lin_master_pin_ctrl_t
主机引脚控制结构体,包含以下字段:
ptr: GPIO 外设基地址baudrate: LIN 波特率config_uart_pin: UART 引脚配置函数config_uart_pin_as_gpio: UART 引脚配置为 GPIO 函数delay_us: 微秒延时函数tx_port: 发送引脚端口号tx_pin: 发送引脚编号
uart_lin_slave_config_t
从机配置结构体,包含以下字段:
ptr: UART 外设基地址pid: LIN 帧受保护 ID(8 位)data: LIN 数据配置(uart_lin_data_t 类型)
uart_lin_data_t
数据传输配置结构体,包含以下字段:
buff: 数据缓冲区指针length: 数据长度(最大 8 字节)enhance_checksum: 是否使用增强型校验和
9.4. API 说明
9.4.1. 主机模式 API
轮询传输接口(阻塞式)
hpm_uart_lin_master_send_frame: 发送完整的 LIN 帧 * 功能:发送同步间隔、同步字段、PID、数据和校验和 * 阻塞等待发送完成 * 适用场景:简单的数据发送,不需要中断处理hpm_uart_lin_master_receive_frame: 接收完整的 LIN 帧 * 功能:发送帧头并接收数据和校验和 * 阻塞等待接收完成 * 适用场景:简单的数据接收,不需要中断处理
非阻塞式传输接口
hpm_uart_lin_master_send_head: 发送帧头 * 功能:发送同步间隔、同步字段和 PID * 将数据写入FIFO后即返回hpm_uart_lin_master_send_data: 发送数据和校验和 * 功能:将数据和校验和写入 UART FIFO * 将数据写入FIFO后即返回 * 适用场景:需要在中断中处理发送完成事件hpm_uart_lin_master_receive_data: 接收并校验数据 * 功能:从 UART FIFO 读取数据并校验 * 适用场景:当RX FIFO接收完数据后,触发中断,在中断中调用该接口从FIFO中读取数据并校验
其他功能接口
hpm_uart_lin_send_wakeup: 发送唤醒信号(阻塞式)hpm_uart_lin_calculate_protected_id: 计算受保护的 ID
9.4.2. 从机模式 API
数据传输接口(非阻塞式)
hpm_uart_lin_slave_send_data: 发送数据和校验和 * 功能:将数据和校验和写入 UART FIFO * 需要配合 UART TX FIFO 中断使用 * 适用场景:在检测到主机请求后发送数据hpm_uart_lin_slave_receive_data: 接收并校验数据 * 功能:从 UART FIFO 读取数据并校验 * 需要配合 UART RX 超时中断使用 * 适用场景:在接收到主机数据后进行处理
9.5. 使用示例
9.5.1. 主机模式示例
轮询方式示例
/* 配置 UART LIN 主机 */
uart_lin_master_config_t uart_lin_config = {
.ptr = TEST_UART,
.pin_ctrl = {
.ptr = HPM_GPIO0,
.baudrate = TEST_UART_LIN_BAUDRATE,
.config_uart_pin = init_uart_pins,
.config_uart_pin_as_gpio = init_uart_pin_as_gpio,
.delay_us = board_delay_us,
.tx_port = BOARD_UART_LIN_TX_PORT,
.tx_pin = BOARD_UART_LIN_TX_PIN,
},
};
/* 发送数据(阻塞式) */
uart_lin_config.id = TEST_MASTER_SEND_ID;
uart_lin_config.data.buff = send_data;
uart_lin_config.data.length = TEST_MASTER_SEND_DATA_LENGTH;
uart_lin_config.data.enhance_checksum = TEST_MASTER_SEND_ENHANCE_CHECKSUM;
hpm_uart_lin_master_send_frame(&uart_lin_config);
中断方式示例
/* 在主循环中发起传输 */
uart_lin_config.id = TEST_MASTER_SEND_ID;
uart_lin_config.data.buff = send_data;
uart_lin_config.data.length = TEST_MASTER_SEND_DATA_LENGTH;
uart_lin_config.data.enhance_checksum = TEST_MASTER_SEND_ENHANCE_CHECKSUM;
hpm_uart_lin_master_send_head(&uart_lin_config);
hpm_uart_lin_master_send_data(&uart_lin_config);
/* 在中断处理函数中 */
void uart_isr(void)
{
volatile uint8_t irq_id = uart_get_irq_id(TEST_UART);
if (irq_id == uart_intr_id_tx_slot_avail) {
uart_lin_send_complete = true;
uart_disable_irq(TEST_UART, uart_intr_tx_slot_avail);
}
if (irq_id == uart_intr_id_rx_timeout) {
if (uart_lin_success == hpm_uart_lin_master_receive_data(&uart_lin_config)) {
uart_lin_receive_complete = true;
}
uart_disable_irq(TEST_UART, uart_intr_rx_data_avail_or_timeout);
}
}
9.5.2. 从机模式示例
以下是使用中断方式接收和发送数据的示例:
/* 配置 UART LIN 从机 */
uart_lin_slave_config_t uart_lin_config = {
.ptr = TEST_UART,
};
/* 配置 UART FIFO 控制 */
uart_fifo_ctrl_t fifo_ctrl = {
.tx_fifo_level = uart_tx_fifo_trg_not_full,
.rx_fifo_level = uart_rx_fifo_trg_not_empty,
.dma_enable = false,
.fifo_enable = true,
};
/* 在中断中处理接收到的帧头 */
void uart_lin_check_head_and_respond(UART_Type *ptr, uint8_t *head_buff)
{
uint8_t pid = head_buff[1];
uint8_t id = pid & 0x3f;
/* 检查同步字段和 PID */
if (0x55 != head_buff[0] ||
pid != hpm_uart_lin_calculate_protected_id(id)) {
return;
}
switch (id) {
case TEST_SLAVE_RECEIVE_ID:
/* 配置接收参数 */
uart_lin_config.pid = pid;
uart_lin_config.data.buff = receive_data;
uart_lin_config.data.length = TEST_SLAVE_RECEIVE_DATA_LENGTH;
uart_lin_config.data.enhance_checksum = TEST_SLAVE_RECEIVE_ENHANCE_CHECKSUM;
break;
case TEST_SLAVE_SEND_ID:
/* 配置发送参数并发送数据 */
uart_lin_config.pid = pid;
uart_lin_config.data.buff = send_data;
uart_lin_config.data.length = TEST_SLAVE_SEND_DATA_LENGTH;
uart_lin_config.data.enhance_checksum = TEST_SLAVE_SEND_ENHANCE_CHECKSUM;
hpm_uart_lin_slave_send_data(&uart_lin_config);
uart_enable_irq(ptr, uart_intr_tx_slot_avail);
break;
}
}
/* 在中断处理函数中 */
void uart_isr(void)
{
volatile uint8_t irq_id = uart_get_irq_id(TEST_UART);
/* 检测到 LIN break 信号 */
if (irq_id == uart_intr_id_rx_line_stat) {
if (uart_check_status(TEST_UART, uart_stat_line_break)) {
uart_clear_rx_fifo(TEST_UART);
head_index = 0;
uart_config_fifo_ctrl(TEST_UART, &fifo_ctrl);
uart_enable_irq(TEST_UART, uart_intr_rx_data_avail_or_timeout);
}
}
/* 接收并处理帧头 */
if (irq_id == uart_intr_id_rx_data_avail) {
if (uart_check_status(TEST_UART, uart_stat_data_ready)) {
head_buff[head_index++] = uart_read_byte(TEST_UART);
}
if (head_index == 2) {
uart_lin_check_head_and_respond(TEST_UART, head_buff);
}
}
/* 发送完成处理 */
if (irq_id == uart_intr_id_tx_slot_avail) {
uart_lin_send_complete = true;
uart_disable_irq(TEST_UART, uart_intr_tx_slot_avail);
}
/* 接收完成处理 */
if (irq_id == uart_intr_id_rx_timeout) {
if (uart_lin_success == hpm_uart_lin_slave_receive_data(&uart_lin_config)) {
uart_lin_receive_complete = true;
}
uart_disable_irq(TEST_UART, uart_intr_rx_data_avail_or_timeout);
}
}