stm32f10x的外设--中断

1.关于中断

中断就是执行程序的过程中,打断执行过程,跳转到中断执行程序中,执行完成后再返回原来的程序

举例: 你在炒菜的过程中接到电话(中断触发),那你就先关火(保护现场),去接电话(执行中断程序),接完电话继续炒菜(执行完,恢复现场,继续原来的程序)

2.中断的作用

我们这里看下异常向量表,CPU是根据异常向量表来决定,某个异常出现后会跳转到哪个中断函数。特定的异常跳转到特点的函数,一般是固化好的。

前三个,优先级为负数的异常,不能进行设置。前面10个异常是ARM公司自带的(系统的异常),后面的异常是st公司加上的(外设的异常)

 

//在嵌入式编程中,PC 通常指的是 Program Counter,即 程序计数器。程序计数器是一个特殊的寄存器,负责存储下一条将要执行的指令的内存地址。

如果出现硬件失效异常,CPU就会跳转到0x0000 0008这个地址(也就是PC指针会立刻指向0x0000 0008),并执行里面的程序。

如果出现WWDG看门狗异常,CPU就会跳转到0x0000 0040这个地址(也就是PC指针会立刻指向0x0000 0008),并执行里面的程序。

 

2.1这个异常向量表在是通过汇编程序startup_stm32f10x_md.s设置好的

 中断向量表(Interrupt Vector Table)是嵌入式系统中一个非常重要的概念。它是存储中断服务程序(ISR,Interrupt Service Routine)入口地址的表格。

当某个中断事件发生时,处理器会查找对应的中断向量表项,跳转到中断服务程序(ISR)中处理相关任务

 往下翻,就可以看到对应的中断向量表。

上面的表格前3个是reset ,NMI,  hardfault。

下面的向量表前三个是reset ,NMI,  hardfault。   两者是一一对应的。地址也是对的上的

 

 

我们把stm32f10x_it.c加到库里,外设的中断处理函数可以统一写到这里,也可以写在硬件驱动文件里面,函数名其实就是一个地址。选中,跳转到定义,就会发现要么是空,要么没有写

(因为设计者不知道你要在中断执行程序里面做什么操作,所以中断程序要么是空的,要么压根就没有写)

 

 

 3.中断的使用

下面这个文件,实现的是按键按下,LED灯取反。(LED初始化在其他文件)

 

   这个文件分成两个部分,一个是中断和按键配置的初始化。另一个是中断处理函数。

   定义完结构体后使能工作时钟,外设工作大都需要时钟

   初始化按键的GPIO口

   接着对NVIC中断控制器进行初始化,因为存在不同中断的情况,需要NVIC中断控制器进行协调

   最后对GPIO口的中断进行初始化,GPIOA0的中断挂着EXTI0总线上,对EXTI0总线进行初始化就是对GPIOA0初始化

 

后面还有一个中断函数,注意一定要手动清除中断的标志位,如果没有清除,程序就会一直跳转到中断程序里面,被中断占用。

(就像你坐高铁,上厕所关门后,占用灯就会亮起,如果你不用,还一直关着门,占用灯常亮,就会影响别人)

 

#include "exti.h"

void exti_configuration(void)
{

//定义结构体
EXTI_InitTypeDef EXTI_InitStruct;
GPIO_InitTypeDef GPIO_InitStruct;
NVIC_InitTypeDef NVIC_InitStruct;   
// 3. 启用外部中断控制器的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
// 2. 配置 PA0 为上拉输入状态
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入状态
GPIO_Init(GPIOA, &GPIO_InitStruct);

// 4. 配置 PA0 为外部中断线路 0
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);

// 5. 配置外部中断触发模式为下降沿触发

EXTI_InitStruct.EXTI_Line = EXTI_Line0;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 中断模式
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE; // 启用中断
EXTI_Init(&EXTI_InitStruct);

// 6. 配置 NVIC(中断控制器)

NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn; // 外部中断 0
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0; // 优先级设置为 0
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; // 子优先级为 0
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; // 启用中断
NVIC_Init(&NVIC_InitStruct);

}


void EXTI0_IRQHandler(void)
{
if (EXTI_GetITStatus(EXTI_Line0) != RESET) // 检查是否是PA0引脚触发的中断
{
EXTI_ClearITPendingBit(EXTI_Line0); // 清除中断标志
LED_Switch_off;
// 在这里处理外部中断,比如切换LED状态或其他操作
// 例如:GPIO_SetBits(GPIOC, GPIO_Pin_13); // 如果有LED连接在PC13

}
}

posted @ 2024-11-16 15:34  嵌入式新手  阅读(315)  评论(0)    收藏  举报