STM32 嵌入式开发学习笔记五 :中断

本文转载自:https://www.cnblogs.com/isakovsky/p/11437202.html
我们了解了用循环实现延时,或用系统滴答计时器实现延时,但这两种方法都有一种问题:会阻塞处理器的运行。下面我们学习一种不阻塞处理器运行其他事件的功能:时钟中断。

所谓中断,就是让处理器放下手头的事情,立刻去做一件事情,做完了再做原来的事情。比如说你在写作业,但是突然来了一个人找你说话,你就停下来跟他说话,这就是中断。

要实现时钟中断,我们必须了解两种特性:通用定时器和中断控制器。

通用定时器也是通过晶体产生脉冲信号用于定时的定时器,和滴答计时器(systick)的区别是通用定时器在外设上,滴答定时器在内核里。通用定时器一共有8个,分别为TIM1-TIM8,其中TIM2-5是普通定时器,剩下的是高级定时器。

所以说,中断之所以能不阻塞处理器的运行,是因为通用定时器独立于系统内核,不占用处理器的运行时间。

中断控制器,顾名思义是用来控制各种各样种类繁多的中断的,这些中断有先有后,优先级有高有低,因此需要一个专门的控制器来控制它们。

我们尝试实现一个中断控制,选用TIM2作为控制中断的定时器,首先需要配置TIM2,我们查阅技术手册,通用定时器由TIM_TimeBaseInitTypeDef结构体来初始化,此结构体有如下成员。

typedef struct
{
    u16 TIM_Period;       //重装载值
    u16 TIM_Prescaler;    //预分频值
    u8 TIM_ClockDivision; //时钟分割
    u16 TIM_CounterMode;  //计数模式
} TIM_TimeBaseInitTypeDef; 

通用定时器的时钟频率还是72MHz,因此我们设定分频值为72方便计算。

TIM_TimeBaseInitTypeDef TIME2_INIT;
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIME2_INIT.TIM_Prescaler=72;
TIME2_INIT.TIM_Period=2000;
TIME2_INIT.TIM_CounterMode=TIM_CounterMode_Down;
TIME2_INIT.TIM_ClockDivision=TIM_CKD_DIV1;
TIME2_INIT.TIM_RepetitionCounter=1;
TIM_TimeBaseInit(TIM2,&TIME2_INIT);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

如此,便将通用计时器初始化。

然后我们设置中断控制器,中断控制器由NVIC_InitTypeDef结构体来初始化,成员如下

typedef struct
{
    u8 NVIC_IRQChannel;   //中断通道,接受什么信号才中断
    u8 NVIC_IRQChannelPreemptionPriority;  //主优先级
    u8 NVIC_IRQChannelSubPriority;   //从优先级
    FunctionalState NVIC_IRQChannelCmd;   //使能
} NVIC_InitTypeDef; 

另外,中断控制器还十分有意思,主优先级和从优先级的值,共同占用4位寄存器,因此还得用NVIC_PriorityGroupConfig函数分配一下,这四位寄存器哪几位代表主优先级,哪几位代表从优先级。

函数 NVIC_PriorityGroupConfig

函数名NVIC_PriorityGroupConfig
函数原形void NVIC_PriorityGroupConfig(u32 NVIC_PriorityGroup)
功能描述设置优先级分组:先占优先级和从优先级
输入参数NVIC_PriorityGroup:优先级分组位长度 ;参阅 Section:NVIC_PriorityGroup 查阅更多该参数允许取值范围
输出参数
返回值
先决条件优先级分组只能设置一次
被调用函数

参数 NVIC_PriorityGroup :该参数设置优先级分组位长度

NVIC_PriorityGroup描述
NVIC_PriorityGroup_0先占优先级 0 位 ;从优先级 4 位
NVIC_PriorityGroup_1先占优先级 1 位;从优先级 3 位
NVIC_PriorityGroup_2先占优先级 2 位;从优先级 2 位
NVIC_PriorityGroup_3先占优先级 3 位;从优先级 1 位
NVIC_PriorityGroup_4先占优先级 4 位;从优先级 0 位
NVIC_InitTypeDef NVIC_INIT;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_INIT.NVIC_IRQChannel=TIM2_IRQn;
NVIC_INIT.NVIC_IRQChannelPreemptionPriority=2;
NVIC_INIT.NVIC_IRQChannelSubPriority=2;
NVIC_INIT.NVIC_IRQChannelCmd=ENABLE;
NVIC_Init(&NVIC_INIT);

接下来,使能一下TIM2即可

TIM_Cmd(TIM2,ENABLE);

然后,中断控制器当中断条件达成时,会自动调用一下TIM2_IRQHandler函数,注意这个函数名是在库里写死的。我们需要定义一下中断时的行为。

但是,有一点需要注意,在TIM2_IRQHandler函数里面,我们要确认一下这个函数是因为中断请求而调用的,如果是意外调用的则拒绝执行,直接退出,这种编程思想叫做防御式编程,即不信任传入的参数,要在执行前检查参数的合法性。

void TIM2_IRQHandler(){
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){
        //中断时执行的事件
    }
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}

完整代码如下:

#ifndef _TIME2_H
    #define _TIME2_H
    void time2_configer();
    void TIM2_IRQHandler();
#endif
//time2.h
#include <time2.h>
#include <stm32f10x.h>
void time2_configer(){
    TIM_TimeBaseInitTypeDef TIME2_INIT;
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    TIME2_INIT.TIM_Prescaler=72;
    TIME2_INIT.TIM_Period=2000;
    TIME2_INIT.TIM_CounterMode=TIM_CounterMode_Down;
    TIME2_INIT.TIM_ClockDivision=TIM_CKD_DIV1;
    TIME2_INIT.TIM_RepetitionCounter=1;
    TIM_TimeBaseInit(TIM2,&TIME2_INIT);
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
    
    NVIC_InitTypeDef NVIC_INIT;
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_INIT.NVIC_IRQChannel=TIM2_IRQn;
    NVIC_INIT.NVIC_IRQChannelPreemptionPriority=2;
    NVIC_INIT.NVIC_IRQChannelSubPriority=2;
    NVIC_INIT.NVIC_IRQChannelCmd=ENABLE;
    NVIC_Init(&NVIC_INIT);
    
    TIM_Cmd(TIM2,ENABLE);
}
void TIM2_IRQHandler(){
    if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){
        
    }
    TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}
//time2.c

附:《STM32固件库使用手册》和《STM32参考手册》下载地址:
https://blog.csdn.net/weixin_41561640/article/details/107124800

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值