STM32F103C8T6-中断

一、中断原理

 

 

 灰色为内核中断,中断地址是每次中断后跳转的地址,是固定的。

 

 

相同的PIN不能同时触发中断,比如GPIOA1,GPIOB1.,可触发中断响应,也可以触发事件响应

 

2、内部电路运行逻辑

1、输入进入,根据触发边沿选择,选择是否触发进入信号。有边沿触发和软件触发 

 2、然后进入两路,分别是触发中断和触发事件,触发中断会经过请求挂起寄存器(硬件中断标志位,等待处理)。中断屏蔽寄存器是中断总线上的中断使能。

触发事件会通过事件屏蔽寄存器,同使能,然后到达脉冲发生器,及电平脉冲,用来触发动作。

3、外部中断配合的传感器

外部驱动的很快的突发信号。比如编码器和红外遥控接收头的输出,按键虽然也是,但是中断不好处理按键抖动的问题。都是转瞬即逝的。

传感器1,对射式红外传感器测速,红外光受到遮挡和透过交替,来获取转速,和角度的方波。但是模块只有1路输出,正反转无法区分。

传感器2(2个图):是旋转编码器,内部使用金属触点来通断,是机械触点式编码器。AB点通过机械触点的角度差在旋转时可以得到正交波形,来判断转速和方向。上面的两个点用于按钮导通,按下导通,松手断开。一般用于调节音量等作为旋钮。

传感器3:是附在电机后面的霍尔式编码器,中间是一个圆形磁铁,边上两个位置错开的霍尔传感器,磁铁旋转时,通过霍尔传感器可以输出正交的方波信号。一般用于测速。

旋转编码器的远离电路:

上拉Vcc用来保持默认高电平,当旋钮导通,变为低电平,连接到GND,AB做AB相,引脚用上拉输入即可。

二、示例

1、外部中断对红外传感器计次

 根据流程配置外部中断

 1、RCC时钟开启

2、输入端口模式

3、配置AFIO,选择使用的GPIO,连接到后免得EXTI

4、配置EXTI,选择边沿触发方式,选择触发响应方式,可以选择中断响应和事件响应

5、配置NVIC,配置优先级

 

 CountSensor.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
int Count = 0;
void CountSensor_Init(void){
	//RCC
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//引脚时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);//AFIO时钟使能
	//GPIO
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	//AFIO
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
	//EXTI
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_Init(&EXTI_InitStructure);
	//NVIC misc.h  stm32f10x.h - 根据实际使用的芯片选择,STM32F103C8T6使用的是MD
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;//固定通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;//抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;//响应优先级
	NVIC_Init(&NVIC_InitStructure);
}
//中断函数 startup_stm32f10x_hd.s
void EXTI15_10_IRQHandler(){//固定名称
	if(EXTI_GetITStatus(EXTI_Line14)== SET){//防止中断判断错误,对中断标志位进行判断
		Delay_ms(10);
		while(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_14)== RESET);
		Delay_ms(10);
		Count++;
		EXTI_ClearITPendingBit(EXTI_Line14);//清除中断标志位
	}
}

  CountSensor.h

#ifndef __COUNTSENSOR_H
#define __COUNTSENSOR_H
#include "stm32f10x.h"                  // Device header
extern int  Count;
void CountSensor_Init(void);


#endif

main.c

#include "stdio.h"
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CountSensor.h"
extern int Count;
int main(){
	OLED_Init();
	CountSensor_Init();
	OLED_ShowString(1,1,"Infrared:");
	while(1){
		//LED
		OLED_ShowNum(1,10,Count,4);
	}
	return 0;
}

中断函数命名使用唯一名称。

2、旋转编码器采集测速

方法1: 使用A的下降沿中断,判断B的电平来判断正反转

方法2:使用A、B的下降沿中断,判断A、B的电平来判断正反转

此处使用方法二

main.c

#include "stdio.h"
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"
int16_t Num;//全局变量默认初始化0
int main(){
	OLED_Init();
	Encoder_Init();
	OLED_ShowString(1,1,"Count:");
	
	while(1){
		//LED
		Num += Encoder_Get();
		OLED_ShowSignedNum(1,7,Num,4);
	}
	return 0;
}

Encoder.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
int16_t Encoder_Count = 0;
void Encoder_Init(void){
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Speed  = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	//AFIO 中断引脚选择
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);//AFIO配置中断引脚的通道
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource0);
	
	//EXTI 边沿检测以及控制
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_InitStructure.EXTI_Line = EXTI_Line0 | EXTI_Line1;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE ;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	//引脚1 NVIC配置-中断优先级和中断对应通道使能
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
	
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_Init(&NVIC_InitStructure);
	//引脚1 NVIC配置
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
}
//每次获取编码器的增量,获取后对编码器计数进行清零
int16_t Encoder_Get(void){
	int16_t Temp=0;
	Temp = Encoder_Count;
	Encoder_Count=0;
	return Temp;
} 
//GPIOB0外部中断函数
void EXTI0_IRQHandler(){
	if(EXTI_GetFlagStatus(EXTI_Line0) == SET){//判断A相下降沿触发中断
		Delay_ms(3);
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == RESET){//再次判断A相电平,防止抖动
			if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET){//判断B相
				Encoder_Count--;//反转 --
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line0);//清除中断标志位 否则卡死
	}
}
//GPIOB1外部中断函数
void EXTI1_IRQHandler(){
	if(EXTI_GetFlagStatus(EXTI_Line1) == SET){//B相下降沿触中断
		Delay_ms(3);
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == RESET){//再次判断B相电平,防止抖动
			if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == RESET){//判断A相电平
				Encoder_Count++;//正转 --
			}
		}
		EXTI_ClearITPendingBit(EXTI_Line1);//清除中断标志位 否则卡死
	}
}

Encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H
#include "stm32f10x.h"                  // Device header
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif

三、中断编程建议

 1、不要再中断函数中处理耗时过长的代码,主程序会受到严重的阻塞

2、中断中不要使用例如屏幕显示等这种有原子性的程序,这样会导致中断程序和主程序的调用冲突。

3、多使用变量和标志位,增加程序内部的内聚性,减少模块之间的耦合性。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值