STM32H7 串口 空闲中断 硬件FIFO 任意长接收 Hal库 IDLE

news2024/9/27 17:21:36

STM32H7 串口 空闲中断 硬件FIFO 任意长接收 Hal库 IDLE

由于工作原因好久不接触ST的芯片了,所以断更ST的东西了,不过偶尔玩玩也挺好的。

接着上篇继续说串口的事儿,这次是FIFO,STM32H7的串口都是带硬件FIFO,大小是发送和接收各16个字节,其他新出的系列,例如H5的串口带8字节的硬件FIFO,这种情况下DMA咱就可以省略了,直接用FIFO就行。

使用之前呢,先要说明本次使用的环境以及库版本,编译环境是MDK5.27 ,hal库版本是1.11版本。这个很重要。

前两篇文章里边用的hal库版本比较老,缺失了很多。例如新版本已经增加了对idle的支持。并且修复了一些错误,例如硬件FIFO深度宏定义。

好,进入正题。

插个题外话,未经允许不得转载哦。

我们的目标呢,依旧是接收任意长数据。

我们拆解开来看,里边是有两个点需要注意,一个是IDLE,一个是硬件FIFO。

首先是IDLE,这个中断在hal库中定义为事件。我们在这里称为空闲中断。目前看这个中断是ST的芯片独有的,其他的芯片不一定有,可能有其他方式实现。空闲中断嘛,顾名思义就是串口在闲的时候发出中断,有闲就有忙,那这里的忙是什么?按照hal库里的实现,可以理解为,只要串口在收发数据的过程中就是忙,反之所谓的空闲就是没有在收发数据中。这个IDLE空闲中断特指的是串口在没有接收数据,注意啊,不关发送的事儿,因为串口本身就是异步全双工的,可以理解为发送是一个硬件,接收是一个硬件,两个是互相不干扰的。

再说说IDLE空闲中断发生的时机。我记得之前在103的手册中看到过,说是串口接收到最后一个字节后,在超过一个字节的时间里没有收到数据,会发生这个中断。当然H743里边也有单独实现超时机制(指定超时时间,硬件实现哦,题外话:soc中常用这个,soc的FIFO一般是64字节),不在本次实现验证说明中。这段主要就是想说IDLE发生在接收到最后一字节之后的一个字节时间之后且一次传输只发生一次。

然后是串口的硬件FIFO,F7 我没有看手册,就当作没有实现哈,就当作H7是ST公司首次在STM32系列MCU中加入硬件FIFO的功能。在不考虑DMA的情况下,我们通过串口接收接收数据,每收到一个数据就要发生一次中断。在cortexM3手册中是明确说明的,从触发中断到响应中断的第一条指令开始,是需要12个cpu周期的,cortexM7,我就懒得翻了,不知道有没有这个说明,STM32F103系列在72MHz主频下,中断频率最高是200Khz。说这些东西呢,是想让各位读者知道,中断对单片很重要,但不能滥用,要好好的规划才行,尤其是你的系统很复杂的时候, 这里用FIFO和IDLE的目的就是减少中断,还不影响实时性。

相关的知识点就先说这么多。

接下来就说怎么实现了,这次就不分析hal库了,大概前两篇的差不多。剩下的我就直接贴代码了。

这是C文件里的涉及到的宏定义以及全局变量。

#define BuffSize	128ul

UART_HandleTypeDef hUart1 = {0};

uint8_t RxData[2][BuffSize];

这段是uart1的初始化。

void Uart1_Init(void)
{
	hUart1.Instance = USART1;
	hUart1.Init.BaudRate = 115200;
	hUart1.Init.ClockPrescaler = UART_PRESCALER_DIV2;
	hUart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
	hUart1.Init.Mode = UART_MODE_TX_RX;
	hUart1.Init.OneBitSampling = UART_ONEBIT_SAMPLING_DISABLED;
	hUart1.Init.OverSampling = UART_OVERSAMPLING_8;
	hUart1.Init.Parity = UART_PARITY_NONE;
	hUart1.Init.StopBits = UART_STOPBITS_1;
	hUart1.Init.WordLength = UART_WORDLENGTH_8B;
	
	HAL_UART_Init(&hUart1);
	
	HAL_UARTEx_EnableFifoMode(&hUart1);
	HAL_UARTEx_SetTxFifoThreshold(&hUart1,UART_TXFIFO_THRESHOLD_8_8);
	HAL_UARTEx_SetRxFifoThreshold(&hUart1,UART_RXFIFO_THRESHOLD_8_8);
	
	__HAL_UART_ENABLE_IT(&hUart1,UART_IT_IDLE);
	HAL_NVIC_EnableIRQ(USART1_IRQn);
	HAL_NVIC_SetPriority(USART1_IRQn,14,0);
	HAL_UARTEx_ReceiveToIdle_IT(&hUart1,RxData[0],BuffSize);
}

这段是uart1引脚配置。

void HAL_UART_MspInit(UART_HandleTypeDef *huart)
{
	if(huart == &hUart1)//串口1
	{
		GPIO_InitTypeDef GPIO_InitStruct;
		
		GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
		GPIO_InitStruct.Pull = GPIO_PULLUP;
		GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
		GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
		GPIO_InitStruct.Pin = GPIO_PIN_10 | GPIO_PIN_9;
		
		__HAL_RCC_GPIOA_CLK_ENABLE();
		__HAL_RCC_USART1_CLK_ENABLE();
		
		HAL_GPIO_Init(GPIOA,&GPIO_InitStruct);
	}
}

这是中断相关处理。

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
	HAL_UARTEx_RxEventCallback(huart,BuffSize);
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
	if(huart == &hUart1)
	{
		if(huart->pRxBuffPtr <= RxData[1])
		{
			HAL_UARTEx_ReceiveToIdle_IT(huart,RxData[1],BuffSize);
			Uart1_RxData_NotifityISR(RxData[0],Size);
		}
		else
		{
			HAL_UARTEx_ReceiveToIdle_IT(huart,RxData[0],BuffSize);
			Uart1_RxData_NotifityISR(RxData[1],Size);
		}
	}
}

void USART1_IRQHandler(void)
{
	HAL_UART_IRQHandler(&hUart1);
}

这是对外接口部分,也就收发数据接口。

__weak void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count)
{
}

uint32_t Uart1_TxData(uint8_t *pTxData,uint32_t Count)
{
	if(HAL_UART_GetState(&hUart1) & 0x01)return 1;
	HAL_UART_Transmit_IT(&hUart1,pTxData,Count);
	return 0;
}

c文件呢一共就这么多。

下边这段是h文件,是不是非常简洁。

#ifndef __Uart_H_
#define __Uart_H_

#include "stdint.h"

void Uart1_Init(void);
void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count);
uint32_t Uart1_TxData(uint8_t *pTxData,uint32_t Count);

#endif

下边这段是测试代码,功能是回显。

static uint8_t *pvRxData;
static volatile uint32_t RxCount = 0;

void Uart1Step(void)//Rate:10ms
{
	if(RxCount > 0)
	{
		if(Uart1_TxData(pvRxData,RxCount) == 0)RxCount = 0;
	}
}

void Uart1_RxData_NotifityISR(uint8_t *pRxData,uint32_t Count)
{
	pvRxData = pRxData;
	RxCount = Count;
}

测试结果,如图所示
在这里插入图片描述

好了,今天就这么多,有问题可以联系我,共同探讨,单片机疑难杂症就可以找我探讨哦。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2104418.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java重点学习-redis

一.redis 穿透无中生有key&#xff0c;布隆过滤nul隔离 锁与非期解难题。缓存击穿过期key&#xff0c; 雪崩大量过期key&#xff0c;过期时间要随机。 面试必考三兄弟&#xff0c;可用限流来保底。 1.1 Redis的使用场景 根据自己简历上的业务进行回答 缓存穿透、击穿、雪崩、双…

人工智能再次进化 善用AI提升营运效率

人工智能无疑为我们的生活带来不少便利&#xff0c;也为商界和社会发展作出了重大贡献。事实上&#xff0c;它的起源最早可以追溯到70年前&#xff0c;只可惜过往的 AI 技术尚未如现时般成熟&#xff0c;可以做到的事也远比现在少&#xff1b;直至近期的 AI 技术取得了重大突破…

Redis缓存预热方案详解:提升应用性能与用户体验

文章目录 引言1. 为什么需要缓存预热&#xff1f;2. 缓存预热的基本原理2.1 数据选择2.2 加载策略 3. Redis缓存预热方案设计3.1 方案概述3.2 数据选择3.3 加载策略3.4 实现方式 4. 测试与监控4.1 单元测试4.2 监控 5. 总结 引言 在现代Web应用中&#xff0c;缓存技术已经成为…

【并行计算】CUDA基础

cuda程序的后缀&#xff1a;.cu 编译&#xff1a;nvcc hello_world.cu 执行&#xff1a;./hello_world.cu 使用语言还是C。 1. 核函数 __global__ void add(int *a, int *b, int *c) {*c *a *b; }核函数只能访问GPU的内存。也就是显存。CPU的存储它是碰不到的。 并且核…

【技术解析】工厂内部导航系统:高精度定位与智能路径规划的技术实现

一、工厂内部导航系统概述 工厂内部导航系统集成了最新的GPS室内定位技术、蓝牙定位技术&#xff0c;实现了对工厂内部环境的无缝覆盖与高精度定位。无论是繁忙的生产线、错综复杂的仓库还是广阔的厂区&#xff0c;都能轻松应对。 二、工厂内部导航系统核心功能 实时定位&…

PromptReps: 解锁LLM的检索力量

论文&#xff1a;https://arxiv.org/pdf/2404.18424代码&#xff1a;https://github.com/ielab/PromptReps机构&#xff1a;CSIRO、昆士兰大学、滑铁卢大学领域&#xff1a;retrieval、embedding model发表&#xff1a;arXiv 当前大型语言模型用于zero-shot文档排序的方法主要有…

台球助教系统开发概述:技术架构与功能实现

在现代体育训练领域&#xff0c;技术的融合正不断推动运动教学方式的革新。台球&#xff0c;作为一项集策略、技巧与心理素质于一体的运动&#xff0c;其教学过程的优化显得尤为重要。因此&#xff0c;开发一套高效、智能的台球助教系统&#xff0c;旨在通过技术手段提升学员的…

【微处理器系统原理与应用设计第五讲】再探Cortex-M4处理器结构、总线、异常与中断、SysTick

一、处理器结构 如下图所示&#xff0c;主要包括处理器内核、嵌套向量中断控制器&#xff08;NVIC&#xff09;、系统节拍定时器&#xff08;SysTick&#xff09;以及可选的浮点单元&#xff0c;还有一些内部总线系统、可选的存储器保护单元&#xff08;MPU&#xff09;以及支…

【AI】前向和反向传播的关系

这个例子来自ChatGPT&#xff0c;很有趣的解释了一个模型在trian的过程中前向传播和反向传播的过程。 其中Sigmoid的导数是 自身乘以1-自身的结果。 这也是上述式子中为什么有0.622*&#xff08;1-0.622&#xff09;。

Android Telephony总结

1、Telephony 业务介绍 Android telephony涉及较多模块 1.1、STK业务介绍 1.1.1、STK域选 1.1.2、是否支持STK Telephon STK-CSDN博客 1.1.3、STK应用的安装卸载 1.2、SS补充业务 1.3、通话业务 1.3.1、紧急号码 ECC 号码总结_ecc号码-CSDN博客 1.4、SMS 1.4.1 短信发送方式…

相亲交友系统如何运用算法匹配理想伴侣

在数字化时代&#xff0c;相亲交友系统已经成为寻找理想伴侣的重要途径。作为程序员&#xff0c;我们致力于通过先进的算法&#xff0c;为用户提供精准的匹配服务&#xff0c;让相亲交友变得更加高效和有趣。 相亲交友系统的核心在于算法&#xff0c;我们的团队运用了多种算法…

一线大厂软件测试面试题及答案解析,2024最强版...

1、什么是兼容性测试?兼容性测试侧重哪些方面? 参考答案: 兼容测试主要是检查软件在不同的硬件平台、软件平台上是否可以正常的运行&#xff0c;即是通常说的软件的可移植性。 兼容的类型&#xff0c;如果细分的话&#xff0c;有平台的兼容&#xff0c;网络兼容&#xff0…

达梦创建新连接

小伙伴是不是遇到过什么都没有的达梦数据库页面&#xff0c;很慌 我们直接点击窗口——视图——对象导航 出来了以后&#xff0c;点击小图标进行新建链接 输入自己的密码用户名&#xff0c;就能新建一个链接了&#xff0c;希望可以帮助到各位小伙伴

软件测试之压力测试知识总结

&#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 压力测试 压力测试是一种软件测试&#xff0c;用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力&…

window系统开机执行bat脚本

1&#xff0c;win R 打开运行对话框&#xff0c;然后如下图所示输入 第二&#xff0c;打开启动文件夹后&#xff0c;将想要执行的bat脚本&#xff0c;创建快捷方式&#xff0c;放在这里&#xff0c;重启电脑时就会执行这个程序

银行接口测试的具体流程及内容?

银行接口测试的具体流程及内容可以概括为以下几个关键步骤&#xff1a; 一、测试前准备 接口测试计划制定&#xff1a; 确定测试目标、范围、人员分工、时间计划等。 编写接口测试计划文档&#xff0c;明确测试策略、测试方法、测试工具等。 接口文档解析&#xff1a; 深入理…

Linux进程状态 僵尸进程 孤儿进程

进程状态 R (running) Linux 的运行状态(循环空语句) S (sleeping) 阻塞状态 称为浅度睡眠(可以被唤醒)死循环打印语句时等待输入时使用 sleep 函数时 D (disk sleep) 也是一种阻塞状态&#xff0c;称为深度睡眠进程在等待磁盘写入完毕期间&#xff0c;这个进程不能被任何人杀…

一键云迁移:利用VMware PowerCLI将OVA虚拟机顺利迁移到AWS

哈喽大家好&#xff0c;欢迎来到虚拟化时代君&#xff08;XNHCYL&#xff09;。 “ 大家好&#xff0c;我是虚拟化时代君&#xff0c;一位潜心于互联网的技术宅男。这里每天为你分享各种你感兴趣的技术、教程、软件、资源、福利…&#xff08;每天更新不间断&#xff0c;福利…

【学习AI-相关路程-工具使用-自我学习-jetson收集数据-图片采集-训练前准备-基础样例 (5)】

【学习AI-相关路程-工具使用-自我学习-jetson&模型训练-图片识别-使用模型检测图片-基础样例 &#xff08;5&#xff09;】 1 -前言2 -环境说明3 -先行了解&#xff08;1&#xff09;整理流程了解&#xff08;2&#xff09;了解模型-MobileNet1、MobileNetV2 的主要特性&am…

大模型推理框架 RTP-LLM 架构解析

RTP-LLM 是阿里巴巴智能引擎团队推出的大模型推理框架&#xff0c;支持了包括淘宝、天猫、闲鱼、菜鸟、高德、饿了么、AE、Lazada 等多个业务的大模型推理场景。RTP-LLM 与当前广泛使用的多种主流模型兼容&#xff0c;使用高性能的 CUDA kernel, 包括 PagedAttention、FlashAtt…