IRQ Handler 的使用——以USART串口接收中断分别在标准库与HAL库版本下的举例

news2024/11/27 12:34:20

 前言:

1.中断系统及EXTI外部中断知识点见我的博文:

9.中断系统、EXTI外部中断_eirq-CSDN博客文章浏览阅读301次,点赞7次,收藏6次。EXTI(Extern Interrupt)外部中断EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。引脚电平变化,申请中断支持的触发方式(引脚电平的变化类型):上升沿(电平从低电平变到高电平的瞬间触发中断)/下降沿(电平从高电平变到低电平的瞬间触发中断)/双边沿(上升沿和下降沿都可以触发中断)/软件触发(程序执行代码就能触发中断)_eirqhttps://blog.csdn.net/m0_61712829/article/details/132433502?spm=1001.2014.3001.55022.本文重点讲USART串口接收中断分别在标准库和HAL库版本下如何使用,其它例如串口初始化程序就不重点阐述了。


 IRQ(Interrupt Request)是一种用于请求中断服务的机制,IRQ Handler就是负责处理IRQ中断的中断处理程序。

 “IRQHandler” 是中断处理程序的意思。中断处理程序是在计算机系统遇到硬件中断时执行的函数或程序代码。硬件中断可以由外部设备(如键盘、鼠标或计时器)触发,也可以由内部事件(如除零错误或内存故障)触发。 当一个中断事件发生时,操作系统会暂停当前的执行任务,跳转到相应的中断处理程序中执行。中断处理程序通常用于处理和响应中断事件,采取必要的操作来处理中断,并在完成后返回到中断发生的地方继续执行。

当串口接收到数据时,可以配置USART串口使用中断来触发数据接收中断。当接收到数据时,中断处理程序会被调用,可以在其中读取接收到的数据并进行处理。使用中断可以避免轮询方式的查询接收,提高实时性和效率。

使用标准库--USART串口接收中断

1.在usart.c文件中写中断接收和变量的封装函数并重写USART1中断函数接受字符串数据函数。代码如下:

/**
 * @brief       中断接收和变量的封装函数
 * @param       无
 * @retval      无
 */
uint8_t Serial_GetRxFlag(void)//读后自动清除标志位
{
	if(usart1_RxFlag == 1)
	{
		usart1_RxFlag = 0;
		return 1;
	}
	return 0;
}

uint8_t Serial_GetRxData(void)
{
	return usart1_RxData;
}


/**
 * @brief       重写USART1中断函数接受字符串数据
 * @param       无
 * @retval      无
 */

void USART1_IRQHandler(void)
{
	if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET)
	{
		usart1_RxData = USART_ReceiveData(USART1);
		usart1_RxFlag = 1;
		USART_ClearITPendingBit(USART1,USART_IT_RXNE);
	}
	
}

uint8_t Serial_GetRxFlag(void)函数解释如下。

  1. 判断usart1_RxFlag变量是否为1,表示接收到了新的数据。
  2. 如果接收到了新的数据,将usart1_RxFlag变量置为0,表示接收标志位已被清除。
  3. 返回1,表示接收到了新的数据。
  4. 如果没有接收到数据,返回0。

uint8_t Serial_GetRxData(void)函数解释如下。

  1. 该函数用于获取接收到的数据。
  2. 直接返回usart1_RxData变量,该变量存储了接收到的数据。

void USART1_IRQHandler(void)函数解释如下。

  1. 该函数是重写的USART1中断处理函数,用于接收字符串数据。
  2. 通过判断USART1的接收中断标志位USART_IT_RXNE是否被置位,确定是否接收到了新的数据。
  3. 如果接收到了新的数据,使用USART_ReceiveData()函数从USART1接收数据,并将数据存储到usart1_RxData变量中。
  4. usart1_RxFlag变量置为1,表示接收到了新的数据。
  5. 使用USART_ClearITPendingBit()函数清除USART1的接收中断标志位。 需要注意的是,以上代码中的函数调用和变量使用可能依赖于库函数和全局变量的定义,确保在使用这些函数之前进行适配,且USART1已正确初始化和配置中断。

2.在main.c中的main函数的while(1)循环中,定义串口中断接收函数。代码如下,这部分代码是在使用串口接收数据并进行处理的部分。

uint8_t RXData;//串口1接收数据

...省略
usart1_Init();//串口1初始化
...

/**
 * @brief       串口1接收数据
 *   @ntoe      
 * @param       无
 * @retval      无
 */        
            if(Serial_GetRxFlag() == 1) 
        {
            RXData = Serial_GetRxData();
            Serial_SendByte(RXData);//数据回传功能,将接收到的这一字节数据回传到电脑
            OLED_ShowHexNum(1,8,RXData,2);
        }    

首先,声明了一个RXData变量用于保存串口1接收到的数据。 然后,调用了usart1_Init()函数进行串口1的初始化设置。 接下来是一个条件判断语句,通过调用Serial_GetRxFlag()函数判断是否接收到了新的数据。 如果接收到了新的数据,执行以下操作:

  1. 调用Serial_GetRxData()函数获取接收到的数据,将其存储到RXData变量中。
  2. 调用Serial_SendByte(RXData)函数将接收到的数据回传到电脑。
  3. 调用OLED_ShowHexNum(1,8,RXData,2)函数在OLED屏幕上显示接收到的数据的十六进制形式。 需要注意的是,以上代码中的函数调用和变量使用可能依赖于其他部分的定义和实现,确保在使用之前进行适配,且串口1已正确初始化和配置。

 

3.串口接收数据测试。在main.c中的main函数的while(1)循环前,借用oled显示屏来显示接收到的串口数据。使用如下代码:

        OLED_ShowString(1,1,"RxData:");//串口1接收数据测试

使用HAL库--USART串口接收中断

1.在stm32f1xx_it.c文件中,写void USART2_IRQHandler(void)函数。当USART2的中断发生时,系统会自动跳转到这个函数进行处理。

/**
  * @brief This function handles USART2 global interrupt.
  */
void USART2_IRQHandler(void)
{
  /* USER CODE BEGIN USART2_IRQn 0 */
  uart2_receiver_handle();
  /* USER CODE END USART2_IRQn 0 */
  HAL_UART_IRQHandler(&huart2);
  /* USER CODE BEGIN USART2_IRQn 1 */

  /* USER CODE END USART2_IRQn 1 */
}

解释如下:

  1. uart2_receiver_handle();:这是用户自定义的函数,用于处理USART2接收到的数据。在USART2接收到数据时,该函数将被调用,用户可在该函数内部处理接收到的数据。
  2. HAL_UART_IRQHandler(&huart2);:这是调用HAL库函数的代码,用于处理USART2的中断。HAL库是一种硬件抽象层库,用于简化嵌入式系统的开发。该函数会处理USART2的中断,并根据具体情况执行相应的操作,如处理发送和接收缓冲区、错误处理等。 在这段代码中,用户可以根据自己的需求,在"USER CODE"注释处插入额外的代码来处理特定的操作或事件。例如,可以在USART2接收到数据后,根据接收的数据进行一些特定的处理,如解析命令、更新状态等。 需要注意的是,以上代码是一段模板代码,具体的操作和功能取决于用户自定义的函数和使用的USART2的配置。用户需要根据具体的需求,在USART2_IRQHandler函数和uart2_receiver_handle()函数中实现自己所需要的功能。

2.然后在usart.c文件中写串口数据接收处理与数据接收清0函数。

unsigned char receive_buf[512];	  //串口2接收缓存数组
unsigned char receive_start = 0;	//串口2接收开始标志位
uint16_t receive_count = 0;	      //串口2接收数据计数器
uint16_t receive_finish = 0;	    //串口2接收结束标志位 

/**
  * @brief          串口2数据接收处理函数
  * @param[in]      none
  * @retval         none
  */
void uart2_receiver_handle(void)
{
  unsigned char receive_data = 0;   
  if(__HAL_UART_GET_FLAG(&huart2,UART_FLAG_RXNE) != RESET)
  { 
    HAL_UART_Receive(&huart2, &receive_data, 1, 1000);//串口2接收1位数据
    receive_buf[receive_count++] = receive_data;
    receive_start = 1;	                              //串口2接收数据开始标志位置1
    receive_finish = 0;	                              //串口2接收数据完成标志位清0
  }
}
/**
  * @brief          串口2数据接收清0函数
  * @param[in]      len:清空的数据长度
  * @retval         none
  */
void uart2_receiver_clear(uint16_t len)	
{
	memset(receive_buf,0x00,len);
	receive_count = 0;
	receive_start = 0;
	receive_finish = 0;
}

以上函数中的关键步骤如下: 

  1. 声明一个无符号字符变量receive_data,用于保存接收到的数据。
  2. 通过判断UART2的接收标志位UART_FLAG_RXNE是否被置位,确定是否接收到了数据。
  3. 如果接收到了数据,使用HAL库函数HAL_UART_Receive()从UART2接收1个字节的数据,并存储到receive_data变量中。
  4. 将接收到的数据存储到一个接收缓冲区receive_buf[]中,使用receive_count变量记录接收到的数据字节数。
  5. 设置receive_start变量为1,表示串口2开始接收数据。
  6. 清零receive_finish变量,表示串口2接收数据还未完成。 然后是uart2_receiver_clear()函数,该函数用于清空接收缓冲区的数据。函数中的关键步骤如下:
  7. 使用memset()函数将接收缓冲区receive_buf[]中的数据清零,长度为len
  8. receive_countreceive_startreceive_finish变量都重新赋值为0,表示接收缓冲区已清空,接收数据未开始。 这两个函数可以根据具体需求进行使用,如根据receive_countreceive_buf[]中的数据进行进一步处理、解析等。需要注意的是,以上代码中的函数调用和变量使用可能依赖于库函数和全局变量的定义,确保在使用这些函数之前进行适配,且串口2已正确初始化和配置。

3.根据串口接收开始标志位,进行使用串口接收中断。如上程序中使用到的标志位receive_start,为1则开始串口接收数据。在当判断标志位为1时,执行相应的功能程序就可以了。使用如下代码:
        if(receive_start == 1)    {.....}

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

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

相关文章

Group k-fold解释和代码实现

Group k-fold解释和代码实现 文章目录 一、Group k-fold解释和代码实现是什么?二、 实验数据设置2.1 实验数据生成代码2.2 代码结果 三、实验代码3.1 实验代码3.2 实验结果3.3 结果解释 四、总结 一、Group k-fold解释和代码实现是什么? 0,1…

MP4文件中mvhd容器中的“下一个track ID”字段的作用是什么?(下一个轨道id)(新轨道id)

文章目录 mvhd容器中有以下字段其中有个“下一个track ID”字段不知道是干什么用的,它被放在这个mvhd容器的最后“下一个track ID”什么是“下一个track ID”“下一个track ID”的作用唯一性标识轨道管理 “下一个track ID”的必要性命令/代码演示 新轨道ID的含义和…

MySQL8.0 ROW_NUMBER 调用案例

ROW_NUMBER()是一个窗口函数或分析函数,它为从1开始应用的每一行分配一个序号。 创建表和生成所需要的数据 CREATE TABLE chapter11 ( shopname VARCHAR(255) NULL, sales VARCHAR(255) NULL, sale_date DATE NULL ); INSERT INTO chapter11 (shopname, sales, sal…

C语言之scanf浅析

前言&#xff1a; 当有了变量&#xff0c;我们需要给变量输入值就可以使用scanf函数&#xff0c;如果需要将变量的值输出在屏幕上的时候可以使用printf函数&#xff0c;如&#xff1a; #include <stdio.h> int main() {int score 0;printf("请输⼊成绩:");sc…

《2023年企业IoT和OT威胁报告》:物联网恶意软件攻击增长400%

内容概括&#xff1a; 物联网&#xff08;IoT&#xff09;设备无疑改变了我们生活、工作和管理运营技术&#xff08;OT&#xff09;环境的方式。总体而言&#xff0c;到2027年&#xff0c;全球物联网设备数量预计将超过290亿&#xff0c;比2023年的167亿大幅增加。设备和智能技…

中文数字的魅力:古今中外的传承与创新

一、引言 中文数字&#xff0c;作为世界上最古老、最具特色的数字系统之一&#xff0c;已经伴随着中华文化走过了几千年的历史。它既是我们祖先智慧的结晶&#xff0c;也是现代生活中不可或缺的元素。本文将从各个方面介绍和解释中文数字的用途&#xff0c;带领大家领略中文数…

Python编程新技能:如何优雅地实现水仙花数?

水仙花数&#xff08;Narcissistic number&#xff09;也被称为阿姆斯特朗数&#xff08;Armstrong number&#xff09;或自恋数等&#xff0c;它是一个非负整数&#xff0c;其特性是该数的每个位上的数字的n次幂之和等于它本身&#xff0c;其中n是该数的位数。简单来说&#x…

渗透线上下料控制(SCL源代码)

有关渗透线的其它详细介绍请参考下面链接文章&#xff1a; https://rxxw-control.blog.csdn.net/article/details/133611151https://rxxw-control.blog.csdn.net/article/details/133611151这里的渗透线上下料属于整个渗透线流程里的最前端和最后端&#xff0c;分别负责待处理…

Unity坦克大战开发全流程——游戏场景——主玩家——可击毁箱子

游戏场景——主玩家——可击毁箱子 添加特效 CubeObj的代码如下 using System.Collections; using System.Collections.Generic; using UnityEngine;public class CubeObj : MonoBehaviour {//关联的奖励物品public GameObject[] rewardObjects;//关联的特效public GameObject …

大模型入门0: 基础知识

transformerscaling law分布式训练 自然语言处理包括几大任务 NLP: 文本分类&#xff0c;词性标注&#xff0c;信息检索NLG&#xff1a;机器翻译&#xff0c;自动摘要&#xff0c;问答QA、对话机器ChatBot下游任务: 词性标注&#xff08;POS&#xff09;&#xff0c;句法分析…

计算机网络(1)

计算机网络&#xff08;1&#xff09; 小程一言专栏链接: [link](http://t.csdnimg.cn/ZUTXU) 计算机网络和因特网&#xff08;1&#xff09;因特网概念解读服务常见的服务 协议网络边缘特点强调 网络核心特点强调 小程一言 我的计算机网络专栏&#xff0c;是自己在计算机网络…

Django开发3

Django开发3 Django开发编辑用户9.靓号管理9.1 表结构9.2 靓号列表9.3 新建靓号9.4 编辑靓号9.5 搜索手机号9.6 分页 10.时间插件11.ModelForm和BootStrap操作 各位小伙伴想要博客相关资料的话关注公众号&#xff1a;chuanyeTry即可领取相关资料&#xff01; Django开发 部门管…

simulink代码生成(五)——ePWM模块初级应用

前面分别讲到了SCI及ADC的配置及使用&#xff0c;现在梳理一下ePWM的配置和使用&#xff1b; 先打一些基础的DSP28335的基础知识&#xff1b; F28335 关于ePWM中断与SOC采样信号的一些思考_socasel-CSDN博客 F28335 ePWM模块简介——TMS320F28335学习笔记&#xff08;四&…

普通人变现天花板,月入10w是什么体验?

我是顺哥&#xff08;shundazy1&#xff09;&#xff0c;一个三观超正的6年互联网创业者&#xff0c;信因果、利他思维一直伴随着我的商业生涯。 经历过无数风风雨雨&#xff0c;实现过年入几百万&#xff0c;也曾在一年内亏了100多万。 我们项目的网站 首先介绍我们项目干啥…

消融实验(ablation study)——全网最全解读

消融实验&#xff08;ablation study&#xff09; 是什么优势与劣势案例总结 是什么 消融实验是一种科学研究方法&#xff0c;用于确定一个条件或参数对结果的影响程度。当研究者提出了一个新的方案或方法时&#xff0c;消融实验通过逐一控制一个条件或参数&#xff0c;来观察…

24届春招实习必备技能(一)之MyBatis Plus入门实践详解

MyBatis Plus入门实践详解 一、什么是MyBatis Plus? MyBatis Plus简称MP&#xff0c;是mybatis的增强工具&#xff0c;旨在增强&#xff0c;不做改变。MyBatis Plus内置了内置通用 Mapper、通用 Service&#xff0c;仅仅通过少量配置即可实现单表大部分 CRUD 操作&#xff0…

2024年山东省中职“网络安全”试题——B-3:Web安全之综合渗透测试

B-3&#xff1a;Web安全之综合渗透测试 服务器场景名称&#xff1a;Server2010&#xff08;关闭链接&#xff09; 服务器场景操作系统&#xff1a;"需要环境有问题加q" 使用渗透机场景Kali中的工具扫描服务器&#xff0c;通过扫描服务器得到web端口&#xff0c;登陆…

Kasada p.js (x-kpsdk-cd、x-kpsdk-ct、integrity)

提供x-kpsdk-cd的API服务 详细请私信~ 可试用~ V:zhzhsgg 一、简述 integrity是通过身份验证Kasada检测机器人流量后获得的一个检测结果&#xff08;数据完整性&#xff09; x-kpsdk-cd 是经过编码计算等等获得。当你得到正确的解决验证码值之后&#xff0c;解码会看到如下图…

iToF人脸识别

iToF(间接飞行时间)是一种测量光飞行时间的技术,主要应用于人脸识别。 iToF人脸识别技术在哪些场景下会用到 iToF人脸识别技术可以应用于许多场景,以下是一些常见的应用场景: 平安城市:在城市监控系统中,iToF人脸识别技术可以用于实时监控、目标检测和识别,以及异常行为…

关于 bringup sensor 时,曝光时间异常的问题排查

1、问题背景 这两天在配置 sc223a 这颗 sensor 的驱动&#xff0c;按 datasheet 的要求配置 sensor 的曝光后&#xff0c;发现最大曝光时间增加了一倍&#xff0c; sensor setting 用的是30fps &#xff0c;理论上最大的绝对曝光时间应该是 33ms 才正确&#xff0c;但实际用 …