/** * @file uart1.c * @brief UART1 第一阶段占位实现。 */ #include #include "uart1.h" #include "stm8s003_registers.h" /** UART1 接收环形缓冲区容量,必须使用 2 的幂便于快速回绕。 */ #define UART1_RX_BUFFER_SIZE 64u /** UART1 接收环形缓存,保存尚未交给协议层处理的原始字节。 */ static volatile uint8_t rx_buffer[UART1_RX_BUFFER_SIZE]; /** 环形缓存写入位置,由 UART 接收任务推进。 */ static volatile uint8_t rx_write_index; /** 环形缓存读取位置,由上层协议任务推进。 */ static volatile uint8_t rx_read_index; /** * 将一个字节写入接收环形缓冲区。 * * 该函数只由 UART1 接收中断调用。缓冲区满时丢弃新字节,绝不覆盖尚未 * 被主循环读取的数据,避免破坏正在解析的 Mesh 帧。 */ static void Uart1_RxPush(uint8_t value) { uint8_t next_index = (uint8_t)((rx_write_index + 1u) & (UART1_RX_BUFFER_SIZE - 1u)); if (next_index != rx_read_index) { rx_buffer[rx_write_index] = value; rx_write_index = next_index; } } /** 初始化 UART1,并开启 UART1 接收寄存器非空中断。 */ void Uart1_Init(void) { /* 先关闭 UART,再配置 9600 baud@16 MHz:BRR=0x0683。 */ REG8(UART1_CR2_ADDR) = 0x00u; REG8(UART1_BRR2_ADDR) = 0x03u; REG8(UART1_BRR1_ADDR) = 0x68u; REG8(UART1_CR1_ADDR) = 0x00u; REG8(UART1_CR3_ADDR) = 0x00u; rx_write_index = 0u; rx_read_index = 0u; /* RE=1、TE=1、RIEN=1:接收数据由UART1中断保存到环形缓冲区。 */ REG8(UART1_CR2_ADDR) = 0x2Cu; } /** * UART1接收任务入口。 * * 接收字节已经由 UART1 接收中断写入环形缓冲区,因此主循环不再轮询UART * 硬件寄存器。保留该接口是为了维持主循环结构和后续扩展接口兼容性。 */ void Uart1_Task(void) { /* UART硬件接收由Uart1_InterruptHandler()完成,此处无需执行任何操作。 */ } /** 发送一个字节;当前阶段不连接真实 UART 寄存器。 */ void Uart1_WriteByte(uint8_t value) { while ((REG8(UART1_SR_ADDR) & 0x80u) == 0u) { } REG8(UART1_DR_ADDR) = value; } /** 从接收环形缓冲区读取一个字节;当前阶段始终表示无数据。 */ uint8_t Uart1_ReadByte(uint8_t *value) { if ((value == (uint8_t *)0) || (rx_read_index == rx_write_index)) { return 0u; } *value = rx_buffer[rx_read_index]; rx_read_index = (uint8_t)((rx_read_index + 1u) & (UART1_RX_BUFFER_SIZE - 1u)); return 1u; } /** 返回接收缓冲区当前字节数,供协议层判断是否需要继续读取。 */ uint8_t Uart1_Available(void) { return (uint8_t)((rx_write_index - rx_read_index) & (UART1_RX_BUFFER_SIZE - 1u)); } /** * UART1接收中断处理函数。 * * STM8S003F3 UART1接收中断向量为19。中断中只读取状态和数据寄存器, * 将无错误字节快速放入环形缓冲区;协议解析、CRC和业务控制全部放在主循环。 */ void Uart1_InterruptHandler(void) { uint8_t status = REG8(UART1_SR_ADDR); uint8_t value; if ((status & 0x0Fu) != 0u) { /* STM8 UART错误标志需要先读SR再读DR清除;错误字节不送入协议层。 */ value = REG8(UART1_DR_ADDR); (void)value; } else if ((status & 0x20u) != 0u) { value = REG8(UART1_DR_ADDR); Uart1_RxPush(value); } } /** UART1接收寄存器非空中断向量,IRQ号19。 */ void Uart1_RX_IRQHandler(void) __interrupt(19) { Uart1_InterruptHandler(); }