基于51单片机按键控制流水灯设计

描述

遇到一个问题,如何按键按下既能控制流水灯又能把键值在数码管中显示呢?流水灯500ms的延时,和数码管动态刷新延时小于10ms显示有冲突。

bit和sbit,sfr都是C51扩展的变量类型,不是标准C语言类型

1.bit类型的值是一个二进制位,不是0就是1,类似布尔类型

2.sbit大部分是用在寄存器中的,方便对寄存器的某位进行操作的。

sbit LED1 = P0^0 把P0端口的第0位命名为LED1,方便使用

sbit 位变量名=SFR 名称^变量 位地址值

3.sfr也是一种扩充数据类型:,占用一个内存单元,利用它可以访问51单片机内部的所有特殊功能寄存器。如用sfr P1 = 0x90 指定P1来操作地址为0X90的寄存器

改变流水灯的方向

按键控制流水灯实现的功能:

1.key1启动键,首次按下可以产生自上向下的流水灯效果

2.key2停止键,按下可以终止流水灯的运动

3.key3和key4分别产生自上向下和自下向上的流水灯效果

实现的方法:

1.利用标志位Startflag来控制流水灯的开始和停止,初始化定义为0停止,为1时上电便有流水灯效果。用标志位UpDownflag控制流水灯的方向,初始化的值0,1来控制自上而下还是从下到上

2.利用移位运算符实现流水灯效果

注意:移位运算符实现循环移位才能实现流水灯的效果

C51库函数自带循环移位的效果:crol 循环左移 _cror_循环右移

寄存器

按键应用层功能函数

void Key_Service()
{
	switch(Key_Scan())
	{
		case 1: Startflag = 1;break;//开始
		case 2: Startflag = 0;break;//停止
		case 3:	UpDownflag =1;break;//向上流水灯
		case 4: UpDownflag =0;break;//向下流水灯
		default :break;
	}
	if(Startflag) 
	{
		
		P0 = temp;
		if(UpDownflag)
		{
			
			temp = (temp>>1)|0x80;  //右移一位
			if(temp == 0xff) //条件判断给temp重新赋值,实现循环移位功能
				temp = 0x7f; 
		
		}
		else
		{
			temp = (temp<<1)|0x1;//左移一位
			if(temp == 0xff) //条件判断给temp重新赋值,实现循环移位功能
				temp = 0xfe;
			
		}
		DelayXms(500);
	}
	
}

寄存器

自己遇到的一个问题:按键按下既能控制流水灯又能把键值在数码管中显示

2个功能分开都能正确运行

糅合在一起就会出问题。

因为延时500ms数码管动态刷新有问题

void main()
{
	LEDBuf[0]=23;
	LEDBuf[1]=23;
	LEDBuf[2]=23;
	
	while(1)
	{
		Key_Service();
		
		Didplay_Service();
	}

}

void Didplay_Service()
{
	switch(Key_Scan())
	{
		case 1:LEDBuf[3]=1;break;
		case 2:LEDBuf[3]=2;break;
		case 3:LEDBuf[3]=3;break;
		case 4:LEDBuf[3]=4;break;
		default :break;
	}
	Display();	
}

如果删除500ms的延时,显示效果是这样的.

寄存器

加上500ms延时,按键好像失效似的,返回显示的键值也不对,很奇怪的问题。

打开APP阅读更多精彩内容
声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉

全部0条评论

快来发表一下你的评论吧 !

×
20
完善资料,
赚取积分