打印
[应用相关]

STM32的外部中断

[复制链接]
642|37
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
实验目的:

当按键按下时,让PF10引脚的LED灯亮,
当按键再次按下时,让PF10引脚的LED灯灭;
无论按下与否,PF9引脚的LED灯循环闪烁;

使用特权

评论回复
沙发
键盘手没手|  楼主 | 2022-3-29 15:23 | 只看该作者
实验步骤:

使用特权

评论回复
板凳
键盘手没手|  楼主 | 2022-3-29 15:23 | 只看该作者
实验程序:
/***********************************led.c*********************************/
#include 'stm32f4xx.h'  //在SYSTEM目录下可以找到
#include 'sys.h'
void LED_Init(void){
        RCC->AHB1ENR = 1<<5;  //使能GPIO端口的F时钟
        GPIO_Set(GPIOF,PIN9|PIN10,GPIO_MODE_OUT,GPIO_OTYPE_PP,GPIO_SPEED_25M,GPIO_PUPD_PU);
        PFout(9) = 1;
        PFout(10) = 1;
}

/***********************************led.h*********************************/
#ifndef _LED_H
#define _LED_H
void LED_Init(void);
#endif

/********************************************key.c***************************************/
#include 'sys.h'
void Key_Init(void){
        RCC->AHB1ENR|=1<<4;     //使能PORTE时钟
        //void GPIO_Set(GPIO_TypeDef* GPIOx,u32 BITx,u32 MODE,u32 OTYPE,u32 OSPEED,u32 PUPD);//GPIO设置函数
        GPIO_Set(GPIOE,PIN3,GPIO_MODE_IN,0,0,GPIO_PUPD_PU);        //PE3设置上拉输入,这样的话,
                                                                //当按键没有按下时,默认电平为高;
}


/********************************************key.h***************************************/
#ifndef _KEY_H
#define _KEY_H
void Key_Init(void);
#endif


/************************************exti.c********************************/
#include 'sys.h'
#include 'delay.h'
#include 'stm32f4xx.h'
/*

使用特权

评论回复
地板
键盘手没手|  楼主 | 2022-3-29 15:25 | 只看该作者
本示例的作用就是,
当按键按下时,蜂鸣器发出声音,
当按键再次按下时,蜂鸣器静音;
*/
/*
中断初始化函数:
主要是关于寄存器的相关配置
*/
void EXTI3_Init(void){
        //方法一:
        RCC->APB2ENR |= 1 << 14;  //开启SYSCFG时钟
        SYSCFG->EXTICR[0] |= 0x4 << 12;//设置IO口与中断线的映射关系;
        EXTI->IMR |= 1 << 3;  //开启对应中断线上的中断
        EXTI->FTSR |= 1 << 3;  //设置中断触发条件
        //SCB和NVIC,可参考STM32F3与STM32F4系列Cortex M4内核编程手册.pdf
        SCB->AIRCR |= 0x5 << 8; //设置分组
        NVIC->IP[9] |= 0; //设置优先级,具体可分析MY_NVIC_Init()函数;
        NVIC->ISER[0] |= 1 << 9;  //使能中断;
        //方法二:
/************************************
        使用SYSTEM目录下提供的API来实现,
        具体可参考正点原子示例
************************************/
}
void EXTI3_IRQHandler(void){
        /*
        此按键,在按键按下时,处理不是很到位,
        有待进一步改进,主要是在连按那一个环节。
        */
        delay_ms(20);  //消抖
        if(PEin(3) == 0){
                PFout(10) = !PFout(10);
        }
        /*
        在中断里边最后记得清中断:
        */
        EXTI->PR |= 1 << 3;
}

使用特权

评论回复
5
键盘手没手|  楼主 | 2022-3-29 15:26 | 只看该作者
/*************************************exti.h*******************************/
#ifndef _EXTI_H
#define _EXTI_H
void EXTI3_Init(void);
#endif

使用特权

评论回复
6
键盘手没手|  楼主 | 2022-3-29 15:27 | 只看该作者
/*************************************test.c*******************************/
#include 'sys.h'
#include 'delay.h'
#include 'key.h'
#include 'beep.h'
#include 'exti.h'
#include 'led.h'
//int i = 0;
int main(void){
        Stm32_Clock_Init(336,8,2,7);//设置时钟,168Mhz  
        delay_init(168);                //初始化延时函数
        Beep_Init();
        Key_Init();
        EXTI3_Init();
        LED_Init();
        while(1){
                PFout(9) = 0;
                delay_ms(500);
                PFout(9) = 1;
                delay_ms(500);
        }
}

使用特权

评论回复
7
键盘手没手|  楼主 | 2022-3-29 15:27 | 只看该作者
实验分析:

我们主要分析一下exti.c中的寄存器设置的这几个步骤:

1. RCC->APB2ENR |= 1 << 14;

这一步的作用就是使能SYSCFG时钟,

在使用外部中断的时候一定要先使能SYSCFG时钟;

使用特权

评论回复
8
键盘手没手|  楼主 | 2022-3-29 15:28 | 只看该作者
2. SYSCFG->EXTICR[0] |= 0x4 << 12;

这一步的作用就是设置IO口与中断线的映射关系;

那么问题来了,我如何知道的我的IO口与哪根中断线是关联起来的呢?

使用特权

评论回复
9
键盘手没手|  楼主 | 2022-3-29 15:29 | 只看该作者

使用特权

评论回复
10
键盘手没手|  楼主 | 2022-3-29 15:30 | 只看该作者
而我们是通过KEY1按键,对应的IO口就是PE3,所以由上图的映射关系,我们知道,我们应该选择中断线3与之对应;

使用特权

评论回复
11
键盘手没手|  楼主 | 2022-3-29 16:35 | 只看该作者
在官方提供的头文件stm32f4xx.h中,我们可以看到:

typedef struct
{
  __IO uint32_t MEMRMP;       /*!< SYSCFG memory remap register,                      Address offset: 0x00      */
  __IO uint32_t PMC;          /*!< SYSCFG peripheral mode configuration register,     Address offset: 0x04      */
  __IO uint32_t EXTICR[4];    /*!< SYSCFG external interrupt configuration registers, Address offset: 0x08-0x14 */
  uint32_t      RESERVED[2];  /*!< Reserved, 0x18-0x1C                                                          */
  __IO uint32_t CMPCR;        /*!< SYSCFG Compensation cell control register,         Address offset: 0x20      */
} SYSCFG_TypeDef;

使用特权

评论回复
12
键盘手没手|  楼主 | 2022-3-29 16:36 | 只看该作者

使用特权

评论回复
13
键盘手没手|  楼主 | 2022-3-29 16:38 | 只看该作者
结合上述三幅图,我们可以得知:

由于PE3对应的中断线为EXTI3,所以,我们我们这里仅需配置EXTI3,而EXTI3是在SYSCFG_EXTICR1中的;

所以我们仅需配置SYSCFG_EXTICR1寄存器的12位-15位为0100,而SYSCFG_EXTICR1寄存器在配置文件中,

对应的是SYSCFG->EXTICR[0],所以我们就写成了SYSCFG->EXTICR[0] |= 0x4 << 12;

使用特权

评论回复
14
键盘手没手|  楼主 | 2022-3-29 16:40 | 只看该作者
3. EXTI->IMR |= 1 << 3;

这条语句的作用就是:开启对应中断线上的中断

由于我们操作的中断线是EXTI3,而IMR寄存器各位解释如下:

使用特权

评论回复
15
键盘手没手|  楼主 | 2022-3-29 16:41 | 只看该作者
所以对应的,我们操作EXTI_IMR寄存器的第3位MR3即可;

所以这条语句就写成了:EXTI->IMR |= 1 << 3

使用特权

评论回复
16
键盘手没手|  楼主 | 2022-3-29 16:42 | 只看该作者
4. EXTI->FTSR |= 1 << 3;

这条语句的作用就是设置中断触发条件;

在我的开发板中,当按键按下时,其端口就会变成低电平,在没有按下时,其是为高电平的;

因为我们key.c中,将按键的引脚设置成了上拉;所以在这里,我得将其设置成下降沿触发;

使用特权

评论回复
17
键盘手没手|  楼主 | 2022-3-29 16:42 | 只看该作者

使用特权

评论回复
18
键盘手没手|  楼主 | 2022-3-29 16:43 | 只看该作者
又由于我们这条中断线是中断线3,所以这条语句就写成了:EXTI->FTSR |= 1 << 3

使用特权

评论回复
19
键盘手没手|  楼主 | 2022-3-29 16:44 | 只看该作者
5. SCB->AIRCR |= 0x5 << 8;

这条语句的作用就是:设置分组;

使用特权

评论回复
20
键盘手没手|  楼主 | 2022-3-29 16:45 | 只看该作者

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

104

主题

1179

帖子

0

粉丝