51单片机学习笔记,4*4矩阵键盘

今天学习了下矩阵键盘,

4*4,  分别代表0~F这16个数字

我们按了哪个键就显示到数码管上

 

看完郭老师讲解原理后就自己动手写了,郁闷的是

在keil软件中,我在switch-case语句中 少了个冒号,竟然编译通过!

结果当然不正确了,然后我再keil中调试代码,那更郁闷了,P3口在扫描到第2行键盘时就

会复位成0xff,怎么赋值都没用,其实是没写冒号啊!

 

调了半天都不行,最后不得不将STC89C52RC换上仿真芯片SST89E516,在线调试后才发现的错误,

然后参考书上的代码才调试成功的,表示无语~~~

 

mark下

 

#include <reg52.h>
#include "MY51.H"

void showKey(uint8 num); //静态显示
void keyScan();
void main() 	
{	
    showKey(18); 	//初始显示的是6个负号
	while(1)
	{	//循环检测
        keyScan();
	}
}

void showKey(uint8 num)
{
	P0=0xc0;        //11000000 打开6个数码管
	wela=open;
	wela=lock;
	
	P0=table[num];
	dula=1;
	dula=0;
}
void keyScan()
{
    uint8 num=0;  	             //定义显示的数字
	uint8 temp=0; 	             //P3口回读信息
	uint8 i=0;                      //定义矩阵键盘行号索引	
    for(i=0; i<4;i++)           //共4行
    {
        P3=_crol_(0xfe,i);      //扫描的行索引号,从第0行到第3行
        temp=P3;                  //读取P3口
        temp=temp&0xf0;   		//提取高4位
        if(temp!=0xf0)          //按键了
        {
            delayms(5);          //消抖
            temp=P3;
            temp=temp&0xf0;
            if(temp!=0xf0)     //真的按键了
            {
                switch(temp)
                {
                    case  0xe0:         //1110 0000
                    {
                        num=0+4*i;
                        break;
                    }
                    case  0xd0:         //1101 0000
                    {
                        num=1+4*i;
                        break;
                    }
                    case  0xb0:         //1011 0000
                    {
                        num=2+4*i;
                        break;
                    }
                    case  0x70:         //0111 0000
                    {
                        num=3+4*i;
                        break;
                    }         
                    default:
                    {
                        num=18;         //18号索引是负号
                        led7=0;           // 按了不该按的指示灯
                        break;
                    }

                }
                while(1)    //松开按键检测
                {
                    temp=P3;               //读取P3口
                    temp=temp&0xf0;   //提取高4位
                    if(temp==0xf0)      //松开按键了
                    {
                        delayms(5);
                        temp=P3;
                        temp=temp&0xf0;
                        if(temp==0xf0)  //真的松开键盘了
                        {
                            break;
                        }
                    }
                }
                showKey(num); 	//静态显示按键
            }
        }
    }  	
}
void T0_Work()  //T0定时器调用的工作函数
{  

}


 

 

#ifndef _MY51_H_
#define _MY51_H_
#include <math.h>
#include <intrins.h>

typedef int   				int16  ;
typedef int   				INT16  ;
typedef unsigned int    uint16 ;
typedef unsigned int    UINT16 ;
typedef unsigned short  uint ;
typedef unsigned short  UINT ;
typedef unsigned short  word ;
typedef unsigned short  WORD ;
typedef unsigned long   uint32 ;
typedef unsigned long   UINT32 ;
typedef unsigned long   DWORD ;
typedef unsigned long   dword ;
typedef signed long	   int32	 ;
typedef signed long	   INT32  ;
typedef float		    	    float32	 ;
typedef double		    	double64  ;
typedef signed char		int8 ;
typedef signed char 		INT8 ;
typedef unsigned char	byte ;
typedef unsigned char    BYTE 	 ;		//WINDOWS的windef.h里面是这么定义的
typedef unsigned char	uchar ;
typedef unsigned char	UCHAR ;
typedef unsigned char	UINT8 ;
typedef unsigned char	uint8 ;
typedef unsigned char	BOOL	 ;		//windows中定义BOOL为int
typedef unsigned char	bool	 ;		    //bool是c++的内置类型

#define TRUE     1
#define true     1
#define FALSE    0
#define false    0

#define open     1    //open和close用于 标志打开和关闭状态
#define OPEN     1
#define close    0
#define CLOSE    0
#define lock     0
#define start    1
#define START    1
#define stop     0
#define STOP     0
#define keyDown  0
#define keyUp    1

sbit dula =P2^6;  //段选锁存器控制  控制笔段
sbit wela =P2^7;  //位选锁存器控制  控制位置

#define led P1    //灯总线控制
sbit led0=P1^0;   //8个led灯,阴极送低电平点亮
sbit led1=P1^1;
sbit led2=P1^2;
sbit led3=P1^3;
sbit led4=P1^4;
sbit led5=P1^5;
sbit led6=P1^6;
sbit led7=P1^7;

sbit keyS2=P3^4; 	//4个独立按键
sbit keyS3=P3^5;
sbit keyS4=P3^6;
sbit keyS5=P3^7;

void displaySMG(uint8 one,uint8 two,uint8 three,uint8 four,uint8 five,uint8 six,uint8 dot); 
void delayms(uint16 ms);
void T0_Work();

void delayms(uint16 ms)  //软延时函数
{
	uint16 i,j;
	for(i=ms;i>0;i--)
	{
        for(j=113;j>0;j--)
        {}
	}
}
///////////////////////////////////////////////////////////////////////////
#define dark	0x11  //在段中,0x11是第17号元素,为0是低电平,数码管不亮
#define dotDark 0xff //小数点全暗时
uint8 code table[]= { 			//0~F外加小数点和空输出的数码管编码
 0x3f , 0x06 , 0x5b , 0x4f , // 0 1 2 3
 0x66 , 0x6d , 0x7d , 0x07 , // 4 5 6 7
 0x7f , 0x6f , 0x77 , 0x7c , // 8 9 A B
 0x39 , 0x5e , 0x79 , 0x71 , // C D E F
 0x80 , 0x00 ,0x40              // . 空  负号      空时是第0x11号也就是第17号元素
 };

/////////////////////////////////////////////////////////////////////////////
uint8   TH0Cout=0 ;	    //初值	
uint8   TL0Cout=0 ;	   
uint16  T0IntCout=0;     //中断计数
uint16  T0IntCountAll=0; //(N-1)/65536+1;  //总中断次数
bool    bT0Delay=false;  //使用延时函数标志,初始未用
bool    bT0Over=false; 	 //中断处理函数执行结果之一

void startT0(uint32 ms)  //开启定时器
{	
	float32   	t=ms/1000.0;		   		 //定时时间
	double64    fox =11.0592*(pow(10,6));   //晶振频率
	uint32    	N=(t*fox)/12 ; 				 //定时器总计数值

	TH0Cout =(65536-N%65536)/256;      	 //装入计时值零头计数初值
	TL0Cout =(65536-N%65536)%256;
	T0IntCountAll=(N-1)/65536+1;			 //总中断次数
	TMOD=TMOD | 0x01; 						 //设置定时器0的工作方式为1
	
	EA =open;   //打开总中断
	ET0=open;   //打开定时器中断

	TH0=TH0Cout;  //定时器装入初值
	TL0=TL0Cout;
	TR0=start;	 //启动定时器
}

void delayT0(uint32 ms)		//硬延时函数,自己乱写的不好用,求指点
{
	startT0(ms);				//启动定时器
	bT0Delay=true;    		//告诉T0定时器,起用延时模式
	while(bT0Over==false);	//时间没到的话继续检测
	bT0Over=false;				//时间到了,让标志复位
}

void T0_times() interrupt 1 //T0定时器中断函数
{
	T0IntCout++;
	if(T0IntCout==T0IntCountAll)  //达到总中断次数值
	{	
		T0IntCout=0; 		 //中断次数清零,重新计时
		bT0Over=true;     //时间真的到了
		if(bT0Delay)		//本次中断是用来延时的吗
		{
			TR0=stop; 		 //如果是由延时函数开启T0的话,关闭T0
			return;
		}

		TH0=TH0Cout;   		//循环定时的话要重装初值,每次定时1秒,重装一次
		TL0=TL0Cout;
		T0_Work();     		//工作函数
	}
}

////////////////////////////////////////////////////////////////////////////////
void displaySMG(uint8 oneWela,uint8 twoWela,uint8 threeWela,uint8 fourWela,uint8 fiveWela,uint8 sixWela,uint8 dot)
{		//控制6位数码管显示函数,不显示的位用参数 dark
		P0=0;
		dula=1;
		dula=0;	 //段选数据清空并锁定
//////////////////////////
		P0=0xff; //送位数据前关闭所有显示
		wela=1;
		P0=0xfe;
		wela=0;

		P0=0;  	//低电平输到数码管阳极,避免数码管吴亮
      dula=1;
		P0=table[oneWela]|((0x01&dot)?0x00:0x80);   //送段数据,使用小数点显示标志
		dula=0;
		delayms(2);
/////////////////////////
		P0=0xff;
		wela=1;
		P0=0xfd;
		wela=0;

		P0=0;
		dula=1;
		P0=table[twoWela]|((0x02&dot)?0x00:0x80);
		dula=0;
		delayms(2);
/////////////////////////
		P0=0xff;
		wela=1;
		P0=0xfb;
		wela=0;
		P0=0;
		dula=1;
		P0=table[threeWela]|((0x04&dot)?0x00:0x80);
		dula=0;
		delayms(2);
/////////////////////////
		P0=0xff;
		wela=1;
		P0=0xf7;
		wela=0;

		P0=0;
		dula=1;
		P0=table[fourWela]|((0x08&dot)?0x00:0x80);
		dula=0;
		delayms(2);
/////////////////////////
		P0=0xff;
		wela=1;
		P0=0xef;
		wela=0;

		P0=0;
		dula=1;
		P0=table[fiveWela]|((0x10&dot)?0x00:0x80);
		dula=0;
		delayms(2);
/////////////////////////
		P0=0xff;
		wela=1;
		P0=0xdf;
		wela=0;

		P0=0;
		dula=1;
		P0=table[sixWela]|((0x20&dot)?0x00:0x80);
		dula=0;
		delayms(2);
}

#endif

 

 

你可能感兴趣的:(矩阵键盘)