单片机中断与定时器的应用

晨曦微光 2019-12-30 ⋅ 15 阅读

在MCU开发中,中断与定时器是非常重要的概念,它们可以极大地方便我们对外部事件或时间进行响应。本文将为大家介绍单片机中断与定时器的应用。

中断的概念及作用

中断是指当单片机执行某个任务时,突然发生了一个重要的时间或事件,此时需要暂时中断当前任务去处理这个时间或事件。中断使得处理器能够在同一时间执行多个任务,提高了系统的效率。常见的中断包括外部中断、定时器中断、串口中断等。

中断的作用主要有以下几个方面:

  1. 实时响应外部事件:外部设备产生中断信号后,立即停止当前任务去处理事件,确保对事件的实时响应。
  2. 节约资源:使用中断可以减少CPU资源的浪费。在没有中断机制的情况下,CPU需要不断地轮询各个外部设备的状态,而使用中断后,CPU可以继续执行其他任务,只在有中断产生时才去处理中断事件。
  3. 提高系统的可靠性:通过中断,可以及时处理外部设备可能产生的故障,确保系统的稳定性。

定时器的概念及应用

定时器是单片机中的一个重要硬件模块。它可以生成精确的时间延迟,并且可以自动触发中断。定时器可以用于很多应用,例如计时、脉冲测量、PWM波生成等。

定时器的应用主要有以下几个方面:

  1. 实现精确的时间延迟:通过配置定时器的计数值以及分频系数,可以实现精确的微秒、毫秒甚至秒级的延迟,用于控制任务的执行时间。
  2. 生成周期性的中断信号:通过配置定时器的计数值和计数模式,可以实现周期性的中断信号,用于定时触发某个任务或事件。
  3. 生成PWM波:定时器可以用于生成PWM波,通过改变占空比可以实现对电机速度、亮度等参数的精确控制。

单片机中断与定时器的应用案例

以STM32为例,具体介绍一下中断与定时器的应用。

中断的应用

STM32系列的单片机具有丰富的外部中断线,可以对外部事件进行实时响应。以下是一个简单的外部中断应用案例,用于检测外部按键的按下事件:

#include "stm32f10x.h"

void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        // 处理按键按下事件
        // ...
        
        // 清除中断标志位
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

int main(void)
{
    // 外部中断初始化
    EXTI_InitTypeDef EXTI_InitStructure;
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_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_Falling; // 下降沿触发
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);
    
    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)
    {
        // 执行其他任务
        // ...
    }
}

以上代码将PA0引脚配置为外部中断引脚,使用下降沿触发外部中断。当按键按下时,触发外部中断,跳入EXTI0_IRQHandler函数进行按键事件处理。

定时器的应用

以下是一个定时器中断应用案例,用于周期性地向GPIO输出 LED 翻转的信号:

#include "stm32f10x.h"

void TIM2_IRQHandler(void)
{
    if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
    {
        // 翻转LED引脚状态
        GPIO_WriteBit(GPIOC, GPIO_Pin_13, (BitAction)(1 - GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_13)));
        
        // 清除中断标志位
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

int main(void)
{
    // 定时器初始化
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
    
    TIM_TimeBaseStructure.TIM_Period = 4999; // 计数周期为5000,即1ms
    TIM_TimeBaseStructure.TIM_Prescaler = 7199; // 72MHz时钟,预分频7200,即10kHz的计数频率
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
    
    TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
    TIM_Cmd(TIM2, ENABLE);
    
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x01;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    
    // GPIO初始化
    GPIO_InitTypeDef GPIO_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init(GPIOC, &GPIO_InitStructure);
    
    while (1)
    {
        // 执行其他任务
        // ...
    }
}

以上代码使用定时器TIM2配置为1ms的计数周期,通过翻转GPIOC的引脚状态实现LED的闪烁效果。

小结

中断与定时器是单片机开发中非常重要的概念和模块。通过合理的应用中断和定时器,可以实现对外部事件和时间的实时响应,提高系统的效率和稳定性。希望本文对大家理解中断与定时器的应用有所帮助。


全部评论: 0

    我有话说: