当前位置: 首页 > ds >正文

嵌入式-EXTI的工作原理和按钮实验-Day19

一、EXTI的工作原理

1.EXTI模块简介

简单就说就是用来捕捉信号的变化(信号的上升(沿)或者下降(沿))并输出中断


2.EXTI应用举例

前面DAY15做了一个按钮实验,那里因为我们专门要实现当按钮松开的时候实现灯的亮/灭,那里使用的是时刻判断两个变量是否不相等,不相等表明电压变化了,并且电压如果是高电压表示当前按钮松开了(变量分别记录之前的电压和当前的电压)

这里可以很方便的使用EXTI去判断是否是上升沿,是的话就直接产生中断然后在中断响应函数里面编写函数就行,就不用前面那么麻烦了


3.线的概念


4.线的内部结构

简单来看就是左边有一个AFIO的复用器,就是用来把EXTI的每个线分配给某个GPIOx

之后经过边沿检测电路(就是用来检测是上升沿还是下降沿),之后有三条路,上声沿到开关再到中断,还有下降沿类似,以及还有一个是双(只要是变化的,即但凡有一个是上升或者下降的就产生中断)

注意:这个中断也可以使用软件方式来控制,即代码输出1使其产生中断

二、按钮实验

1.实验目的

按左边的按钮实线点亮,右边的按钮实现熄灭

2.搭建电路


3.初始化板载LED和按钮

板载LED就是初始化为输出开漏

按钮的话就是初始化两按钮对应的引脚都为输入上拉

4.给EXTI线分配输入的引脚(即信号是从哪传进来的)

就是使用复用器(前面学过是用来复用映射的),为当前的EXTI的线分配GPIOx,以及选择GPIO的某条引脚与其连接


4.配置EXTI线的模块

因为是有两按钮,即单片机外面传输进行的信号有两个渠道,所以说需要分配两条EXTI的线


5.配置NVIC下的中断

这里唯一一个值得注意的是,线五和线六同属于一个中断,所以不用配置两个中断,一个就行了。
首先,注意这个NVIC这个片上外设比较特殊,他中断开关的配置是在自身的定义里面,不像前面的USART一样要专门闭合中断的开关,所以这里直接就配置NVIC就行(即规则+抢占和子优先级的值+闭合NVIC的开关)


6.编写中断响应函数

这里需要判断你这个中断是哪个线触发的,所以使用下面的标志位去判断。

还有一件事,使用完中断后一定要关闭,即clear,因为他两共用一个中断(前面提到过),你触发了,别人也想要触发啊,你触发不关闭,就导致这个中断独属于你,别人用不了。

举例:那假设这个属于线5的中断一直开着,那就是你不管按啥按钮,虽然都触发了中断,但是因为线5导致中断响应,既而引起了亮灯,但是你没关中断,就导致你这个if判断下的标志位(线5产生的中断==1)是一直成立的,所以两按钮不管按哪个都是亮的

7.代码

#include "stm32f10x.h"
#include "Delay.h"void My_BoardLed_Init(void);
void My_USART_Init(void);
uint16_t adjustDelay=100;
void USART1_IRQHandler(void);
void App_Button_Init(void);
void EXTI9_5_IRQHandler(void);//实验目的,两按钮分别在松开的时候实现灯的亮/灭int main(void)
{//首先就是配置中断的时候标志的中断规则NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//初始化亮灯My_BoardLed_Init();//初始化两个按钮App_Button_Init();while(1){GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);Delay(adjustDelay);GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);Delay(adjustDelay);}
}void App_Button_Init(){//首先使用按钮的初始化封装函数来实现RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct={0};GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_5;GPIO_Init(GPIOC,&GPIO_InitStruct);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_6;GPIO_Init(GPIOC,&GPIO_InitStruct);//初始化后当按钮按下,信号传输进来,此时也要传输到EXTI线上//所以配置EXTI//首先给EXTI的两条线复用分配输入的引脚//启用复用AFIORCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource5);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource6);//分配完后,初始化EXTIEXTI_InitTypeDef EXTI_InitStruct={0};EXTI_InitStruct.EXTI_Line=EXTI_Line5;EXTI_InitStruct.EXTI_LineCmd=ENABLE;EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStruct);EXTI_InitStruct.EXTI_Line=EXTI_Line6;EXTI_InitStruct.EXTI_LineCmd=ENABLE;EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;EXTI_Init(&EXTI_InitStruct);//配置中断NVIC_InitTypeDef NVIC_InitStruct={0};NVIC_InitStruct.NVIC_IRQChannel=EXTI9_5_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStruct);}//配置中断响应函数
void EXTI9_5_IRQHandler(){//如果接收到线5的中断就亮灯,否则线6的则灭灯if(EXTI_GetFlagStatus(EXTI_Line5)==SET){EXTI_ClearFlag(EXTI_Line5);GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);}else if(EXTI_GetFlagStatus(EXTI_Line6)==SET){EXTI_ClearFlag(EXTI_Line5);GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);}}//初始化板载LED
void My_BoardLed_Init(){//GPIO的引脚13初始化RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);GPIO_InitTypeDef GPIO_InitStruct={0};GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_13;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;GPIO_Init(GPIOC,&GPIO_InitStruct);}
void My_USART_Init(){//初始化IORCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitTypeDef GPIO_InitStruct={0};GPIO_InitStruct.GPIO_Mode=GPIO_Mode_AF_OD;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_9;GPIO_InitStruct.GPIO_Speed=GPIO_Speed_2MHz;GPIO_Init(GPIOA,&GPIO_InitStruct);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IPU;GPIO_InitStruct.GPIO_Pin=GPIO_Pin_10;GPIO_Init(GPIOA,&GPIO_InitStruct);//初始化本身RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//五个USART_InitTypeDef USART_InitStruct={0};USART_InitStruct.USART_BaudRate=115200;USART_InitStruct.USART_Mode=USART_Mode_Rx | USART_Mode_Tx;USART_InitStruct.USART_Parity=USART_Parity_No;USART_InitStruct.USART_StopBits=USART_StopBits_1;USART_InitStruct.USART_WordLength=8;USART_Init(USART1,&USART_InitStruct);//开启USARTUSART_Cmd(USART1,ENABLE);//开启中断USART_ITConfig(USART1,USART_IT_RXNE,ENABLE);//给每个中断配置NVIC模块下的中断配置NVIC_InitTypeDef NVIC_InitStruct={0};NVIC_InitStruct.NVIC_IRQChannel=USART1_IRQn;NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=0;NVIC_InitStruct.NVIC_IRQChannelSubPriority=0;NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;NVIC_Init(&NVIC_InitStruct);}
void USART1_IRQHandler(void){if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE)==SET){uint8_t temp=USART_ReceiveData(USART1);if(temp==0){adjustDelay=10000;}else if(temp==1){adjustDelay=1000;}else if(temp==2){adjustDelay=100;}}}

http://www.xdnf.cn/news/18637.html

相关文章:

  • 我从零开始学习C语言(13)- 循环语句 PART2
  • QT-窗口类部件
  • K8S高可用集群
  • K8s的相关知识总结
  • 如何理解面向过程和面向对象,举例说明一下?
  • Qt5 的跨平台开发详细讲解
  • 计算机毕设选题推荐 基于Spark的家庭能源消耗智能分析与可视化系统 基于机器学习的家庭能源消耗预测与可视化系统源码
  • 告别第三方流氓工具,如何实现纯净系统维护
  • DIC技术极端环境高温案例分享——从1600℃的锆合金力学性能测试到3000℃变形测试的DIC测量
  • 手机、电脑屏幕的显示坏点检测和成像原理
  • k8s----学习站点搭建
  • C++显示类型转换运算符static_cast使用指南
  • 贪吃蛇--C++实战项目(零基础)
  • 大模型微调:从理论到实践的全面指南
  • 【链表 - LeetCode】19. 删除链表的倒数第 N 个结点
  • Laravel 使用阿里云OSS S3 协议文件上传
  • Java多线程面试题二
  • Flask电影投票系统全解析
  • WPF控件随窗体大宽度高度改变而改变
  • 金融风控AI引擎:实时反欺诈系统的架构设计与实现
  • Rust 入门 注释和文档之 cargo doc (二十三)
  • AP服务发现PRS_SOMEIPSD_00255 的解析
  • 《WINDOWS 环境下32位汇编语言程序设计》第7章 图形操作(1)
  • UNIKGQA论文笔记
  • XP系统安装Android Studio 3.5.3并建立Java或Native C++工程,然后在安卓手机上运行
  • 算法题(188):团伙
  • Linux--进程核心概念
  • 论文精读(三)|智能合约漏洞检测技术综述
  • (纯新手教学)计算机视觉(opencv)实战七——边缘检测Sobel 算子(cv2.Sobel())详解
  • 递归思路:从DFS到二叉树直径的实战(通俗易懂)