实现GD32系列单片机串口收发的环形队列

文章介绍了如何在GD32单片机中使用环形队列进行串口通信的数据缓存和发送,包括定义数据结构、初始化、写入、读取数据的步骤,并提到了线程安全问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

环形队列是一种常用的数据结构,它具有先进先出的特点,能够很好地解决数据缓存和处理的问题。在单片机的串口通信中,使用环形队列可以实现数据的缓存和发送,从而提高通信效率和稳定性。

在GD32单片机中,实现串口收发信息的环形队列步骤如下:

1. 定义环形队列数据结构

首先需要定义一个结构体,用于存储环形队列的相关属性,例如队列的大小、当前读写位置以及数据缓存区等。

typedef struct{

uint8_t *buffer; //数据缓存区

uint8_t size; //队列大小

uint8_t readPtr; //读指针

uint8_t writePtr; //写指针

}UART_RingBuffer;

2. 初始化环形队列

初始化环形队列时,需要为其分配一定的内存空间,并设定相关属性,例如队列大小、读写指针的初始值等。

void UART_RingBuffer_Init(UART_RingBuffer *rb, uint8_t *buf, uint8_t size){

rb->buffer = buf;

rb->size = size;

rb->readPtr = 0;

rb->writePtr = 0;

}

3. 向队列中写入数据

当从串口接收到数据时,需要将其写入环形队列,可以通过修改写指针的位置来实现。

void UART_RingBuffer_Write(UART_RingBuffer *rb, uint8_t data){

uint8_t nextPtr = (rb->writePtr + 1) % rb->size; //计算下一个写指针位置

if(nextPtr != rb->readPtr){

//写入数据

*(rb->buffer + rb->writePtr) = data;

rb->writePtr = nextPtr; //更新写指针位置

}

}

4. 从队列中读取数据

当需要从队列中读取数据时,可以通过修改读指针的位置来实现。

uint8_t UART_RingBuffer_Read(UART_RingBuffer *rb){

uint8_t data = 0;

if(rb->readPtr != rb->writePtr){

//读取数据

data = *(rb->buffer + rb->readPtr);

rb->readPtr = (rb->readPtr + 1) % rb->size; //更新读指针位置

}

return data;

}

5. 其他辅助函数

在实际应用中,除了读写数据之外,还可能需要其他一些辅助函数,例如查询队列是否已满或已空。

例如,下面是一个用于查询队列是否已满的函数:

bool UART_RingBuffer_IsFull(UART_RingBuffer *rb){

uint8_t nextPtr = (rb->writePtr + 1) % rb->size;

return (nextPtr == rb->readPtr);

}

最后,需要注意的是,环形队列是一个循环的数据结构,写指针和读指针都需要经过取模运算,保证其不会越界。同时,在多线程应用中,需要确保对队列的读写操作是线程安全的,否则可能会出现数据竞争的问题。

### GD32 串口通信中的奇偶校验错误中断解决方案 对于GD32微控制器,在遇到串口通信过程中出现的奇偶校验错误中断问题时,可以通过调整硬件配置以及编写相应的软件处理程序来解决问题。 #### 配置串口初始化设置 当初始化串口外设时,确保正确设置了波特率、数据位长度、停止位数量以及其他必要的参数。特别是关于奇偶校验的选择上,应该依据实际需求决定是否启用此功能及其模式(奇数还是偶数)。通常情况下,默认关闭奇偶校验能够减少不必要的复杂度并提高传输效率[^1]。 ```c // 初始化USART设备 void USART_Config(void){ // ...其他初始化代码... /* Configure the USART */ usart_deinit(USARTx); struct st_usart_init uartInitStructure; memset(&uartInitStructure, 0x00, sizeof(uartInitStructure)); uartInitStructure.baud_rate = 9600; // 设置波特率为9600 bps uartInitStructure.word_length = USART_WL_8B; // 数据帧为8位宽 uartInitStructure.stop_bits = USART_STPB_1; // 单个停止位 uartInitStructure.parity = USART_PM_NONE; // 不使用奇偶校验 usart_init(USARTx, &uartInitStructure); // 开启接收和发送使能 usart_enable_rx_interrupt(USARTx); // 启用RXNE IE (Receive Data Register Not Empty Interrupt Enable) usart_transmit_config(USARTx, USART_TRANSMIT_ENABLE); } ``` #### 处理奇偶校验错误中断 为了有效应对可能发生的奇偶校验错误事件,可以在ISR(Interrupt Service Routine)内部加入特定逻辑分支用于检测此类异常情况的发生,并采取适当措施恢复正常的通讯状态或记录下错报信息以便后续分析。 ```c // 定义全局变量存储接收到的数据缓冲区索引位置 volatile uint8_t g_u8RxIndex = 0; // USART中断服务例程 void USART_IRQHandler(void){ if(usart_flag_get(USARTx, USART_FLAG_PE)){ // 清除PE标志位 usart_clear_flag(USARTx, USART_CLEAR_PEF); // 记录日志或其他操作... printf("Parity Error Detected!\n"); // 可选:跳过当前字符继续监听下一个字节的到来 while(usart_flag_get(USARTx, USART_FLAG_RXNE) != RESET){}; } if(usart_flag_get(USARTx, USART_FLAG_RXNE)){ char chData = usart_data_receive(USARTx); // 将新到达的数据存入环形队列或者其他形式的缓存机制中去 RingBuffer_WriteByte(chData); } } ``` 通过上述方法可以有效地管理和纠正由于奇偶校验失败而引发的各种潜在问题,从而保障了整个系统的稳定性和可靠性。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值