基于STM32F103C8T6利用外部中断加按键进行点亮或熄灭LED灯

本文介绍了基于STM32的EXTI外部中断功能,通过配置GPIO和EXTI初始化,实现下降沿触发中断,从而控制LED灯的亮灭。程序中使用了位带操作简化GPIO访问,并通过NVIC设置中断优先级。当EXTI0线路检测到下降沿时,执行中断服务函数,改变LED的状态并清除中断标志位。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 EXTI简介:

EXTI (Extern Interrupt)外部中断
EXTI可以监测指定GPIO口的电平信号,当其指定的GPIO口产生电平变化时,EXTI将立即向NVIC发出中断申请,经过NVIC裁决后即可中断CPU主程序,使CPU执行EXTI对应的中断程序。
支持的触发方式:上升沿/ 下降沿/双边沿/软件触发。
支持的GPIO口:所有GPIO口,但相同的Pin不能同时触发中断通道数: 16个GPIO_ _Pin,外加PVD输出、RTC闹钟、USB唤醒、以太网唤醒。
触发响应方式:中断响应/事件响应。
 

                                                                                原理图 1

本程序是基于原理图 1采用下降沿触发选择寄存器,软件中断寄存器。

                                                                     原理图2

 基于原理图 2 选择PA0-->EXTI0

AFIO主要用于引脚复用功能的选择和重定义。

在STM32中,AFIO主要完成两个任务:复用功能引脚重映射、中断引脚选择。

                                                                     原理图 3 

本程序还涉及相应的位带操作的知识点:

                                                                 原理图 4 

从原理图中可以看出,位带操作是在简化了代码规模的同时也提高了编写代码的便捷性。

主函数main.c代码:

#include "stm32f10x.h"                  // Device header
#include"led.h"
#include"exti.h"

int main(void)
{
	exti_init();
	led_init();
	while(1);
}

位带操作sys.h代码段:

#ifndef __SYS_H_
#define __SYS_H_

//位带操作实现51类似的GPIO控制功能
//addr&0xF0000000取出最高的四位,其实就是用于区别SRAM(0x20000000)还是片上外设(0x40000000)的
//+0x2000000对于SRAM位带区则得到0x22000000,对于片上外设位带则得到0x42000000
//(addr&0xFFFFF)等效于(addr&0x000FFFFF),就是屏蔽掉高12位,地址范围是0x20000000-0x200FFFFF和0x40000000-0x400FFFFF
//<<5相当于乘以32,同样<<2相当于乘以4


#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) //addr&0xF0000000:?ùéèê?????GPIOAμ??3????£?0x4001080C,???′?a???????μ?í?á°?2??à?éμ????á±?μ?£?±?3é0x4000 0000
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 
//GPIO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C 
#define GPIOB_ODR_Addr    (GPIOB_BASE+12) //0x40010C0C 
#define GPIOC_ODR_Addr    (GPIOC_BASE+12) //0x4001100C 
#define GPIOD_ODR_Addr    (GPIOD_BASE+12) //0x4001140C 
#define GPIOE_ODR_Addr    (GPIOE_BASE+12) //0x4001180C 
#define GPIOF_ODR_Addr    (GPIOF_BASE+12) //0x40011A0C    
#define GPIOG_ODR_Addr    (GPIOG_BASE+12) //0x40011E0C    

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 
#define GPIOB_IDR_Addr    (GPIOB_BASE+8) //0x40010C08 
#define GPIOC_IDR_Addr    (GPIOC_BASE+8) //0x40011008 
#define GPIOD_IDR_Addr    (GPIOD_BASE+8) //0x40011408 
#define GPIOE_IDR_Addr    (GPIOE_BASE+8) //0x40011808 
#define GPIOF_IDR_Addr    (GPIOF_BASE+8) //0x40011A08 
#define GPIOG_IDR_Addr    (GPIOG_BASE+8) //0x40011E08 
 
//GPIO口操作,只对单一的GPIO口,确保n值小于16;
#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //输出 
#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //输入 

#define PBout(n)   BIT_ADDR(GPIOB_ODR_Addr,n)  //输出 
#define PBin(n)    BIT_ADDR(GPIOB_IDR_Addr,n)  //输入 

#define PCout(n)   BIT_ADDR(GPIOC_ODR_Addr,n)  //输出 
#define PCin(n)    BIT_ADDR(GPIOC_IDR_Addr,n)  //输入 

#define PDout(n)   BIT_ADDR(GPIOD_ODR_Addr,n)  //输出 
#define PDin(n)    BIT_ADDR(GPIOD_IDR_Addr,n)  //输入 

#define PEout(n)   BIT_ADDR(GPIOE_ODR_Addr,n)  //输出 
#define PEin(n)    BIT_ADDR(GPIOE_IDR_Addr,n)  //输入

#define PFout(n)   BIT_ADDR(GPIOF_ODR_Addr,n)  //输出 
#define PFin(n)    BIT_ADDR(GPIOF_IDR_Addr,n)  //输入

#define PGout(n)   BIT_ADDR(GPIOG_ODR_Addr,n)  //输出 
#define PGin(n)    BIT_ADDR(GPIOG_IDR_Addr,n)  //输入

#endif

led.c代码段:

#include "stm32f10x.h"                  // Device header
#include"led.h"

void led_init(void)
{
	
	GPIO_InitTypeDef GPIO_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);//使能或者失能 AHB 外设时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//GPIO_Speed 用以设置选中管脚的速率。//GPIO_Speed_50MHz 最高输出速率 50MHz
	GPIO_InitStructure.GPIO_Mode =	GPIO_Mode_Out_PP;//GPIO_Mode 用以设置选中管脚的工作状态 //GPIO_Mode_Out_PP 推挽输出
	GPIO_Init(GPIOC,&GPIO_InitStructure);//根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
	
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//设置指定的数据端口位
}

void led_on(void)
{
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);//设置或者清除指定的数据端口位//Bit_SET: 设置数据端口位//Bit_RESET: 清除数据端口位
}



void led_off(void)
{
	GPIO_SetBits(GPIOC,GPIO_Pin_13);//设置指定的数据端口位
}


led.h代码段:

#ifndef __LED_H_
#define __LED_H_

void led_init(void);
void led_on(void);
void led_off(void);


#endif

exti.c代码段:

#include "stm32f10x.h"                  // Device header
#include"led.h"
#include"exti.h"
#include"sys.h"



void exti_init(void)
{
  	EXTI_InitTypeDef EXTI_InitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	/*使能GPIO时钟 PA 使能AFIO时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);
	//RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	/*配置PA0上拉输入模式*/
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;//GPIO_Mode 用以设置选中管脚的工作状态。 //上拉输入模式  低电平有效
	GPIO_Init(GPIOA,&GPIO_InitStructure);//根据 GPIO_InitStruct 中指定的参数初始化外设 GPIOx 寄存器
	
	/*连接EXT0 到 PA0 引脚*/
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource0);//选择 GPIO 管脚用作外部中断线路
	
	/*配置EXTI0 */
	EXTI_InitStructure.EXTI_Line = EXTI_Line0;//EXTI_Line 选择了待使能或者失能的外部线路。 //EXTI_Line0外部中断线 0
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;//设置 EXTI 线路为中断请求
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//EXTI_Trigger 设置了被使能线路的触发边沿。//EXTI_Mode_Interrupt设置输入线路下降沿为中断请求
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;//EXTI_LineCmd 用来定义选中线路的新状态
	EXTI_Init(&EXTI_InitStructure);//根据 EXTI_InitStruct 中指定的参数初始化外设 EXTI 寄存器
	
	/*配置EXTI0优先级及中断向量入口地址 */
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;//NVIC_IRQChannel 该参数用以使能或者失能指定的 IRQ 通道。
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//该参数设置了成员 NVIC_IRQChannel 中的先占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//该参数设置了成员 NVIC_IRQChannel 中的从优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;//该参数指定了在成员 NVIC_IRQChannel 中定义的 IRQ 通道被使能还是失能。
	NVIC_Init(&NVIC_InitStructure);//根据 NVIC_InitStruct 中指定的参数初始化外设 NVIC 寄存器
	
}

void EXTI0_IRQHandler(void)
{
	if(EXTI_GetITStatus(EXTI_Line0) != RESET) //SET  // EXTI_GetITStatus检查指定的 EXTI 线路触发请求发生与否//EXTI_Line0 外部中断线 0
	{
		PCout(13)^=1;//对1进行异或操作哦,进而实现按键使LED一亮一灭
		
		EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位
	}
}	

exti.h代码段:

#ifndef _EXTI_H__
#define _EXTI_H__


void exti_init(void);

#endif

代码总体布局:

 现象展示:

STM32外部中断控制LED亮灭

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值