STM32 寄存器配置笔记——USART配置中断接收乒乓缓存处理

一、概述

本文主要介绍如何配置USART接收中断,使用乒乓缓存的设计接收数据并将其回显在PC 串口工具上。以stm32f10为例,配置USART1 9600波特率。具体配置参考上一章节STM32 寄存器配置笔记------USART配置 打印。

乒乓缓存的设计应用场景:当后面的处理单元在工作期间,前面的 buffer 的内容不能被释放。或者,在处理单元工作期间, buffer 的特定地址的内容不止被访问一次。优点是相比全部写完再读的方式,可以节约读写时序。

二、中断优先级

STM32 的中断向量具有两个属性,一个为抢占属性,另一个为响应属性,其属性编号越小,表明它的优先级别越高。即抢占优先级和响应优先级。

抢占

抢占,是指打断其他中断的属性,即因为具有这个属性会出现嵌套中断(在执行中断服务函数A 的过程中被中断B 打断,执行完中断服务函数B 再继续执行中断服务函数A),抢占属性由NVIC_IRQChannelPreemptionPriority 的参数配置。

响应

响应属性则应用在抢占属性相同的情况下,当两个中断向量的抢占优先级相同时,如果两个中断同时到达, 则先处理响应优先级高的中断, 响应属性由NVIC_IRQChannelSubPriority 参数配置。

二、配置流程

1)使能RXNE中断

接收缓冲区非空中断使能,通过MY_NVIC_init函数配置中断的抢占优先级和响应优先级为3(这里可以随意配置本章重点不在这)。最后一个参数表示分组为2。即有2位用来表示抢占优先级,2位用来表示响应优先级。

复制代码
    USART1->CR1 |= 1 << 5;                                // enable RXNE interrupt 
	MY_NVIC_Init(3,3,USART1_IRQn,2);                      // 2bit PreemptionPriority 3 2bit SubPriority 3

2)编写串口中断函数

USART1_IRQHandler是在启动文件里定义的只要有串口中断便会跑进来。查询状态寄存器USART_SR的RXNE位为1则表示收到数据可以读出。此时从USART_DR寄存器读取数据。

三、乒乓缓存设计

1)数据结构定义

复制代码
typedef struct
{
    u8 USART_RX_BUF[USART_REC_LEN];
	u16 len;
} USART_DATA;

typedef struct
{
   USART_DATA stUartFifo[2];
   u8 curRecFifo;
} USART_HANDLE;

static USART_DATA *p_cur_Usart1_Handle = NULL;
static USART_DATA *p_cur_Data_ProcessingHandle = NULL;
static USART_HANDLE g_Usart1Handle;

uin16 needPro = 0;

2)乒乓缓存初始化

复制代码
void init_usart_handle(void)
{
	memset((u8*)&g_Usart1Handle, 0, sizeof(USART_HANDLE));
    p_cur_Usart1_Handle = &g_Usart1Handle.stUartFifo[0];
}

3)乒乓缓存接收

复制代码
void USART1_IRQHandler(void)
{
    if(USART1->SR&(1<<5))
	{
		p_cur_Usart1_Handle->USART_RX_BUF[p_cur_Usart1_Handle->len++] = USART1->DR;
	}
}

4)乒乓缓存切换

这里是以每收到一帧完整帧的数据都是以0x0d 0x0a结尾的数据为例。收到一帧完整帧将当前乒乓缓存A切换为处理,乒乓缓存B切换为接收。

复制代码
void change_curFifo(void)
{
    u16 len = p_cur_Usart1_Handle->len;
	if (len >= 2)
	{
		if (p_cur_Usart1_Handle->USART_RX_BUF[len - 2] == 0x0d 
			&& p_cur_Usart1_Handle->USART_RX_BUF[len - 1] == 0x0a)
		{
			printf("curFifo:%d len:%d\r\n", g_Usart1Handle.curRecFifo, len);
			p_cur_Data_ProcessingHandle = p_cur_Usart1_Handle;
			g_Usart1Handle.curRecFifo++;
			p_cur_Usart1_Handle = &g_Usart1Handle.stUartFifo[g_Usart1Handle.curRecFifo % 2];
			p_cur_Usart1_Handle->len = 0;
            needPro = 1;
		}

	}
}

5)乒乓缓存处理

打印接收内容。

复制代码
void data_processing(void)
{
    if (needPro)
	{
        needPro = 0;
		p_cur_Data_ProcessingHandle->USART_RX_BUF[p_cur_Data_ProcessingHandle->len] = 0;
	    printf("func:%s dat:%s\r\n", __func__, p_cur_Data_ProcessingHandle->USART_RX_BUF);
	}
}

6)调用如下

主循环一直轮询是否需要切换乒乓缓存以及是否存在数据待处理。

相关推荐
羊群智妍9 小时前
2026 AI搜索流量密码:免费GEO监测工具,优化效果看得见
笔记·百度·微信·facebook·新浪微博
BackCatK Chen10 小时前
第 8 篇:TMC2240 电机正反转实现|DIR 引脚控制 + 代码优化(稳定不抖动)
stm32·单片机·嵌入式硬件·保姆级教程·电机正反转·tmc2240·dir引脚控制
星马梦缘11 小时前
EDA彩灯电路绘制
单片机·嵌入式硬件·物联网·pcb·eda·嘉立创
山岚的运维笔记11 小时前
SQL Server笔记 -- 第18章:Views
数据库·笔记·sql·microsoft·sqlserver
lpruoyu13 小时前
【Android第一行代码学习笔记】Android架构_四大组件_权限_持久化_通知_异步_服务
android·笔记·学习
wdfk_prog13 小时前
[Linux]学习笔记系列 -- [drivers][mmc][mmc_sdio]
linux·笔记·学习
果果燕13 小时前
今日学习笔记:双向链表、循环链表、栈
笔记·学习·链表
觉醒大王13 小时前
AI写的青基中了
人工智能·笔记·深度学习·学习·职场和发展·学习方法
明月醉窗台13 小时前
qt使用笔记六之 Qt Creator、Qt Widgets、Qt Quick 详细解析
开发语言·笔记·qt
wangjialelele13 小时前
平衡二叉搜索树:AVL树和红黑树
java·c语言·开发语言·数据结构·c++·算法·深度优先