STM32中断和外部中断

 

NVIC:嵌套中断向量控制器:用于统一分配中断优先级和管理中断

响应式优先级:也可以称为插队式优先级哪个优先级高优先处理哪个

抢占式优先级:优先级高的可以优先被处理,相当于CPU可以暂时中断当前处理的程序,优先处理优先级更高的程序,该程序执行完成后再执行原先没有执行完毕的程序,也可以称之为嵌入式中断优先级

AFIO中断引脚选择:是一个中断引脚选择器可以在前面GPIO外设的16个引脚中选择一个连接到EXTI边沿检测及控制中所以

相同的Pin不能同时触发中断,因为PA0,PB0,PC0通过AFIO选择后只有其中一个可以连接到EXTI的通道0上,PB1,PC1等也只有一个可以接入EXTI上

模拟电子技术与或门基础

旋转编码器讲解

旋转编码器的硬件电路

外部中断寄存器代码

1:接线

#include "stm32f10x.h"                  // Device header// 编写初始化函数--->模块化的第一步是编写初始化函数
void CountSersor_Init(void){/*外部中断配置  1: 配置RCC进涉及的外部中断时钟全部打开2:配置GPIO选择端口为输入模式3: 配置AFIO选择需要使用到的GPIO并连接后面的exit4:配置EXTI选择边沿触发的方式如上升沿,下降沿,或者是双边沿,选择触发响应的方式5:配置NVIC给中断选择一个合适的优先级*/}

AFIO相关函数


             用于复位AFIO外设,调用这个函数会清除AFIO外设
             void GPIO_AFIODeInit(void);
             用于锁定GPIO配置调用这个函数参数指定某个引脚,锁定引脚配置防止意外更改
             void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
             以下的两个函数是用于配置AFIO的事件输出功能
           void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
           void GPIO_EventOutputCmd(FunctionalState NewState);

             这个函数可以用作引脚重映射,第一个参数是重映射的方式,第二个参数是新的状态
             void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
          
  这个函数外部中断需要使用到的函数,调用这个函数可以选择我们的中断引脚
       void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);
             和以太网相关外设暂时没有使用到
             void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);

EXTI相关函数

NVIC配置

编写中断函数代码实现当遮挡传感器时oled显示屏中的数字加1

中断函数代码

#include "stm32f10x.h"                  // Device header
uint16_t CountSensor_Count;// 编写初始化函数--->模块化的第一步是编写初始化函数
void CountSersor_Init(void){//1------>todo : 配置RCC进涉及的外部中断时钟全部打开// 开启GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 开启AFIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// EXPI和NVIC的时钟一直处于打开状态不需要我们手动开启//2------>todo : 配置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初始化函数,初始GPIOBGPIO_Init(GPIOB,&GPIO_InitStructure);// 3:todo ------->  配置AFIO选择需要使用到的GPIO并连接后面的exitGPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource14);// 3:todo ------->配置EXTI选择边沿触发的方式如上升沿,下降沿,或者是双边沿,选择触发响应的方式EXTI_InitTypeDef Exit_InitStruct;// 引出结构体成员Exit_InitStruct.EXTI_Line =EXTI_Line14; // 指定需要配置的中断线Exit_InitStruct.EXTI_LineCmd =ENABLE; // 开启中断Exit_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 模式:中断模式Exit_InitStruct.EXTI_Trigger =EXTI_Trigger_Falling ;// 下降沿触发EXTI_Init(&Exit_InitStruct);// 选择中断分组函数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 CountSensor_Get(void){return CountSensor_Count;
}void  EXTI15_10_IRQHandler(void){if(EXTI_GetITStatus(EXTI_Line14) == SET){CountSensor_Count++;// 中断程序结束后一定要清除中断程序标志位函数EXTI_ClearITPendingBit(EXTI_Line14);}
}

中断函数头文件

#ifndef __COUNT_SENSOR_H__
#define __COUNT_SENSOR_H__/*外部中断配置  1: 配置RCC进涉及的外部中断时钟全部打开2:配置GPIO选择端口为输入模式3: 配置AFIO选择需要使用到的GPIO并连接后面的exit4:配置EXTI选择边沿触发的方式如上升沿,下降沿,或者是双边沿,选择触发响应的方式5:配置NVIC给中断选择一个合适的优先级*/
void CountSersor_Init(void);
uint16_t CountSensor_Get(void);#endif

主函数调用代码

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "CounterSensor.h"int main(void)
{// 初始化oledOLED_Init();CountSersor_Init();// 使用OLED显示字符串OLED_ShowString(1,3,"Count:");while (1){OLED_ShowNum(1, 7, CountSensor_Get(), 5);   }
}

旋转编码器中断

接线

编写中断函数模块部分代码

Encoder.c

#include "stm32f10x.h"                  // Device headerint16_t Encoder_Count;// 编辑初始化函数
void Encoder_Init(void){//1------>todo : 配置RCC进涉及的外部中断时钟全部打开// 开启GPIOB的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);// 开启AFIO的时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);// EXPI和NVIC的时钟一直处于打开状态不需要我们手动开启//2------>todo : 配置GPIO选择端口为输入模式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初始化函数,初始GPIOBGPIO_Init(GPIOB,&GPIO_InitStructure);// 3:todo ------->  配置AFIO选择需要使用到的GPIO并连接后面的exitGPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource0);GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource1);// 3:todo ------->配置EXTI选择边沿触发的方式如上升沿,下降沿,或者是双边沿,选择触发响应的方式EXTI_InitTypeDef Exit_InitStruct;// 引出结构体成员Exit_InitStruct.EXTI_Line =EXTI_Line0 | EXTI_Line1; // 指定需要配置的中断线Exit_InitStruct.EXTI_LineCmd =ENABLE; // 开启中断Exit_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt; // 模式:中断模式Exit_InitStruct.EXTI_Trigger =EXTI_Trigger_Falling ;// 下降沿触发EXTI_Init(&Exit_InitStruct);// 选择中断分组函数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);
}//中断函数
void EXTI0_IRQHandler(void){// 检查中断标志位if(EXTI_GetITStatus(EXTI_Line0) ==  SET){// 判断另外一个引脚的电平if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_1) == 0){// 向着相反的方向旋转Encoder_Count--;}EXTI_ClearITPendingBit(EXTI_Line0);}
}// 调用函数后返回count的变化值
int16_t Encoder_Get(void){int16_t Temp;Temp = Encoder_Count;Encoder_Count = 0;return Temp;
}void EXTI1_IRQHandler(void){// 检查中断标志位if(EXTI_GetITStatus(EXTI_Line1) ==  SET){// 判断引脚的电平if(GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_0) == 0){// 向着正方向旋转Encoder_Count++;}EXTI_ClearITPendingBit(EXTI_Line1);}
}

Encoder.h代码

#ifndef  __ENCODER_H__
#define  __ENCODER_H__
void Encoder_Init(void);
int16_t Encoder_Get(void);
#endif

main.c调用编写好的中断函数

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encoder.h"int16_t Num;
int main(void)
{// 初始化oledOLED_Init();Encoder_Init();// 使用OLED显示字符串OLED_ShowString(1,1,"Num:");while (1){Num += Encoder_Get();OLED_ShowSignedNum(1,5,Num,5);}
}

注:编写中断函数代码时尽量做到简洁,同时主函数中使用到的功能模块函数不要编写在中断函数中,会出行编译错误,中断程序中避免添加延时函数,中断函数多事件的实时性处理能力较强。

以上是本人基于STM32中断部分知识的学习总结,参考B站江科大教程

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

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

相关文章

Python算法(列表排序)

一。冒泡排序: 列表每两个相邻的数,如果前面比后面大,则交换这两个数 一趟排序完成后,则无序区减少一个数,有序区增加一个数 时间复杂度:O(n*n) 优化后:已经排序好后立马停止,加快…

【力扣 - 合并区间】

题目描述 以数组 intervals 表示若干个区间的集合,其中单个区间为 intervals[i] [start_i, end_i] 。请你合并所有重叠的区间,并返回 一个不重叠的区间数组,该数组需恰好覆盖输入中的所有区间 。 示例 1: 输入:int…

环形缓冲区在stm32上的使用

目录 环形缓冲区在stm32上的使用前言实验目的环形缓冲区的定义和初始化写入数据到环形缓冲区从环形缓冲区读取数据实验结果本文中的实践工程 环形缓冲区在stm32上的使用 本文目标:环形缓冲区在stm32上的使用 按照本文的描述,应该可以跑通实验并举一反三…

Day31:安全开发-JS应用WebPack打包器第三方库JQuery安装使用安全检测

目录 打包器-WebPack-使用&安全 第三方库-JQuery-使用&安全 思维导图 JS知识点: 功能:登录验证,文件操作,SQL操作,云应用接入,框架开发,打包器使用等 技术:原生开发&…

使用Nginx进行负载均衡

什么是负载均衡 Nginx是一个高性能的开源反向代理服务器,也可以用作负载均衡器。通过Nginx的负载均衡功能,可以将流量分发到多台后端服务器上,实现负载均衡,提高系统的性能、可用性和稳定性。 如下图所示: Nginx负…

如何注册Devin-首个全自主AI软件工程师

最近devin大火,具体的就不说了,大家应该都知道,写代码非常nb,这里说一下devin的注册方式,目前devin的内测已经开启。 官网https://www.cognition-labs.com/blog注册网址Your reliable AI software engineerhttps://pr…

一文扫荡,12个可视化图表js库,收藏备用。

一、什么是可视化图表 可视化图表是通过图形化的方式将数据可视化展示出来的一种方式。它能够将复杂的数据以直观、易懂的形式呈现给用户,帮助用户更好地理解和分析数据。 可视化图表可以包括各种类型的图表,如线形图、柱状图、饼图、散点图、雷达图等。…

查看docker安装MySQL版本

要查看Docker中安装的MySQL版本,您可以按照以下步骤操作: 首先确保您有一个正在运行的MySQL Docker容器。如果尚未启动MySQL容器,请使用类似下面的命令启动它(假设已经从Docker Hub拉取了镜像): docker run…

L2-034: 口罩发放(Python)

为了抗击来势汹汹的 COVID19 新型冠状病毒,全国各地均启动了各项措施控制疫情发展,其中一个重要的环节是口罩的发放。 某市出于给市民发放口罩的需要,推出了一款小程序让市民填写信息,方便工作的开展。小程序收集了各种信息&…

centos命令history设置记录10000行

今天在操作服务器的时候,用history查看操作记录的时候,发现只能查看10条,这样不行啊,我想查看所有人对服务器操作的命令。 [rootbogon ~]# history解决办法: #1、找到/etc/profile文件中的histsize 把10改成10000 […

【django framework】ModelSerializer+GenericAPIView,如何在提交前修改某些字段值

【django framework】ModelSerializerGenericAPIView,如何在提交前修改某些字段值 我们经常会遇到下面这种情况: 序列化器用的是ModelSerializer,写视图的时候继承的是generics.CreateAPIView。现在我想在正式提交到数据库(perform_create)之…

Windows kafka 简单集群搭建

Windows kafka 简单集群搭建 文章目录 Windows kafka 简单集群搭建1.环境说明2.Zookeeper集群搭建2.1 ZooKeeper下载2.2 ZooKeeper安装2.2.1 解压zookeeper-3.4.8.tar.gz2.2.2 进入conf目录下,复制zoo_sample.cfg为zoo.cfg2.2.3 修改zoo.cfg文件2.2.4 生成myid文件2…

24GB内存就能跑7B参数大模型?全新训练策略GaLore助你突破内存瓶颈

训练大型语言模型,内存总是个大问题。 权重啊、优化器状态啊,都得吃内存,而且吃得还不少。 为了省内存,有人就想出了一些招儿,比如低秩适应(LoRA),就是给预训练权重添点儿可训练的…

基于YOLOv8深度学习的木薯病害智能诊断与防治系统【python源码+Pyqt5界面+数据集+训练代码】深度学习实战

《博主简介》 小伙伴们好,我是阿旭。专注于人工智能、AIGC、python、计算机视觉相关分享研究。 ✌更多学习资源,可关注公-仲-hao:【阿旭算法与机器学习】,共同学习交流~ 👍感谢小伙伴们点赞、关注! 《------往期经典推…

基于C++的一种字符串切分方法及示例代码

一、概述 在 Java 和 python 中,都有实现字符串切分的方法, 如split() ,使用起来较为方便,但是在标准的 C 中,却没有内置的 split() 方法。 我们可以使用标准库中的一些函数和方法来实现字符串的切分,这里…

【Java系列】OOM 时,JVM 堆栈信息保存和分析

一、前言 在日常开发中,即使代码写得再谨慎,免不了还是会发生各种意外的事件,比如服务器内存突然飙高,又或者发生内存溢出(OOM)。当发生这种情况时,我们怎么去排查,怎么去分析原因呢? 一般遇到…

前端开发小技巧【Vue篇】 - 样式穿透 + 绑定变量

前言 样式穿透 Vue都是通过深度选择器来样式穿透的。当我们在写项目的时候,经常会导入第三方库,有些特殊的情况,就是在导入第三方库后,呈现的样式并不是我们想要的样式,所以我们需要对第三方的样式进行修改&#xff1…

Java毕业设计 基于SSM jsp房屋租赁系统 房屋出租系统

Java毕业设计 基于SSM jsp房屋租赁系统 房屋出租系统 SSM jsp 房屋租赁系统 房屋出租系统 功能介绍 用户:首页 图片轮播 搜索 登录注册 新闻公告 新闻公告详情 装修广告 热门房源 房源详情 合租 整租 商业办公 普通民宅 酒店式公寓 全部房源 留言交流 发布帖子 模…

汽车大灯罩汽车尾灯罩破裂裂纹破损破洞掉角崩角等问题能修复吗?怎么修复?

汽车大灯汽车尾灯破裂裂纹破损破洞掉角崩角等问题是一定可以修复的。 汽车灯罩的修复方法取决于灯罩的破损程度和材质。以下是一些常见的汽车灯罩修复方法: 肥皂水清洗:如果灯罩只是轻微模糊或发黄,可以使用肥皂水进行清洗。将肥皂水涂抹在…

opencv-python连通域分割connectedComponents

文章目录 连通域简介绘图代码函数说明 连通域简介 所谓连通域,即Connected Component,是一组彼此相连的像素点的集合,这些像素点彼此之间可以假设一条互相链接的路径,路径上所有像素的灰度一致,或者符合某个特定的条件…