精华内容
下载资源
问答
  • /****************************************键盘_不采用定时器_不延时特点:按键在松手后有效,灵敏度高,消耗资源少,运行效率高独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7;矩阵键盘为:行(上到下)_P2.3_P...
  • #include "REG52.H" ... * 调整抖动时间阀值的大小,可以更改按键的触发灵敏度。 * 去抖动的时间本质上等于累计定时中断次数的时间。 */ #define const_key_time_short120//短按的按键去抖动延时的时间 #d...
    1. #include "REG52.H"  
    2.   
    3. #define const_voice_short  20   //蜂鸣器短叫的持续时间  
    4. #define const_voice_long   140   //蜂鸣器长叫的持续时间  
    5.   
    6. /* 注释一:
    7. * 调整抖动时间阀值的大小,可以更改按键的触发灵敏度。
    8. * 去抖动的时间本质上等于累计定时中断次数的时间。
    9. */  
    10. #define const_key_time_short1  20    //短按的按键去抖动延时的时间  
    11. #define const_key_time_long1   400     //长按的按键去抖动延时的时间  
    12.   
    13. #define const_key_time_short2  20    //短按的按键去抖动延时的时间  
    14. #define const_key_time_long2   400     //长按的按键去抖动延时的时间  
    15.   
    16. void initial_myself();      
    17. void initial_peripheral();  
    18. void delay_long(unsigned int uiDelaylong);  
    19. void T0_time();  //定时中断函数  
    20. void key_service(); //按键服务的应用程序  
    21. void key_scan(); //按键扫描函数 放在定时中断里  
    22.   
    23. sbit key_sr1=P3^2; //对应朱兆祺学习板的S1键  
    24. sbit key_sr2=P3^3; //对应朱兆祺学习板的S5键  
    25. sbit key_gnd_dr=P0^4; //模拟独立按键的地GND,因此必须一直输出低电平  
    26.   
    27. sbit beep_dr=P2^7; //蜂鸣器的驱动IO口  
    28.   
    29. unsigned char ucKeySec=0;   //被触发的按键编号  
    30.   
    31. unsigned int  uiKeyTimeCnt1=0; //按键去抖动延时计数器  
    32. unsigned char ucKeyLock1=0; //按键触发后自锁的变量标志  
    33. unsigned char ucShortTouchFlag1=0; //短按的触发标志  
    34.   
    35. unsigned int  uiKeyTimeCnt2=0; //按键去抖动延时计数器  
    36. unsigned char ucKeyLock2=0; //按键触发后自锁的变量标志  
    37. unsigned char ucShortTouchFlag2=0; //短按的触发标志  
    38.   
    39. unsigned int  uiVoiceCnt=0;  //蜂鸣器鸣叫的持续时间计数器  
    40.   
    41. void main()  
    42.   {  
    43.    initial_myself();    
    44.    delay_long(100);    
    45.    initial_peripheral();  
    46.    while(1)    
    47.    {  
    48.        key_service(); //按键服务的应用程序  
    49.    }  
    50.   
    51. }  
    52.   
    53. void key_scan()//按键扫描函数 放在定时中断里  
    54. {    
    55. /* 注释二:
    56. * 长按与短按的按键扫描的详细过程:
    57. * 第一步:平时只要按键没有被按下时,按键的自锁标志,去抖动延时计数器一直被清零。
    58. * 第二步:一旦两个按键都被按下,去抖动延时计数器开始在定时中断函数里累加,在还没累加到
    59. *         阀值const_key_time_short1或者const_key_time_long1时,如果在这期间由于受外界干扰或者按键抖动,而使
    60. *         IO口突然瞬间触发成高电平,这个时候马上把延时计数器uiKeyTimeCnt1
    61. *         清零了,这个过程非常巧妙,非常有效地去除瞬间的杂波干扰。这是我实战中摸索出来的。
    62. *         以后凡是用到开关感应器的时候,都可以用类似这样的方法去干扰。
    63. * 第三步:如果按键按下的时间超过了短按阀值const_key_time_short1,则马上把短按标志ucShortTouchFlag1=1;
    64. *         如果还没有松手,一旦发现按下的时间超过长按阀值const_key_time_long1时,
    65. *         先把短按标志ucShortTouchFlag1清零,然后触发长按。在这段程序里,把自锁标志ucKeyLock1置位,
    66. *         是为了防止按住按键不松手后一直触发。
    67. * 第四步:等按键松开后,自锁标志ucKeyLock12及时清零,为下一次自锁做准备。如果发现ucShortTouchFlag1等于1,
    68. *         说明短按有效,这时触发一次短按。
    69. * 第五步:以上整个过程,就是识别按键IO口下降沿触发的过程。
    70. */  
    71.   if(key_sr1==1)//IO是高电平,说明两个按键没有全部被按下,这时要及时清零一些标志位  
    72.   {  
    73.       ucKeyLock1=0; //按键自锁标志清零  
    74.       uiKeyTimeCnt1=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。      
    75.             if(ucShortTouchFlag1==1)  //短按触发标志  
    76.           {  
    77.              ucShortTouchFlag1=0;  
    78.                  ucKeySec=1;    //触发一号键的短按  
    79.           }  
    80.   }  
    81.   else if(ucKeyLock1==0)//有按键按下,且是第一次被按下  
    82.   {  
    83.      uiKeyTimeCnt1++; //累加定时中断次数  
    84.      if(uiKeyTimeCnt1>const_key_time_short1)  
    85.      {  
    86.             ucShortTouchFlag1=1;   //激活按键短按的有效标志    
    87.      }  
    88.   
    89.      if(uiKeyTimeCnt1>const_key_time_long1)  
    90.      {  
    91.             ucShortTouchFlag1=0;  //清除按键短按的有效标志  
    92.   
    93.         uiKeyTimeCnt1=0;  
    94.         ucKeyLock1=1;  //自锁按键置位,避免一直触发  
    95.   
    96.         ucKeySec=2;    //触发1号键的长按  
    97.                 
    98.      }  
    99.   
    100.   }  
    101.   
    102.   if(key_sr2==1)//IO是高电平,说明两个按键没有全部被按下,这时要及时清零一些标志位  
    103.   {  
    104.       ucKeyLock2=0; //按键自锁标志清零  
    105.       uiKeyTimeCnt2=0;//按键去抖动延时计数器清零,此行非常巧妙,是我实战中摸索出来的。      
    106.             if(ucShortTouchFlag2==1)  //短按触发标志  
    107.           {  
    108.              ucShortTouchFlag2=0;  
    109.                  ucKeySec=3;    //触发2号键的短按  
    110.           }  
    111.   }  
    112.   else if(ucKeyLock2==0)//有按键按下,且是第一次被按下  
    113.   {  
    114.      uiKeyTimeCnt2++; //累加定时中断次数  
    115.      if(uiKeyTimeCnt2>const_key_time_short2)  
    116.      {  
    117.             ucShortTouchFlag2=1;   //激活按键短按的有效标志    
    118.      }  
    119.   
    120.      if(uiKeyTimeCnt2>const_key_time_long2)  
    121.      {  
    122.             ucShortTouchFlag2=0;  //清除按键短按的有效标志  
    123.   
    124.         uiKeyTimeCnt2=0;  
    125.         ucKeyLock2=1;  //自锁按键置位,避免一直触发  
    126.   
    127.         ucKeySec=4;    //触发2号键的长按  
    128.                 
    129.      }  
    130.   
    131.   }  
    132.   
    133.   
    134. }  
    135.   
    136.   
    137. void key_service() //第三区 按键服务的应用程序  
    138. {  
    139.   switch(ucKeySec) //按键服务状态切换  
    140.   {  
    141.     case 1:// 1号键的短按  对应朱兆祺学习板的S1键  
    142.   
    143.           uiVoiceCnt=const_voice_short; //按键声音的短触发,滴一声就停。  
    144.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
    145.           break;          
    146.     case 2:// 1号键的长按  对应朱兆祺学习板的S1键  
    147.   
    148.           uiVoiceCnt=const_voice_long; //按键声音的长触发,滴一声就停。  
    149.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
    150.           break;        
    151.     case 3:// 2号键的短按  对应朱兆祺学习板的S5键  
    152.   
    153.           uiVoiceCnt=const_voice_short; //按键声音的短触发,滴一声就停。  
    154.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
    155.           break;          
    156.     case 4:// 2号键的长按  对应朱兆祺学习板的S5键  
    157.   
    158.           uiVoiceCnt=const_voice_long; //按键声音的长触发,滴一声就停。  
    159.           ucKeySec=0;  //响应按键服务处理程序后,按键编号清零,避免一致触发  
    160.           break;    
    161.   }                  
    162. }  
    163.   
    164.   
    165.   
    166. void T0_time() interrupt 1  
    167. {  
    168.   TF0=0;  //清除中断标志  
    169.   TR0=0; //关中断  
    170.   
    171.   key_scan(); //按键扫描函数  
    172.   
    173.   if(uiVoiceCnt!=0)  
    174.   {  
    175.      uiVoiceCnt--; //每次进入定时中断都自减1,直到等于零为止。才停止鸣叫  
    176.          beep_dr=0;  //蜂鸣器是PNP三极管控制,低电平就开始鸣叫。  
    177.   }  
    178.   else  
    179.   {  
    180.      ; //此处多加一个空指令,想维持跟if括号语句的数量对称,都是两条指令。不加也可以。  
    181.            beep_dr=1;  //蜂鸣器是PNP三极管控制,高电平就停止鸣叫。  
    182.   }  
    183.   
    184.   
    185.   TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f  
    186.   TL0=0x2f;  
    187.   TR0=1;  //开中断  
    188. }  
    189.   
    190.   
    191. void delay_long(unsigned int uiDelayLong)  
    192. {  
    193.    unsigned int i;  
    194.    unsigned int j;  
    195.    for(i=0;i<uiDelayLong;i++)  
    196.    {  
    197.       for(j=0;j<500;j++)  //内嵌循环的空指令数量  
    198.           {  
    199.              ; //一个分号相当于执行一条空语句  
    200.           }  
    201.    }  
    202. }  
    203.   
    204.   
    205. void initial_myself()  //第一区 初始化单片机  
    206. {  
    207. /* 注释三:
    208. * 矩阵键盘也可以做独立按键,前提是把某一根公共输出线输出低电平,
    209. * 模拟独立按键的触发地,本程序中,把key_gnd_dr输出低电平。
    210. * 朱兆祺51学习板的S1和S5两个按键就是本程序中用到的两个独立按键。
    211. */  
    212.   key_gnd_dr=0; //模拟独立按键的地GND,因此必须一直输出低电平  
    213.   
    214.   
    215.   beep_dr=1; //用PNP三极管控制蜂鸣器,输出高电平时不叫。  
    216.   
    217.   
    218.   TMOD=0x01;  //设置定时器0为工作方式1  
    219.   
    220.   
    221.   TH0=0xf8;   //重装初始值(65535-2000)=63535=0xf82f  
    222.   TL0=0x2f;  
    223.   
    224. }  
    225. void initial_peripheral() //第二区 初始化外围  
    226. {  
    227.   EA=1;     //开总中断  
    228.   ET0=1;    //允许定时中断  
    229.   TR0=1;    //启动定时中断  
    230.   
    展开全文
  • 51单片机按键扫描

    2015-05-02 10:38:05
    比行列扫描简单点,代码更短,之需要一次数据反转(2次的数据输入输出)就可以定位按键
  • 用定时器扫描 可实现长安短按
  • 本文为51单片机矩阵键盘扫描程序,希望对你的学习有所帮助。
  • 按键扫描还在用DELAY延时吗?你OUT啦 定时器扫描强势来袭,你值得拥有。最大的亮点就是解决了按键的WU操作
  • 1四按键控制程序(汇编) (您的关注点赞是作者创作的最大动力哦) //******************************************************* //题目:独立四键控制事件(按键分为有锁存和无锁存) //语言:汇编语言(51MCU) ...

    一,按键控制数码管 

    1四按键控制程序(汇编)

    (您的关注点赞是作者创作的最大动力哦) 

    //*******************************************************
    //题目:独立四键控制事件(按键分为有锁存和无锁存)
    //语言:汇编语言(51MCU)
    //功能:任意独立按键控制(带扫描式的)
    //优点:中间有20ms延时函数消抖;可以扩展任意个按键;可移植
    //      含扫描按键所有操作;
    //作者: 梦
    //提醒: 记得点赞哦!!!!!
    //转载要著名出处,原创不易!!!
    //*******************************************************
    K1 BIT P3.1
    K2 BIT P3.0
    K3 BIT P3.2
    K4 BIT P3.4
    LED EQU P2
    KEY EQU P3
    ORG 0000H
    AJMP  MAIN
    ORG 0030H
    MAIN: 
        MOV LED ,#0FFH
        MOV P0,#0FFH
        CLR RS1
        CLR RS0    //调用第0组寄存器
    KLOOP:
        SETB K1    //先置高,再检测低
        SETB K2
        SETB K3
        SETB K4
        JB K1, KT1
        MOV  A, #11H
        ACALL DELAY200MS  //消除抖动
        AJMP TRS1
    KT1:JB K2, KT2
        MOV  A, #22H
        ACALL DELAY200MS  //消除抖动
        AJMP TRS1
    KT2:JB K3, KT3
        MOV  A, #44H
        ACALL DELAY200MS  //消除抖动
        AJMP TRS1
        
    KT3:JB K1, KLOOP
        MOV  A, #88H
        ACALL DELAY200MS  //消除抖动    
        
    TRS1:
        JB K1, KT1_T
        MOV  A, #11H
        ;CPL A
        ;MOV LED,A
        ;JNB K1,$     //无锁存
        AJMP CONVERS_T
    KT1_T:JB K2, KT2_T
        MOV  A, #22H
        ;CPL A
        ;MOV LED,A
        ;JNB K2,$     //无锁存
        AJMP CONVERS_T
    KT2_T:JB K3, KT3_T
        MOV  A, #44H
        ;CPL A
        ;MOV LED,A
        ;JNB K3,$       //无锁存
        AJMP CONVERS_T    
    KT3_T:JB K4, KLOOP
        MOV  A, #88H
        
    CONVERS_T:
        ;MOV A,#00H  //无锁存
        CPL A
        MOV LED,A
    LJMP KLOOP
        
    DELAY200MS:   ;误差 0us
        SETB RS1
        SETB RS0  //调用第3组寄存器
        MOV R7,#43H
    DL1:
        MOV R6,#8EH
    DL0:
        MOV R5,#09H
        DJNZ R5,$
        DJNZ R6,DL0
        DJNZ R7,DL1
        CLR RS1
        CLR RS0    //调用第0组寄存器
        RET
    END

     

     

    2矩阵键盘(4X4)按键控制程序(汇编)控制led数码管1个 

    //*******************************************************
    //题目:4X4矩阵键盘控制LED数码管(按键分为有锁存和(隔离的为)无锁存)
    //语言:汇编语言(51MCU)
    //功能:任意独立按键控制(带扫描式的)
    //优点:中间有20ms延时函数消抖;两种扫描方式其中定时器扫描很大程度优化CPU;可移植
    //      含扫描按键所有操作;
    //矩阵键盘目前扫描方法:(1)程序扫描(本程序) (2)定时器扫描(本程序也有) (3)中断扫描(51中断固定不能实现)
    //作者: 梦
    //提醒: 记得点赞哦!!!!!
    //转载要著名出处,原创不易!!!
    //*******************************************************
    KEY EQU  P1   //程序扫描 但由于大部分CPU在扫描键盘,当要显示两个数码管值显然做不到
    LED EQU  P0  //按键控制一个数码管(数码管带锁存芯片)
    KEY1 EQU P2.0
    KEY4 EQU P2.4
    ORG 0000H
       AJMP MAIN
    ORG 0030H
    MOV 30H,#00H
    MOV 31H,#00H
    ORG 0035H
    MAIN:
            CLR   RS0
    	    CLR   RS1   //使用寄存器组0
    START: 
          MOV   KEY,  #11110000B    //矩阵键盘高四位通过电阻串联电阻,接高电平(初始化)
          MOV   A,  KEY      //读按键值, 
          XRL   A,    #11110000B
          JNZ   KEY_ENA
    	  ;CJNE A, #00H,KEY_ENA  //两种处理办法
    	  ;AJMP START
    	  AJMP  START
    KEY_ENA:
          ACALL DELAY200MS
    	  MOV   KEY,#11110000B    //矩阵键盘高四位通过电阻串联电阻,接高电平(初始化)
          MOV   A,KEY      //读按键值, 
          XRL   A, #11110000B
          JNZ   KEY_ENB
    	  ;CJNE A, #00H,KEY_ENB  //两种处理办法
    	  ;AJMP START
    	  AJMP  START
    KEY_ENB:
    KEY111:     //扫描第一列
          MOV   KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	  JB    KEY.0,KEY5
    	  MOV   A, #1
    	  AJMP  CONVER
    KEY5: MOV   KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	  JB    KEY.1,KEY9
    	  MOV   A, #5
    	  AJMP  CONVER
    KEY9: MOV   KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	  JB    KEY.2,KEY13
    	  MOV   A, #9
    	  AJMP  CONVER
    KEY13: MOV  KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	  JB    KEY.3,KEY22
    	  MOV   A, #13
    	  AJMP  CONVER
    KEY22: MOV  KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	  JB    KEY.0,KEY6
    	  MOV   A, #2
    	  AJMP  CONVER
    KEY6: MOV   KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	  JB    KEY.1,KEY10
    	  MOV   A, #6
    	  AJMP  CONVER
    KEY10:MOV   KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	  JB    KEY.2,KEY14
    	  MOV   A, #10
    	  AJMP  CONVER
    KEY14:MOV   KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	  JB    KEY.3,KEY33
    	  MOV   A, #14
    	  AJMP  CONVER
    KEY33: MOV  KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	  JB    KEY.0,KEY7
    	  MOV   A, #3
    	  AJMP  CONVER
    KEY7: MOV   KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	  JB    KEY.1,KEY11
    	  MOV   A, #7
    	  AJMP  CONVER
    KEY11:MOV  KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	  JB    KEY.2,KEY15
    	  MOV   A, #11
    	  AJMP  CONVER
    KEY15: MOV  KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	  JB    KEY.3,KEY44
    	  MOV   A, #15
    	  AJMP  CONVER
    KEY44:MOV   KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	  JB    KEY.0,KEY8
    	  MOV   A, #4
    	  AJMP  CONVER
    KEY8: MOV   KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	  JB    KEY.1,KEY12
    	  MOV   A, #8
    	  AJMP  CONVER
    KEY12:MOV   KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	  JB    KEY.2,KEY16
    	  MOV   A, #12
    	  AJMP  CONVER
    KEY16:MOV   KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	  JB    KEY.3,KEY_BACK
    	  MOV   A, #16
    	  AJMP  CONVER
    KEY_BACK:  AJMP START
    CONVER:  //一般都会吧二进制转10进制  就是把得到数据A(1-16)看成 个数
          MOV  B,#10
    	  DIV  AB
    	  MOV  30H,A//存储高位
    	  MOV  A,B
    	  MOV  31H,A//存储低位
    	  
    	  MOV  DPTR,#TABLE_CC
    	  MOV  A,31H
    	  MOVC A, @A+DPTR
    	  CLR   KEY1
    	  MOV   LED, A  
    	 AJMP START
    TABLE_CC:DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f 
    
    DELAY200MS:   ;误差 0us
        SETB RS0
    	SETB RS1     //使用寄存器组3
        MOV R7,#43H
    DL1:
        MOV R6,#8EH
    DL0:
        MOV R5,#09H
        DJNZ R5,$
        DJNZ R6,DL0
        DJNZ R7,DL1
    	CLR RS0
    	CLR RS1     //使用寄存器组0
        RET
    
    END
    

    3矩阵键盘(4X4)汇编语言控制多个数码管,使用定时器扫描,数码管不带锁存芯片 

    //*******************************************************
    //题目:4X4矩阵键盘控制LED数码管(按键分为有锁存和(隔离的为)无锁存)
    //语言:汇编语言(51MCU)
    //功能:任意独立按键控制(带扫描式的)
    //优点:中间有20ms延时函数消抖;两种扫描方式其中定时器扫描很大程度优化CPU;可移植
    //      含扫描按键所有操作;
    //矩阵键盘目前扫描方法:(1)程序扫描(本程序也有) (2)定时器扫描(本程序) (3)中断扫描(51中断固定不能实现)
    //作者: 梦
    //提醒: 记得点赞哦!!!!!
    //转载要著名出处,原创不易!!!
    //*******************************************************
    KEY   EQU   P1   //定时器扫描 设置定时时常,中断读键盘是否按下,按下得到输出标志,得到提示,然后在主函数提示扫描键盘
    LED   EQU   P0  //其他时间显示键盘控制两个数码管(数码管不带锁存芯片)
    LED1  EQU   P2.0   
    LED2  EQU   P2.4//KEY为矩阵键盘  LED1为数码管1公共端,LED2为数码管2公共端,LED为数码管(这里共阴)
    ORG 0000H
    AJMP MAIN
    ORG 000BH
    AJMP INI_T0    //定时器中断
    ORG 0030H
    MOV 30H,#00H  //存高位
    MOV 31H,#00H  //存低位
    MOV 32H,#00H  //00表示没有键盘按下,01表示有键盘按下
    ORG 0035H
    MAIN:
      CLR RS0
      CLR RS1     //使用寄存器组0
         MOV   TMOD,#01H
         MOV   TH0,#0F0H
    	 MOV   TL0,#60H
    	 SETB  EA
    	 SETB  ET0
    	 SETB  TR0//定时器初始化20MS扫描
    //------------------------
    DISPLAY:
          MOV   DPTR,#TABLE_CC
    	  MOV   R1,#30H
    	  MOV   A,@R1
    	  MOVC  A, @A+DPTR
    	  CLR   LED1
    	  SETB  LED2
    	  MOV   LED, A  
          ACALL DELAY1MS
    	 //ACALL  DELAY50US  //个位ms级别扫描稳定
          MOV   R1,#31H
    	  MOV   A,@R1
    	  MOVC  A, @A+DPTR
    	  CLR   LED2
    	  SETB  LED1
    	  MOV   LED, A  
          ACALL DELAY1MS
    	 // ACALL DELAY50US
    	  MOV   R1,#32H
    	  MOV   A,@R1
    	  CJNE  A,#01H,KEY_FIRST   //初次判断没有按键按下
          ACALL KEY_BOARD
    KEY_FIRST:AJMP  DISPLAY
    
    
    //---------------------------------
    INI_T0:
               MOV   KEY,  #11110000B    //矩阵键盘高四位通过电阻串联电阻,接高电平(初始化)
               MOV   A,  KEY            //读按键值, 
               XRL   A,    #11110000B
               JNZ   KEY_EN00
    	       AJMP  initT0_END	  
    KEY_EN00: 
               MOV   R1,#32H
    		   MOV   @R1,#01H  //传递主函数标志
    initT0_END:
               MOV   TH0,#0F0H
               MOV   TL0,#60H
               RETI
    
    //--------------------------
    KEY_BOARD:
             ACALL   DELAY200MS
    	     MOV     KEY,#11110000B    //矩阵键盘高四位通过电阻串联电阻,接高电平(初始化)
             MOV     A,KEY      //读按键值, 
             XRL     A, #11110000B
             JNZ     KEY_ENB
    	     ;CJNE   A, #00H,KEY_ENB  //两种处理办法
    	     ;AJMP   START
    	     AJMP    BACK   //-------
    KEY_ENB:
    KEY111:     //扫描第一列
            MOV      KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	    JB       KEY.0,KEY5
    	    MOV      A, #1
    	    AJMP     CONVER
    KEY5:   MOV      KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	    JB       KEY.1,KEY9
    	    MOV      A, #5
    	    AJMP     CONVER
    KEY9:   MOV      KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	    JB       KEY.2,KEY13
    	    MOV      A, #9
    	    AJMP     CONVER
    KEY13:  MOV      KEY,#11101111B   //在第一列中如果按下那么低四位肯定有为0的
    	    JB       KEY.3,KEY22
    	    MOV      A, #13
    	    AJMP     CONVER
    KEY22:  MOV      KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	    JB       KEY.0,KEY6
    	    MOV      A, #2
    	    AJMP     CONVER
    KEY6:   MOV      KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	    JB       KEY.1,KEY10
    	    MOV      A, #6
    	    AJMP     CONVER
    KEY10:  MOV      KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	    JB       KEY.2,KEY14
    	    MOV      A, #10
    	    AJMP      CONVER
    KEY14:  MOV      KEY,#11011111B   //在第2列中如果按下那么低四位肯定有为0的
    	    JB       KEY.3,KEY33
    	    MOV      A, #14
    	    AJMP     CONVER
    KEY33:  MOV      KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	    JB       KEY.0,KEY7
    	    MOV      A, #3
    	    AJMP     CONVER
    KEY7:   MOV      KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	    JB       KEY.1,KEY11
    	    MOV      A, #7
    	    AJMP     CONVER
    KEY11:  MOV      KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	    JB       KEY.2,KEY15
    	    MOV      A, #11
    	    AJMP     CONVER
    KEY15:  MOV      KEY,#10111111B   //在第3列中如果按下那么低四位肯定有为0的
    	    JB       KEY.3,KEY44
    	    MOV      A, #15
    	    AJMP     CONVER
    KEY44:  MOV      KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	    JB       KEY.0,KEY8
    	    MOV      A, #4
    	    AJMP     CONVER
    KEY8:   MOV      KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	    JB       KEY.1,KEY12
    	    MOV      A, #8
    	    AJMP     CONVER
    KEY12:  MOV      KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	    JB       KEY.2,KEY16
    	    MOV      A, #12
    	    AJMP     CONVER
    KEY16:  MOV      KEY,#01111111B   //在第4列中如果按下那么低四位肯定有为0的
    	    JB       KEY.3,BACK
    	    MOV      A, #16
    	    AJMP     CONVER
    KEY_BACK:  //AJMP START
    CONVER:  //一般都会吧二进制转10进制  就是把得到数据A(1-16)看成 个数
            MOV     B,#10
    	    DIV     AB
    	    MOV     R1,#30H
    	    MOV     @R1, A//存储高位
    	    MOV     A,B
    	    MOV     R1,#31H
    	    MOV     @R1,A  //存储低位  
    BACK:	  
    	    MOV    R1,#32H
    	    MOV    @R1,#00H
            RET
    TABLE_CC:DB 0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f //共阴(0-9)
    
    DELAY1MS:   ;误差 0us
        SETB RS0
    	SETB RS1     //使用寄存器组3
        MOV R7,#01H
    DL11:
        MOV R6,#8EH
    DL00:
        MOV R5,#02H
        DJNZ R5,$
        DJNZ R6,DL00
        DJNZ R7,DL11
    	CLR RS0
    	CLR RS1     //使用寄存器组0	
        RET
    DELAY200MS:   ;误差 0us
        SETB RS0
    	SETB RS1     //使用寄存器组3
        MOV R7,#43H
    DL1:
        MOV R6,#8EH
    DL0:
        MOV R5,#09H
        DJNZ R5,$
        DJNZ R6,DL0
        DJNZ R7,DL1
    	CLR RS0
    	CLR RS1     //使用寄存器组0
        RET
    DELAY50US:   ;误差 0us
        MOV R6,#01H
    DL05:
        MOV R5,#16H
        DJNZ R5,$
        DJNZ R6,DL05
        RET
    END
    

     

    4效果图 (您的关注点赞是作者创作的最大动力哦)

     

     

    二,UART通信 

     基础知识:CPU与外界交换的信息称为通信。通信分为并行通信(速度快,连接复杂)和串行通信(速度相对慢)。

    串行通信又分为异步通信(需要每发送一个字节要验证UART)和同步通信(无需校验位,只要时钟脉冲约定典型iic,spi)。

    UART为全双工串口。                                                                                                                     

    80C51串行口是一个可编程、全双工的串行口,它由两个独立的发送器和接收器构成,通过设置SCON、PCON这两个寄存器来控制串行口的工作方式和波特率。
    发送器可以自动将CPU放入到发送缓冲器中的数据,完成并/串转换(以后的如果深学的化,有模拟iic通信,就有串并转换代码),从TXD(P3.1)引脚串行输出;接收器可以自动将数据从RXD(P3.0)引脚串行输入,完成串/并转换,送入接收缓冲器,由CPU取走。发送缓冲器与接收缓冲器,物理上是独立的,可由CPU直接访问。对于发送缓冲器来说,它只能写入而不能读出数据;对于接收缓冲器来说,它只能读出而不能写入数据,因此赋予两个缓冲器同一个名称(SBUF)和地址(99H)。CPU对SBUF执行写操作,就是将数据写入发送缓冲器;对SBUF执行读操作,就是读出接收缓冲器的内容。 

    1.串行口控制寄存器SCON和PCON


    STC89C52系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON特率选择特殊功能寄存器PCON

     SCON :串行控制寄存器(可位寻址)

     SMO/FE:当PCON寄存器中的SMODO/PCON.6位为1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位。它必须由软件清零。
    当PCON寄存器中的SMOD0/PCON.6位为0时,该位和SM1一起指定串行通信的工作方式,如下表所示。
    其中SM0,SM1按下列组合确定串行口的工作方式:

     当单片机工作在12T模式时,定时器1的溢出率=SYSclk/12/( 256-T HI);当单片机工作在6T模式时,定时器1的溢出率=SYSclk / 6/ ( 256-T HI)(注意SMOD为1为小分频,加倍效果)

    (方式0又叫同步移位串行方式)

    多机通

    目录

    一,按键控制数码管 

    1四按键控制程序(汇编)

    (您的关注点赞是作者创作的最大动力哦) 

    2矩阵键盘(4X4)按键控制程序(汇编)控制led数码管1个 

    3矩阵键盘(4X4)汇编语言控制多个数码管,使用定时器扫描,数码管不带锁存芯片 

    4效果图 (您的关注点赞是作者创作的最大动力哦)

    二,UART通信 

    1.串行口控制寄存器SCON和PCON

    STC89C52系列单片机的串行口设有两个控制寄存器:串行控制寄存器SCON和波特率选择特殊功能寄存器PCON。 SCON :串行控制寄存器(可位寻址)​

    电源控制寄存器PCON(不可位寻址)

    波特率


    信SM2功能

    •  REN:接收允许位。由软件置位或复位。REN=0,则禁止串行口接收;若REN=1,则允许串行口接收。
    • TB8:发送数据的第9位,用于在方式2和方式3时存放发送数据的第9位。TB8由软件置位或复位。在方式0和方式1中,该位未使用。
    • RB8:接收数据的第9位。用于在方式2和方式3时存放接收数据的第9位。在方式1下,若SM2=0,则RB8用于存放接收到的停止位;对于方式0,该位未使用。
    • TI:发送中断请求标志位。用于指示一帧数据是否发送完。在方式0下,发送器发送完第8位数据时,TI由内部硬件自动置1,向主机请求中断,响应后软件清零;在其他方式下,TI在发送器开始发送停止位时置1。当TI=1时,向CPU请求中断,CPU响应中断后,必须由软件清零。
    • RI:接收中断请求标志位。用于指示一帧数据是否接收完。在方式0下,RI在接收器接收到第8位数据时由内部硬件自动置1向主机请求中断,响应后软件清零;在其他方式下,RI在接收器接收到停止位的中间时刻由内部硬件自动置1。当RI=1时,向CPU请求中断,CPU响应中断后,必须由软件清零。

    电源控制寄存器PCON(不可位寻址)

     (复位值为0,SMOD=1控制加倍 PCON.6前面已讲到)

    波特率

    在串行通信中,常用波特率表征数据传输的速度。波特率用每秒钟传送二进制数码的位数来表示,单位为位/秒(b/s)。例如:传送的速率为120字符/秒,而每个字符又包含10位(1位起始位,7位数据位,1位奇偶校验位,1位停止位),则波特率为:120字符/秒×10位/字符=1200位/秒在串行通信中,发送端与接收端必须按照约定的数据帧格式及比特率进行通信,这样才能成功地传输数据。异步通信的重要指标:字符帧格式和波特率

    波特率因子

    在波特率指定后,输入移位寄存器/输出移位寄存器在接收时钟/发送时钟控制下,按指定的波特率速度进行移位。一般几个时钟脉冲移位一次。要求:接收时钟/发送时钟是波特率的16、32或64倍。波特率因子就是发送/接收1个数据(1个数据位)所需要的时钟脉冲个数,其单位是个/位。如波特率因子为16,则16个时钟脉冲移位1次。 例:波特率=9600bps,波特率因子=32,则 接收时钟和发送时钟频率=9600×32=297200Hz。

    展开全文
  • 本文为 51单片机矩阵键盘扫描程序,下面一起来学习一下
  • 一个51单片机键盘扫描程序,算法简单有效  发一个51单片机键盘扫描程序,算法简单有效   再给大家分享一个不错按键程序(来自ourdev) /****************************************  键盘_不采用...
    一个51单片机的键盘扫描程序,算法简单有效 
    


    发一个51单片机的键盘扫描程序,算法简单有效 
                                          再给大家分享一个不错按键程序(来自ourdev)
    /**************************************** 


    键盘_不采用定时器_不延时 


    特点: 
    按键在松手后有效,灵敏度高,消耗资源少,运行效率高 


    独立键盘为:K01=P2^4;K02=P2^5;K03=P2^6;K04=P2^7; 
    矩阵键盘为:行(上到下)_P2.3_P2.2_P2.1_P2.0 
               列(左到右)_P2.7_P2.6_P2.5_P2.4 


    提供的操作函数: 


    //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key 
    extern unsigned char keyboard_self(); 


    //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 
    extern unsigned char keyboard_matrix(); 


    ****************************************/


    .
     


    先看独立键盘(和矩阵键盘的算法一样) 
    ----------------------------------------------------------------------- 
    #include<reg52.h> 
    #include<intrins.h> 


    //独立键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key 
    extern unsigned char keyboard_self() 

            unsigned char num_key=0;//按键号 
            unsigned char temp=0;//用于读取P2线上按键值 
            static unsigned char temp_code=0;//保存按键值 
            static unsigned char num_check=0;//低电平有效次数 
            static unsigned char key_flag=0;//按键有效标识 


            temp=P2&0xF0;//读取P2线数据 


            if(temp!=0xF0)//低电平判断 
            { 
                    num_check++; 
                    if(num_check==10)//连续10次(10ms)低电平有效,则认为按键有效 
                    { 
                            key_flag=1;//使能按键有效标识 
                            temp_code=temp;//保存按键值 
                    } 
            } 
            else//松手时判断 
            { 
                    num_check=0; 


                    if(key_flag==1)//按键有效 
                    { 
                            key_flag=0; 


                            switch(temp_code)//读取按键号 
                            { 
                                    case 0xE0: num_key=1; 
                                               break; 
                                    case 0xD0: num_key=2; 
                                               break; 
                                    case 0xB0: num_key=3; 
                                               break; 
                                    case 0x70: num_key=4; 
                                               break; 
                            } 
                    } 
            } 


            return(num_key); 

     


    现在是矩阵键盘的 
    ----------------------------------------------------------------------- 
    #include<reg52.h> 
    #include<intrins.h>  


    //矩阵键盘.无按键动作时其返回值num_key=0,否则返回按键号num_key****检测高四位 
    extern unsigned char keyboard_matrix() 

            unsigned char num_key=0;//按键号 
            unsigned char temp=0;//读取P2口线数据 
            static unsigned char temp_code=0;//用于保存按键值 
            static unsigned char temp_circle=0xFE;//保存P2线上的循环扫描值 
            static unsigned char num_check=0;//低电平计数 
            static unsigned char key_flag=0;//按键有效标识 


            P2=temp_circle;//0xFX 
            temp=P2;//读取P2口线数据 
            if(temp!=temp_circle)//有按键动作 
            { 
                    num_check++;//低电平计数|逢低电平加1 
                    if(num_check==10)//连续10次(10ms)低电平有效 
                    { 
                            key_flag=1;//按键有效标识置1 
                            temp_code=temp;//保存按键值 
                    } 
            } 
            else//松手OR无按键动作,此时应该改变扫描线 
            { 
                    num_check=0; 
                    if(key_flag==1)//按键有效判断 
                    { 
                            key_flag=0; 
                            switch(temp_code)//读取按键号 
                            { 
                                    //P2^0线 
                                    case 0xEE: num_key=1; 
                                               break; 
                                    case 0xDE: num_key=2; 
                                               break; 
                                    case 0xBE: num_key=3; 
                                               break; 
                                    case 0x7E: num_key=4; 
                                               break; 
                                    //P2^1线 
                                    case 0xED: num_key=5; 
                                               break; 
                                    case 0xDD: num_key=6; 
                                               break; 
                                    case 0xBD: num_key=7; 
                                               break; 
                                    case 0x7D: num_key=8; 
                                               break; 
                                    //P2^2线 
                                    case 0xEB: num_key=9; 
                                               break; 
                                    case 0xDB: num_key=10; 
                                               break; 
                                    case 0xBB: num_key=11; 
                                               break; 
                                    case 0x7B: num_key=12; 
                                               break; 
                                    //P2^3线 
                                    case 0xE7: num_key=13; 
                                               break; 
                                    case 0xD7: num_key=14; 
                                               break; 
                                    case 0xB7: num_key=15; 
                                               break; 
                                    case 0x77: num_key=16; 
                                               break; 
                            } 
                    } 
                    temp_circle=_crol_(temp_circle,1);//改变扫描线 
                    if(temp_circle==0xEF) 
                    { 
                            temp_circle=0xFE; 
                    } 
            } 
            return(num_key);//返回按键号 



    /************************************************************************* 


    未按键时,扫描线一直变化。 
    长按键时,扫描线不变化,使得该行按键变成了独立按键,这样的扫描效率极高。 
    如当按下P2.0线上的某个键时,程序将扫描到这个键,而后扫描线不变化, 
    当键盘程序连续10次进入时检测到10次按键有效,直到松手后扫描线才变化 


    *************************************************************************/


    http://bbs.elecfans.com/jishu_184831_1_1.html


    展开全文
  • 51单片机键盘扫描程序,算法简单有效,键盘_不采用定时器_不延时,按键在松手后有效,灵敏度高,消耗资源少,运行效率高.
  • 本文给大家分享了51单片机行列式键盘扫描程序
  • 51单片机矩阵键盘扫描

    千次阅读 多人点赞 2015-06-24 14:53:00
    矩阵键盘检测之行列扫描法:对矩阵键盘按1至16的顺序进行编号,通过下面的扫描程序得到返回数值即可确定是哪个键被按下。矩阵键盘检测原理: 1、查询是否有键按下。 2、键的抖动处理。 3、查询按下键所在行和列...

    矩阵键盘检测之行列扫描法:

    对矩阵键盘按1至16的顺序进行编号,通过下面的扫描程序得到返回数值即可确定是哪个键被按下。

    我所用开发板的矩阵键盘


    矩阵键盘检测原理:
    1、查询是否有键按下。
    2、键的抖动处理。
    3、查询按下键所在行和列位置,得到键值。


    先行后列扫描法

    #include<reg51.h>
        #define uchar unsigned char
        #define uint unsigned int
        #define temp P2           //定义按键I/O口
        uchar keyscan()
        {
           uchar num;
           temp=0xf0;
           if(temp!=0xf0)    //检测是否有键按下
           {
              delay_ms(5);    //延时消抖
              if(temp!=0xf0)   //再次检测是否有键按下
              {
                 temp=0xf0;     //对应IO口拉高,以便检测
                 switch(temp)   //先确定行
                 {
                    case 0x70: num=1;  break;   //第一行
                    case 0xb0: num=5;  break;   //第二行
                    case 0xd0: num=9;  break;   //第三行
                    case 0xe0: num=13; break;   //第四行
                 }
                 temp=0x0f;     //对应IO口拉高,以便检测
                 switch(temp)   //再确定列
                 {
                    case 0x07: num=num+0; break;   //第一列
                    case 0x0b: num=num+1; break;   //第二列
                    case 0x0d: num=num+2; break;   //第三列
                    case 0x0e: num=num+3; break;   //第四列
                 }
              }
           }
           return num;   //结合行列扫描的值得出按键对应的数值,并返回
        }
    
    

    先列后行扫描法

    #include<reg51.h>
        #define uchar unsigned char
        #define uint unsigned int
        #define temp P2
        uchar keyscan()
        {
           uchar num;
           temp=0x0f;
           if(temp!=0x0f)   
           {
              delay_ms(5);
              if(temp!=0x0f)
              {
                 temp=0x0f;    //先确定列
                 switch(temp)
                 {
                    case 0x07: num=1; break;
                    case 0x0b: num=2; break;
                    case 0x0d: num=3; break;
                    case 0x0e: num=4; break;
                 }
                 temp=0xf0;   //再确定行
                 switch(temp)
                 {
                    case 0x70: num=num+0;  break;
                    case 0xb0: num=num+4;  break;
                    case 0xd0: num=num+8;  break;
                    case 0xe0: num=num+12; break;
                 }
              }
           }
           return num;      
        }
    

    注:这里的行列是相对的,看你自己的接线是怎样的,请自己动手体会,希望能对大家有所帮助!

    展开全文
  • 51单片机矩阵按键扫描

    千次阅读 2018-10-03 10:43:55
    目标:获取矩阵键盘的按键值(按下按键,在单个数码管上显示出键值) 连线: P1与矩阵键盘连接,P0 与单个数码管连接 代码如下: #include &lt;reg51.h&gt; unsigned char code table[] = {0x80,0x40,0x...
  • 51单片机控制4*4矩阵键盘行列扫描keil工程文件C源文件,4*4矩阵按键,带数码管显示,按下按键后在数码管显示按键编号
  • 51单片机为控制芯片,矩阵式按键详细程序
  • 51单片机矩阵键盘扫描程序 超简洁程序实现数码管显示哦
  • 51单片机按键控制程序源代码,单片机按键控制源码包括:CPU控制的按键扫描实验、按键加1数码管显示、按键可调节的电子时钟、定时中断控制的按键程序、独立式键盘的按键一键多功能程序、独立式键盘控制的4级变速流水...
  • 一、使用proteus绘制...二、编写程序 /******************************************************************************************************************** ---- @Project: Independent-KEY ---- @File: ...
  • 51单片机扫描键盘程序   //-----------------------函数声明,变量定义-------------------------------------------------------- #include sbit LED_1 =P1^4; sbit LED_2 =P1^5; sbit LED_3 =P1^6; sbit ...
  • 名称:矩阵键盘依次输入控制 使用行列逐级扫描 中断方式 内容:如计算器输入数据形式相同 从右至左 使用行列扫描方法 中断方式可以有效提供cpu工作效率,在有按键动作时才扫描,平时不进行扫描工作
  • 在我们的实际产品开发过程中,为了节省成本,常常会采用按键和LED复用,从而达到节省IO口的目的。...(上一讲已经讲过,我个人比较喜欢状态机编程,因此这里还是采用状态机编程的方法,来实现按键和LED复用扫描功能)。
  • 51单片机c语言按键扫描及Proteus仿真,程序使用定时器进行了任务的时间片分配,同时实现了按键的“长按”检测
  • 此程序为51单片机开发中常用的4x4矩阵键盘扫描程序,精简,稳定,注释详细
  • 适合89c51单片机的4*4矩阵按键扫描程序,精简,优化。
  • 单片机键盘程序(4×4矩阵式)设计:用AT89S51的并行口P1接4×4矩阵键盘,以P1.0-P1.3作输入线,以P1.4-P1.7作输出线;在数码管上显示每个按键的“0-F”序号。
  • 51单片机控制4*4矩阵键盘反转扫描keil工程文件C源文件,采用反转扫描方式读取4*4矩阵键盘,按下按键后数码管显示相应数码管编码

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 2,699
精华内容 1,079
关键字:

51单片机按键扫描程序