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

文章目录

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



一、介绍部分

简介中断系统

在这里插入图片描述

中断执行流程

在这里插入图片描述

STM32中断

在这里插入图片描述
在这里插入图片描述
此地址是用于编译器来跳转到中断函数的地址

NVIC基本结构

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

在这里插入图片描述

NVIC优先级分组

在这里插入图片描述

外部中断

外部中断简介

在这里插入图片描述

外部中断基本结构

在这里插入图片描述

外部中断的流程

**

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

**

AFIO

在这里插入图片描述

EXTI框图

在这里插入图片描述

相关外设介绍

旋转编码器介绍

在这里插入图片描述

硬件电路

在这里插入图片描述

对射式红外传感器

两个面板对射红外线,被遮挡恢复一次后就会产生一个电平变化。
在这里插入图片描述

二、代码实现

对射式红外传感器计次

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

连接电路

在这里插入图片描述

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

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){// 计数器+1Count++;}// 清除中断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);}
}

旋转编码器计数

连接电路

在这里插入图片描述

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

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

Encoder.c内容

#include "stm32f10x.h"                  // Device headeruint16_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);

中断函数可以在开始文件中寻找
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/451371.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】统信服务器操作系统V20 1060a-AMD64 Vmware安装

目录 ​编辑 一、概述 1.1 简介 1.2 产品特性 1.3 镜像下载 二、虚拟机安装 一、概述 1.1 简介 官网:统信软件 – 打造操作系统创新生态 统信服务器操作系统V20是统信操作系统(UOS)产品家族中面向服务器端运行环境的,是一款…

mysql升级到8.x

1.下载和安装 1.1.下载 mysql下载地址: https://dev.mysql.com/downloads/mysql/5.5.html?os31&version5.1 应该下载这个类似版本 mysql-8.0.36-linux-glibc2.17-x86_64-minimal.tar.xz 1.2 安装 解压: tar xvf mysql-8.0.36-linux-glibc2.17…

C语言-2

自定义类型 基本认识 /*引入:学生:姓名,学号,年龄,成绩请为学生们专门定制一个类型(创造一个类型)结构体格式:struct 标识符 // 标识符即自定义类型的名称{成员; // 自己设置…

【洛谷】P2392 kkksc03考前临时抱佛脚

本题最重要的思路是:将题目转化为 01 背包模型。 注意点: (1)要求最短时间,则需让左右脑花费的时间最接近,极限状态下是左脑时间和右脑时间相等,且等于 m sum / 2(其中sum是一道…

如何使用项目管理工具进行任务分配和进度跟踪

项目管理是一项重要的工作,有效的任务分配和进度跟踪是项目成功的关键因素。 项目经理可以选择合适的项目管理工具来管理项目,在选择项目管理工具时,需要根据项目的特点和需求进行评估。本文将介绍如何使用项目管理工具来进行任务分配和进度…

已解决: ModuleNotFoundError: No module named ‘tensorflow‘ 问题

博主猫头虎的技术世界 🌟 欢迎来到猫头虎的博客 — 探索技术的无限可能! 专栏链接: 🔗 精选专栏: 《面试题大全》 — 面试准备的宝典!《IDEA开发秘籍》 — 提升你的IDEA技能!《100天精通鸿蒙》 …

【蓝桥杯冲冲冲】[NOIP2001 普及组] 装箱问题

蓝桥杯备赛 | 洛谷做题打卡day26 文章目录 蓝桥杯备赛 | 洛谷做题打卡day26题目描述输入格式输出格式样例 #1样例输入 #1样例输出 #1 提示思路 题解代码我的一些话 [NOIP2001 普及组] 装箱问题 题目描述 有一个箱子容量为 V V V,同时有 n n n 个物品,每…

2024年【熔化焊接与热切割】考试题及熔化焊接与热切割操作证考试

题库来源:安全生产模拟考试一点通公众号小程序 熔化焊接与热切割考试题根据新熔化焊接与热切割考试大纲要求,安全生产模拟考试一点通将熔化焊接与热切割模拟考试试题进行汇编,组成一套熔化焊接与热切割全真模拟考试试题,学员可通…

手把手教你开发Python桌面应用-PyQt6图书管理系统-图书类别添加代码逻辑实现

锋哥原创的PyQt6图书管理系统视频教程: PyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~_哔哩哔哩_bilibiliPyQt6图书管理系统视频教程 Python桌面开发 Python入门级项目实战 (无废话版) 火爆连载更新中~共计24条视频&…

大模型增量预训练新技巧:解决灾难性遗忘

大家好,目前不少开源模型在通用领域具有不错的效果,但由于缺乏领域数据,往往在一些垂直领域中表现不理想,这时就需要增量预训练和微调等方法来提高模型的领域能力。 但在领域数据增量预训练或微调时,很容易出现灾难性…

c++重载、隐藏和覆盖

重载 函数名字相同&#xff0c;但参数列表或者返回值不同一组函数要重载必须处在同一作用域中 class Base { public:Base(int data0):m_a(data){}void show(){cout<<"Base::show()"<<endl;}void show(int){cout<<"Base:show(int)"<&l…

STM32--SPI通信协议(2)W25Q64简介

一、W25Q64简介 1、W25Qxx中的xx是不同的数字&#xff0c;表示了这个芯片不同的存储容量&#xff1b; 2、存储器分为易失性与非易失性&#xff0c;主要区别是存储的数据是否是掉电不丢失&#xff1a; 易失性存储器&#xff1a;SRAM、DRAM&#xff1b; 非易失性存储器&#xff…