登录  | 立即注册

游客您好!登录后享受更多精彩

扫一扫,访问微社区

QQ登录

只需一步,快速开始

开启左侧

[寒假笔记] 电器开发部的单片机的按键扫描

[复制链接]
发表于 2019-1-24 21:34:50 | 显示全部楼层 |阅读模式
学习笔记
学习科目: 单片机知识以及单片机的编程
学习安排: 今天学了单片机的按键扫描和用中断消抖
以及一些office知识
开始时间: 2019-01-24
结束时间: 2019-01-24
看代码之前呢 还是要看一下电路图,个人感觉,单片机的学习不能脱离电路图以及编程的练习,可能开始只是照猫画虎,仿照别人的代码,但我相信,经常仿照别人的代码并自己独立敲出来别人的代码,量边会引起质变,到时候会有厚积薄发的感觉的。好了,咱们一起看代码吧 QQ图片20190122195331.png QQ图片20190122195347.png QQ图片20190122195353.png XUL5~T(DASJEP~W@%9G$O.png
#include <STC12C5A60S2.H>

#define SET 1000                                   
sbit ENLED = P1^1;

unsigned int code wei[]={0x00,0x01,0x02,0x03,0x04,0x05};
unsigned int code duan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};//数码管的显示
                                                                                                                       
unsigned int k,tflag;                                                                                       

unsigned int key_scan();                                                  //矩阵键盘扫描函数
void display(unsigned int a,unsigned int b);        //数码管显示函数
void delay_us(unsigned int n);
void delay_ms(unsigned int n);
void main()//主函数
{
        TMOD=0x01;                                        //使用定时器0的模式1:即16位计数器,优点:可装载的值较多,计时可较长
        TH0=(65535-SET)/256;                //缺点:不是自动重装,所以在中断服务程序中还需装入初值
        TL0=(65535-SET)%256;         
        ET0=1;//打开定时器0的中断
        TR0=1;//打开定时器0
        EA=1;        //打开总中断
        while(1)
        {       
                display(5,k-1);
        }
}
void timer_0() interrupt 1
{
         TH0=(65535-SET)/256;
         TL0=(65535-SET)%256;
         tflag++;
         if(tflag == 1)                 // 3ms*x 数码管扫描
         {         
                  ENLED = 1;
                 key_scan();
                 tflag = 0;
         }
}
void display(unsigned int a,unsigned int b)
{
        P2 = wei[a];                                                         
        P0 = duan;
        ENLED = 0;
}
unsigned int key_scan()                                                   //矩阵按键扫描程序
{
        P2=0x7f;
        if(P2 != 0x7f)
        {       
                P0=0xff;                                                               
                delay_ms(5);
                if(P2 != 0x7f)
                {                       
                        switch(P2)
                        {
                                case 0x77:k=4;break;
                                case 0x7b:k=3;break;
                                case 0x7d:k=2;break;
                                case 0x7e:k=1;break;
                        }
                        while(P2 != 0x7f);
                }
        }
        P2=0xbf;
        if(P2 != 0xbf)
        {
                P0=0xff;
                delay_ms(5);
                if(P2 != 0xbf)
                {                       
                        switch(P2)
                        {
                                case 0xb7:k=8;break;
                                case 0xbb:k=7;break;
                                case 0xbd:k=6;break;
                                case 0xbe:k=5;break;
                        }
                        while(P2 != 0xbf);
                }
        }
        P2=0xdf;
        if(P2 != 0xdf)
        {
                P0=0xff;
                delay_ms(5);
                if(P2!=0xdf)
                {               
                        switch(P2)
                        {
                                case 0xd7:k=12;break;
                                case 0xdb:k=11;break;
                                case 0xdd:k=10;break;
                                case 0xde:k=9;break;
                        }
                        while(P2 != 0xdf);
                }
        }
        P2=0xef;
        if(P2 != 0xef)
        {       
                P0=0xff;
                delay_ms(5);
                if(P2 != 0xef)
                {                       
                        switch(P2)
                        {
                                case 0xe7:k=16;break;
                                case 0xeb:k=15;break;
                                case 0xed:k=14;break;
                                case 0xee:k=13;break;
                        }
                        while(P2 != 0xef);
                }
        }
}
void delay_us(unsigned int n)//延时函数
{
    extern void _nop_(void);
    register unsigned char i = n, j = (n>>8);
    _nop_(); _nop_(); _nop_();
    if ((--i) | j)
    {
        do
        {
            _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();
            if (0xFF == (i--)) j--; else {_nop_(); _nop_(); _nop_(); _nop_(); _nop_(); _nop_();};
        } while (i | j);
    }
}

void delay_ms(unsigned int n) //延时函数
{
        while (n--) delay_us(1000);
}
这段函数是援引自第41届学长的,并不是本人编写完成,我发表一下我对这段函数的理解,这提供了一个很好的思路(对于IO口冲突的问题),矩阵按键就是通过行线和列线来确定哪个按键被按下的。

  在按键的扫描中断时,每次让矩阵按键的1个KOUT口输出低电平,其他三个输出高电平,判断当前所有的p20,p21,p22,p23的状态,下次中断时再让下一个KOUT输出低电平,其他三个输出高电平,再次判断所有的p20~p23的状态,通过快速的中断不停地循环进行判断,就可以最终确定那个按键被按下了,改用了1ms中断,按照板子的按键按下即可,数码管显示值=按键值-1;请大家认真分析一下这段例程,会对你的单片机学习有帮助的。还请各位高手斧正。
好懒~~不想说~~~
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表