119 lines
3.5 KiB
C
119 lines
3.5 KiB
C
/**
|
||
* @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();
|
||
}
|