STM32嵌入式开发学习笔记(五):中断
我们过去了解了用循环实现延时,或用系统滴答计时器实现延时,但这两种方法都有一种问题:会阻塞处理器的运行。下面我们学习一种不阻塞处理器运行其他事件的功能:时钟中断。
所谓中断,就是让处理器放下手头的事情,立刻去做一件事情,做完了再做原来的事情。比如说你在写作业,但是突然来了一个人找你说话,你就停下来跟他说话,这就是中断。
要实现时钟中断,我们必须了解两种特性:通用定时器和中断控制器。
通用定时器也是通过晶体产生脉冲信号用于定时的定时器,和滴答计时器(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=;
TIME2_INIT.TIM_Period=;
TIME2_INIT.TIM_CounterMode=TIM_CounterMode_Down;
TIME2_INIT.TIM_ClockDivision=TIM_CKD_DIV1;
TIME2_INIT.TIM_RepetitionCounter=;
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_InitTypeDef NVIC_INIT;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
NVIC_INIT.NVIC_IRQChannel=TIM2_IRQn;
NVIC_INIT.NVIC_IRQChannelPreemptionPriority=;
NVIC_INIT.NVIC_IRQChannelSubPriority=;
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);
}
完整代码如下:
#include <time2.h>
#include <stm32f10x.h>
void time2_configer(){
TIM_TimeBaseInitTypeDef TIME2_INIT; RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
TIME2_INIT.TIM_Prescaler=;
TIME2_INIT.TIM_Period=;
TIME2_INIT.TIM_CounterMode=TIM_CounterMode_Down;
TIME2_INIT.TIM_ClockDivision=TIM_CKD_DIV1;
TIME2_INIT.TIM_RepetitionCounter=;
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=;
NVIC_INIT.NVIC_IRQChannelSubPriority=;
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
#ifndef _TIME2_H
#define _TIME2_H
void time2_configer();
void TIM2_IRQHandler();
#endif
//time2.h
STM32嵌入式开发学习笔记(五):中断的更多相关文章
- STM32嵌入式开发学习笔记(一)
本文中,笔者将介绍使用嵌入式开发工具Keil uVision5,使用C语言,对微处理器STM32F103C8进行嵌入式开发. 开发使用C语言,首先需要新建一个C语言文件,将其设为主函数的入口,因此,将 ...
- STM32嵌入式开发学习笔记(六):串口通信(上)
本文我们将了解STM32与外部设备通过串口通信的方式. 所谓串口通信,其实是一个类似于计算机网络的概念,它有物理层,比如规定用什么线通信,几伏特算高电平,几伏特算低电平.传输层,通信前要发RTS,CT ...
- STM32嵌入式开发学习笔记(七):串口通信(下)
下面我们进行几个串口通信的实际应用. 实验一:发信实验,让开发板通过串口向电脑发送信息: #include <stdio.h> #include <stm32f10x.h> # ...
- STM32嵌入式开发学习笔记(四):使用滴答计时器实现精准计时
前面我们讲过,因为在STM32上没有系统时间的接口,因此无法调用sleep函数,在本文中,笔者将利用滴答计时器实现精准延时. 查阅技术手册,滴答计时器依赖于一个SysTick_Type类型寄存器,定义 ...
- STM32嵌入式开发学习笔记(三):使用按键控制小灯
按键和小灯一样,也是通过GPIO外设与主板连接,也是通过GPIO_InitStruct类型结构体控制其工作. 查阅技术手册,按钮连接GPIOA控制下的管脚0. 但与之不同的是,按键是一种输入设备,输入 ...
- STM32嵌入式开发学习笔记(二):将功能封装为库文件
将所有的函数都堆在main.c文件里不是好的选择,庞大的代码文件会是你维护的障碍,明智的做法是,一种功能封装到一个库文件里. 库文件就是你代码开始部分写的#include<xxxx.h>里 ...
- stm32学习笔记——外部中断的使用
stm32学习笔记——外部中断的使用 基本概念 stm32中,每一个GPIO都可以触发一个外部中断,但是,GPIO的中断是以组为一个单位的,同组间的外部中断同一时间只能使用一个.比如说,PA0,PB0 ...
- python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍
python3.4学习笔记(五) IDLE显示行号问题,插件安装和其他开发工具介绍 IDLE默认不能显示行号,使用ALT+G 跳到对应行号,在右下角有显示光标所在行.列.pycharm免费社区版.Su ...
- stm32寄存器版学习笔记03 外部中断
stm32的每个I/O口都可以作为中断输入,要把I/O口设置为外部中断输入,必须将I/O口设置为上拉/下拉输入 或 浮空输入(但浮空的时候外部一定要带上拉或下拉电阻,否则可能导致 中断不停的触发),干 ...
随机推荐
- linux系统一些信息(待整理)
Linux查看物理CPU个数.核数.逻辑CPU个数 复制代码 # 总核数 = 物理CPU个数 X 每颗物理CPU的核数 # 总逻辑CPU数 = 物理CPU个数 X 每颗物理CPU的核数 X 超线程数 ...
- haproxy笔记
haproxy安装.启动.日志配置 方法1:#安装 yum install haproxy -y #日志配置 sed -i 's/^#$ModLoad imudp/$ModLoad imudp/g' ...
- 探索Redis设计与实现4:Redis内部数据结构详解——ziplist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- svm 之 线性可分支持向量机
定义:给定线性可分训练数据集,通过间隔最大化或等价的求解凸二次规划问题学习获得分离超平面和分类决策函数,称为线性可分支持向量机. 目录: • 函数间隔 • 几何间隔 • 间隔最大化 • 对偶算法 1. ...
- 82、TensorFlow教你如何构造卷积层
''' Created on 2017年4月22日 @author: weizhen ''' import tensorflow as tf #通过tf.get_variable的方式创建过滤器的权重 ...
- 【转】开源框架是如何通过JMX来做监控的(一) - JMX简介和Standard MBean
原文链接:https://www.cnblogs.com/trust-freedom/p/6842332.html#autoid-0-0-0 相信很多做Java开发的同学都使用过JDK自带的 jcon ...
- 打开myeclipse出现这个错是为什么
- Windows10下运行Android Studio3.3时关于AMD处理器不支持Intel硬件加速的解决办法
我的电脑是Thinkpad E485系列,CPU是AMD Ryzen 5 2500U,电脑预装系统是Windows10 X64家庭版,如下图所示: 下载安装了Android Studio3.3,创建了 ...
- libvirt虚拟机管理常用指令
创建虚拟机 virt-install virt-install --connect qemu:///system -n $NAME -r $MEM -f $DISK -s $DISK_SIZE --v ...
- 聊聊redis实际运用及骚操作
前言 聊起 redis 咱们大部分后端猿应该都不陌生,或多或少都用过.甚至大部分前端猿都知道. 数据结构: string. hash. list. set (无序集合). setsorted(有序集合 ...