STM32学习笔记——中断(2)

外部中断

认识外部中断

STM32的外部中断是一种用于检测和响应外部事件的机制。它允许微控制器在发生特定的外部信号变化时,立即暂停当前执行的任务,转而执行一个中断服务例程(ISR)。这对于处理时间敏感的任务,如按钮按下、传感器信号变化等,非常重要。
STM32芯片有19个EXTI外部中断源,其中GPIO外部中断源16个,分别对应7个中断向量,即对应着7个中断服务函数。
在这里插入图片描述

外部中断的触发条件

  1. 下降沿触发(Falling Edge Trigger)
    条件:当外部信号从高电平变为低电平时触发中断。
    应用:适用于需要对信号的负跳变进行响应的场合,例如检测按钮的按下。
  2. 上升沿触发(Rising Edge Trigger)
    条件:当外部信号从低电平变为高电平时触发中断。
    应用:适用于需要对信号的正跳变进行响应的场合,例如检测按钮的释放。
  3. 双沿触发(Both Edge Trigger)
    条件:当外部信号在上升沿或下降沿时都会触发中断。
    应用:适用于需要对信号的任何边沿变化都进行响应的场合,例如高频信号的边沿检测。
  4. 电平触发(Level Trigger)
    条件:当外部信号保持在特定电平(高或低)时触发中断。STM32F103中不直接支持电平触发,但可以通过外部电路来实现电平触发的效果。
    应用:适用于需要对信号电平状态变化的监控,但通常需要额外的电路来转换为边沿触发的信号。

注意:所有的GPIO口都可以触发中断,但相同的Pin号不能同时触发中断。
在这里插入图片描述

代码示例

配置过程中我们需要使用到一些库函数,如GPIO库函数、RCC库函数、EXTI库函数、NVIC库函数。
在这里插入图片描述
除了GPIO的基本配置函数,这里还需使用GPIO库函数的最后一个,即选择GPIO管脚用作外部中断线路。
在这里插入图片描述在这里插入图片描述
我们需要使能GPIO的时钟、AFIO的时钟、外部中断的时钟。
在这里插入图片描述
根据功能要求使用相应的EXTI库函数。
在这里插入图片描述
NVIC库函数提供了对中断控制和管理的全面支持,包括中断使能、禁用、优先级设置和优先级分组等功能。

static void ConfigEXTIGPIO(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;  //GPIO_InitStructure用于存放GPIO的参数
                                                                     
  //使能RCC相关时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能GPIOA的时钟
                                                                                       
  //配置PA0
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;           //设置引脚
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;        //设置输入类型
  GPIO_Init(GPIOA, &GPIO_InitStructure);                //根据参数初始化GPIO
}

初始化PA0引脚,对应STM32板子上的KEY3。

static void ConfigEXTI(void)
{
  EXTI_InitTypeDef EXTI_InitStructure;  //EXTI_InitStructure用于存放EXTI的参数
  NVIC_InitTypeDef NVIC_InitStructure;  //NVIC_InitStructure用于存放NVIC的参数
  
  //使能RCC相关时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);  //使能AFIO的时钟

 //配置PA0的EXTI和NVIC
  GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);   //选择引脚作为中断线
  EXTI_InitStructure.EXTI_Line = EXTI_Line0;                    //选择中断线
  EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;           //开放中断请求
  EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;        //设置为上升沿触发
  EXTI_InitStructure.EXTI_LineCmd = ENABLE;                     //使能中断线 
  EXTI_Init(&EXTI_InitStructure);                               //根据参数初始化EXTI
  
  NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;              //中断通道号
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;     //设置抢占优先级
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;            //设置响优先级
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;               //使能中断
  NVIC_Init(&NVIC_InitStructure);                               //根据参数初始化NVIC
}
  1. EXTI_InitTypeDef EXTI_InitStructure; 和 NVIC_InitTypeDef NVIC_InitStructure;定义了两个结构体,用于存储 EXTI 和 NVIC 的初始化配置参数。
  2. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);使能 AFIO外设的时钟,这是配置外部中断所必须的。AFIO 允许将 GPIO引脚配置为外部中断源。
  3. GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);配置GPIOA 的第 0 引脚(PA0)为外部中断源 EXTI0。这是将具体的 GPIO 引脚映射到 EXTI 线的步骤。
  4. EXTI_InitStructure.EXTI_Line = EXTI_Line0;选择 EXTI0 作为外部中断线。STM32 的EXTI 线用于处理外部信号中断。
  5. EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;配置为中断模式。中断模式会在触发条件满足时产生中断请求。
  6. EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;设置中断触发条件为上升沿触发。即当 PA0 引脚检测到上升沿时,会产生中断。
  7. EXTI_InitStructure.EXTI_LineCmd = ENABLE;使能 EXTI0 中断线,表示启用配置好的中断线。
  8. EXTI_Init(&EXTI_InitStructure);根据配置参数初始化 EXTI 外部中断线。
  9. NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;设置 NVIC 中断通道为EXTI0 中断通道,NVIC 用于中断管理。
  10. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;:设置 EXTI0中断的抢占优先级为 2。抢占优先级用于确定中断是否可以打断当前正在执行的中断。
  11. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;设置 EXTI0中断的响应优先级为 2。响应优先级用于在同一抢占优先级下决定中断的优先处理顺序。
  12. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;使能 EXTI0 中断通道。
  13. NVIC_Init(&NVIC_InitStructure);根据配置参数初始化 NVIC 中断控制器。

这段代码的目的是配置外部中断线 EXTI0,并设置中断触发条件、优先级等,使得当 PA0 引脚检测到上升沿时,会产生中断请求并由处理器处理。

void EXTI0_IRQHandler(void)
{
  if(EXTI_GetITStatus(EXTI_Line0) != RESET) //判断中断是否发生
  {   
    //LED1状态取反
    GPIO_WriteBit(GPIOC, GPIO_Pin_4, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_4)));
    //LED2状态取反
    GPIO_WriteBit(GPIOC, GPIO_Pin_5, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_5)));    
    EXTI_ClearITPendingBit(EXTI_Line0);     //清除Line0上的中断标志位
  }
}

上述代码实现的是,按键KEY3每按下一次,LED1和LED2状态进行一次翻转。

### STM32 ADC 学习教程和笔记 #### 一、STM32 ADC 基本概念 STM32F103ZET6 单片机配备有三个12位精度的模拟数字转换器(ADC),总共提供18个通道,能够处理来自外部的16个信号源以及两个内部信号源。这些通道支持多种工作模式,包括但不限于单次转换、连续转换、扫描模式和间断模式。值得注意的是,为了确保正常运作,ADC模块所需的输入时钟频率不应超过14MHz,该时钟是从APB2总线上的PCLK2经过预分频得到的[^3]。 #### 二、ADC 软件启动机制分析 对于通过软件指令来发起一次新的转换操作而言,在某些情况下可能会涉及到查询`ADC_GetSoftwareStartConvStatus()`函数的状态返回值;然而实际上此方法并不常用,因为其功能较为有限,并未被广泛应用于实际项目开发当中[^2]。 #### 三、触发方式的选择 除了上述提到的纯软件控制之外,还可以利用硬件事件作为触发条件来进行自动化的数据采集过程。这类触发源通常来源于定时器产生的中断请求或者其他外设发出的相关脉冲信号。此外,整个AD转换流程依赖于由RCC配置好的专用时钟源——即所谓的ADC_CLK,它是驱动逐次逼近型A/D变换的核心动力源泉[^4]。 #### 四、性能参数考量 假设当前使用的ADC时钟频率设定为最大允许值14MHz,则完成一轮完整的采样加量化所需时间大约等于1微秒左右。具体计算公式如下所示: \[T_{conv}=(SMPR+12.5)\times\frac{1}{f_{adc}} \] 其中\( SMPR \)代表样本保持阶段所占用的时间长度,默认设置下取值为1.5个周期数[^5]。 ```python # Python代码片段用于验证理论计算结果 def calculate_conversion_time(f_adc, smpr=1.5): """Calculate the conversion time based on given parameters.""" t_conv = (smpr + 12.5) * (1 / f_adc) return round(t_conv, ndigits=9) print(calculate_conversion_time(14e6)) # Output should be close to 1 us ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值