实训day4|stm32f407外部中断

方法步骤

在这里插入图片描述

How to use this driver里就讲述了怎么运用,此处是设置exti(中断),像之前的gpio操作步骤亦是如此。点击相应的文档How to use this driver处就可以知道如何操作了
在这里插入图片描述

注意:有些函数需要往下寻找,比如清除中断标志位(下面的步骤6)
在这里插入图片描述

以下是exti的步骤:

  1. 使能SYSCFG时钟:RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE)
  2. IO口初始化为输入:GPIO_Init()
  3. 设置IO口与中断线的映射关系:SYSCFG_EXTILineConfig()
  4. 设置触发外部中断的条件:EXTI_Init()
  5. 配置中断分组(NVIC)并且使能中断:NVIC_Init()
  6. 清除中断标志位:EXTI_ClearITPendingBit()
  7. 编写中断服务函数(这个是在.s文件里):EXTIx_IRQHandler()
    在这里插入图片描述
    在设置函数的相关参数时双击对应参数,然后右击选择Go To Definition Of ‘XXX’,层层递进查阅相关操作

代码

main.c

#include "led.h"
#include "sys.h"
#include "exti.h"
#include "delay.h"

int main(void)
{
	/*初始化*/
	LED_init();
	led_off();
	
	Exti_Init();			//按一下灯亮,再按一下灯灭
	return 0;
}

sys.h

#ifndef __SYS_H__
#define __SYS_H__

//位带操作
//IO口操作宏定义
#define BITBAND(addr, bitnum) (0x42000000 +((addr-0x40000000)<<5)+(bitnum<<2)) 
#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 
#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

//IO口地址映射
#define GPIOA_ODR_Addr    (GPIOA_BASE+20) //0x40020014
#define GPIOB_ODR_Addr    (GPIOB_BASE+20) //0x40020414 
#define GPIOC_ODR_Addr    (GPIOC_BASE+20) //0x40020814 
#define GPIOD_ODR_Addr    (GPIOD_BASE+20) //0x40020C14 
#define GPIOE_ODR_Addr    (GPIOE_BASE+20) //0x40021014 
#define GPIOF_ODR_Addr    (GPIOF_BASE+20) //0x40021414      20 = 0x14
#define GPIOG_ODR_Addr    (GPIOG_BASE+20) //0x40021814   
#define GPIOH_ODR_Addr    (GPIOH_BASE+20) //0x40021C14    
#define GPIOI_ODR_Addr    (GPIOI_BASE+20) //0x40022014     

#define GPIOA_IDR_Addr    (GPIOA_BASE+16) //0x40020010 
#define GPIOB_IDR_Addr    (GPIOB_BASE+16) //0x40020410 
#define GPIOC_IDR_Addr    (GPIOC_BASE+16) //0x40020810 
#define GPIOD_IDR_Addr    (GPIOD_BASE+16) //0x40020C10 
#define GPIOE_IDR_Addr    (GPIOE_BASE+16) //0x40021010 
#define GPIOF_IDR_Addr    (GPIOF_BASE+16) //0x40021410       16 = 0x10
#define GPIOG_IDR_Addr    (GPIOG_BASE+16) //0x40021810 
#define GPIOH_IDR_Addr    (GPIOH_BASE+16) //0x40021C10 
#define GPIOI_IDR_Addr    (GPIOI_BASE+16) //0x40022010 
 
//IO口操作,只对单一的IO口!
//确保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)  //输入

#define PHout(n)   BIT_ADDR(GPIOH_ODR_Addr,n)  //输出 
#define PHin(n)    BIT_ADDR(GPIOH_IDR_Addr,n)  //输入

#define PIout(n)   BIT_ADDR(GPIOI_ODR_Addr,n)  //输出 
#define PIin(n)    BIT_ADDR(GPIOI_IDR_Addr,n)  //输入

#endif			//此行后面留一行空不然会有警告,可能是代码规范问题吧


delay.h

#ifndef __DELAY_H__
#define __DELAY_H__

#include "stm32f4xx.h"

void delay_us(unsigned int nus);
void delay_ms(unsigned int nms);
void delay_s(unsigned int ns);
#endif			//此行后面留一行空不然会有警告


led.h

#ifndef __LED_H__
#define __LED_H__

#include "stm32f4xx.h"

void LED_init(void);
void led_off(void);


#endif			//此行后面留一行空不然会有警告


exti.h

#ifndef __EXTI_H__
#define __EXTI_H__

#include "stm32f4xx.h"
void Exti_Init(void);

#endif

delay.c

#include "delay.h"

void delay_us(unsigned int nus)
{
	SysTick->LOAD = (168000000/8/1000000)*nus;//重装载值
	SysTick->CTRL |= 1;//使能CTRL开始计数
	SysTick->VAL = 0;
	while((SysTick->CTRL & (1<<16))==0);
	SysTick->CTRL &= ~1;//失能CTRL开始计数
	SysTick->VAL = 0;
}
//最多能帮你延时 798.9 ms
void delay_ms(unsigned int nms)
{
	SysTick->LOAD = (168000000/8/1000)*nms;//重装载值
	SysTick->CTRL |= 1;//使能CTRL开始计数
	SysTick->VAL = 0;
	while((SysTick->CTRL & (1<<16))==0);
	SysTick->CTRL &= ~1;//失能CTRL开始计数
	SysTick->VAL = 0;
}

void delay_s(unsigned int ns)
{
	while(ns--)
	{
		delay_ms(500);
		delay_ms(500);
	}
}


led.c

#include "led.h"

void LED_init(void)
{
	GPIO_InitTypeDef A;
	
	//必须先初始化时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOF | RCC_AHB1Periph_GPIOE | RCC_AHB1Periph_GPIOE, ENABLE);
	
	A.GPIO_Pin =      GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;//PF8   PF9   PF10
	A.GPIO_Mode =    GPIO_Mode_OUT;//输出模式
	A.GPIO_OType =   GPIO_OType_PP;//推挽输出
	A.GPIO_PuPd =    GPIO_PuPd_UP;//上拉
	A.GPIO_Speed =   GPIO_Fast_Speed;//高速   50MHz
	GPIO_Init(GPIOF,&A);

	A.GPIO_Pin =     GPIO_Pin_13 | GPIO_Pin_14;//PE13  PE14
	A.GPIO_Mode =    GPIO_Mode_OUT;//输出模式
	A.GPIO_OType =   GPIO_OType_PP;//推挽输出
	A.GPIO_PuPd =    GPIO_PuPd_UP;//上拉
	A.GPIO_Speed =   GPIO_Fast_Speed;//高速   50MHz
	GPIO_Init(GPIOE,&A);

}

void led_off()
{
	GPIO_SetBits(GPIOF,GPIO_Pin_9 | GPIO_Pin_10);
	GPIO_SetBits(GPIOE,GPIO_Pin_13 | GPIO_Pin_14);
}


exti.c

#include "exti.h"
#include "sys.h"
void Exti_Init(void)
{
	GPIO_InitTypeDef GPIO_InitStruct;
	EXTI_InitTypeDef EXTI_InitStruct;
	NVIC_InitTypeDef NVIC_InitStruct;
	//必须先初始化时钟
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOE, ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
	
	GPIO_InitStruct.GPIO_Pin   =   GPIO_Pin_0;//PA0
	GPIO_InitStruct.GPIO_Mode  =   GPIO_Mode_IN;//输入模式
	GPIO_InitStruct.GPIO_OType =   GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_PuPd  =   GPIO_PuPd_UP;//上拉
	GPIO_InitStruct.GPIO_Speed =   GPIO_Fast_Speed;//高速   50MHz
	GPIO_Init(GPIOA,&GPIO_InitStruct);
    
	GPIO_InitStruct.GPIO_Pin   =   GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4;//PE3  PE4   PE2
	GPIO_InitStruct.GPIO_Mode  =   GPIO_Mode_IN;//输入模式
	GPIO_InitStruct.GPIO_OType =   GPIO_OType_PP;//推挽输出
	GPIO_InitStruct.GPIO_PuPd  =   GPIO_PuPd_UP;//上拉
	GPIO_InitStruct.GPIO_Speed =   GPIO_Fast_Speed;//高速   50MHz
	GPIO_Init(GPIOE,&GPIO_InitStruct);
	
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA,EXTI_PinSource0);//PA0  ---》EXTI0
	
	EXTI_InitStruct.EXTI_Line    =  EXTI_Line0;//PA0  ---》EXTI0
	EXTI_InitStruct.EXTI_LineCmd =  ENABLE;//使能
	EXTI_InitStruct.EXTI_Mode    =  EXTI_Mode_Interrupt;//中断
	EXTI_InitStruct.EXTI_Trigger =  EXTI_Trigger_Falling;//下降沿触发
	EXTI_Init(&EXTI_InitStruct);
	
	NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//EXTI0
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x1;//抢占优先级   0-3
	NVIC_InitStruct.NVIC_IRQChannelSubPriority =0x3;//响应优先级           0-3
	NVIC_Init(&NVIC_InitStruct); 	
}

//中断服务函数     在startup_stm32f40_41xxx.s 里面找
void EXTI0_IRQHandler(void)
{
	//判断确实进中断
	if(EXTI_GetITStatus(EXTI_Line0)==SET)
	{
		delay_xd(5);
		//立马清楚中断线
		EXTI_ClearITPendingBit(EXTI_Line0);
		PFout(9)=!PFout(9);
	
	}
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值