STM32中断编程入门

文章目录

  • 一、 理论部分
    • 1.中断系统
    • 2.中断执行流程
    • 3.NVIC的基本结构
    • 4.EXTI介绍
    • 5.AFIO复用IO口
  • 二、实验目的:学习stm32中断原理和开发编程方法。使用标准完成以下任务:
    • (一)实验一 开关控制LED的亮灭
      • 1.代码部分
      • 2.运行结果
    • (二)实验二 接收单个字符控制发送数据
      • 1.代码部分
      • 2.运行结果
    • (三)实验三 接收字符串控制发送数据
      • 1.代码部分
      • 2.运行结果
  • 三、总结

一、 理论部分

1.中断系统

在这里插入图片描述

2.中断执行流程

在这里插入图片描述

3.NVIC的基本结构

在这里插入图片描述

在这里插入图片描述

4.EXTI介绍

在这里插入图片描述在这里插入图片描述

5.AFIO复用IO口

在这里插入图片描述

二、实验目的:学习stm32中断原理和开发编程方法。使用标准完成以下任务:

用stm32F103核心板的GPIOA端一管脚接一个LED,GPIOB端口一引脚接一个开关(用杜邦线模拟代替)。采用中断模式编程,当开关接高电平时,LED亮灯;接低电平时,LED灭灯。
可参考教材课件上的6.4.3示例
采用串口中断方式重做上周的串口通信作业,分别实现:1)当stm32接收到字符“s”时,停止持续发送“hello windows!”; 当接收到字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);2)当stm32接收到字符“stop stm32!”时,停止持续发送“hello windows!”; 当接收到字符“go stm32!”时,持续发送“hello windows!”(提示:要将接收到的连续字符保存到一个字符数组里,进行判别匹配。写一个接收字符串的函数。

(一)实验一 开关控制LED的亮灭

1.代码部分

//exti_key.c文件
#include "exti_key.h"
#include "misc.h"



void EXTI_Key_Init()
{
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_AFIO,ENABLE);  //打开GPIOA和复用输入输出口的时钟
	
	//配置GPIO口
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Mode = GPIO_Pin_3;     
	GPIO_InitStructure.GPIO_Pin = GPIO_Mode_IN_FLOATING;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	//配置NVIC(Nested Vectored Interrupt Controller:嵌套向量中断控制器)
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitStructure.NVIC_IRQChannel = EXTI3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	//配置EXTI(External Interrupt/Event Controller:外部中断/事件控制器)
	EXTI_InitTypeDef EXTI_InitStructure;
	EXTI_ClearITPendingBit(EXTI_Line3);
	GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource3);
	EXTI_InitStructure.EXTI_Line = EXTI_Line3;
	EXTI_InitStructure.EXTI_LineCmd = ENABLE;
	EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
	EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
	EXTI_Init(&EXTI_InitStructure);
	
}
#include "stm32f10x.h"  
#include "exti_key.h"
#include "LED.h"

uint8_t led = 1;
int main()
{
	
	GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET); //默认为熄灭
	EXTI_Key_Init();
	while(1)
	{}
}

void EXTI3_IRQHandler()
{
	
	if(EXTI_GetITStatus(EXTI_Line3) != RESET )
	{
	led = ~led;
	if(led == 1)
	{
		GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);
	}
		
	
	else
	{
		GPIO_WriteBit(GPIOB,GPIO_Pin_5,Bit_SET);
	}		
	EXTI_ClearITPendingBit(EXTI_Line3);
	
	}
	
}


2.运行结果

20240519_002

(二)实验二 接收单个字符控制发送数据

采用串口中断方式,当stm32接收到1个字符“s”时,停止持续发送“hello windows!”; 当接收到1个字符“t”时,持续发送“hello windows!”(提示:采用一个全局标量做信号灯);

1.代码部分

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

int status = 0;//设置是否发送数据的标志位
int main()
{	
	//开启GPIOA和USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
	
	
	
	//实例化控制器的对象
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	//先配置GPIO控制器
	//1.设置PA9为复用推挽输出模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置为复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
	GPIO_Init(GPIOA,&GPIO_InitStructure);   //老子草了没写这一句,以为只GPIO_Init()一次就可以了,结果忘了这些参数会覆盖的。
	
	//2.设置PA10为浮空输入模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置为浮空输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	//再配置USART控制器
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //硬件流控制:选择无流控制
	USART_InitStructure.USART_Mode = USART_Mode_Tx |USART_Mode_Rx; //模式选择发送和接收
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_ClearFlag(USART1, USART_FLAG_TC);
	
	USART_Init(USART1,&USART_InitStructure);  //初始化串口1
	
	
	//配置中断源
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//当USART串口接收到数据的时候,就触发USART中断
	
	// 4.给这个中断源配置相应的抢占优先级和执行优先级
		NVIC_InitTypeDef  NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;      
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //设置抢占(主)优先级    
		NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;      // 设置子优先级   
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             
		NVIC_Init(&NVIC_InitStructure);    
	
	
	USART_Cmd(USART1,ENABLE);			//使能串口1
	
	char transmitArray[18]={"hello windows! \r\n "};   //windows系统串口发送时,用回车换行组合 (\r\n) 来实现换行
	
	while(1)
	{	
		if(status == 1) //标志位status = 1 发送
		{for(int i=0;i<=17;i++)
		{
		USART_SendData(USART1,transmitArray[i]);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)== RESET);  //RESET就是0,表示不符合,TXE的E是empty,表示发送寄存器不符合为空,即里面有东西,还在发送。	
		}
		Delay_s(1);
		}
	}
	
}

void USART1_IRQHandler(void)
{
	while(USART_GetITStatus(USART1,USART_IT_RXNE) == RESET ) //这里不再是USART_GetFlagStatus、USART_FLAG_RXNE,而是USART_GetITStatus、SART_IT_RXNE,要换成中断
	{};  
	uint8_t RData=USART_ReceiveData(USART1);
	if(RData == 's')
	{
		status = 0;
	}
	
	else if (RData == 't')
	{
		status = 1;
	}

}

2.运行结果

在这里插入图片描述

(三)实验三 接收字符串控制发送数据

1.代码部分

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

void InitRDataArray();

int status = 0;//设置是否发送数据的标志位

char RDataArray[20];//接收指令的字符数组


int main()
{	
	//开启GPIOA和USART1的时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA|RCC_APB2Periph_USART1,ENABLE);
	
	
	
	//实例化控制器的对象
	GPIO_InitTypeDef GPIO_InitStructure;
	USART_InitTypeDef USART_InitStructure;
	
	//先配置GPIO控制器
	//1.设置PA9为复用推挽输出模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置为复用推挽输出
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz ;
	GPIO_Init(GPIOA,&GPIO_InitStructure);   //老子草了没写这一句,以为只GPIO_Init()一次就可以了,结果忘了这些参数会覆盖的。
	
	//2.设置PA10为浮空输入模式
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //设置为浮空输入
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	
	//再配置USART控制器
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;  //硬件流控制:选择无流控制
	USART_InitStructure.USART_Mode = USART_Mode_Tx |USART_Mode_Rx; //模式选择发送和接收
	USART_InitStructure.USART_Parity = USART_Parity_No;
	USART_InitStructure.USART_StopBits = USART_StopBits_1;
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;
	USART_ClearFlag(USART1, USART_FLAG_TC);
	
	USART_Init(USART1,&USART_InitStructure);  //初始化串口1
	
	
	//配置中断源
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//当USART串口接收到数据的时候,就触发USART中断
	
	// 4.给这个中断源配置相应的抢占优先级和执行优先级
		NVIC_InitTypeDef  NVIC_InitStructure;
		NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;      
		NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3; //设置抢占(主)优先级    
		NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;      // 设置子优先级   
		NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;             
		NVIC_Init(&NVIC_InitStructure);    
	
	
	USART_Cmd(USART1,ENABLE);			//使能串口1
	
	char transmitArray[18]={"hello windows! \r\n "};   //windows系统串口发送时,用回车换行组合 (\r\n) 来实现换行
	
	
	InitRDataArray();  //初始化用来接收指令的字符数组
	
	while(1)
	{	
		
		
		
		
		if(status == 1) //标志位status = 1 发送
		{for(int i=0;i<=17;i++)
		{
		USART_SendData(USART1,transmitArray[i]);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)== RESET);  //RESET就是0,表示不符合,TXE的E是empty,表示发送寄存器不符合为空,即里面有东西,还在发送。	
		}
		Delay_s(1);
		}
		
		
	}
	
}


//初始化字符数组
void InitRDataArray()
{
 for(int i=0;i<20;i++)
	{
	RDataArray[i]=0;
	}
}

void USART1_IRQHandler(void)
{
	int i=0;
	 if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)//判断中断是接收数据中断
    {
       RDataArray[i]= USART_ReceiveData(USART1); //接收字符
				i++;
    } 

if (strcmp(RDataArray,"stop stm32!")==0)
				{
            			status = 0;//结束发送
					InitRDataArray();  //初始化用来接收指令的字符数组
					
        }
else if (strcmp(RDataArray,"go stm32!")==0)
        {
           				 status = 1;//发送数据
		  InitRDataArray();  //初始化用来接收指令的字符数组
					
        }
}



2.运行结果

在这里插入图片描述

三、总结

我刚把串口通信学得差不多,现在又来了这个中断,中断我感觉比之前学的东西都要难。我也说不出为什么,就是觉得它很抽象。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

网络空间安全数学基础·整除与同余

主要内容&#xff1a; 整除的基本概念&#xff08;掌握&#xff09; 素数&#xff08;掌握&#xff09; 同余的概念&#xff08;掌握&#xff09; 1.1整除 定义&#xff1a;设a&#xff0c;b是任意两个整数&#xff0c;其中b≠0&#xff0c;如果存在一个整数q&#xff0c;使 …

如何网页在线编辑 Office word 文档,并支域功能:创建域/插入域/替换域等

在日常在线办公场景中&#xff0c;我们经常会遇到一些复杂的文档编辑需求&#xff0c;特别是我们经常会遇到一些复杂的数学公式&#xff0c;会用到“域”功能&#xff0c;“域”功能便是一个高级且实用的工具。通过设置域&#xff0c;用户可以实现文档的自动化处理&#xff0c;…

卷积神经网络CNN动态演示和输出特征图计算公式

目录 一、卷积运算 1、卷积&#xff08;Convolution&#xff09; 2、填充&#xff08;Padding&#xff09; &#xff08;1&#xff09;Valid Padding &#xff08;2&#xff09;Same Padding 3、步长 4、卷积核大小为什么一般为奇数奇数&#xff1f; 5、卷积核kernel和…

【C++】哈希和unordered系列容器

目录 一、unordered系列关联式容器的引入 二、容器使用 2.1 unordered_map的文档说明 2.2 unordered_map的使用 2.3 unordered_set 三、底层结构 3.1 哈希概念 3.2 哈希表 3.3 哈希冲突 3.4 哈希函数 3.5 哈希冲突解决 3.5.1 闭散列 3.5.2 开散列 3.5.3 思考 四…

【微积分】CH16 integrals and vector fields听课笔记

【托马斯微积分学习日记】13.1-线积分_哔哩哔哩_bilibili 概述 16.1line integrals of scalar functions [中英双语]可视化多元微积分 - 线积分介绍_哔哩哔哩_bilibili 16.2vector fields and line integrals&#xff1a; work circulation and flux 向量场差不多也是描述某种…

Vitis HLS 学习笔记--控制驱动任务示例

目录 1. 简介 2. 代码解析 2.1 kernel 代码回顾 2.2 功能分析 2.3 查看综合报告 2.4 查看 Schedule Viewer 2.5 查看 Dataflow Viewer 3. Vitis IDE的关键设置 3.1 加载数据文件 3.2 设置 Flow Target 3.3 配置 fifo 深度 4. 总结 1. 简介 本文对《Vitis HLS 学习…

Android面试题之Kotlin常见集合操作技巧

本文首发于公众号“AntDream”&#xff0c;欢迎微信搜索“AntDream”或扫描文章底部二维码关注&#xff0c;和我一起每天进步一点点 list 创建和修改 不可变list,listOf var list listOf("a","d","f") println(list.getOrElse(3){"Unkn…

《计算机网络微课堂》2-5 信道的极限容量

本节课我们介绍信道极限容量的有关问题。 我们都知道信号在传输过程中会受到各种因素的影响&#xff0c;如图所示&#xff0c;这是一个数字信号&#xff0c;‍‍当它通过实际的信道后&#xff0c;波形会产生失真&#xff0c;当失真不严重时&#xff0c;在输出端‍‍还可根据以失…

Mysql教程(0):学习框架

1、Mysql简介 MySQL 是一个开放源代码的、免费的关系型数据库管理系统。在 Web 开发领域&#xff0c;MySQL 是最流行、使用最广泛的关系数据库。MySql 分为社区版和商业版&#xff0c;社区版完全免费&#xff0c;并且几乎能满足全部的使用场景。由于 MySQL 是开源的&#xff0…

力扣刷题---409. 最长回文串【简单】

题目描述 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回 通过这些字母构造成的 最长的回文串 。 在构造过程中&#xff0c;请注意 区分大小写 。比如 “Aa” 不能当做一个回文字符串。 示例 1: 输入:s “abccccdd” 输出:7 解释: 我们可以构造的最长的回文串…

Docker部署SpringBoot项目(jar包+Mysql)

部署Java项目 项目准备准备Java项目镜像准备配置网络 部署项目细节展示 项目准备 准备Java项目 hmall项目是一个maven聚合项目&#xff0c;使用IDEA打开hmall项目&#xff0c;查看项目结构如图&#xff1a; 我们要部署的就是其中的hm-service&#xff0c;其中的配置文件采用…

Java网络编程之TCP协议核心机制(三)

题外话 最近学习内容很多嗷 正题 延时应答机制 当客户端发送数据到服务器时,服务器不会立即返回ACK,而是等待一会再返回ACK 这段等待时间应用程序可能会消化掉接收缓冲区中的数据,当服务器返回ACK时,就会携带此时接收缓冲区大小的信息 当客户端下次再发送数据的时候就可以…

WebGL的室内设计软件

WebGL (Web Graphics Library) 是一个JavaScript API&#xff0c;它提供了一种在网页上渲染3D图形的方法&#xff0c;无需使用插件。利用WebGL&#xff0c;开发者可以创建和展示复杂的3D场景&#xff0c;包括室内设计。以下是开发基于WebGL的室内设计软件时可能涉及的一些关键步…

青鸟云报修系统:实现高效、便捷的维修申请处理

在日常生活和工作中&#xff0c;故障报修难免会遇到&#xff0c;售后报修服务则成为了解决问题的关键。纸质化售后报修维修申请单&#xff0c;作为报修流程中的重要一环&#xff0c;在一定程度上能够记录和追踪售后报修维修流程&#xff0c;但在实际操作过程中却存在着诸多弊端…

【MySQL数据库】:MySQL表的操作

目录 创建表 创建表案例 查看表结构 修改表 插入数据 新增列 删除一行数据 修改列类型 修改列名 修改表名 删除列 删除表 表操作至少会涉及如下两类SQL语句&#xff1a; DDL&#xff08;Data Definition Language&#xff09;数据定义语言&#xff1a;比如…

【c语言】了解指针,爱上指针(5)

了解指针&#xff0c;爱上指针&#xff08;5&#xff09; 回调函数qsort函数冒泡排序模拟实现qsort函数 回调函数 回调函数&#xff1a;就是一个通过函数指针调用的函数。 把函数的指针作为参数传给另一个函数&#xff0c;当这个指针被用来调用指向的函数时&#xff0c;此时被…

Vue CLI 的服务介绍与使用(2024-05-20)

1、介绍 Vue CLI 是一个基于 Vue.js 进行快速开发的完整系统&#xff0c;提供&#xff1a; 通过 vue/cli 实现的交互式的项目脚手架。 通过 vue/cli vue/cli-service-global 实现的零配置原型开发。 一个运行时依赖 (vue/cli-service)&#xff0c;该依赖&#xff1a; 可升级…

【论文阅读】使用深度学习及格子玻尔兹曼模拟对SEM图像表征粘土结构及其对储层的影响

文章目录 0、论文基本信息1、深度学习2、可运行程序—Matlab3、深度切片3、LBM模拟4、局限性 0、论文基本信息 论文标题&#xff1a;Characterizing clay textures and their impact on the reservoir using deep learning and Lattice-Boltzmann simulation applied to SEM i…

EI稳定检索--人文社科类会议(ICBAR 2024)

【ACM独立出版】第四届大数据、人工智能与风险管理国际学术会议 (ICBAR 2024) 2024 4th International Conference on Big Data, Artificial Intelligence and Risk Management 【高录用•快检索&#xff0c;ACM独立出版-稳定快速EI检索 | 往届均已完成EI, Scopus检索】 【见…

[less配置]vue2引入less

1、终端输入&#xff1a;npm install less less-loader --save-dev 2、在package.json查看是否安装less依赖 3、调用