STM32入门学习之外部中断

news2024/11/19 4:40:27

1.STM32的IO口可以作为外部中断输入口。本文通过按键按下作为外部中断的输入,点亮LED灯。在STM32的19个外部中断中,0-15为外部IO口的中断输入口。STM32的引脚分别对应着0-15的外部中断线。比如,外部中断线0对应着GPIOA.0-GPIOG.0,以此类推就可以将所以的IO映射到0-15个外部中断线上。STM32的IO的外部中断映射图如下:

 2.外部中断的配置步骤:

(1)将IO口映射到对应的外部中断线上,中断线河中断初始化。

(2)配置外部中断,即配置中断管理NVIC。

 (3)重写中断服务函数,即中断回调函数。这些中断回调函数在startup_stm32f10x_xx.s中被规定好了名称,我们只需要重写对应的中断回调函数即可。

3.工程代码:

delay.h:

#ifndef __DELAY_H
#define __DELAY_H

#include "stm32f10x.h"

void delay_us(uint32_t us);									//ÑÓʱ΢Ãë
void delay_ms(uint32_t ms);									//ÑÓʱºÁÃë

#endif

delay.c:

#include "delay.h"

void delay_us(uint32_t us)
{
	uint32_t i;
	
	//1.Ñ¡ÔñHCLKʱÖÓ£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµ
	SysTick_Config(72);
	
	for(i = 0;i < us;i++)
	{
		while(!((SysTick->CTRL) & (1 << 16)));		//µÈ´ý¼ÆÊýÍê³É
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}

void delay_ms(uint32_t ms)
{
	uint32_t i;
	//1.Ñ¡ÔñHCLKʱÖÓÔ´£¬²¢ÉèÖõδðʱÖÓ¼ÆÊýÖµ
	SysTick_Config(72000);
	
	for(i = 0;i < ms;i++)
	{
		while(!((SysTick->CTRL) & (1 << 16)));		//µÈ´ý¼ÆÊýÍê³É
	}
	SysTick->CTRL &= ~SysTick_CTRL_ENABLE_Msk;	//Ñ¡ÔñSTCLKʱÖÓÔ´£¬²¢Ê§Äܶ¨Ê±Æ÷
}

key.h:

#ifndef __KEY_H
#define __KEY_H

#include "stm32f10x.h"

#define KEY_0 GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5)			//¶ÁÈ¡°´¼üµÄ״̬
#define KEY_1 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_15)
#define KEY_2 GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_0)

void KEY_Init(void);
void KEY_Scan(void);						//°´¼üɨÃ躯Êý

#endif

key.c:

#include "key.h"
#include "delay.h"
#include "led.h"

void KEY_Init(void)
{
	/*1.¶¨ÒåÒý½ÅµÄ½á¹¹Ìå¡£
	  2.ʹÄÜÒý½Å¶ÔÓ¦µÄʱÖÓ¡£
	  3.ÅäÖÃÒý½ÅÐÅÏ¢*/
	
	//¶¨ÒåÒý½Å½á¹¹Ì壺
	GPIO_InitTypeDef GPIO_InitStruct;
	
	//ʹÄÜʱÖÓ£º
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC,ENABLE);
	
	//ÅäÖÃÒý½ÅÐÅÏ¢(KEY0)£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_5;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
	
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	
	//ÅäÖÃKEY1£º
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_15;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; //ÉèÖóÉÉÏÀ­ÊäÈë

	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//ÅäÖð´¼üWK_UP:
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	LED_Init();									//³õʼ»¯LED
}

void KEY_Scan(void)
{
	static u8 key_up = 1;				//°´¼üËÉ¿ª±ê־λ
	if(key_up && (KEY_0 == 0||  KEY_1  == 0|| KEY_1 == 1))
	{
		delay_ms(10);						  //È¥¶¶¶¯
		key_up = 0;
		if(KEY_0 == 0)
		{
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
			GPIO_SetBits(GPIOA,GPIO_Pin_8);
			//delay_ms(1000);
		}
		else if(KEY_1 == 0)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_SetBits(GPIOD,GPIO_Pin_2);
			//delay_ms(1000);
		}
		else if(KEY_2 == 1)
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
		}
	}
	else if(KEY_0==1&&KEY_1==1&&KEY_2==0)
	{
		key_up = 1;
	}
}

exti.h:

#ifndef __EXTI_H
#define __EXTI_H

#include "stm32f10x.h"

void EXTIx_Init(void);

#endif

exti.c:

#include "exti.h"
#include "key.h"
#include "delay.h"

void EXTIx_Init(void)
{
	/*ÍⲿÖжϵÄÅäÖ÷½·¨£º
	  1.½«IO¿ÚÓ³Éäµ½¶ÔÓ¦ÍⲿÖжÏÏßÉÏ
	  2.ÅäÖÃÍⲿÖжÏ
	  3.ÖØдÖжϷþÎñº¯Êý£¬¼´Öжϻص÷º¯Êý*/
	
	//¶¨ÒåÍⲿÖжϺÍÖжϵĽṹÌ壺
	EXTI_InitTypeDef EXTI_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	//ʹÄÜʱÖÓ£º
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//ÍⲿÖжÏÐèÒª¸´ÓÃʱÖÓ
	KEY_Init();			//³õʼ»¯°´¼ü
	
	//GPIOC.5µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãº
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource5);	//GPIOÓëÖжÏÏß½øÐÐÓ³Éä
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line5;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling;
	
	EXTI_Init(&EXTI_InitStructure);//½«ÉÏÃæÅäÖõÄÐÅϢдÈëEXTI¼Ä´æÆ÷ÖÐ
	
	//GPIOA.0µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãº
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);	//GPIOÓëÖжÏÏß½øÐÐÓ³Éä
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
	
	EXTI_Init(&EXTI_InitStructure);
	
	//GPIOA.15µÄÖжÏÏߺÍÖжϳõʼ»¯ÅäÖãº
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource15);	//GPIOÓëÖжÏÏß½øÐÐÓ³Éä
	
	EXTI_InitStructure.EXTI_Line = EXTI_Line15;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	
	EXTI_Init(&EXTI_InitStructure);
	
	//ÖжϹÜÀíÅäÖãº
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	
	NVIC_Init(&NVIC_InitStructure);
	
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	
	NVIC_Init(&NVIC_InitStructure);	
}

//ÖØдÖжϷþÎñº¯Êý.
void EXTI0_IRQHandlÕâЩÖжϻص÷º¯ÊýÔÚstartup_stm32f10x_xx.sÖб»¹æ¶¨ºÃÁËÃû³Æer(void)
{
	//¾²Ì¬±äÁ¿Ö»»áÔÚµÚÒ»´ÎÔËÐÐʱ±»³õʼ»¯¡£ËùÒÔ£¬¿ÉÒÔÀí½âΪÕâÌõÓï¾äÖ»Ö´ÐÐÒ»´Î
	static u8 flag1 = 1;	
	delay_ms(10);				//Ïû¶¶
	if(KEY_2 == 1)
	{
		if(flag1)
		{
			//GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
			GPIO_SetBits(GPIOA,GPIO_Pin_8);
			flag1 = !flag1;
		}
		else
		{
			GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
			//GPIO_SetBits(GPIOD,GPIO_Pin_2);
			flag1 = !flag1;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line0);
}

void EXTI9_5_IRQHandler(void)
{
	static u8 flag2 = 1;
	delay_ms(10);				//Ïû¶¶
	if(KEY_0 == 0)
	{
		if(flag2)
		{
			//GPIO_ResetBits(GPIOA,GPIO_Pin_8);
			GPIO_SetBits(GPIOD,GPIO_Pin_2);
			flag2 = !flag2;
		}
		else
		{
			//GPIO_ResetBits(GPIOA,GPIO_Pin_8);
			GPIO_ResetBits(GPIOD,GPIO_Pin_2);
			flag2 = !flag2;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line5);
}

void EXTI15_10_IRQHandler(void)
{
	static u8 flag3 = 1;
	delay_ms(10);				//Ïû¶¶
	if(KEY_1 == 0)
	{
		if(flag3)
		{
			GPIO_ResetBits(GPIOA,GPIO_Pin_8);
			GPIO_ResetBits(GPIOD,GPIO_Pin_2);
			flag3 = !flag3;
		}
		else
		{
			GPIO_SetBits(GPIOA,GPIO_Pin_8);
			GPIO_SetBits(GPIOD,GPIO_Pin_2);
			flag3 = !flag3;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line15);
}

main.c:

#include "stm32f10x.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"

int main(void)
{
	//LED_Init();
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// ÉèÖÃÖжÏÓÅÏȼ¶·Ö×é2
	KEY_Init();
	EXTIx_Init();
	while(1)
	{
//		GPIO_ResetBits(GPIOD ,GPIO_Pin_2);
//		GPIO_SetBits(GPIOA,GPIO_Pin_8);
//		delay_ms(1000);
//		GPIO_ResetBits(GPIOA ,GPIO_Pin_8);
//		GPIO_SetBits(GPIOD,GPIO_Pin_2);
//		delay_ms(1000);
		//KEY_Scan();
	}
}


4.运行结果:按下key0,LED1亮,再按一下熄灭。按下key1,LED0亮,再按一下熄灭。按下key3,两个LED亮,再按一下两个LED熄灭。

 

 

 

 5.总结:本文是通过key的外部中断来控制led的亮灭。其原理是利用STM32的IO可作为外部中断的输入口。当按下key时,对应的IO空作为输入会触发外部中断,然后系统会去调用对应的外部中断服务函数。通过中断,可以不用阻塞程序,在中断未被触发时,程序可以去执行其他的工作,提高系统的效率。

在配置外部中断的相关信息时,主要是配置相关的结构体信息、将IO映射到对应的中断线、配置中断管理NVIC。

 

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

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

相关文章

SpaceX 摊上事?未获环境许可,星舰发射系统涉嫌违规排放污染物

马斯克“寄予厚望”的星舰SpaceX最近可能摊上事了&#xff0c;疑似未申请环境许可&#xff0c;星舰发射系统涉嫌违规排放污染物。 据报导&#xff0c;SpaceX可能在火焰偏转器系统方面存在环境许可问题&#xff0c;其在火箭发射时&#xff0c;可能涉及违反相关环境法规。 最近&a…

深入学习 Redis - 基于 Spring Data Redis 操作 Redis

目录 一、前置工作 1.1、引入 Spring Data Redis 依赖 1.2、编写配置文件 二、Spring Data Redis 2.1、前置知识 2.2、演示 Demo 一、前置工作 1.1、引入 Spring Data Redis 依赖 1.2、编写配置文件 spring:redis:host: 127.0.0.1port: 8888二、Spring Data Redis 2.1、…

yolo系列笔记(v4-v5)

YOLOv4 YOLOv4网络详解_哔哩哔哩_bilibili 网络结构&#xff0c;在Yolov3的Darknet的基础上增加了CSP结构。 CSP的优点&#xff1a; 加强CNN的学习能力 去除计算瓶颈。 减少显存的消耗。 结构为&#xff1a; 、 其实还是类似与残差网络的结构&#xff0c;保留下采样之前…

标准IO_格式化IO之printf函数

目录 1.可变参数原理 1.1 函数参数入栈原理 1.2 可变参数如何实现&#xff1f; 1.2.1 可变参数实现原理 1.2.2 固定参数有什么用&#xff1f; 1.2.3 va_start,va_arg,va_end如何使用&#xff1f; 2.printf函数实现原理 2.1 printf函数流程 2.2 printf函数格式解析原理…

WebSocket协议解析

文章目录 概要一、WS原理1.1、帧格式 二、WS实战2.1、客户端发起协议升级请求2.2、服务端响应协议升级2.3、核心事件2.4、心跳保活 三、总结 概要 项目中的IM系统是基于WebSocket做的&#xff0c;所以这里聊一下。 说到WS&#xff0c;不得不提HTTP,HTTP是基于TCP&#xff0c;面…

Mycat分片函数详解

Mycat新一代Mysql分布式集群,大数据处理中间件,中国第一开源软件 Checkout项目 可以用eclipse的svn插件来进行项目检出,也可以用Tortoise SVN等工具检出,由于maven(M2)中的buildnumber-maven-plugin 中的SVNkit最高支持1.7的SVN仓库,因此当你用Tortoise SVN 1.8的工具或版…

聊聊原子弹之父:奥本海默

最近诺兰的电影奥本海默即将热映,其改编自Kai Bird和 Martin J. Sherwin的 2005 年Pulitzer Prize 获奖小说:“American Prometheus: The Triumph and Tragedy of J. Robert Oppenheimer”。这本小说作者研究奥本海默25年,才得以成形,可见奥神本人身上的故事曲折和传奇。 …

MP的开发流程-2

RESTful的实现等级 0级&#xff1a;传统的RPC&#xff0c;基于SOAP的WS&#xff0c;调用的服务名&#xff0c;参数放在HTTP协议的body里面&#xff0c;同时必须以POST方式提交&#xff0c;问题在于你必须清楚的知道所有服务&#xff0c;子服务&#xff0c;及其参数的信息&…

SpringBoot环境标识设置及nacos匹配配置

本地环境标识设置 本地父类maven配置 可以看到相关的分类&#xff0c;设置环境标识主要需要用到profiles; <profiles><profile><id>dev</id><properties><!-- 环境标识&#xff0c;需要与配置文件的名称相对应 --><profiles.active&…

AX7A200教程(8): HDMI输入和输出显示1080p视频

文章目录 本章节主要将hdmi输入的1080p视频通过ddr3缓存&#xff0c;然后通过hdmi输出口输出到显示屏上显示 一&#xff0c; 突发读写命令 设置读写突发长度为64 //parameter defineparameter WRITE_LENGTH 64;parameter READ_LENGTH 64;parameter IDLE 3d0; …

SSM面试题-Spring容器的启动流程

解答: 1. BeanDefinitionReader读取配置文件(xml yml properties),创建BeanDefinition(存储bean的定义信息) 2. 配置文件读取成功后&#xff0c;将相应的配置转换成 BeanDefinition 的对象实例保存在DefaultListableBeanFactory#beanDefinitionMap 中 3. 根据配置的 BeanFacto…

fastadmin采坑之固定表格某一列

// 初始化表格table.bootstrapTable({url: $.fn.bootstrapTable.defaults.extend.index_url,pk: id,sortName: id,fixedColumns: true,fixedRightNumber: 1,columns: [[{checkbox: true},{field: id, title: __(Id)},{field: proposal_title, title: __(Proposal_title), opera…

Modbus Poll 软件----下载和安装

Modbus Poll 下载 modbus tools 官网地址&#xff1a;https://www.modbustools.com/ 步骤1 点击进入官网&#xff0c;然后点击 DOWNLOAD&#xff0c;进入下载界面。 步骤2 在下载界面&#xff0c;点击 Download 64bit &#xff0c;下载 Modbus Poll。 步骤3 下载完成 Mo…

如何生成丰富的啸叫样本?

前段时间有个公众号的朋友问我如何生成丰富的啸叫类型&#xff0c;当时回答比较简单&#xff0c;只是把啸叫产生的条件说了一下&#xff0c;后来在写AI降噪的N种数据扩增方法时候也简单提了一下使用冲激响应(Impluse Respose, IR)和增益产生啸叫&#xff0c;今天我们把这个坑填…

RabbitMQ 教程 | 第3章 客户端开发向导

&#x1f468;&#x1f3fb;‍&#x1f4bb; 热爱摄影的程序员 &#x1f468;&#x1f3fb;‍&#x1f3a8; 喜欢编码的设计师 &#x1f9d5;&#x1f3fb; 擅长设计的剪辑师 &#x1f9d1;&#x1f3fb;‍&#x1f3eb; 一位高冷无情的编码爱好者 大家好&#xff0c;我是 DevO…

第1章 JavaScript简史

JavaScript的起源 JavaScript是Netscape公司与Sun公司合作开发的在JavaScript诞生之前游览器就是显示超文本文档的简单的软件&#xff0c;JavaScript为此增加了交互行为ECMAScript是JavaScript的标准化&#xff0c;本质上是同一个语言JavaScript是一门脚本语言通常只能运行在游…

VCS ICO - Intelligent Coverage Optimization

ico是vcs提供的用于优化覆盖率的feature&#xff1b;一般用户通过dist solver bofore等约束了变量的随机概率&#xff0c;而ico会在用户约束的基础上&#xff0c;做一些自动“修正”&#xff0c;以此来优化随机激励&#xff0c;提高随机多样性&#xff0c;加速覆盖率收敛&#…

【腾讯云 Cloud Studio 实战训练营】通过云IDE构建Web3项目

文章目录 背景一、 前言二、 Cloud Studio 主要功能三、Cloud Studio 实验前期准备3.1. 注册平台 四、构建Web3项目项目中技术栈 五、其他功能演示六、常见问题及注意事项七、总结八、相关链接 ​ Cloud Studio 是基于浏览器的集成式开发环境&#xff08;IDE&#xff09;&#…

《吐血整理》进阶系列教程-拿捏Fiddler抓包教程(12)-Fiddler设置IOS手机抓包,你知多少???

1.简介 Fiddler不但能截获各种浏览器发出的 HTTP 请求&#xff0c;也可以截获各种智能手机发出的HTTP/ HTTPS 请求。 Fiddler 能捕获Android 和 Windows Phone 等设备发出的 HTTP/HTTPS 请求。同理也可以截获iOS设备发出的请求&#xff0c;比如 iPhone、iPad 和 MacBook 等苹…

每日一题——只出现一次的数字

只出现一次的数字 题目链接 思路 要求为线性时间复杂度&#xff0c;即时间复杂度为O(n)&#xff0c;那么我们就不能用简单的两层循环来解决问题 要求只能使用常量额外空间&#xff0c;即空间复杂度为O(1)&#xff0c;那么我们就不能额外开辟一个数组来记录每个元素出现的次数…