STM32学习之中断入门实验

一、中断原理

单片机的中断原理涉及CPU在执行程序过程中对紧急事件的响应机制。

假如有一个程序B必须要在程序A执行完毕后才能执行。这样在实际情况中可能会遇到一个问题。就是程序B有的时候需要先处理。比如,假设程序B是个按键程序,用户按下按键时,需要优先处理按键程序,而这个时候程序A还没有处理完,假设还需要3秒钟才能处理完。这个时候,用户就得等3秒才能得到程序响应,这样用户就会觉得程序卡顿。这种情况显然是要避免的.要解决这种情况,也就是当按键按下时,要暂停程序A,先去处理程序B,等响应完成后,再回头去处理程序A。这就是所谓的中断机制。

单片机的中断机制允许CPU暂停当前正在执行的任务,转而去处理一个紧急事件或称为中断源的特殊请求,处理完毕后再返回继续执行原来的任务。这个过程大致可以分为以下步骤:

1.中断请求:这是中断过程的开始,由中断源发起。中断源可以是外围设备、定时器溢出、外部信号变化等。
2.中断响应:CPU识别到中断请求后,如果条件允许(例如,当前没有执行更高优先级的中断服务程序),会暂停当前的程序执行,准备响应中断。
3.中断处理:CPU跳转到对应的中断服务程序去处理中断请求。这个过程中,CPU会保存当前执行状态(断点)以便之后能够恢复执行原程序。
4.中断返回:中断服务程序执行完成后,CPU从中断返回到之前被中断的程序继续执行。返回的过程中需要恢复之前保存的执行环境。

二、中断实例实验

利用中断控制LED灯的亮灭

要求:用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。
项目配置流程参考手把手教你STM32入门教程(标准库)
代码实现
led.h头文件

#ifndef __LED_H
#define __LED_H

#include "stm32f10x.h"
void LED_Init(void); 

#endif

led.c文件(初始化LED)

#include "led.h"  

void LED_Init(void)  // 定义LED初始化函数
{
    GPIO_InitTypeDef GPIO_InitStructure;  // 定义GPIO初始化结构体

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);  // 使能GPIOA时钟

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // 设置GPIO引脚为PA0

    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  // 设置GPIO模式为推挽输出

    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  // 设置GPIO速度为50MHz

    GPIO_Init(GPIOA, &GPIO_InitStructure);  // 根据初始化结构体配置GPIOA
}

中断函数配置:exti_key.h

#ifndef __EXTI_KEY_H
#define __EXTI_KEY_H
#include "stm32f10x.h"
void EXTI_Key_Init(void);
#endif

exti_key.c

#include "exti_key.h" 
#include "misc.h"  

void EXTI_Key_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;  // 定义GPIO初始化结构体

    // 配置GPIOB的PB0引脚为输入模式
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);  // 使能GPIOB时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;  // 设置GPIO引脚为PB0
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;  // 设置GPIO模式为上拉输入模式
    GPIO_Init(GPIOB, &GPIO_InitStructure);  // 根据初始化结构体配置GPIOB

    EXTI_InitTypeDef EXTI_InitStructure;  // 定义外部中断初始化结构体
    NVIC_InitTypeDef NVIC_InitStructure;  // 定义NVIC中断初始化结构体

    // 使能AFIO时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

    // 将GPIOB的PB0引脚映射到外部中断线0
    GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);

    // 配置外部中断线0的触发方式为下降沿触发
    EXTI_InitStructure.EXTI_Line = EXTI_Line0;  // 设置外部中断线为0
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;  // 设置外部中断模式为中断模式
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;  // 设置外部中断触发方式为下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;  // 使能外部中断线0
    EXTI_Init(&EXTI_InitStructure);  // 根据初始化结构体配置外部中断

    // 配置NVIC中断优先级分组2
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

    // 配置外部中断线0的中断优先级
    NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;  // 设置中断通道为外部中断线0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  // 设置抢占优先级为1
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  // 设置子优先级为0
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  // 使能中断通道
    NVIC_Init(&NVIC_InitStructure);  // 根据初始化结构体配置NVIC中断
}

主函数main.c

#include "stm32f10x.h"
#define unsigned int uint8_t 
#include "led.h"
#include "exti_key.h"

int main(void)
{
    LED_Init();
    EXTI_Key_Init();
    while(1)
    {
    }
  }

void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        // 切换LED的状态
        GPIOA->ODR ^= GPIO_Pin_0;

        // 清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

实物运行结果

按键中断点灯

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值