中断(NVIC)的使用--EXTI--TIM

目录

中断是什么

轮询

中断

中断调用情况

中断的分类

内部中断(TIM、UART等)

tim.c

tim.h

外部中断EXTI

exti.c

exti.h


中断是什么

在处理事件的时候有两种方式:轮询和中断。

轮询

顾名思义,就是每轮都询问一次。比如while循环的每一次,就会执行检查,1.此处串口是否有数据到来。2.每次都检测一下引脚状态,是否为低电平。在有大量事件发生时,cpu按照事件到来的先后顺序依次执行,不考虑时间的紧急性和事件大小,也就是不考虑时间的优先级。

中断

中断也是一种对于数据获取的调度方式。通过中断源来提醒CPU,数据已经更新,可以读取新数据。给每个事件设置优先级,在有大量事件发生时,cpu按照事件的优先级率先完成紧急性事件和处理时间短的事件

中断调用情况

CPU对于调度频次不高的任务(函数),或者特别紧急的任务(刹车制动这种) 给出的一种任务执行关系,这种关系的本质就是函数功能一旦出现,就要立即实施。这两种形式的任务一般都以中断形式调度,对于上一种任 务,优势在于提升系统运行速率,后一种提升了系统的实时性。 中断是一种芯片的内部的宝贵资源,数量是十分有限的。

中断的分类

内部资源根据硬件细节不同分出内部中断,和外部中断两种。

内部中断(TIM、UART等)

CPU内部有一个硬件结构叫做NVIC,也叫做中断管理控制器, NVIC管理着很多引脚,当特定事件发生时,会给NVIC发送一个信号,NVIC调用相应的中断函数传给CPU让其执行。

tim.c

#include "stm32f4xx.h"                  // Device header
#include "stdio.h"

//定时器的初始化
void Time_Init()
{
	//时钟使能
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);//1
	//参数配置,84M 84 000 000
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;//3
	TIM_TimeBaseInitStruct.TIM_ClockDivision=TIM_CKD_DIV1;//4
	TIM_TimeBaseInitStruct.TIM_CounterMode=TIM_CounterMode_Up;
	TIM_TimeBaseInitStruct.TIM_Period=(5000-1);//工作量(路程),每一趟执行一次中断
	TIM_TimeBaseInitStruct.TIM_Prescaler=(8400-1);//84M除以8400=10 000,工作速度(10 000/s)
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter=0;
	
	TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStruct);//2
	
	//让定时器开始工作
	
	TIM_Cmd(TIM2,ENABLE);
	
	//定时器开启中断,看到TIM_Period,数到头,给NVIC说一声
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	//中断分组
	//分组方式,2位给抢占优先级,2位给响应优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//从此处判断核心需求数量(2)
	
	//NVIC参数配置
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=TIM2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;
	
	NVIC_Init(&NVIC_InitStruct);
	
}
void TIM2_IRQHandler()
{
	//信号判断,中断进一步确认
	if(TIM_GetITStatus(TIM2,TIM_IT_Update))
	{
		printf("not apple tree!\n");
	}
	//中断信号清除
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
}

tim.h

#include "stm32f4xx.h"                  // Device header
void Time_Init();

外部中断EXTI

上图紫色线路为轮询机制。黑色线路部分为内部中断。红色线路部分为外部中断NVIC处理的是中断信号,不是电平信号。

为什么GPIO需要接入EXTI产生中断信号,而不直接连到NVIC上?

usart,TIM,IIC这些芯片 内部器件本身就可以产生中断信号,因此就可以直接与NVIC连接。但是,光突突的GPIO本身就是一根电线,肯定不具备产生中断信号的功能。因此连接 EXTI,依靠EXTI产生中断信号。 原因2:中断通达数量比较少,EXTI的多路复选的功能扩充了接口。一个EXTI可 以接16个GPIO引脚呢。

exti.c

#include "stm32f4xx.h"                  // Device header
#include "BitBand.h"
#include "stdio.h"
#include "delay.h"

void exti_key_init()
{
	//时钟配置
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG,ENABLE);
	
	//给GPIO参数配置
	GPIO_InitTypeDef GPIO_InitStruct;
	
	GPIO_InitStruct.GPIO_Mode=GPIO_Mode_IN;
	GPIO_InitStruct.GPIO_OType=GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_2;
	GPIO_InitStruct.GPIO_PuPd=GPIO_PuPd_UP;
	GPIO_InitStruct.GPIO_Speed=GPIO_High_Speed;
	
	GPIO_Init(GPIOE,&GPIO_InitStruct);
	//把GPIOE组的第2个引脚连接到EXTI2
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource2);
	//把GPIOE组的第3个引脚连接到EXTI3
	SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE,EXTI_PinSource3);
	
	//EXTI参数配置
	//告诉EXTI2、3,看见上升沿,就给NVIC发送中断信号
	EXTI_InitTypeDef EXTI_InitStruct;
	
	EXTI_InitStruct.EXTI_Line=EXTI_Line2|EXTI_Line3;
	EXTI_InitStruct.EXTI_LineCmd=ENABLE;
	EXTI_InitStruct.EXTI_Mode=EXTI_Mode_Interrupt;
	EXTI_InitStruct.EXTI_Trigger=EXTI_Trigger_Rising;
	
	EXTI_Init(&EXTI_InitStruct);
	
	//分组方式,2位给抢占优先级,2位给响应优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//从此处判断核心需求数量(2)
	
	NVIC_InitTypeDef NVIC_InitStruct;
	NVIC_InitStruct.NVIC_IRQChannel=EXTI2_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;
	
	NVIC_Init(&NVIC_InitStruct);
	
	//分组方式,2位给抢占优先级,2位给响应优先级
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);//从此处判断核心需求数量(2)
	
	NVIC_InitStruct.NVIC_IRQChannel=EXTI3_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd=ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority=2;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority=2;
	
	NVIC_Init(&NVIC_InitStruct);
}

//中断服务子函数,给EXTI2服务
void EXTI2_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line2))
	{
		printf("key2 apple tree\n");
	}
	
	EXTI_ClearITPendingBit(EXTI_Line2);
}

//中断服务子函数,给EXTI3服务
void EXTI3_IRQHandler()
{
	if(EXTI_GetITStatus(EXTI_Line3))
	{
		printf("key3 apple tree\n");
	}
	
	EXTI_ClearITPendingBit(EXTI_Line3);
}
	

exti.h

#include "stm32f4xx.h"                  // Device header

void exti_key_init();

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值