Files
STM8_Mesh_Control/src/drivers/uart1.c
T

119 lines
3.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* @file uart1.c
* @brief UART1 第一阶段占位实现。
*/
#include <stdint.h>
#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();
}