原创 4&4键盘扫描程序(C+汇编)

2009-3-30 21:31 3810 3 3 分类: MCU/ 嵌入式

(单片机学习 之一)    


最近开始学习MCS51单片机,这是自己编的首个程序,如有什么错误,请各位大侠帮忙指正,谢谢!!!


扫描原理如下:


1.      判断是否有键按下:高四位高电平扫描,假设送端口数据0xf0,延迟一段时间,再读取该端口数据,与原数据0xf0相异或,如果不等于零则说明有键按下。


2.       通过扫描程序(列扫描)得出其键号:扫描第一列首先给出扫描信号如0xfe, 依次判断第一行,第二行,第三行,第四行是否为零;扫描完一列后继续下一列。



     C语言程序:


#include<reg51.h>


#define uchar unsigned char
#define uint unsigned int
#define LED P0   
#define Key_num() (~P3)&0x0f      //读入P3低四位数 
                             


void Delay(uint count);  //数码管显示
uint KEY_IF(void);   //判断有无键按下
uint KEY_NUM(void); //计算按键号
void LED_DIS(uint  num) ; //   显示


const uchar Seg_led[]={ 0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,
      0x77,0x7c,0x39,0x5E,0x79,0x71,0x40};
       //七段SEG位码   0~16,按键错误显示负号


void main (void)
{
 uint k_num=8;
 LED_DIS(k_num);
 while(1)
 {
  if(KEY_IF())
  {
   Delay(2); 
   if(KEY_IF()) //   是否真的按下
   { 
    k_num=KEY_NUM();
    LED_DIS(k_num);
       while(Key_num()!=0);   //  按键是否已释放
       Delay(2);   // 延时消抖 
   }
  }
  
 }


  
}
uint KEY_IF(void)
{
  P3=0xf0;
  Delay(2);
  while(1)
  {
   if(P3== 0xf0)
    continue;
   else
    return 1;
  }   
}


uint KEY_NUM(void)
{
 uchar col,row;     //  行号与列号
 uint scan,keyin,kcode; //  kcode记录键号
 scan = 0xef;  // 扫描码
 for(col=0;col < 4 ; col ++)
 {
  P3 = scan;
  keyin = Key_num();
  if(keyin != 0)
  {
   for (row=0;row<4;row++)
   {
    if(keyin == (0x01<<row))
    {
      kcode = row + 4*col;
      return  kcode;
    }
   }
   if(row == 4)
    return 16;  // 按键错误,数码管显示负号
  }
  scan = (scan<<1)|0x01; // 扫描码移位
 }
}


void LED_DIS(uint num)
{
  LED = Seg_led[num] ;
}
void Delay(uint count)
{
 unsigned char i,j,k;  
 for(;count-->0;)
  for(i=5;i>0;i--)   
   for(j=4;j>0;j--)   
       for(k=10;k>0;k--);
}


汇编程序如下:


       ORG  00H


START:
 MOV R0,#0FEH   ;R0扫描值
 MOV R1,#00H  ;R1记录列号
 MOV DPTR,#D_SEG     
 LCALL IF_KEY
 JZ START
 LCALL DELAY10MS 
 LCALL IF_KEY
 JZ START      
KEY_NUM:
 MOV A,#0FFH
 MOV P3,A
 MOV A,R0
 MOV P3,A
    LCALL DELAY10MS
 MOV A,P3
 JB ACC.4,LONE
 MOV A,#0 ;行值
 ADD A,R1
 MOV R2,A
 AJMP DISPLAY
LONE:
 JB ACC.5,LTWO
 MOV A,#4 ;行值
 ADD A,R1
 MOV R2,A
 AJMP DISPLAY
LTWO:
 JB ACC.6,LTHR
 MOV A,#8 ;行值
 ADD A,R1
 MOV R2,A
 AJMP DISPLAY
LTHR:
 JB ACC.7,NEXT_COL
 MOV A,#0CH ;行值
 ADD A,R1
 MOV R2,A
 AJMP DISPLAY
NEXT_COL:
 INC R1  ;列值加一
 MOV A,R0
 JNB ACC.3,START
 RL A
 MOV R0,A
 AJMP KEY_NUM
IF_KEY:
 MOV A,#0FFH
 MOV P3,A
 ANL A,#0F0H
 MOV P3,A
    LCALL DELAY10MS
 MOV A,P3
 XRL A,#0F0H
 RET
DELAY10MS:
 MOV R7,#40
D0:
 MOV R6,#250
 DJNZ R6,$
 DJNZ R7,D0
 RET
DISPLAY:
 MOV A,R2
 MOVC A,@A+DPTR
 MOV P0,A
 AJMP START
D_SEG:
    DB 3FH,06H,5BH,4FH,66H,6DH,7DH,07H
 DB 7FH,6FH,77H,7CH,39H,5EH,79H,71H
 RET
 END
  

PARTNER CONTENT

文章评论0条评论)

登录后参与讨论
EE直播间
更多
我要评论
0
3
关闭 站长推荐上一条 /3 下一条