矩阵键盘与数码管显示

这个实验的内容是:采用4x4矩阵按键,预先对每个矩阵按键的键值进行设置,然后通过按下按键,在四位数码管上以滚显的方式显示相应的值,并在Proteus上仿真。

我设置的矩阵按键为:
矩阵键盘与数码管显示_第1张图片

Proteus图:
矩阵键盘与数码管显示_第2张图片

通过使用行列扫描法对矩阵按键进行扫描监测,具体实现过程会在程序中详细讲解。

具体实现方式请看下面的程序:

#include"main.h" 
							
void main() 
{
      
 	unsigned char temp=0; 
 	unsigned char keyValue[4]={
     0};  //定义一个数组,用来存放四个数码管所显示的值
 	while(1){
      
    	temp=keyScan();  //keyScan()为矩阵按键扫描函数
      if(temp!=16) {
       //因为矩阵按键所表示的值是0~15(在数码管上是显示0~F),所以要满足temp<16才执行下面滚显的指令
				//当按键按了后,有新值进入数码管时,数码管的旧值都往左移一位,腾出一个位置给新值显示
				keyValue[3]=keyValue[2];
				keyValue[2]=keyValue[1];
				keyValue[1]=keyValue[0];
				keyValue[0]=temp;  
      } 
        segDisplay(keyValue);  //显示键值函数
  }  
} 
 

#ifndef __MAIN_H__
#define __MAIN_H__

	#include"segDisplay.h"
	#include"keyScan.h" 	

#endif
#include"keyScan.h"

unsigned char keyScan(){
      
	unsigned char a=0;
	unsigned char t; 
	unsigned char KeyValue=16;   //无按键按下时反馈回去16 
	P2=0xF0;  //高四位全为1,代表矩阵按键的列,低四位全为0,代表矩阵按键的行,
	          //只要有按键按下时,按下的按键所在的列就会为0
	if(P2!=0xF0){
      //读取按键是否按下      
    	//Delay(1000);//延时 10ms 进行按键消抖,因为按键按下时,有一小段电压不稳定的时间 
	   	
		//for循环用的是一个定时器延时,作用和delay(1000)是一样的,定时器延时可以节省CPU开销
		for(t=0;t<10;t++){
     
			timer0_init();
			while(~TF0);
				TF0=0;				
		}
		//再次检测键盘是否按下
  if(P2!=0xF0){
             //再次检测键盘是否按下 
			
		//一个按键的位置是由行和列决定的,下面程序是先确定按键的列再确定按键的行
    //测试列 
    P2=0XF0; 
    switch(P2){
      
      case(0X70): KeyValue=3;break;  //从左往右,第四列,P2=0111 0000,下面同理
      case(0XB0): KeyValue=2;break; 
      case(0XD0): KeyValue=1;break; 
      case(0XE0): KeyValue=0;break; 
    } 
    //测试行 
    P2=0X0F; 
    switch(P2){
      
      case(0X07): KeyValue=KeyValue+12;break;  //从上往下,第四行,P2=0000 0111,下面同理
      case(0X0B): KeyValue=KeyValue+8;break; 
      case(0X0D): KeyValue=KeyValue+4;break; 
      case(0X0E): KeyValue=KeyValue;break; 
    } 
    //延迟一段时间,以确保按键松开,否则在按下其间会多次扫描按键 ,我是延时0.5秒
    while((a<50)&&(P2!=0x0F)){
      
      //Delay(1000); 
      //下面又是定时器延时
			for(t=0;t<10;t++){
     
			  timer0_init();
				while(~TF0);
				TF0=0;					
		  }
			a++; 
    } 
  } 
    
  return KeyValue;  //返回键值 
}
#ifndef __KEYSCAN_H__
#define __KEYSCAN_H__

	#include"timer0_init.h"
	unsigned char keyScan();
	extern unsigned char keyValue[4];  //外部变量声明

#endif
#include"segDisplay.h"

//显示0~F的值,采用共阳数码管
//定义中的code代表的是把定义的数据表存储在flash存储器中,如去掉code则存储在RAM中
unsigned char code sgmduan[16]={
     0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8, 
	                            0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};

void segDisplay(unsigned char *value){
      
	unsigned char i; 
    for(i=0;i<4;i++){
      
    	switch(i){
                //位选,选择点亮的数码管,  
        	//数码管从右往左排序
				  case(0): 
            LSA=0;LSB=0;LSC=0;LSD=1; break;//显示第 0 位 
          case(1): 
            LSA=0;LSB=0;LSC=1;LSD=0; break;//显示第 1 位 
          case(2): 
            LSA=0;LSB=1;LSC=0;LSD=0; break;//显示第 2 位 
          case(3): 
            LSA=1;LSB=0;LSC=0;LSD=0; break;//显示第 3 位  
      } 
	    P0=sgmduan[value[i]];//发送段码 
        
			//Delay(100); //间隔一段时间扫描 
		  //定时器延时
			timer0_init();
		  while(~TF0);
			TF0=0;		 
      P0=0xFF;//消隐上次显示的数字,使下次显示更清晰 
    }  
} 
#ifndef __SEGDISPLAY_H__
#define __SEGDISPLAY_H__

	#include"timer0_init.h"
	sbit LSA=P1^3; 
	sbit LSB=P1^2; 
	sbit LSC=P1^1; 
	sbit LSD=P1^0;
	void segDisplay(unsigned char *value);

#endif
#include"timer0_init.h"

void timer0_init(){
       //定时器初始化函数
	EA=1;  //打开总中断
	ET0=1;  //中断0控制允许位
	TR0=1;  //开启中断0
	TMOD=0x01;//定时器工作模式为1
	TH0=0xfc;//定时器延时10ms(延时1ms为FC66H)
	TL0=0x66;
}

#ifndef __TIMER0_INIT_H__
#define __TIMER0_INIT_H__

	#include"reg52.h"
	void timer0_init();

#endif

你可能感兴趣的:(单片机)