STM32外部中断实验控制按键点亮LED和控制蜂鸣器

## 开发手册讲解

 

 

 

 ## 开发步骤

一,NVIC总体控制函数编写

1.使能外设中断,                   这个具体是由外设相关中断使能位来控制,比如定时 器有溢出中断,这个可由定时器的控制寄存器中相应中断使能位来控制

 2.)设置中断优先级分组,       初始化 NVIC_InitTypeDef 结构体,设置抢占 优先级和响应优先级,使能中断请求。

3.编写中断服务函数

二.exti外部中断函数编写(ps:优先级分组在结构体中先分组,然后再在主函数中设置分组)

(1)使能 IO 口时钟,               配置 IO 口模式为输入     由于本章使用开发板上 4 个按键 IO 口作为外部中断输入线,因此需要使能 对应的 IO 口时钟及配置 IO 口模式,在按键实验章节中,我们就介绍过要把对应 IO 口设置为输入模式,这部分配置与按键实验一样。

(2)开启 AFIO 时钟,                   设置 IO 口与中断线的映射关系 接下来我们需要将 GPIO 映射到对应的中断线上,只要使用到外部中断,就 必须先使能 AFIO 时钟,前面已经说了它是挂接在 APB2 总线上的,所以使能 AFIO 时钟库函数

(3)配置中断分组(NVIC),                          使能中断 我们知道 EXTI 产生中断线路最终是流向 NVIC 控制器的,由 NVIC 调用中断 服务函数,因此我们需要对 NVIC 进行配置。

(4)初始化 EXTI,选择触发方式

## exti.h

#ifndef _exti_H
#define _exti_H

#include "system.h"

void MY_EXTI_Init();






#endif

## exti.c

#include "exti.h"
#include "key.h"
#include "led.h"
#include "beep.h"
#include "SysTick.h"
void MY_EXTI_Init()
{
	NVIC_InitTypeDef NVIC_InitStructure;
	EXTI_InitTypeDef EXTI_InitStructure;
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO , ENABLE );
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource2);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource3);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOE, GPIO_PinSource4);

	NVIC_InitStructure.NVIC_IRQChannel=EXTI0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占式优先级,按自己需求配置
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=3;//响应式优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);

	NVIC_InitStructure.NVIC_IRQChannel=EXTI2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);

  NVIC_InitStructure.NVIC_IRQChannel=EXTI3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=1;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);
 
  NVIC_InitStructure.NVIC_IRQChannel=EXTI4_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority=0;
	NVIC_InitStructure.NVIC_IRQChannelCmd=ENABLE;
	
	NVIC_Init(&NVIC_InitStructure);

	
	EXTI_InitStructure.EXTI_Line=EXTI_Line0;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Rising;//KEY_UP高电平触发,因此要用上升沿
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;

	EXTI_Init(&EXTI_InitStructure);

	EXTI_InitStructure.EXTI_Line=EXTI_Line2 | EXTI_Line3 | EXTI_Line4;
	EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//KEY012低电平触发,因此要用下降沿
	EXTI_InitStructure.EXTI_LineCmd=ENABLE;

	EXTI_Init(&EXTI_InitStructure);
}

void EXTI0_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line0)==SET)//检查中断标志
	{
		delay_ms(10);
		if(KEY_UP==1)
		{
			LED2=0;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志
}
void EXTI2_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line2)==SET)//检查中断标志
	{
		delay_ms(10);
		if(KEY2==0)
		{
			BEEP=1;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line2);//清除中断标志
}
void EXTI3_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line3)==SET)//检查中断标志
	{
		delay_ms(10);
		if(KEY1==0)
		{
			LED2=1;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line3);//清除中断标志
}
void EXTI4_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line4)==SET)//检查中断标志
	{
		delay_ms(10);
		if(KEY0==0)
		{
			BEEP=0;
		}
	}
	EXTI_ClearITPendingBit(EXTI_Line4);//清除中断标志
}

##main.c

#include "stm32f10x.h"
#include "led.h"
#include "system.h"
#include "SysTick.h"
#include "beep.h"
#include "key.h"
#include "exti.h"
int main()
{
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置优先级分组
	u8 i=0;
  SysTick_Init(72);
	BEEP_Init();
	LED_Init();
	KEY_Init();
	MY_EXTI_Init();
	while(1)
	{
	
		i++;
		if(i%20==0)
			LED1=!LED1;//指示灯亮提示机器正在运行
		delay_ms(10);
		
	}
}

  • 3
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,这是一个常见的嵌入式系统应用场景,可以按照以下步骤实现: 1. 配置定时器 首先,需要配置一个定时器,可以选择TIM2,TIM3等定时器。在初始化定时器时,需要设置定时器的预分频系数,以及计数器的自动重载值和工作模式等参数。例如,设置TIM2为1ms的定时器: ```c RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_TimeBaseStructure.TIM_Prescaler = 72 - 1; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseStructure.TIM_Period = 1000 - 1; TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure); TIM_Cmd(TIM2, ENABLE); ``` 2. 配置按键中断 接着,需要配置一个外部中断,以便按键按下时可以触发中断,并执行相应的操作。在初始化外部中断时,需要设置中断触发方式(上升沿/下降沿/双边沿触发)、中断优先级、以及使能中断等参数。例如,配置PA0引脚上的按键为下降沿触发中断: ```c GPIO_InitTypeDef GPIO_InitStructure; EXTI_InitTypeDef EXTI_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_Init(GPIOA, &GPIO_InitStructure); SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0); EXTI_InitStructure.EXTI_Line = EXTI_Line0; EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising_Falling; EXTI_InitStructure.EXTI_LineCmd = ENABLE; EXTI_Init(&EXTI_InitStructure); NVIC_InitStructure.NVIC_IRQChannel = EXTI0_1_IRQn; NVIC_InitStructure.NVIC_IRQChannelPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); ``` 3. 实现中断服务函数 当按键被按下时,会触发中断服务函数,可以在中断服务函数中执行相应的操作。例如,每次按键按下时,LED会闪烁一次: ```c void EXTI0_1_IRQHandler(void) { if (EXTI_GetITStatus(EXTI_Line0) != RESET) { LED_Toggle(); EXTI_ClearITPendingBit(EXTI_Line0); } } ``` 4. 控制LED闪烁 最后,可以在定时器的中断服务函数中控制LED的闪烁。例如,每100ms改变一次LED的状态: ```c void TIM2_IRQHandler(void) { if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET) { LED_Toggle(); TIM_ClearITPendingBit(TIM2, TIM_IT_Update); } } ``` 这样,当按键按下时,LED会闪烁一次,而定时器中断服务函数会每100ms改变一次LED的状态,从而实现LED的闪烁。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值