学习笔记|IO中断|中断号大于31|中断优先级|简易中央门禁|STC32G单片机视频开发教程(冲哥)|第十六集:IO中断

news2024/11/19 15:13:55

文章目录

  • 1.什么是IO中断?
  • 2.IO中断的用法
    • 13.1.3 端口中断模式配置寄存器(PxIM0,PxIM1)
    • 13.1.1 端口中断使能寄存器(PxINTE)
    • 13.1.2端口中断标志寄存器(PxINTF)
    • 13.2 范例程序
    • 3.1.编写P35口的IO中断
      • 实现:
  • 3.中断优先级的设置
    • 3.1 为什么会出现数码管在一位一位的闪动向右刷新过去?
    • 3.2.想让数码管刷新不被打断?有什么办法
  • 4.实战小练
    • 简易中央门禁控制系统
  • 总结
  • 课后练习:

1.什么是IO中断?

在这里插入图片描述

13 普通1/O口均可中断,不是传统外部中断
STC32G系列支持所有的IO中断,且支持4种中断模式:下降沿中断、上升沿中断、低电平中断、高电平中断。每组IO口都有独立的中断入口地址,且每个IO可独立设置中断模式。
注:STC32G12K128-Beta版芯片的普通IO口下降沿中断和上升沿中断暂时不要使用。可以使用低电平和中高电平中断进行实验。
大家思考下它和外部中断有什么区别?
它不是传统的外部中断,可以说51单片机里面这一个IO中断是首创史无前例的。

2.IO中断的用法

13.1.3 端口中断模式配置寄存器(PxIM0,PxIM1)

在这里插入图片描述
它有4种中断模式,配置端口的模式使用:PnIM1.x和PnIMO.x来配置。
本节要做一个P35的一个端口,可以找到我们的P35并且设置它为低电平中断。高位设置为1,低位设置为0。
那么找到我们的P35的一个端口
在这里插入图片描述
在这里插入图片描述
那也就是我们把P3IM1的这一个位,设置为1,写P35IM0的位设置为0,就可以设置我们的一个模式了。
写的时候就是P3IM1等于0X20(B5置1),P3IM0等于0X00(B5置0)是不是就搞定了。

13.1.1 端口中断使能寄存器(PxINTE)

在这里插入图片描述

PnINTE.x:端口中断使能控制位(n=07,x=07)
0:关闭Pn.x口中断功能
1:使能Pn.x口中断功能
故设置:P35INTE = 0x20就可以使能P35。

13.1.2端口中断标志寄存器(PxINTF)

在这里插入图片描述
PnINTF.x:端口中断请求标志位(n=O7,x=07)
0: Pn.x口没有中断请求
1: Pn.x口有中断请求,若使能中断,则会进入中断服务程序。标志位需软件清0。
可以在需要的时候手动清空一下,和定时器一样。

13.2 范例程序

本节是以一个低电平中断来做示例。
在这里插入图片描述
5.9 关于中断号大于31在Keil中编译出错的处理
在这里插入图片描述
方法1:借用13号中断向量
在这里插入图片描述
0~31号中断中,第13号是保留中断号,我们可以借用此中断号,自己研究,本次课程暂不采用。
使用5.9.1 使用网上流行的中断号拓展工具,官网下载:中断号拓展工具,须填写验证码后下载。
完成后选择打开keil的安装目录,自动执行补丁程序。
在这里插入图片描述
在这里插入图片描述
提示已修改过,安装成功。

3.1.编写P35口的IO中断

中断改变SEGO的数值(显示0-9),延时500ms(仅为了课堂演示效果,实际工程中不能加延时),观察定时器刷新数码管。
数码管一个一个刷新过去,SEGO显示也会自动增加。

实现:

复制上一节的工程,并改名为12.IO中断,修改exit.h和exit.h,增加初始化函数 P3Exit_Init和中断服务函数P3Exit_Isr。
中断号根据手册查询,P3中断为40:
在这里插入图片描述
建议把中断程序复制到主函数中去执行:
修改后的exit.c:

//========================================================================
// 函数名称:P3Exit_Init
// 函数功能:P3口的IO中断初始化
// 入口参数:无
// 函数返回:无
// 当前版本: VER1.0
// 修改日期: 2023
// 当前作者:
// 其他备注:
//========================================================================
void P3Exit_Init(void)
{
	P3IM0= 0x00;
	P3IM1 =0xff;		//低电平中断
	P3INTE=0x20;		//P35中断 0010 0000=0x20
}


/*			//复制这个文件的时候,记得把这个中断函数复制到主程序
			//这个是属于用户型的一个文件(用户需要在里面编写自己的功能),建议将其放在主程序main函数之后,方便更好的引用
void P3Exit_Isr(void) interrupt 40		//中断号为0
{
	//编写用户程序,放在这里仅做提醒
}
*/

在demo.c的main函数中加入IO中断初始化,需在总中断EA=1之前执行初始化:P3Exit_Init();
注释掉上节测试中用到的SEG及按键代码段,中断函数中的SEG0累加代码也可以注释掉。
这里为了演示的效果,在中断处理函数中增加了延时代码,实际代码中严禁增加延时代码,一定要记住。
编写中断服务函数模板:

void P3Exit_Isr(void) interrupt 40		//中断号为0
{
	//编写用户中断服务程序
	u8 intf;
	intf = P3INTF; 		//读取P2INTF寄存器的值
	if( intf )
	{
		P3INTF = 0;				//判断前先手动清空
		if( intf && 0X01 )		//P30按下
		{

		}
    }

}

将模板加入demo.c中的main函数,并将判断端口改为P35,即判断条件改为:intf && 0X04
seg_led.h文件中,将数码管初始化改为不显示:u8 Show_Tab[8] = {20,20,20,20,20,20,20,20};
修改后的函数P3Exit_Isr为:

void P3Exit_Isr(void) interrupt 40		//中断号为0
{
	//编写用户中断服务程序
	u8 intf;
	intf = P3INTF; 		//读取P2INTF寄存器的值
	if( intf )
	{
		P3INTF = 0;				//判断前先手动清空中断标志位,必须软件清空
		if( intf && 0X04 )		//P35按下,这里存在错误,应改为:if( intf && 0X20 )		//P35按下 0010 0000 = 0X20
		{
			SEG0 ++;			//数码管循环显示0-9
			if( SEG0 > 9)
				SEG0 = 0;
			delay_ms(500);		//这边是为了演示一个功能,正式代码中中不能再中断中加延时
		}
	}

}

编译下载,P35是下排的第5个按钮。按键按下,无任何反应。
把原来初始化显示的横杠全放出来,看看效果。还是无反应,代码存在错误。
排查:判断条件应该为:if( intf && 0X20 ) //P35按下 0010 0000 = 0X20
修改后,重新编译,按动P35,实验发现数码管在一位一位的闪动刷新过去,SEG0显示自加。

3.中断优先级的设置

3.1 为什么会出现数码管在一位一位的闪动向右刷新过去?

因为Timer0_Isr的中断服务函数中执行SEG_LED_Show,循环刷新8位数码管和LED,每10ms完整刷新一次,如果被打断,就会出现上个步骤的显示效果。
中断时可以设置优先级的,看中断结构图:
在这里插入图片描述
右侧中断优先级控制之下有4条线,说明它可以设置4个优先级。P0-P7也都是这样可以设置0-3的四级优先级。
高优先级可以打断低优先级,同一优先级中断源靠前的可以先执行,再执行靠后的。

在这里插入图片描述
定时器0的中断优先级为:
在这里插入图片描述

PT0H,PT0:定时器0中断优先级控制位
00:定时器0中断优先级为0级(最低级)
01:定时器0中断优先级为1级(较低级)
02:定时器0中断优先级为2级(较高级)
03:定时器0中断优先级为3级(最高级)
P3的中断优先级控制位:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
PxIPH,PxIP:Px口中断优先级控制位
00:Px口中断优先级为0级(最低级)
01:Px口中断优先级为1级(较低级)
02:Px口中断优先级为2级(较高级)
03:Px口中断优先级为3级(最高级)
初始值都为0,均为最低优先级。
相同优先级,靠前的中断源先执行,执行完之后在执行低中断源,且一个中断源在执行的时候不能被打断。
定时器0和P3中断都是最低优先级,定时器0中断号1,P3中断号40,执行完定时器0,再执行P3,再执行定定时器0,再执行…
同时触发,定时器0也会先执行,不能被中断。

3.2.想让数码管刷新不被打断?有什么办法

1)定时器0中断优先级提高,让定时器可以打断P3口中断
根据上图,可以将定时器0改为最高优先级。
那就是PT0H和PT0的这个位都置1(11:定时器О中断优先级为3级(最高级))。
从定时器0初始化函数Timer0_Init声明跳转至函数体,增加:

	IP  = 0X02;				//设置为最高优先级,11,0000 0010 =0X02
	IPH = 0X02;				//设置为最高优先级,11,0000 0010 =0X02

编译后执行,数码管的显示不会被按键打断了。达到了预期效果。
如果2个优先级一样,想要其中一个中断持续执行而且不会被打断,或者他能打断别人,就可以把优先级提高。
系统里出现多个中断的时也可以给他们这样子排排序。
2)定时器0工作模式设置为模式3,不可屏蔽中断。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

TMOD &= 0x30; //设置定时器模式 0011 0000 =0x30

4.实战小练

简易中央门禁控制系统

1.用8个按键代表每个门的门锁开关,8个LED作为每个门的工作状态,点亮表示门己经打开,.熄灭表示门关闭。
2.如遇突发火灾,按下应急按钮立刻打开所有门锁,方便人逃生
3.按下应急按钮后,所有按钮门锁不能上锁,保持畅通。
4.松开应急按钮后,倒计时5秒后恢复之前的状态,并可以操作门锁,
实现:
涉及到8个按键,将矩阵键盘里的代码复制过来,保留适合本例的部分:

if(TIM_10MS_Flag == 1)   //将需要延时的代码部分放入
		{
			TIM_10MS_Flag = 0;		//TIM_10MS_Flag 变量清空置位
			BEEP_RUN();				//蜂鸣运行

			KEY_NUM = MateixKEY_Read();		//当前矩阵按键的键值1-8,代表哪个按键被按
			//SEG7 = KEY_NUM; 	//在数码管最后一位显示
			if( KEY_NUM > 0)				//如果有按键按下
			{
				//BEEP_ON(2);							//蜂鸣20ms

			}
		}

8个LED作为每个门的工作状态,需要赋初始值:u8 LOCK_State = 0XFF; //门锁初始状态,全部上锁
LED = LOCK_State; //开机之前将门锁状态赋值给LED
前述程序已经读取到了按键的键值,用键值去做判断。MateixKEY_Read()函数返回的数值是1-8,
门锁的状态可以直接异或,即每个位单独取反,但是需要的数值只要0-7即可,直接减1:

				LOCK_State ~= (1<<(KEY_NUM-1));			//获取当前是第几个按钮按下,数值是1-8的范围,减1 ,转换为0-7
														//以KEY_NUM=1为例,1<<1= 0010,异或(0010 NOR)后,得到1111 1101,实现了1位的低电平,与LED状态一致。

这样就实现了用8个按键控制8个门锁的状态。
修改后代码为:

		if(TIM_10MS_Flag == 1)   //将需要延时的代码部分放入
		{
			TIM_10MS_Flag = 0;		//TIM_10MS_Flag 变量清空置位
			BEEP_RUN();				//蜂鸣运行

			KEY_NUM = MateixKEY_Read();		//当前矩阵按键的键值1-8,代表哪个按键被按下
			//SEG7 = KEY_NUM; 	//在数码管最后一位显示
			if( KEY_NUM > 0)				//如果有按键按下
			{
				//BEEP_ON(2);							//蜂鸣20ms
				LOCK_State ^= (1<<(KEY_NUM-1));			//获取当前是第几个按钮按下,数值是1-8的范围,减1 ,转换为0-7
														//以KEY_NUM=1为例,1<<1= 0010,异或(0010 NOR)后,得到1111 1101,实现了1位的低电平,与LED状态一致。
			}
			LED = LOCK_State;	 //输出门锁状态
		}

接下来实现“2.如遇突发火灾,按下应急按钮立刻打开所有门锁,方便人逃生”。
拟用P35作为总控开关,在P3Exit_Isr中断里修改添加。
首先门锁要打开:LED0 = 0X00; //打开所有门锁
持续按下的时候,数码管显示5s倒计时,SEG0 = 5; //5S倒计时
5S倒计时需要重新增加变量,u16 Time_CountDown = 0; //全局变量放在main函数外部,文件里所有地方都可以调用.
修改后的P3Exit_Isr:


void P3Exit_Isr(void) interrupt 40		//中断号为0
{
	//编写用户中断服务程序
	u8 intf;
	intf = P3INTF; 		//读取P2INTF寄存器的值
	if( intf )
	{
		P3INTF = 0;				//判断前先手动清空中断标志位,必须软件清空
		if( intf && 0X20 )		//P35按下 0010 0000 = 0X20
		{
 			LED0 = 0X00;     	//打开所有门锁
			SEG0 = 5;   		//5S倒计时,数码管持续显示
			if( Time_CountDown > 0)

			Time_CountDown = 500;//5S倒计时变量
			//SEG0 ++;			//数码管循环显示0-9
//			if( SEG0 > 9)
//				SEG0 = 0;
//			delay_ms(500);		//这边是为了演示一个功能,正式代码中中不能再中断中加延时			}
		}
	}

}

如果Time_CountDown大于0,说明还一直卡在这个中断里,增加判断:

		if(TIM_10MS_Flag == 1)   				//将需要延时的代码部分放入
		{
			TIM_10MS_Flag = 0;					//TIM_10MS_Flag 变量清空置位

			if( Time_CountDown == 0)			//如果没有按下过应急按钮,按下后触发中断变为500,只有在0的时候才能控制按钮
			{
				KEY_NUM = MateixKEY_Read();		//当前矩阵按键的键值1-8,代表哪个按键被按下
				BEEP_RUN();						//蜂鸣运行

				if( KEY_NUM > 0)				//如果有按键按下
					{
						LOCK_State ^= (1<<(KEY_NUM-1));			//获取当前是第几个按钮按下,数值是1-8的范围,减1 ,转换为0-7
																//以KEY_NUM=1为例,1<<1= 0010,异或(0010 NOR)后,得到1111 1101,实现了1位的低电平,与LED状态一致。
					}
				LED = LOCK_State;	 //输出门锁状态
				SEG0 = 0x20;		//如果按键能按动,将数码管熄灭
			}
			else			//按下了应急按钮,
			{
				Time_CountDown--;		//时间倒计时
				SEG0 = Time_CountDown/100+1; //500要显示为单位s,除100
			}
		}

数码管初始化为熄灭:u8 Show_Tab[8] = {20,20,20,20,20,20,20,20};
编译运行。依次按键,门锁代表的灯亮,8个按键控制8个门锁,也能单独控制。但是蜂鸣器不响。
在按键按下的判断中,增加蜂鸣代码:BEEP_ON(2); //蜂鸣20ms
重新编译下载,按下P35,数码管显示5,LED全亮(门全开),按动其他按钮无用。松开,数码管开始倒计时,
0的时候熄灭,门锁恢复之前的状态。

总结

1.了解外部和IO中断的区别,什么时候用哪个中断.
外部中断只有单次触发,要么就是按下或者松开,也就是上升、下降沿,或者单纯的下降沿才能执行;
IO中断暂时只能用高电平中断或者低电平中断,他是可以持续进入中断的,像本例,如果一致按下P35,不允许进行其他操作,
就可以用这个IO中断。那如果说你只要按下一次,然后立马就报警的那种,1次就可以,什么时候用哪个,一定要区分清楚。
2.学会使用IO中断,设置中断的模式
3.学会中断向量号的扩展
4.学会中断优先级的使用

课后练习:

1.今天的小实验倒计时5秒用的一位数码管,改成4位数码管,倒计时50秒,最小单位为10ms。
2.尝试编写P54口的中断,让数码管1从0-9计数
3.修改中断优先级,让P54口的中断优先级高于P35,让他可以打断P35。

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

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

相关文章

C++ 算法学习 之 vector assign

参考c官方手册 vector::assign是C标准模板库中的一个函数&#xff0c;它的主要功能是给vector容器重新赋值。具体来说&#xff0c;vector::assign函数会删除vector中的所有元素&#xff0c;并根据用户提供的参数重新填充。 这个函数有三种形式&#xff1a; template <cla…

基于SpringBoot蜗牛兼职网的设计与实现【附PPT|万字文档(LW)和搭建文档】

主要功能 前台界面&#xff1a; ①首页、兼职信息推荐、查看更多等 ②职位申请、申请日期、上传简历、点击下载简历、留言反馈等 ③个人中心、上传图片、更新信息等 后台登录&#xff1a; ①用户登录&#xff1a; 个人中心、修改密码、个人信息、职位申请管理 ②企业登录&…

基于STM32+华为云IOT设计的智能衣柜

一、项目介绍 随着智能家居的发展&#xff0c;人们对于家居设备的智能化和远程控制需求越来越高。智能衣柜作为智能家居的一部分&#xff0c;可以提供衣物存储和保护的功能&#xff0c;并通过传感器和互联网技术实现对衣柜内部环境的监测和控制&#xff0c;为用户提供更好的使…

Map面试常见问题

Map的特点有哪些&#xff1f; Java中的Map是一种接口&#xff0c;它表示一种将键映射到值的对象。Map的特点主要有以下几点&#xff1a; 键的唯一性&#xff1a;每个键在Map中只能出现一次&#xff0c;不能重复。不保证键的顺序&#xff1a;Map不保证键的插入顺序或者遍历顺序…

MFC 如何启用/禁用菜单(返灰/不可点击状态)

1、为页面&#xff08;窗口&#xff09;添加一个菜单栏和子菜单 2、在XXDlg.h文件中定义一个菜单栏变量和bool变量 CMenu m_Menu; //菜单变量 bool m_EnableMenu;//菜单栏中某个子菜单禁用/启用&#xff08;变灰&#xff09;的控制变量3、在OnInitDialog函数中进行初始化&…

智囊AI-基于 ChatGPT 的 AI 工具产品 你的私人AI助手

智囊AI是一款基于 ChatGPT 的 AI 工具产品&#xff0c;主打免费、智能、方便&#xff0c;可以在此雇佣各种各样的免费智囊进行对话、自己创造和分享智囊、共享有趣有用的对话等。不过使用需要注册登录&#xff0c;可以使用自己的openai key或者使用网站提供的api key&#xff0…

【2023年11月第四版教材】第13章《资源管理》(第一部分)

第13章《资源管理》&#xff08;第一部分&#xff09; 1 章节说明2 管理基础2.1 术语2.2 项目经理的权力有5种来源2.3 优秀团 队的建设5个阶段2.4 激励理论2.4.1 马斯洛需求层次理论2.4.2 赫茨伯格双因素理论&#xff1a;★★★ 2.4.3 X理论&#xff08;不好&#xff09;步丫理…

Postman使用_参数设置和获取

文章目录 参数引用内置动态参数手动添加参数脚本设置参数脚本获取参数 参数就像变量一样&#xff0c;它可以是固定的值&#xff0c;也可以是变化的值&#xff0c;比如&#xff1a;会根据一些条件或其他参数进行变化。我们如果要使用该参数就需要引用它。 参数引用 引用动态参数…

使用凌鲨订阅技术资讯

许多软件研发人员都通过业界资讯媒体和大牛的博客来获取信息。这些渠道提供了最新的行业动态、技术进展和趋势&#xff0c;对开拓视野、保持技术敏锐度和了解业界发展具有重要作用。一些知名的业界资讯媒体和大牛博客&#xff0c;它们在业界有着很高的影响力&#xff0c;为研发…

IDEA2023中使用SpringBoot整合Lombok全过程及详细用法

&#x1f9d1;‍&#x1f4bb;作者名称&#xff1a;DaenCode &#x1f3a4;作者简介&#xff1a;CSDN实力新星&#xff0c;后端开发两年经验&#xff0c;曾担任甲方技术代表&#xff0c;业余独自创办智源恩创网络科技工作室。会点点Java相关技术栈、帆软报表、低代码平台快速开…

在TensorFlow中使用GAN生成图像

一、说明 本文详细论述&#xff0c;如何在tensorflow下&#xff0c;在mnist数据集合上进行GAN实现。包括&#xff1a;框架建立、数据集读出、生成器、鉴别器、代价函数、优化等具体步骤的代码实现。 二、GAN框架介绍 生成器&#xff1a;此组件负责生成新图像。鉴别器&#xf…

OPC DCOM快速配置

目录 1 老系统配置 1.1 移除Windows 安全 1.2 建立相互能识别的用户账号 1.3 配置系统宽泛的DCOM设置 1.4 配置Server的特殊DCOM设置 1.5 恢复Windows安全 1 老系统配置 远程OPC访问必须在服务器和客户端两端配置DCOM。本文讲述如何正确配置 DCOM 的步骤并保证安全。 新…

classification_report

文章目录 classification_report混淆矩阵精确率(精准率)&#xff0c;召回率&#xff0c;F1值精确率召回率F1值精确率、召回率和F1值的应用 参考文献 classification_report 假设使用sklearn.metrics.classification_report生成的分类图像如下图所示&#xff1a; 列名&#xf…

大模型对外提供应用的三种服务方式及示例

最近在研究Llama大模型的本地化部署和应用测试过程中&#xff0c;为了给大家提供更多的应用方式&#xff0c;研究了如何利用python快速搭建各种应用访问服务&#xff0c;一般来说&#xff0c;我们开发完成的软件模块为了体现价值&#xff0c;都需要对外提供服务&#xff0c;最原…

C++ PrimerPlus 复习 第一章 命令编译链接文件 make文件

第一章 命令编译链接文件 C 有什么呢&#xff1f;C 源代码文件后缀运行C过程可执行代码&#xff1a;编译语法&#xff1a;makeMakefile 基础语法编写完make只要和将要编译的文件放一起就行 然后在该目录使用make命令&#xff0c;就将自动运行&#xff1b;基础的Makefile版本 现…

GaussDB(DWS)云原生数仓技术解析:湖仓一体,体验与大数据互联互通

文章目录 前言一、关于数据仓库需求场景分类二、数据仓库线下部署场景2.1、线下部署场景介绍及优劣势说明2.2、线下部署场景对应的客户需求 三、数据仓库公有云部署场景3.1、公有云部署场景介绍及优劣势说明3.2、公有云部署场景对应的客户需求 四、为何重视数据共享&#xff08…

【洛谷 P1364】医院设置 题解(图论+深度优先搜索)

医院设置 题目描述 设有一棵二叉树&#xff0c;如图&#xff1a; 其中&#xff0c;圈中的数字表示结点中居民的人口。圈边上数字表示结点编号&#xff0c;现在要求在某个结点上建立一个医院&#xff0c;使所有居民所走的路程之和为最小&#xff0c;同时约定&#xff0c;相邻接…

windows彻底卸载unity

1.控制面板卸载 双击打开桌面的控制面板&#xff0c;选择卸载程序&#xff0c;选中Unity和UnityHub右击卸载。 2.清除unity的注册表 在运行中输入“regedit”双击打开注册表界面 删除 HKEY_CURRENT_USER\Software\Unity 下所有项 删除 HKEY_CURRENT_USER\Software\Unity Tec…

项目:TCP在线云词典

一.要求 1.搭建的框架环境中实现并发&#xff0c;实现多个用户同时查询的功能。 2.服务器分别保存每个用户的使用记录&#xff0c;客户端可以查询日志的功能。 3.基本的查询单词的功能。 4.密码验证的功能&#xff0c;实现登录验证账号和密码是否正确。 二.流程和框架 框架 …

【Spring容器的启动过程】

Spring容器的启动过程 Spring 在初始化过程中有二个非常重要的步骤&#xff0c;容器的初始化与刷新。 初始化流程 如果想生成 bean 对象&#xff0c;那么就需要一个 beanFactory 工厂&#xff08;DefaultListableBeanFactory&#xff09;如果想让加了特定注解&#xff08;如 …