面试题答案
一键面试关键要点
- 尽量精简代码:中断服务程序应尽可能简短和高效,只完成必要的紧急任务,如标记事件、读取关键数据等。避免在中断服务程序中进行复杂的计算、大量数据处理或调用可能阻塞的函数。
- 使用合适的数据类型:确保在中断服务程序中使用的数据类型与处理器架构和编译器兼容,避免因数据类型转换导致的额外开销。例如,使用无符号整数类型,避免浮点运算(因为浮点运算通常较慢且可能不支持原子操作)。
- 避免全局变量竞争:如果中断服务程序和主程序共享全局变量,需要采取同步机制来避免竞争条件。可以使用临界区(如关中断、开中断操作)或信号量等方式来保护共享资源。
- 优化中断响应时间:
- 减少中断嵌套深度:尽量避免在中断服务程序中再次触发中断,若必须嵌套,确保嵌套层次尽可能少。
- 合理配置中断优先级:根据任务的紧急程度设置中断优先级,确保关键中断能够及时得到响应。
避免对主程序运行干扰
- 中断屏蔽与解屏蔽:在进入中断服务程序后,可以根据需要适当屏蔽其他低优先级中断,防止其他中断干扰当前中断处理。处理完成后及时解屏蔽中断,恢复系统的正常中断响应能力。例如:
void IRQ_Handler(void) {
// 屏蔽低优先级中断
__disable_irq();
// 中断处理代码
// 解屏蔽中断
__enable_irq();
}
- 使用标志位:在中断服务程序中设置标志位,主程序通过轮询标志位来处理后续任务,避免中断服务程序直接执行复杂操作而占用过多时间。例如:
volatile int flag = 0;
void TIMER_IRQHandler(void) {
// 定时器中断处理,设置标志位
flag = 1;
}
int main(void) {
while(1) {
if(flag) {
// 处理任务
flag = 0;
}
}
}
优化中断响应时间示例
以一个简单的按键中断为例,假设按键连接到外部中断引脚。
#include "stm32f10x.h"
// 按键中断服务程序
void EXTI0_IRQHandler(void) {
if(EXTI_GetITStatus(EXTI_Line0) != RESET) {
// 简单处理,例如点亮LED
GPIO_SetBits(GPIOC, GPIO_Pin_13);
// 清除中断标志位
EXTI_ClearITPendingBit(EXTI_Line0);
}
}
int main(void) {
// 初始化GPIO和EXTI相关配置
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);
GPIO_InitTypeDef GPIO_InitStructure;
// 配置按键引脚(PA0)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 配置LED引脚(PC13)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
// 配置EXTI
EXTI_InitTypeDef EXTI_InitStructure;
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);
// 配置NVIC
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
while(1) {
// 主程序其他任务
}
}
在此例中,中断服务程序只完成点亮LED和清除中断标志位的操作,保证了中断响应时间的优化,避免对主程序过多干扰。