STM32CubeMX之外部中断
1.中断简介
中断,是指处理机处理程序运行中出现的紧急事件的整个过程。程序运行过程中,系统外部、系统内部或者现行程序本身若出现紧急事件,处理机立即中止现行程序的运行,自动转入相应的处理程序(中断服务程序),待处理完后,再返回原来的程序运行,这整个过程称为程序中断。当处理机接受中断时,只需暂停一个或几个周期而不执行处理程序的中断,称为简单中断,中断又可分为屏蔽中断和非屏蔽中断两类。
STM32中断特性
● 68个可屏蔽中断通道(不包含16个Cortex™-M3的中断线);
● 16个可编程的优先等级(使用了4位中断优先级);
● 低延迟的异常和中断处理;
● 电源管理控制;
● 系统控制寄存器的实现;
嵌套向量中断控制器(NVIC)和处理器核的接口紧密相连,可以实现低延迟的中断处理和高效地处理晚到的中断。
Cortex‐M3 在内核水平上搭载了一个异常响应系统, 支持为数众多的系统异常和外部中断。其中,编号为 1- 15 的对应系统异常,大于等于 16 的则全是外部中断。除了个别异常的优先级被定死外, 其它异常的优先级都是可编程的(所有能打断正常执行流的事件都称为异常)。
中断向量控制器, 简称 NVIC,是 Cortex‐M3 不可分离的一部分, 它与 CM3 内核的逻辑紧密耦合, 有一部分甚至水乳交融在一起。 NVIC 与 CM3 内核同声相应,同气相求,相辅相成,里应外合,共同完成对中断的响应。 NVIC 的寄存器以存储器映射的方式来访问, 除了包含控制寄存器和中断处理的控制逻辑之外, NVIC 还包含了 MPU的控制寄存器、 SysTick 定时器以及调试控制。
每个外部中断都有一个对应的优先级寄存器,每个寄存器占用 8 位,但是允许最少只使用最高 3 位。 4 个相临的优先级寄存器拼成一个 32 位寄存器。如前所述,根据优先级组设置,优先级可以被分为高低两个位段,分别是抢占优先级和亚优先级。优先级寄存器都可以按字节访问,当然也可以按半字/字来访问。有意义的优先级寄存器数目由芯片厂商实现的中断数目决定。
STM32F10xxx产品(小容量、中容量和大容量)的向量表
2.外部中断(EXTI)
对于互联型产品,外部中断/事件控制器由20个产生事件/中断请求的边沿检测器组成,对于其它产品,则有19个能产生事件/中断请求的边沿检测器。每个输入线可以独立地配置输入类型(脉冲或挂起)和对应的触发事件(上升沿或下降沿或者双边沿都触发)。每个输入线都可以独立地被屏蔽。挂起寄存器保持着状态线的中断请求。
EXTI控制器的主要特性如下:
● 每个中断/事件都有独立的触发和屏蔽
● 每个中断线都有专用的状态位
● 支持多达20个软件的中断/事件请求
● 检测脉冲宽度低于APB2时钟宽度的外部信号。
外部中断框图
要产生中断,必须先配置好并使能中断线。根据需要的边沿检测(上升沿、下降沿)设置2个触发寄存器,同时在中断屏蔽寄存器的相应位写’1’允许中断请求。当外部中断线上发生了期待的边沿时,将产生一个中断请求,对应的挂起位也随之被置’1’。在挂起寄存器的对应位写’1’,将清除该中断请求。
3.硬件接口
根据硬件原理图特实物,Tout0 ~ Tout4对应的GPIO口为PA4 ~ PA7。采用外部中断方式实现触摸按键检测。其中中断线分别为:
PA4 ---EXIT4,PA4是使用外部中断线4;
PA5~PA7 --- EXTI5~9,PA5~PA7是使用外部中断线5~9;具体介绍可查看STM32中文参考手册。
TTP224是一款使用电容式感应原理设计的触摸IC,其稳定的感应方式可以应用到各种不同电子类产品,面板介质可以是完全绝源的材料,专为取代传统的机械结构开关或普通按键而设计.提供4个触摸输入端口及4个直接输出端口。
TTP224特点
- 工作电压 2.4V~5.5V
- 可以由外部Option选择是否启用内部稳压电路功能.
- 工作电流@VDD=3V无负载时:
- 低功耗模式下典型值2.5uA
- 快速模式下典型值9uA
- @VDD=3V时,在快速模式下KEY最快响应时间为100mS,低功耗模式下为200mS.
- 有自动校准功能,当无按键被触摸时,系统重新校准周期约为4.0秒
4.软件设计
根据STM32中文参考手册外部中断章节介绍,边沿检测可选择上升沿、下降沿、双边沿(上升沿和下降沿)
TTP224按键检测这里采用双边沿触发,即可完成按键按下与松开的状态检测。
外部中断使能:
生成代码
触摸按键模式配置代码。
编写中断服务函数
u8 ttp224_stat=0;//按键状态返回值
//按键1按下:ttp224_stat第0位置1
//按键2按下:ttp224_stat第1位置1
//按键3按下:ttp224_stat第2位置1
//按键4按下:ttp224_stat第3位置1
void EXTI4_IRQHandler(void)
{
/* USER CODE BEGIN EXTI4_IRQn 0 */
Delay_Ms(10);//消抖
if(HAL_GPIO_ReadPin(TO0_GPIO_Port,TO0_Pin))//判断按键1是否按下
{
ttp224_stat|=1<<0;
}
else//判断按键是否松开
{
ttp224_stat&=~(1<<0);
}
/* USER CODE END EXTI4_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_4);
/* USER CODE BEGIN EXTI4_IRQn 1 */
/* USER CODE END EXTI4_IRQn 1 */
}
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
Delay_Ms(10);
if(HAL_GPIO_ReadPin(TO1_GPIO_Port,TO1_Pin))//判断按键2是否按下
{
ttp224_stat|=1<<1;
}
if(HAL_GPIO_ReadPin(TO1_GPIO_Port,TO1_Pin)==0)
{
ttp224_stat&=~(1<<1);
}
if(HAL_GPIO_ReadPin(TO2_GPIO_Port,TO2_Pin))//判断按键3是否按下
{
ttp224_stat|=1<<2;
}
if(HAL_GPIO_ReadPin(TO2_GPIO_Port,TO2_Pin)==0)
{
ttp224_stat&=~(1<<2);
}
if(HAL_GPIO_ReadPin(TO3_GPIO_Port,TO3_Pin))//判断按键4是否按下
{
ttp224_stat|=1<<3;
}
if(HAL_GPIO_ReadPin(TO3_GPIO_Port,TO3_Pin)==0)
{
ttp224_stat&=~(1<<3);
}
/* USER CODE END EXTI9_5_IRQn 0 */
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_5);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_6);
HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_7);
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
}
主函数:多个按键同时检测示例
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_TIM4_Init();
MX_USART1_UART_Init();
MX_ADC1_Init();
/* USER CODE BEGIN 2 */
OLED_Init();
OLED_Displey_Imag(48,0,32,32,(u8 *)android);
Delay_Ms(1000);
OLED_Clear();
OLED_Display_folnt(32,0,16,0);
OLED_Display_folnt(32+16,0,16,1);
OLED_Display_folnt(32+16*2,0,16,2);
OLED_Display_folnt(32+16*3,0,16,3);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)//轮询
{
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
switch(ttp224_stat)
{
case 0:
OLED_Display_str(0,2,8,16," ");
break;
case 1:
OLED_Display_str(0,2,8,16," KEY1 ON ");
break;
case 2:
OLED_Display_str(0,2,8,16," KEY2 ON ");
break;
case 3:
OLED_Display_str(0,2,8,16," KEY1 2 ON ");
break;
case 4:
OLED_Display_str(0,2,8,16," KEY3 ON ");
break;
case 5:
OLED_Display_str(0,2,8,16," KEY1 3 ON ");
break;
case 6:
OLED_Display_str(0,2,8,16," KEY2 3 ON ");
break;
case 7:
OLED_Display_str(0,2,8,16," KEY1 2 3 ON ");
break;
case 8:
OLED_Display_str(0,2,8,16," KEY4 ON ");
break;
case 9:
OLED_Display_str(0,2,8,16," KEY1 4 ON ");
break;
case 10:
OLED_Display_str(0,2,8,16," KEY2 4 ON ");
break;
case 11:
OLED_Display_str(0,2,8,16," KEY1 2 4 ON ");
break;
case 12:
OLED_Display_str(0,2,8,16," KEY3 4 ON ");
break;
case 13:
OLED_Display_str(0,2,8,16," KEY1 3 4 ON ");
break;
case 14:
OLED_Display_str(0,2,8,16," KEY2 3 4 ON ");
break;
case 15:
OLED_Display_str(0,2,8,16," KEY1 2 3 4 ON");
break;
}
}
/* USER CODE END 3 */
}
示例效果: