中断方式的数据接收

news/2024/11/17 18:48:42/

中断接收简介

回顾之前的代码在这里插入图片描述
之前的代码是 等待标志位RXNE位为1才有数据 进而读取数据存放在变量c中 再根据c变量的数据是为0还是为1进而编写灯亮灭的代码 if语句
但这样的代码明显不符合裸机多任务的编程模型 因为在while中为进程 进程执行的时间不能大于5ms 但是while(RXNE==0)这条语句的执行时间是由发送数据的一方决定的 当发送方1s后发送数据 这条语句就执行1s 完全超出了裸机多任务模型的时间
右边的代码则是使用了中断 数据通过RX引脚进入 当状态寄存器SR 的RXNE标志位由0变为1就通过USART1触发一次中断 传递到NVIC进而执行中断函数

配置中断源

产生电平型的中断源
在这里插入图片描述
USART产生的是电平型的中断 当标志位由0变为1就产生中断 在SR状态寄存器中 每一个标志位都可以触发中断 都可以触发7个电平型的中断源
中断共用
在这里插入图片描述
这七个标志位共用一个中断源(节省中断源) 在stm32中NVIC是管理中断源的 当这七个标志位当中只要有一个为1通过这个或门就会触发中断源 传递到NVIC中 那如果产生了中断 那到底是那个标志位为1触发了中断呢? 我们去查询sr寄存器即可 if 语句判断到底是那个标志位触发了中断 (可能是一个 也可能是多个)
中断屏蔽
在这里插入图片描述
中断传输到NVIC过程中有一个开关 闭合就能通过中断 打开就屏蔽了中断信号 那我们如何实现屏蔽一个标志位产生的中断呢? 就是左下角的结构 将中断标志位和中断使能位通过一个与门相互连接 当中断使能位为0不管中断标志位为1还是为0都无法通过或门触发中断源 当中断使能位为1就等于闭合了开关 中断标志位即可正常工作 注意中断标志位FE NE ORE都是共用了一个中断使能位eie 当中断使能位eie为0就屏蔽了这三个中断标志位的中断触发请求 其他的中断标志位都是各自有一个独立的中断使能位
编程接口
在这里插入图片描述
第一个编程接口(函数)就是通过配置蓝色的中断使能寄存器来屏蔽 使能中断的 第二个接口就是查询状态寄存器的标志位 第三个接口是清除标志位 当触发了中断 如PE标志位触发了中断就为1 然后需要调用这个函数来手动清零
USART_ITConfig
在这里插入图片描述
USART_GetITStatus
在这里插入图片描述
USART_ClearITPendingBit在这里插入图片描述

中断接收数据的编程思路

数据处理能够瞬间完成
在这里插入图片描述
套用裸机多任务的模型 就是初始化 然后进程函数 再到中断服务函数 但是中断函数中处理数据的速度要大于数据接收的速度(不然等到下一个数据发送过来还在处理上一个数据会造成数据的丢失和出错) 那小于10us就看作瞬间完成 那么这里对数据的处理就是判断if语句还有向对应的gpio模块的ODR寄存器写入对应的0或1 远远小于10us 视为瞬间完成 符合裸机多任务模型的时间需求
在这里插入图片描述
如第一幅图 处理数据的时间远远小于数据传来的时间(箭头代表数据传输进来) 在两个数据传输中数据已经处理完成
第二幅图当箭头传入 (数据传入) 当第一个箭头(第一个数据)传入开始处理数据 第二个箭头(代表第二个数据传入)传入后还在处理第一个数据接着第三个数据传入 导致了第二个数据的重载 (丢失了第二个数据) 导致数据传输的错误
但是数据处理的时间确实太长了怎么办?
在这里插入图片描述
那我们就不在中断服务函数中处理 就把数据传到缓存区在传入进程函数中延时处理

改进串口编程实验

因为 这次数据处理的时间很短就只是个点灯 所以可以放在中断服务函数中执行

usart初始化

在这里插入图片描述
编写中断响应函数
在这里插入图片描述
清除中断的操作可以为第二步和第三步 因为标志位RXNE为1表示有数据接收
当读取了数据RXNE标志位就会由1变为0 所以第三步读取数据也相当于清除了中断

#include "stm32f10x.h"
#include "stm32f10x_pal.h"static  void USART_Recv_Init(void);int main(void)
{NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//NVIC的中断优先级分组PAL_Init();USART_Recv_Init();while(1){}
}static  void USART_Recv_Init(void)
{//1.初始化IO引脚//PB6 Tx PB7  Rx (经过了AFIO映射映射到了PB6和PB7引脚)RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//开启GPIOB的时钟//初始化PB6GPIO_InitTypeDef GPIOInitStruct;GPIOInitStruct.GPIO_Pin = GPIO_Pin_6;GPIOInitStruct.GPIO_Mode =  GPIO_Mode_AF_PP;//PIN6为复用推挽模式GPIOInitStruct.GPIO_Speed = GPIO_Speed_10MHz;GPIO_Init(GPIOB,&GPIOInitStruct);//初始化PB7GPIOInitStruct.GPIO_Pin = GPIO_Pin_7;GPIOInitStruct.GPIO_Mode = GPIO_Mode_IPU;GPIO_Init(GPIOB,&GPIOInitStruct);//初始化PC13RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//开启GPIOC的时钟GPIOInitStruct.GPIO_Pin = GPIO_Pin_13 ;GPIOInitStruct.GPIO_Mode = GPIO_Mode_Out_OD;GPIOInitStruct.GPIO_Speed = GPIO_Speed_2MHz;GPIO_Init(GPIOC,&GPIOInitStruct);//复用功能重映射RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_PinRemapConfig(GPIO_Remap_USART1 ,ENABLE);//使能USART1的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//配置USART的参数//9600 8为数据有效位 无奇偶校验 1停止位为1位  Tx|RxUSART_InitTypeDef USART1InitStruct;USART1InitStruct.USART_BaudRate = 9600;USART1InitStruct.USART_WordLength = USART_WordLength_8b ;USART1InitStruct.USART_StopBits = USART_StopBits_1;USART1InitStruct.USART_Parity = USART_Parity_No;USART1InitStruct.USART_Mode = USART_Mode_Rx|USART_Mode_Tx;USART1InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None ;//硬件流控USART_Init(USART1,&USART1InitStruct);//配置中断源USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//标志位RXNE的使能//NVIC的参数设置NVIC_InitTypeDef NVICInitStruct;NVICInitStruct.NVIC_IRQChannel = USART1_IRQn;NVICInitStruct.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级NVICInitStruct.NVIC_IRQChannelSubPriority =0;//子优先级NVICInitStruct.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVICInitStruct);//闭合总开关USART_Cmd(USART1,ENABLE);
}void USART1_IRQHandler(void)
{uint8_t c;if(USART_GetITStatus(USART1,USART_IT_RXNE) == SET){c = USART_ReceiveData(USART1); //清除了中断也读取了数据if(c == '0'){GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);}if(c == '1'){GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);}}}

http://www.ppmy.cn/news/1236994.html

相关文章

第七章 查找(中)【BST,AVL,红黑树,B树B+树】

1. 二叉排序树BST 1.1 二叉排序树的定义 二叉排序树,又称二叉查找树(BST,Binary Search Tree) 一棵二叉树或者是空二叉树,或者是具有如下性质的二叉树: 左子树上所有结点的关键字均小于根结点的关键字&am…

【Python 千题 —— 基础篇】删除列表值

题目描述 题目描述 删除列表的指定值。有一个列表 [1, 3, 5, 2, 44, 1, 9, 10, 32] ,请使用 for 循环删除该列表中与 [44, 1, 9] 列表相同的值,并输出该列表。 输入描述 无输入。 输出描述 输出操作后的列表。 示例 示例 ① 输出: …

使用Python将图片转换为PDF

将图片转为 PDF 的主要原因之一是为了方便共享和传输。此外,将多张图片合并成一个 PDF 文件还可以简化文件管理。之前文章详细介绍过如何使用第三方库Spire.PDF for Python将PDF文件转为图片,那么本文介绍使用同样工具在Python中实现图片转PDF文件的功能…

我叫:快速排序【JAVA】

1.自我介绍 1.快速排序是由东尼霍尔所发展的一种排序算法。 2.快速排序又是一种分而治之思想在排序算法上的典型应用。 3.本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。 2.思想共享 快速排序(Quicksort)是对冒泡排序的一种改进。基本思想是:通过一趟…

计算机网络——物理层相关习题(计算机专业考研全国统考历年真题)

目录 2012-34 原题 答案 解析 2018-34 原题 答案 解析 2009/2011-34 原题 答案 解析 2016-34 原题 答案 解析 2014-35/2017-34 原题 答案 解析 2013-34 原题 答案 解析 2015-34 原题 答案 解析 物理层的协议众多,这是因为物理层…

uniapp链接WebSocket 常用的api

UniApp是一个基于Vue语法的跨平台应用开发框架,它支持使用WebSocket来实现实时双向通信。WebSocket是一种在单个TCP连接上进行全双工通信的协议,它可以在客户端和服务器之间建立持久性的连接,并允许双向通信。在UniApp中,你可以使…

解决:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘

解决:ImportError: cannot import name ‘Adam‘ from ‘keras.optimizers‘ 背景 在使用之前的代码时,报错: from keras.optimizers import Adam ImportError: cannot import name ‘Adam’ 报错问题 from keras.optimizers import Adam I…

FFmpeg常用命令讲解及实战二

文章目录 前言一、ffmpeg 常用命令1、ffmpeg 的封装转换2、ffmpeg 的编转码3、ffmpeg 的基本编转码原理 二、ffprobe 常用参数1、show_format2、show_frames3、show_streams4、print_format5、select_streams 三、ffplay 的常用命令1、ffplay 常用参数2、ffplay 高级参数3、ffp…