历史上的今天
返回首页

历史上的今天

今天是:2024年12月16日(星期一)

正在发生

2021年12月16日 | STM32F429--EXTI外部中断/事件控制器

2021-12-16 来源:eefocus

EXTI:External interrupt /event controll

具体的表现形式为


导致                 

外部的高低电平变化------------->中断/事件发生(需要配置NVIC)


外部中断/事件控制器功能框图

在这里插入图片描述

具体可以分为两部分:

1- 中断(下图的1,2,3,4,5)

2- 事件(下图的1,2,3,6,7,8)

在这里插入图片描述

由上图可知,外部中断是挂载到APB总线上的,/23表示有23根结构相同的线。

(详情看stm32f4xx的中文参考手册第十章第二小节部分,下面对应的10.x.x代表手册对应章节部分)


1处:输入线

10.2.5 SYSCFG外部中断配置寄存器,16X9=144个GPIO口

在这里插入图片描述
在这里插入图片描述

与上图类似,总共16条

SYSCFG_EXTICR2 EXTIx x(4~7)

SYSCFG_EXTICR3 EXTIx x(8~11)

SYSCFG_EXTICR4 EXTIx x(12~15)

剩余的7条

在这里插入图片描述

2处:边沿检测电路

在这里插入图片描述

3处:软件中断屏蔽寄存器

在这里插入图片描述

事件屏蔽寄存器如下

在这里插入图片描述

4处:挂起寄存器

在这里插入图片描述

5处:NVIC

具体查看官方的misc.h54行,73行(有点多就不一一列举),或者看ARM-Cortex-M4内核的官方手册说明,看名字就可以知道大概意思了,下面是部分截图。

在这里插入图片描述

实验设计

需求

1.PA0连接到EXTI用于产生中断,PA0的电平变化通过按键来控制

2.产生一次中断,LED翻转一次

编程须知:

打开开发板原理图,PA0是按键的连接引脚,默认被地拉低低电平,需要上升沿触发

编程要点:

1.初始化要连接到EXTI的GPIO

2.初始化EXTI用于产生中断事件

3.初始化NVIC,用于处理中断

4.编写中断服务函数

5.main函数


1.bsp_led.c


#include "./led/bsp_led.h"   


 /**

  * @brief  初始化控制LED的IO

  */

void LED_GPIO_Config(void)

{

/*定义一个GPIO_InitTypeDef类型的结构体*/

GPIO_InitTypeDef GPIO_InitStructure;


/*开启LED相关的GPIO外设时钟*/

RCC_AHB1PeriphClockCmd ( LED1_GPIO_CLK|LED2_GPIO_CLK|LED3_GPIO_CLK|LED4_GPIO_CLK, ENABLE); 


/*选择要控制的GPIO引脚*/    

GPIO_InitStructure.GPIO_Pin = LED1_PIN;


/*设置引脚模式为输出模式*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;   

    

    /*设置引脚的输出类型为推挽输出*/

    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;

    

    /*设置引脚为上拉模式*/

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;


/*设置引脚速率为2MHz */   

GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz; 


/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/

GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStructure);

    

    /*选择要控制的GPIO引脚*/    

GPIO_InitStructure.GPIO_Pin = LED2_PIN;

    GPIO_Init(LED2_GPIO_PORT, &GPIO_InitStructure);

    

    /*选择要控制的GPIO引脚*/    

GPIO_InitStructure.GPIO_Pin = LED3_PIN;

    GPIO_Init(LED3_GPIO_PORT, &GPIO_InitStructure);

/*选择要控制的GPIO引脚*/    

GPIO_InitStructure.GPIO_Pin = LED4_PIN;

    GPIO_Init(LED4_GPIO_PORT, &GPIO_InitStructure);

/*关闭RGB灯*/

LED_RGBOFF;

/*指示灯默认开启*/

LED4(ON);

}


2.bsp_led.h


#ifndef __LED_H

#define __LED_H


#include "stm32f4xx.h"


//引脚定义

/*******************************************************/

//R 红色灯

#define LED1_PIN                  GPIO_Pin_10                 

#define LED1_GPIO_PORT            GPIOH                      

#define LED1_GPIO_CLK             RCC_AHB1Periph_GPIOH


//G 绿色灯

#define LED2_PIN                  GPIO_Pin_11                 

#define LED2_GPIO_PORT            GPIOH                      

#define LED2_GPIO_CLK             RCC_AHB1Periph_GPIOH


//B 蓝色灯

#define LED3_PIN                  GPIO_Pin_12                 

#define LED3_GPIO_PORT            GPIOH                       

#define LED3_GPIO_CLK             RCC_AHB1Periph_GPIOH


//小指示灯

#define LED4_PIN                  GPIO_Pin_11                 

#define LED4_GPIO_PORT            GPIOD                       

#define LED4_GPIO_CLK             RCC_AHB1Periph_GPIOD

/************************************************************/


/** 控制LED灯亮灭的宏,

* LED低电平亮,设置ON=0,OFF=1

* 若LED高电平亮,把宏设置成ON=1 ,OFF=0 即可

*/

#define ON  0

#define OFF 1


/* 带参宏,可以像内联函数一样使用 */

#define LED1(a) if (a)

GPIO_SetBits(LED1_GPIO_PORT,LED1_PIN);

else

GPIO_ResetBits(LED1_GPIO_PORT,LED1_PIN)


#define LED2(a) if (a)

GPIO_SetBits(LED2_GPIO_PORT,LED2_PIN);

else

GPIO_ResetBits(LED2_GPIO_PORT,LED2_PIN)


#define LED3(a) if (a)

GPIO_SetBits(LED3_GPIO_PORT,LED3_PIN);

else

GPIO_ResetBits(LED3_GPIO_PORT,LED3_PIN)

#define LED4(a) if (a)

GPIO_SetBits(LED4_GPIO_PORT,LED4_PIN);

else

GPIO_ResetBits(LED4_GPIO_PORT,LED4_PIN)


/* 直接操作寄存器的方法控制IO */

#define digitalHi(p,i) {p->BSRRL=i;}   //设置为高电平

#define digitalLo(p,i) {p->BSRRH=i;} //输出低电平

#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态



/* 定义控制IO的宏 */

#define LED1_TOGGLE digitalToggle(LED1_GPIO_PORT,LED1_PIN)

#define LED1_OFF digitalHi(LED1_GPIO_PORT,LED1_PIN)

#define LED1_ON digitalLo(LED1_GPIO_PORT,LED1_PIN)


#define LED2_TOGGLE digitalToggle(LED2_GPIO_PORT,LED2_PIN)

#define LED2_OFF digitalHi(LED2_GPIO_PORT,LED2_PIN)

#define LED2_ON digitalLo(LED2_GPIO_PORT,LED2_PIN)


#define LED3_TOGGLE digitalToggle(LED3_GPIO_PORT,LED3_PIN)

#define LED3_OFF digitalHi(LED3_GPIO_PORT,LED3_PIN)

#define LED3_ON digitalLo(LED3_GPIO_PORT,LED3_PIN)


#define LED4_TOGGLE digitalToggle(LED4_GPIO_PORT,LED4_PIN)

#define LED4_OFF digitalHi(LED4_GPIO_PORT,LED4_PIN)

#define LED4_ON digitalLo(LED4_GPIO_PORT,LED4_PIN)



/* 基本混色,后面高级用法使用PWM可混出全彩颜色,且效果更好 */


//红

#define LED_RED 

LED1_ON;

LED2_OFF;

LED3_OFF


//绿

#define LED_GREEN

LED1_OFF;

LED2_ON;

LED3_OFF


//蓝

#define LED_BLUE

LED1_OFF;

LED2_OFF;

LED3_ON


//黄(红+绿)

#define LED_YELLOW

LED1_ON;

LED2_ON;

LED3_OFF

//紫(红+蓝)

#define LED_PURPLE

LED1_ON;

LED2_OFF;

LED3_ON


//青(绿+蓝)

#define LED_CYAN

LED1_OFF;

LED2_ON;

LED3_ON

//白(红+绿+蓝)

#define LED_WHITE

LED1_ON;

LED2_ON;

LED3_ON

//黑(全部关闭)

#define LED_RGBOFF

LED1_OFF;

LED2_OFF;

LED3_OFF


void LED_GPIO_Config(void);


#endif /* __LED_H */


3.bsp_exti.c

#include "bsp_exti.h"

//static关键字表明该函数仅在这个文件可以使用

//misc.h54行,misc.h的73行

static void EXTI_NVIC_Config(void)//内核中断外设,都在misc.c文件中,misc.h的73行

{

NVIC_InitTypeDef NVIC_InitStruct; //定义一个NVIC初始化结构体变量

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_1);//优先级分组

NVIC_InitStruct.NVIC_IRQChannel = KEY1_INT_EXTI_IRQ;//中断源

NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级

NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;//子优先级

NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//使能中断,大大门

NVIC_Init(&NVIC_InitStruct); //到此配置完毕

}


/*在stm32f4xx_exit.h文件的93行中,有EXTI初始化结构体

EXTI_InitTypeDef,然后初始化里面的成员,在80行。

值在105行*/

void EXTI_Key_Config(void)

{

/*定义一个GPIO_InitTypeDef类型的结构体*/

GPIO_InitTypeDef GPIO_InitStructure;

EXTI_InitTypeDef  EXTI_InitStruct;  //定义结构体变量


/*开启LED相关的GPIO外设时钟*/

RCC_AHB1PeriphClockCmd ( RCC_AHB1Periph_GPIOA, ENABLE);//打开AHB1总线时钟

/*选择要控制的GPIO引脚*/    

GPIO_InitStructure.GPIO_Pin =  KEY1_GPIO_PIN; //GPIOA的0脚

/*设置引脚模式为输入模式*/

GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;   //输入模式

    /*设置引脚为浮空模式*/

    GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//浮空,在stm32f4xx.gpio.h文件110行位置

/*调用库函数,使用上面配置的GPIO_InitStructure初始化GPIO*/

GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);//将引脚和结构体初始化完成


RCC_APB2PeriphClockCmd ( RCC_APB2Periph_SYSCFG, ENABLE);//用到了EXTI0,挂载到PLCLK2,要打开AHB2总线时钟

SYSCFG_EXTILineConfig(KEY1_INT_EXTI_PORTSOURCE, KEY1_INT_EXTI_PINSOURCE); //作用:把PA0连接到EXTI0.

//param1:中断源端口  GPIOA  

   //param2:中断源引脚  PA0

   

EXTI_InitStruct.EXTI_Line = KEY1_INT_EXTI_LINE; //PA0,选择EXTI0为输入线

EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;//设置模式为中断模式,另一个是事件模式

        EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;//设置触发方式为上升沿触发

EXTI_InitStruct.EXTI_LineCmd = ENABLE;//使能,打开大门

EXTI_Init(&EXTI_InitStruct);//在stm32f4xx_exti.h文件,把配置好的成员写到寄存器里面,到此初始化完毕。

EXTI_NVIC_Config();//调用NVIC中断控制器初始化函数。

}


3.bsp_exti.h


#ifndef __BSE_EXTI_H 

#define __BSE_EXTI_H 


#include "stm32f4xx.h"


#define KEY1_GPIO_PIN             GPIO_Pin_0                 

#define KEY1_GPIO_PORT            GPIOA                      

#define KEY1_GPIO_CLK             RCC_AHB1Periph_GPIOA

#define KEY1_INT_EXTI_LINE        EXTI_Line0


#define KEY1_INT_EXTI_PORTSOURCE  EXTI_PortSourceGPIOA

#define KEY1_INT_EXTI_PINSOURCE   EXTI_PinSource0

#define KEY1_INT_EXTI_IRQ         EXTI0_IRQn


#define KEY1_INT_EXTI_IRQHANDLER  EXTI0_IRQHandler //宏定义中断函数名称




#define KEY2_GPIO_PIN             GPIO_Pin_13                 

#define KEY2_GPIO_PORT            GPIOC                      

#define KEY2_GPIO_CLK             RCC_AHB1Periph_GPIOC



void EXTI_Key_Config(void);


#endif /* __BSE_EXTI_H */


5.stm32f4xx_it.h下面补充编写中断服务函数(一般中断服务函数放在这个地方)


#include "stm32f4xx_it.h"

#include "bsp_led.h"

#include "bsp_exti.h"


/*中断服务函数都写在stm32f4xx_it.c这个函数里面

名字怎么写?看启动文件startup_stm32f429_439xx.s,93行,

这个很重要,如果写错会一直死循环!!!!!!!!!!!

写在文件stm32f4xx_it.c中的函数如下:*/

void KEY1_INT_EXTI_IRQHANDLER(void)

{

if( ( EXTI_GetITStatus(KEY1_INT_EXTI_LINE) ) != RESET )

{

/* 干活 */

LED1_TOGGLE;

}

EXTI_ClearITPendingBit(KEY1_INT_EXTI_LINE);//清除中断标志位,勿忘勿忘

}


6.stm32f4xx_it.h 写着中断服务函数的名字及声明


#ifndef __STM32F4xx_IT_H

#define __STM32F4xx_IT_H


#ifdef __cplusplus

 extern "C" {

#endif 


/* Includes ------------------------------------------------------------------*/

#include "stm32f4xx.h"

推荐阅读

史海拾趣

ADI Electronics Inc公司的发展小趣事

在ADI的发展过程中,并购重组成为其实现规模扩张和增强竞争力的重要手段。其中,2017年对凌力尔特(Linear Technology)的收购是ADI历史上最具影响力的一次并购。这次收购使ADI快速进入电源管理芯片市场,并一跃成为全球第二大模拟芯片厂商。通过并购,ADI不仅扩大了自身的产品线,也提高了其在全球市场的份额和影响力。

C&K Components公司的发展小趣事

1957年,Charles A. Coolidge, Jr.和Marshall Kincaid共同创立了C&K Components公司,起初主要专注于磁芯记忆单元的制造。那个时代的电子行业刚刚起步,市场竞争激烈,技术更新换代迅速。C&K在初创时期就面临了诸多挑战,但两位创始人凭借对技术的热爱和对市场的敏锐洞察,坚持探索新的技术方向,为公司的发展奠定了坚实的基础。

Highland Electronics Co Ltd公司的发展小趣事

High Tech Chips Inc成立之初,便专注于研发高性能的AI芯片。在公司创始人李博士的带领下,团队突破了传统芯片设计的瓶颈,开发出了一款具有超低功耗和高效能比的AI加速器芯片。这款芯片迅速获得了市场的认可,被广泛应用于智能手机、智能家居和自动驾驶等领域。随着技术的不断迭代和产品的持续优化,High Tech Chips Inc逐渐在AI芯片市场占据了一席之地,并成为了行业内的技术领先者。

Altonics公司的发展小趣事

随着技术的不断进步,Altonics公司始终保持着对创新的热情。公司加大研发投入,引进高端技术人才,不断推出具有创新性和竞争力的新产品。其中,公司自主研发的一款智能传感器,凭借其高精度、高稳定性的特点,迅速占领市场份额,成为工业自动化领域的明星产品。

Foxboro I C T Inc公司的发展小趣事

Altonics公司创始人在XXXX年创建了这家公司,初期面临着资金短缺、市场竞争激烈和技术人才缺乏的困境。然而,创始人凭借对电子技术的深刻理解和敏锐的市场洞察力,决定专注于工业自动化控制领域的研发与生产。经过不懈的努力,公司成功开发出一款高性能的自动化控制设备,受到了市场的广泛认可,为公司的后续发展奠定了坚实的基础。

HBH-Microwave公司的发展小趣事

随着技术的不断成熟,HBH-Microwave开始将目光投向更为广阔的航空航天市场。公司凭借其高质量的微波组件和子系统,成功参与了多个国际知名的航天项目,如卫星通信系统和运载火箭的微波子系统。这些项目的成功实施,不仅展示了HBH在极端环境下的产品可靠性,也进一步拓宽了公司的业务范围和市场影响力。

问答坊 | AI 解惑

按Ctrl+Alt+delete没有反应

前天我用木马克星杀了一次毒,等杀完以后,再点击按Ctrl+Alt+delete的键时,系统没有任何反应,不弹出任务管理器,请问这是什么问题 请各位高手给以解答 在此万分感谢!!!…

查看全部问答>

变频器的几种控制方式

低压通用变频输出电压为380~650V,输出功率为0.75~400kW,工作频率为0~400Hz,它的主电路都采用交?直?交电路。其控制方式经历了以下四代。 1. U/f=C的正弦脉宽调制(SPWM)控制方式 其特点是控制电路结构简单、成本较低,机械特性硬度也较 ...…

查看全部问答>

【资料下载】STM32固件库1.0版使用说明的中文翻译

运行于EK-STM32F学习板上的STM32固件库中的例子 相关链接:http://www.stmicroelectronics.com.cn/stonline/mcu/images/STM32F10xxx_Library_Manual_ChineseV2.pdf…

查看全部问答>

请教香主,STM32有内置的硬件CRC计算单元吗?

请问香主,我在www.stmfans.com里面看到了一个帖子说STM32有内置的硬件CRC计算单元,我在库文件、datasheet上都没有找到。请问真是的是有吗?如果有,在那个模块?stmfans的链接如下:http://www.stmfans.com/bbs/viewthread.php?tid=325&high ...…

查看全部问答>

求教2812 ad问题

各位好:我在ad程序里添加了两个变量:float  in_voltage[NP]; float  step_h[NP];后出现这个错误error: can\\\'t allocate .ebss (sz: 00002898 page: 1) in DRAMH0 (avail:            ...…

查看全部问答>

can通讯

    有一个温度程序,用的是mc9s12xs128的,但是不知道怎么通过can输出,请高手指点。…

查看全部问答>

请问各位前辈帮指点一下晚辈 甚是感谢

请问各位前辈 我想知道怎么调节两相占空比相同 相位相差一定角度 比如60 度 90度 在430中应该怎么设定啊…

查看全部问答>

为什么定时器T0.c没有调用

define.h #include #define uchar unsigned char #define uint unsigned int sbit led1=P1^0; uchar num; main.c #include void main(void) { TMOD=0x01; TH0=(65536-45872)/256; TH0=(65536-45872)%256; EA=1; ET0=1; TR0=1; ...…

查看全部问答>

关于I2C发送

我用lm3s6432的i2c给从机发送三个字节的数据,为什么从机接收到四个字节的数据,而且第一个字节和第四个字节的值相同,哪位大侠知道原因,能不能告诉一下,这个问题纠结了一天了 谢谢谢谢!!…

查看全部问答>