c51单片机中断详解--适合初学者

代码文本在文末,文中为代码截图

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

第一题

**每次亮一个灯的流水灯,定义P1为led1。

在这里插入图片描述

外部中断0允许中断:EX0=1;下降沿触发:IT0=1;总开关:EA=1;

在这里插入图片描述

中断要执行的是P0引脚的4个二极管闪六次。
其实这里还有个想说的是,IE在中断请求的时候,会置位为1,然后CPU同意并执行中断程序后,IE自动清零。为什么说这个,这个可以在以后的一些情况,作为中断条件。

在这里插入图片描述

第二题

每次亮一个灯的流水灯和第一题的一样;
中断0下降沿触发也和第二题一样;
中断0程序是:P1引脚每次亮两个二极管的流水灯

讨论一下:每次亮两个二极管,如果低电平亮,那就要11111100B→11110011B。

在这里插入图片描述

个人觉得在中断中使用while造成的后果是很致命的,一般杜绝在里面用while,否则永远跳不出中断。(当然你可以在此中断里边进入另一个中断再跳回main,这样也太麻烦了)

实在不行的话,那就利用中断方式2的IE1吧,在while里边加个判断,break出while循环。(或者随便一个IO引脚,给她一个电平判断,应该也可以跳出while)

在这里插入图片描述

第三题

首先点亮所有灯0x00,然后逐个灭掉

逐个灭掉,补1?好象没有低位补1的,那就可以低位补0,然后取反得1:~(0xff→0xfe)=0x01

在这里插入图片描述
有没有注意到,其实我们总是习惯低电平亮灯,其实也可以高电平亮灯的,这样就不用取反这么麻烦,位的取反会显得复杂。高电平亮灯的话,直接p1=0xff<<i;即可

中断1程序是:P1引脚每次亮两个二极管的流水灯,同时P0和P2引脚闪烁交替(这里的同时不知是什么意思,,难道有多线程?)

在这里插入图片描述
变量的名字乱起的(比如interr0或intter1),自己写代码的时候另起个好听的。
哪里写得有错的话,评论分享一下,谢谢。

补充代码

#include <reg51.h>
#include <intrins.h>
#define uchar unsigned char
#define uint unsigned int
void delay(uint); 
#define led1 P1
sbit oo=P2^7;//测试用
//延迟函数(网上抄的)
void delay(uint t)
{
	register uint bt;
	for(;t;t--)
		for(bt=0;bt<255;bt++);
}

//中断初始化
void interr0()
{
	EA = 1;//总开关
	EX0 = 1;//中断允许位\EX1代表外部中断1
	IT0 = 1;//0为电平触发,1为脉冲触发即上下沿
}
void interr1()
{
	EA = 1;//总开关
	EX1 = 1;//中断允许位\EX1代表外部中断1
	IT1 = 1;//0为电平触发,1为脉冲触发即上下沿
}

//第一二题的main函数
/*void main()
{
		unsigned char i;
		interr0();
		led1 = 0xFE;
		while(1)
		{
			//for(i=0;i<8;i++)
			//{
			//	led1=_crol_(0xfe,i);//不知为何  原理一样的代码led1 = _corl_(led1,1);为什么不可以,还在找资料
			//	delay(200);			
			//}
			//如果不想用上边的代码,可以尝试用这个
			for(i=0;i<=8;i++)
			{
				//led1>>=i;
				led1=~(0x01<<i);//这是左移i微,然后空位补零,取反0变1,灯不亮
				delay(200);
			}
		}
}*/

//第一题中断0的程序
/*void sy1() interrupt 0
{
	unsigned char i;
	P2 = 0x00;//0x00或00000000B

		for(i=0;i<12;i++)//闪六次,也就是亮闪12次
		{
			P2 = ~P2;//由0x00变0xff
			delay(200);
		}			

}*/

//第二题中断0的程序
/*void sy2() interrupt 0
{
	unsigned char i;
	while(1)
	{
		P1 = 0xFC;//11111100B;
		//for(i=0;i<5;i++)
		//{
		//	delay(200);
		//	//P1 = _crol_(P1,2);//哇,这个_crol_又不行呀!!!难受,莫非里面不能用变量?
		//	//P1 = 
		//}
		//上面不行的话只能用这种改循环的ben方法了...
		for(i=0;i<=6;)
		{
			delay(200);
			i=i+2;
			//led1 = _crol_(0xFC,i);
			led1 = ~(0x03<<i);
		}
		if(IE1==1)break;
	}
}*/

//第三题main函数

void main(void)
{
	uint i;
	uchar temp;
	interr1();
	while(1)
	{
		temp=0xFF;
		for(i=0;i<=8;i++)
		{
			P1=temp;
			delay(200);
			temp=~(0xff<<i);//11111111→111111110→00000001
		}
	}
}

void sy3() interrupt 2
{
	while(1)
	{
		uint i;//我在前面定义了的即unsigned char i;
		P1 = 0xFC;
		P0=0x00;
		P2=0xff;
		for(i=0;i<=6;)
		{
			delay(200);
			i=i+2;
			led1 = ~(0x03<<i);
			P0=~P0;
			P2=~P2;
		}
		
		if(IE0==1)break;//来个跳出死循环的条件吧
	}
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值