STM32外部中断(红外传感器与旋转编码器计数案例)

文章目录

  • 一、介绍部分
    • 简介中断系统
    • 中断执行流程
    • STM32中断
    • NVIC基本结构
    • NVIC优先级分组
    • 外部中断
      • 外部中断简介
      • 外部中断基本结构
      • 外部中断的流程
      • AFIO
      • EXTI框图
    • 相关外设介绍
      • 旋转编码器介绍
      • 硬件电路
      • 对射式红外传感器
  • 二、代码实现
    • 对射式红外传感器计次
      • 连接电路
        • 封装红外传感器与中断函数
    • 旋转编码器计数
      • 连接电路
        • 封装旋转编码器函数、外部中断函数
  • 补充



一、介绍部分

简介中断系统

STM32外部中断(红外传感器与旋转编码器计数案例)_第1张图片

中断执行流程

STM32外部中断(红外传感器与旋转编码器计数案例)_第2张图片

STM32中断

STM32外部中断(红外传感器与旋转编码器计数案例)_第3张图片
STM32外部中断(红外传感器与旋转编码器计数案例)_第4张图片
此地址是用于编译器来跳转到中断函数的地址

NVIC基本结构

NVIC作用是为CPU分配各个中断优先级,然后直接告诉CPU先执行的中断函数。

STM32外部中断(红外传感器与旋转编码器计数案例)_第5张图片

NVIC优先级分组

STM32外部中断(红外传感器与旋转编码器计数案例)_第6张图片

外部中断

外部中断简介

STM32外部中断(红外传感器与旋转编码器计数案例)_第7张图片

外部中断基本结构

STM32外部中断(红外传感器与旋转编码器计数案例)_第8张图片

外部中断的流程

**

AFIO先从GPIOA、GPIOB、GPIOC中选择16个不同Pin值的引脚(如不能同时有GPIOA 的PIN_1或GPIOB的PIN_1),以此来选出16个中断通道,然后选择这些中断是否是跳转到其他外设,不是的话就会通过NVIC来配置要打开的中断通道、中断通道的优先级,最后按照优先级顺序依次交予CPU执行

**

AFIO

STM32外部中断(红外传感器与旋转编码器计数案例)_第9张图片

EXTI框图

STM32外部中断(红外传感器与旋转编码器计数案例)_第10张图片

相关外设介绍

旋转编码器介绍

STM32外部中断(红外传感器与旋转编码器计数案例)_第11张图片

硬件电路

STM32外部中断(红外传感器与旋转编码器计数案例)_第12张图片

对射式红外传感器

两个面板对射红外线,被遮挡恢复一次后就会产生一个电平变化。
STM32外部中断(红外传感器与旋转编码器计数案例)_第13张图片

二、代码实现

对射式红外传感器计次

让对射式红外传感器每被遮挡一次时,让OLED显示的数字+1

连接电路

STM32外部中断(红外传感器与旋转编码器计数案例)_第14张图片

封装红外传感器与中断函数

IRSensor.c

#include "stm32f10x.h"                  // Device header
// 初始化
void IRSensor_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_14;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB,&GPIO_InitStructure);
	// 配置AFIO引脚选择
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource14);
	
	EXTI_InitTypeDef EXTI_InitStructure;
	// 选择中断线,14号端口对应14号线
	EXTI_InitStructure.EXTI_Line = EXTI_Line14;
	// 是否开启这条中断线
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	// 中断模式还是事件模式
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	// 触发方式,下降沿触发
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
	// 设置中断优先级组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	// 中断通道
	NVIC_InitStructure.NVIC_IRQChannel = EXTI15_10_IRQn;
	// 是否打开通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	// 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	// 相应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
}
// 用于计数
uint16_t Count = 0;
// 获取计数器的值
uint16_t GetCount(void){
	return Count;
}

// 中断函数
void EXTI15_10_IRQHandler(void){
	// 获取中断线是否打开
	if(EXTI_GetITStatus(EXTI_Line14) == SET){
		// 如果出现数据乱跳的现象,可再次判断引脚电平,以避免抖动
		if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_14) == 0){
			// 计数器+1
			Count++;
		}
		// 清除中断
		EXTI_ClearITPendingBit(EXTI_Line14);
	}
}

主函数main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "IRSensor.h"

int main(void)
{
	OLED_Init();
	IRSensor_Init();
	OLED_ShowString(1,1,"Count:");
	while (1)
	{
		OLED_ShowNum(2,1,GetCount(),4);
	}
}

旋转编码器计数

连接电路

STM32外部中断(红外传感器与旋转编码器计数案例)_第15张图片

封装旋转编码器函数、外部中断函数

有多条中断线时,要分别初始化,不能有相同的优先级,不过定义的初始化结构体可以重复使用。

Encoder.c内容

#include "stm32f10x.h"                  // Device header

uint16_t EncoderCount;
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_PinSource0);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);
	
	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);
	
	// 设置中断优先级组
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	// 为两个通道分别初始化配置优先级
	NVIC_InitTypeDef NVIC_InitStructure;
	// 中断通道
	NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
	// 是否打开通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	// 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	// 相应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	// 中断通道
	NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;
	// 是否打开通道
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	// 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	// 相应优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
	NVIC_Init(&NVIC_InitStructure);
}

// 获取计数数据
uint16_t Encoder_Get(void){
	uint16_t Temp;
	Temp = EncoderCount;
	EncoderCount = 0;
	return Temp;
}

// 中断函数
void EXTI0_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line0) == SET){
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0)
			EncoderCount++;
		// 清除此中断通道标志
		EXTI_ClearITPendingBit(EXTI_Line0);
	}
}
void EXTI1_IRQHandler(void){
	if(EXTI_GetITStatus(EXTI_Line1) == SET){
		if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0)
			EncoderCount--;
		// 清除此中断通道标志
		EXTI_ClearITPendingBit(EXTI_Line1);
	}
}

主函数main.c内容

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"

int16_t Num;
int main(void)
{
	OLED_Init();
	Encoder_Init();
	OLED_ShowString(1,1,"Num:");
	while (1)
	{
		// 每次的数加旋转的数
		Num += Encoder_Get();
		OLED_ShowSignedNum(2,1,Num,5);
	}
}


补充

两种获取中断标志与清除标志函数
前两中适用于普通函数执行
后两种适用于中断函数中执行

// 获取中断线标志
FlagStatus EXTI_GetFlagStatus(uint32_t EXTI_Line);
// 清除此中断线标志
void EXTI_ClearFlag(uint32_t EXTI_Line);
// 获取中断线标志
ITStatus EXTI_GetITStatus(uint32_t EXTI_Line);
// 清除此中断线标志
void EXTI_ClearITPendingBit(uint32_t EXTI_Line);

中断函数可以在开始文件中寻找
STM32外部中断(红外传感器与旋转编码器计数案例)_第16张图片

你可能感兴趣的:(STM32学习记录,stm32,单片机,嵌入式硬件)