2021/11/9独立按键问题

**

预备知识

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

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

在这里插入图片描述

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


1.一键锁定开关

程序效果:开关按下一次小灯点亮,开关再次按下小灯熄灭(主要用过开关按下的电平变化和延时函数实现的,暂时没有利用中断,利用的是程序扫描方式,这里注意消除抖动和松手延时)****


#include<reg52.h>
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
sbit LED=P1;
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
		for(j=124;j>0;j--);
}

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(KEY1==0)//检查按键是否被按下
	{
		DelayXms(8);//延时消抖,一般为5-10ms
		if(KEY1==0)
		{
			KeyNum=1;
		}
	}while(KEY1==0);//松手等待,保证灯不闪亮
	return KeyNum;
}

void main()
{
	while(1)
	{
		unsigned char i=Key_Scan();
		if(i==1)
		{
			P1=~P1;//按字节操作,不是按位操作的哈,也可以按位操作
		}
	}
}

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

2.按下按键由一个数码管显示键值(第几个按键被按下)

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
unsigned char LEDBUF[]={8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(KEY1==0)//检查按键是否被按下
	{
		DelayXms(8);//延时消抖,一般为5-10ms
		if(KEY1==0)
		{
			KeyNum=1;
		}
	}while(KEY1==0);//松手等待,保证灯不闪亮
	
	if(KEY2==0)//检查按键是否被按下
	{
		DelayXms(8);//延时消抖,一般为5-10ms
		if(KEY2==0)
		{
			KeyNum=2;
		}
	}while(KEY2==0);//松手等待,保证灯不闪亮
	
	if(KEY3==0)//检查按键是否被按下
	{
		DelayXms(8);//延时消抖,一般为5-10ms
		if(KEY3==0)
		{
			KeyNum=3;
		}
	}while(KEY3==0);//松手等待,保证灯不闪亮
	
	if(KEY4==0)//检查按键是否被按下
	{
		DelayXms(8);//延时消抖,一般为5-10ms
		if(KEY4==0)
		{
			KeyNum=4;
		}
	}while(KEY4==0);//松手等待,保证灯不闪亮
	
	return KeyNum;
}

void main()
{
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
		switch(Key_Scan())
		{
			case 0:break;
			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();
	}
}

在这里插入图片描述

改进:对上面的Key_Scan()函数进行简化,思路是从一开始判断单个键是否按下到先判断有无键按下,再看按下的键是哪一个。

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
unsigned char LEDBUF[]={8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}

void main()
{
	//unsigned char i;
	LEDBUF[0]=23;
	LEDBUF[1]=23;
	LEDBUF[2]=23;
	while(1)
	{
		switch(Key_Scan())
		{
			case 0:break;
			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();
	}
}

继续加以改进,实现数字加,减,清零,显示功能

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
unsigned char LEDBUF[]={8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}

void main()
{
	unsigned int NumCnt;
	
	while(1)
	{
		LEDBUF[0]=NumCnt/1000;
	    LEDBUF[1]=NumCnt/100%10;
     	LEDBUF[2]=NumCnt/10%10;
		LEDBUF[3]=NumCnt%10;
		switch(Key_Scan())
		{
			case 0:break;
			case 1:NumCnt++;if(NumCnt>9999) NumCnt=0;break;
			case 2:NumCnt--;if(NumCnt>9999) NumCnt=9999;break;
			case 3:NumCnt=0;break;
			case 4:NumCnt=8888;break;
			default:break;
		}
		Display();
	}
}

在这里插入图片描述

改进:对上面的程序再次模块化主要分为延时函数,展示函数,按键扫描函数,按键服务函数,底层个位十位百位千位分离函数

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
unsigned char LEDBUF[]={8,8,8,8};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned int NumCnt;
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
	 unsigned char i;
	//unsigned char i;
	//1,送段码
	
	//2.送位选
	
	//3.延时1ms<10ms
	
	//4.消隐
	switch(i)
	{
		case 0:
		  GPIO_DIG=leddata[LEDBUF[0]];
		  GPIO_PLACE=PLACE_CODE[0];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 1:
		  GPIO_DIG=leddata[LEDBUF[1]];
		  GPIO_PLACE=PLACE_CODE[1];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 2:
		  GPIO_DIG=leddata[LEDBUF[2]];
		  GPIO_PLACE=PLACE_CODE[2];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i++;
		  break;
			
		case 3:
		  GPIO_DIG=leddata[LEDBUF[3]];
		  GPIO_PLACE=PLACE_CODE[3];
		  DelayXms(1);
		  GPIO_DIG=0xff;
		  i=0;
		  break;	
		default:break;
	}
}

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}
void Key_Service()
{
	switch(Key_Scan())
		{
			case 0:break;
			case 1:NumCnt++;if(NumCnt>9999) NumCnt=0;break;
			case 2:NumCnt--;if(NumCnt>9999) NumCnt=9999;break;
			case 3:NumCnt=0;break;
			case 4:NumCnt=8888;break;
			default:break;
		}
}
void Dis_Service()
{
	  LEDBUF[0]=NumCnt/1000;
	  LEDBUF[1]=NumCnt/100%10;
   	  LEDBUF[2]=NumCnt/10%10;
	  LEDBUF[3]=NumCnt%10;
	
}
void main()
{
	while(1)
	{
		Dis_Service();
		Key_Service();
		Display();
	}
}

3.按键控制流水灯

在这里插入图片描述

简述程序思想:

1. 首先判断哪个键被按下,Key_Scan()函数实现该功能
2. 其次根据按下的键值,制定相应的状态,1-》启动 2-》停止 3-》从上到下走,4-》从下往上走
3. 根据状态实现相应的函数功能,流水灯实现的方法有下面几种方法

方法一:简单语言

#include<reg52.h>
//方法一:简单语言
void DelayXms(unsigned int xms);
void main()
{
	while(1)
	{
		P1=0xfe;//1111 1110
		DelayXms(1000);
		
		P1=0xfd;//1111 1101
		DelayXms(1000);
		
		P1=0xfb;//1111 1011
		DelayXms(1000);
		
		P1=0xf7;//1111 0111
		DelayXms(1000);
		
		P1=0xef;//1110 1111
		DelayXms(1000);
		
		P1=0xdf;//1101 1111
		DelayXms(1000);
		
		P1=0xbf;//1011 1111
		DelayXms(1000);
		
		P1=0x7f;//0111 1111
		DelayXms(1000);

	}
}
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
	  for(j=124;j>0;j--);
}

方法二:数组方法实现流水灯

#include<reg52.h>
//方法二:数组方法实现流水灯
unsigned char code LEDBUF[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};//常量放到ROM中,增加关键词code
void DelayXms(unsigned int xms);
void main()
{
	  unsigned char cnt;
		while(1)
		{
			for(cnt=0;cnt<8;cnt++)
			{
				P1=LEDBUF[cnt];
				DelayXms(1000);
			}
		}
}
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
	  for(j=124;j>0;j--);
}

**

方法三:库函数_crol_(左移)cror(右移)实现流水灯

**

先看一个例子

**

#include <intrins.h>
void test_crol (void) {
  char a;
  char b;

  a = 0xA5;
  b = _crol_(a,3); /* b now is 0x2D */
}

具体实现如下

#include <intrins.h>
#include<reg52.h>
void DelayXms(unsigned int xms);
void main()
{
	unsigned char temp=0xfe;//1111 1110
	while(1)
	{
		P1=temp;
		temp=_crol_(temp,1);
		DelayXms(1000);
	}
}
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
	  for(j=124;j>0;j--);
}

**

方法四:使用位移动运算符

**

//方法四:C语言移位运算符的方式实现
void DelayXms(unsigned int xms);
void main()
{
	unsigned char temp=0x1;//0000 0001
	unsigned char i;
	while(1)
	{
		P1=~(temp<<i++);//取反
		if(i==8) i=0;
		DelayXms(1000);
		//下面的程序可以和上面的程序互换
		//for(i=0;i<8;i++)
		//{
		//    P1=~(temp<<i);
		//    DelayXms(1000);
	  //}
	}
}
void DelayXms(unsigned int xms)
{
	unsigned int i,j;
	for(i=xms;i>0;i--)
	  for(j=124;j>0;j--);
}

实验代码:

#include<reg52.h>
#include <intrins.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
sbit LED=P1;
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
bit Startflag=0;
bit UpDownflag=0;
unsigned char temp=0xfe;
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}
void Key_Service()
{
   switch(Key_Scan())
	 {
		 case 1:Startflag=1;break;//启动
		 case 2:Startflag=0;break;//停止
		 case 3:UpDownflag=1;break;//Down
		 case 4:UpDownflag=0;break;//Up
	 }
	 if(Startflag==1)
	 {
		 P1=temp;
		 if(UpDownflag==1)
		 {
			 temp=_crol_(temp,1);
		 }
		 //if(UpDownflag==0)
		 if(UpDownflag==0)
		 {
			 temp=_cror_(temp,1);
		 }
		 
		 DelayXms(500);
	 }
}

void main()
{
	while(1)
	{
		Key_Service();
	}
}

在这里插入图片描述

4.多窗口分屏显示参数

在这里插入图片描述

(这个实验比较复杂,有点不容易理解) 详细分析以下思路:

1. 首先是按下KEY1,窗口切换,意思就是P1XX-》P2XX-》P3XX-》P4XX,我们发现只有窗口2发生了变化,所以这里就主要控制数码管2的显示1,2,3,4
2. 按下KEY1对应的键盘值 KeyNum=1,那么窗口值wnd++,但是窗口只有4个,wnd值只能是0 1 2 3
3. 根据wnd值再来判断对相应窗口剩下的两位进行操作,比如wnd=0时按下KEY2对应的键盘值是KeyNum=2,就对数码管3和数码管4一起表示的数加1,按下KEY3对应的键盘值是KeyNum=3,就对数码管3和4一起表示的数减1,按下KEY4对应的键盘值是KeyNum=4,就对数码管3和4一起表示的数变为00,所以综上所述,是根据wnd值来实现不同窗口显示数值的操作。
4.接下来我们分析Key_Sevice()函数

switch(Key_Scan())
{   
    case 1:wnd++;if(wnd>3) wnd=0;break;//这里的wnd开始是0,wnd++表示先用wnd的值为0,再wnd++
    //case 1:++wnd;if(wnd>4) wnd=0;break;后面嵌套在内部的case 要从case 1开始
    case 2:
        switch(wnd)
        {
          case 0:parm1++;if(parm1>99) parm1=0;break;
          case 1:......
          case 2:......
          case 3:......
        }
        break;
    case 3:
        switch(wnd)
        {
          case 0:parm1--;if(parm1>99) parm1=0;break;
          case 1:......
          case 2:......
          case 3:......
        }
        break;
   case 4:
        switch(wnd)
        {
          case 0: parm1=0;break;
          case 1:......
          case 2:......
          case 3:......
        }
        break;
    default break;
}

**

具体实现代码如下

**

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
unsigned char LEDBUF[]={22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
unsigned char wnd=0;
unsigned char parm1=0;
unsigned char parm2=0;
unsigned char parm3=0;
unsigned char parm4=0;
sbit KEY1=P3^0;
sbit KEY2=P3^1;
sbit KEY3=P3^2;
sbit KEY4=P3^3;
//延时函数
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
//段码表
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};

unsigned char Key_Scan()
{
	unsigned char KeyNum=0;//这里一定要附上初值,保证每次回来都为0
	if(!KEY1||!KEY2||!KEY3||!KEY4)//检查按键是否被按下
	{
		DelayXms(8);
		if(!KEY1||!KEY2||!KEY3||!KEY4)//检查具体哪一个按键被按下
		{
			if(!KEY1)
				KeyNum=1;
			if(!KEY2)
				KeyNum=2;
			if(!KEY3)
				KeyNum=3;
			if(!KEY4)
				KeyNum=4;
		}while(!KEY1||!KEY2||!KEY3||!KEY4);//松手等待
	}
	return KeyNum;
}

//显示函数
void Display()
{
	//static unsigned char i=0;
	unsigned char i;
	//1,送段码
	GPIO_DIG=leddata[LEDBUF[i]];
	//2.送位选
	GPIO_PLACE=PLACE_CODE[i];
	//3.延时1ms<10ms
	DelayXms(1);
	//4.消隐
	GPIO_DIG=0xff;
	i++;
	if(N==i)
	{
		i=0;
	}
}
//按键函数
void Key_Service()
{
	switch(Key_Scan())
	{
		case 1:wnd++;if(wnd>3) wnd=0;break;
		case 2:
			switch(wnd)
			{
				case 0:
					parm1++;if(parm1>99) parm1=0;break;
				case 1:
					parm2++;if(parm2>99) parm2=0;break;
				case 2:
					parm3++;if(parm3>99) parm3=0;break;
				case 3:
					parm4++;if(parm4>99) parm4=0;break;
				default:break;
			}
			break;
		case 3:
			switch(wnd)
			{
				case 0:
					parm1--;if(parm1>99) parm1=0;break;
				case 1:
					parm2--;if(parm2>99) parm2=0;break;
				case 2:
					parm3--;if(parm3>99) parm3=0;break;
				case 3:
					parm4--;if(parm4>99) parm4=0;break;
				default:break;
			}
			break;
		case 4:
			switch(wnd)
			{
				case 0:
					parm1=0;break;
				case 1:
					parm2=0;break;
				case 2:
					parm3=0;break;
				case 3:
					parm4=0;break;
				default:break;
			}
			break;
			default:break;
	}
	
}
//底层控制显示的的数据,图形
void dis_Service()
{
		switch(wnd)
		{
			case 0:
			  LEDBUF[0]=20;
			  LEDBUF[1]=1;
			  LEDBUF[2]= parm1/10;
			  LEDBUF[3]= parm1%10;
				break;
			case 1:
			  LEDBUF[0]=20;
			  LEDBUF[1]=2;
			  LEDBUF[2]= parm2/10;
			  LEDBUF[3]= parm2%10;
				break;
			case 2:
			  LEDBUF[0]=20;
			  LEDBUF[1]=3;
			  LEDBUF[2]= parm3/10;
			  LEDBUF[3]= parm3%10;
				break;
			case 3:
			  LEDBUF[0]=20;
			  LEDBUF[1]=4;
			  LEDBUF[2]= parm4/10;
			  LEDBUF[3]= parm4%10;
			  break;
			default:break;
		}
}



void main()
{
	unsigned int i;
	for(i=0;i<5000;i++)
	{
		Display();
	}
	while(1)
	{
		
	    Key_Service();
		dis_Service();
		Display();
	}
}

在这里插入图片描述

5.独立按键外部中断方式实现数码管显示(注意比较程序扫描方式)

#include<reg52.h>
#define GPIO_DIG P0  //断码IO口
#define GPIO_PLACE P2  //位选IO口
#define N  4           //数码管个数
unsigned char LEDBUF[]={22,22,22,22};//数据显示缓冲区
unsigned char code PLACE_CODE[]={0x01,0x02,0x04,0x08};//位信号
void EX0_Init();
void EX1_Init();
unsigned int parmeter=0;
void DelayXms(unsigned int xms)
{
  unsigned int i,j;
  for(i=xms;i>0;i--)
    for(j=124;j>0;j--);
}
//段码表
unsigned char leddata[]={ 

						0xC0,  //"0"
						0xF9,  //"1"
						0xA4,  //"2"
						0xB0,  //"3"
						0x99,  //"4"
						0x92,  //"5"
						0x82,  //"6"
						0xF8,  //"7"
						0x80,  //"8"
						0x90,  //"9"
						0x88,  //"A"
						0x83,  //"B"
						0xC6,  //"C"
						0xA1,  //"D"
						0x86,  //"E"
						0x8E,  //"F"
						0x89,  //"H"
						0xC7,  //"L"
						0xC8,  //"n"
						0xC1,  //"u"
						0x8C,  //"P"
						0xA3,  //"o"
						0xBF,  //"-"
						0xFF,  //熄灭
};
void Display()
{
	//static unsigned char i=0;
	unsigned char i;
	//1,送段码
	GPIO_DIG=leddata[LEDBUF[i]];
	//2.送位选
	GPIO_PLACE=PLACE_CODE[i];
	//3.延时1ms<10ms
	DelayXms(1);
	//4.消隐
	GPIO_DIG=0xff;
	i++;
	if(N==i)
	{
		i=0;
	}
}

void Dis_Service()
{
	LEDBUF[0]=parmeter/1000;
	LEDBUF[1]=parmeter/100%10;
	LEDBUF[2]=parmeter/10%10;
	LEDBUF[3]=parmeter%10;
}

void main()
{
	unsigned int i;
	EX0_Init();
	EX1_Init();
	EA=1;
	for(i=0;i<2000;i++)
	{
		Display();
	}
	while(1)
	{
		Dis_Service();
		Display();
	}
}
void EX0_Init()
{
	IT0=1;
	EX0=1;
}
void EX1_Init()
{
	IT1=1;
	EX1=1;
}
void EX0_ISR(void) interrupt 0
{
	DelayXms(10);//消抖
	if(INT0==0){
		parmeter++;
		if(parmeter==9999)
		{
			parmeter=0;
		}
}
	
}
void EX1_ISR(void) interrupt 2//注意这里是2不是1
{
	DelayXms(10);
	if(INT1==0){
		parmeter--;
		if(parmeter>9999)
		{
			parmeter=9999;
	  }
  }
}

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值