(踩坑)LED流水灯暂停和按键扫描

任务:
基本要求:
摁键流水灯,上电后LED不亮,摁下s1,LED从d1亮到d8,摁下S5,停下来。再次摁一下S1,从上次停下来的地方继续向原来方向闪烁

看来仅需要 矩阵按键的库啊

不过首先我需要写流水灯;

首先我是这么想的

for(int i=0;i<8;i++)
{
    P2=~(0x01<<i);
    Delay(500);
}

这时我意识到了一个问题:这样子的流水灯是“一次性”的,我无法重新流一遍,那么自然而然想到了无限循环的while(1),于是天坑来了;

int i=0;
while(i++)
{
       P2=~(0x01<<(i-1));
		Delay(500);
       if(i==8)
     {
        i=0;
     }
}

这里有两个问题:

1.当i=0时,while里面i先给while其值=0再自增,直接跳出。

所以我又改进了一下:

int i=0;
while(++i)
{
       P2=~(0x01<<(i-1));
		Delay(500);
       if(i==8)
     {
        i=0;
     }
}

好!噩梦开始!

while死循环跳不出去!!!

最后是这样解决的:

while(++i)
 {
	if(MatrixKey()==5)
		{
	  while(1)
		 {
		   if(MatrixKey()==1)
			goto T;
		 }
		}	
		
	T:   P2=~(0x01<<(i-1));
		while(k--);
			if(i==9)
			{
				i=0;
		  	}
		
}

由题当s5按下时暂停,所有我不得不用了goto。目前来看成功了。

总代码:

#include <regx52.h>
#include "MatrixKey.h"
int count=0;
int moshi=0;
	void main () {
	int k=2500;
	int i;
	int j=100;
		while(1){
			if(MatrixKey()==1)
		{	
			while(++i)
		{
	if(MatrixKey()==5)
		{
			while(1)
			{
			if(MatrixKey()==1)
				goto T;
		    }
		}	
		
	T:	P2=~(0x01<<(i-1));
		while(k--);
			if(i==9)
				{
				i=0;
		  	}
			}
		
		}
}
		
		
	
}

但是还是有两个问题:

1.我不想用goto

2.s5按下时间要长才能成功。

如果不用定时器,要在按键按下后用Delay函数进行软件消抖,还要用while(P1_7==0)来判断是否松手,如果长期不松手,则CPU会卡在该死循环里,不能执行其他代码,造成某些功能代码失效。

于是我想到了定时器扫描按键:(一开始没用,这个是的,我当时并没有意识到)

void time_routine() interrupt 1{
	TH0=0xFC;
	TL0=0x18;
	count++;
	if(count==20)
  {
    t=MatrixKey(); 
  } 	
	
}

在主函数中进行判断那一个键

再想着

定时器中断里面加入变量j,j++;      定时器是循环往复的,而且不被while框死

并将LED移动用if(j>500)括起来

这样当j=500时 让j=0,完成一个循环 这样就能延时了

这样是没有问题的。算是成功了(并未用扫描,先解决的如何不被while卡死)

#include <regx52.h>
#include "MatrixKey.h"
int t;
int k=2500;
int j=0;
int moshi=4;
int count=0;
int b=0;
int i=0;
void time_init()
{  
	TMOD=0x01;
	TF0=0;
	TR0=1;
	TH0=0xFC;
	TL0=0x18;
	
	ET0=1;
	EA=1;
	
	
}
void main()
{
	time_init();
	while(1)
		{	
  t=MatrixKey();
	if(t)
{
	if(t==1)
	{
	moshi=0;	
	}
	if(t==5)
	{
	moshi=1;
	}
	if(t==9)
	{
	moshi=2;
	}
	if(t==13)
	{
    moshi=3;
	}
}
if(j==500)
{
      if(moshi==0)
	{
						
	   P2=~(0x01<<i);
       i++;
	   if(i==9)
		{
		i=0;
		}
						
	
	}
			j=0;
}
		}
	}
void time_routine() interrupt 1{
	TH0=0xFC;
	TL0=0x18;
	count++;
	j++;
	
	
}

也可以将LED放在中断里面,

但当扫描按键放在中断时候要注意:

错误如下:

void time_routine() interrupt 1{
	TH0=0xFC;
	TL0=0x18;
	count++;
	j++;
	if(count==2){
    t=MatrixKey(); //错误!不能放中断里(起码我失败了)
	if(t)
{
if(t==1)
	{
	moshi=0;	
	}
	if(t==5)
	{
	moshi=1;
	}
	if(t==9)
	{
	moshi=2;
	}
	if(t==13)
	{
	moshi=3;
	}
}
count=0
}
	if(j==500)
		{
      if(moshi==0)
		{
						
		P2=~(0x01<<i);
			i++;
		if(i==9)
			{
		i=0;
			}
						
	
			}
			j=0;
		}
	
}

if(count==2){

  t=MatrixKey(); //错误!!!!!!

不能这么写!

要这么写

中断中:
if(count==2){	
   MatrixKey();
	count==0;
				
}

主函数中:
while(1)
{	
	t=MatrixKey();//接收按键状态
	if(t==1)
	{
	moshi=0;	
	}
	if(t==5)
	{
	moshi=1;
	}
	if(t==9)
	{
	moshi=2;
	}
	if(t==13)
	{
	moshi=3;
	}
}

在定时器里面疯狂扫描,按键中的delay也可以删掉了

在主函数while里面一直判断MatrixKey()的返回值!

                        作用:你可以快快乐乐的把一个按键【想按多长时间就按多长时间】了

(按下不停止,松开才停止) 

或许是用在闹钟上面???

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值