基于马潮老师修改的按键状态机(包括矩阵键盘)keilC51

2020-01-24 12:05发布

我是新手,不要嘲笑我,希望这些例程对正在受“天祥”大叔的按键子程序残害的人有所帮助吧
希望大家都能用上状态机。
谢谢马老师的例程。
==================================================================================
独立按键(简单的状态机,无连_发)
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
sbit led=P0^0;
void delay()
{
        uint i,j;
        for(i=100;i>0;i--)
        for(j=118;j>0;j--);
}
uchar readkey()
{
        static keystate=0,keytime=0;
        uchar keypress,keyreturn=0;
        keypress=P1;
        switch(keystate)
        {
                case 0:
                if (keypress!=0xff)
                {
                        keystate=1;
                       
                }
                break;

                case 1:
                if (keypress!=0xff)
                {
                        keystate=2;
                        keytime=0;
                }
                else
                keystate=0;
                break;

                case 2:
                if (keypress==0xff)
                {
                        keystate=0;
                        keyreturn=1;
                }
                else if (++keytime>=20000)
                {
                        keystate=3;
                        keytime=0;
                        keyreturn=2;
                }
                break;

                case 3:
                if (keypress==0xff)
                {
                        keystate=0;
                }
                else
                {
                        if (++keytime>=10000)
                        {
                                keytime=0;
                                keyreturn=2;
                        }
                }
                break;
        }
        return keyreturn;
}

void main()
{
        uchar k;
        while(1)
        {
                switch(readkey())
                {
                        case 1:
                        led=!led;
                        break;

                        case 2:
                        P0=0xfe;
                        for(k=0;k<8;k++)
                        {
                                delay();
                                P0=P0<<1|0X01;       
                        }
                        break;
                       
                }
        }
}

注:该子程序最好在中断设置标志位,10ms进入检测一次即可。本例程没有,为了方便。

=================================================================================================
矩阵键盘状态机(4×4,无连_发)
#include <reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define nokey 255
#define keymask 0x0f
sbit cs1=P1^0;
sbit cs2=P1^1;
sbit clk=P1^2;
uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
uchar num,timecount=0;
bit timeok;
void delay_us(uint us)
{
        while(--us);
}
//==============================延时子程序==================================
void delay_ms(uint ms)
{
        uint i,j;
        for(i=ms;i>0;i--)
        for(j=118;j>0;j--);
}
//==============================显示子程序=================================
void display(void)
{
        P2=tab[num];
        cs1=0;
        clk=0;clk=1;
        cs1=1;

        P2=0xfe;
        cs2=0;
        clk=0;clk=1;
        cs2=1;
        delay_ms(1);
}
//============================矩阵键盘按键状态机========================
uchar readkeyboard()
{
        static uchar keystate=0,keyvalue,keyline;
        uchar keyreturn=nokey,i;
        switch(keystate)
        {
                case 0:
                keyline=0x10;
                for (i=1;i<=4;i++)
                {
                        P0=~keyline;
                        P0=~keyline;
                        keyvalue=keymask&P0;
                        if (keyvalue==keymask)
                        {
                                keyline<<=1;
                        }
                        else
                        {
                                keystate++;
                                break;
                        }
                }
                break;

                case 1:
                if (keyvalue==(keymask&P0))
                {
                        switch(keyline|keyvalue)
                        {
                                case 0x87:keyreturn=0;break;
                                case 0x8b:keyreturn=1;break;
                                case 0x8d:keyreturn=2;break;
                                case 0x8e:keyreturn=3;break;

                                case 0x47:keyreturn=4;break;
                                case 0x4b:keyreturn=5;break;
                                case 0x4d:keyreturn=6;break;
                                case 0x4e:keyreturn=7;break;

                                case 0x27:keyreturn=8;break;
                                case 0x2b:keyreturn=9;break;
                                case 0x2d:keyreturn=10;break;
                                case 0x2e:keyreturn=11;break;

                                case 0x17:keyreturn=12;break;
                                case 0x1b:keyreturn=13;break;
                                case 0x1d:keyreturn=14;break;
                                case 0x1e:keyreturn=15;break;
                        }
                        keystate++;
                }

                else
                keystate--;
                break;

                case 2:
                P0=0x0f;
                P0=0x0f;
                if ((keymask&P0)==keymask)
                {
                        keystate=0;
                }
                break;
        }
        return keyreturn;
}
//==============================主程序==========================
void main()
{
        uchar keytemp;
        TMOD=0x01;
        TH0=(65536-2000)/256;
        TL0=(65536-2000)%256;
        EA=1;
        ET0=1;
        TR0=1;
        while(1)
        {
                if (timeok)
                {        keytemp=readkeyboard();
                        if (keytemp!=nokey)
                        {
                                num=keytemp;
                        }
                }
        }
}
//=================================中断服务子程序====================
void timer0() interrupt 1
{
        TH0=(65536-2000)/256;
        TL0=(65536-2000)%256;
        display();
        if (++timecount>=5)
        {
                timecount=0;
                timeok=1;       
        }       
}

================================================================================
以上都是自己写的程序,希望不要喷我,我就是想让初学者的朋友们使用上状态机~
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
52条回答
yao1
1楼-- · 2020-01-26 00:41
 精彩回答 2  元偷偷看……
1273753254
2楼-- · 2020-01-26 06:32
回复【9楼】edaworld 笨笨小熊
-----------------------------------------------------------------------

我的审核还没有通过
yao1
3楼-- · 2020-01-26 08:04
回复【楼主位】zhaoxukiller 搁浅的夜
-----------------------------------------------------------------------
#define uchar unsigned char
#define uint unsigned int
看这2句 就知道你也是郭天祥的弟子 竟然这么骂老师
你真以为人家不会你这种写法啊 人家写给初学者看才那么写的

你写的这程序是给初学者看的 没有层次感没有注释 很多初学者看不懂你知道吗?你看上面有几楼在问你问题了
你如果不骂人 我是不会喷你的

附郭天祥介绍:
       郭天祥(1983.10- ),老家新疆伊宁,原哈尔滨工程大学学生,后接触单片机,现在已经成为单片机领域的一个企业家,名下有天祥电子网站,其最大成就之一是开设了十天学会单片机系列课程并录制出来,现在网络上广泛流传,有《十天学会51单片机视频教程》、《十天学会PIC单片机视频教程》、《十天学会AVR单片机视频教程》,可以说这三种单片机类型几乎涵盖了市面上近90%的单片机产品,这些视频教程为广大单片机爱好者提供了最好的学习材料,另外还有关于ARM、嵌入式系统的视频教程,因其名誉广传,被广大学生敬称为郭天祥老师。
yao1
4楼-- · 2020-01-26 09:04
回复【7楼】Ilove51andAVR
-----------------------------------------------------------------------
1)bit位变量 就是标志位
“按键什么时候按下了?你不知道 所以做个标志bit=1, 只要bit=1 就代表按键按下了 bit=0就是没有按下”
  其他地方一样用 比如闹钟定时到100响 你可以开始定义bit=0 当时间走到100时,令bit=1 代表闹钟时间到了 你只要判断bit的状态就行了  if(bit==1) {闹钟时间到了,执行这里}
LZ的程序是 如果10ms时间到了 bit=1;代表如果bit=1说明10ms到了


2)static称为静态变量。根据变量的类型可以分为静态局部变量和静态全程变量。
    1. 静态局部变量
    它与局部变量的区别在于: 在函数退出时, 这个变量始终存在, 但不能被其它函数使用, 当再次进入该函数时, 将保存上次的
结果。其它与局部变量一样。
    2. 静态全程变量
    静态全程变量就是指只在定义它的源文件中可见而在其它源文件中不可见的变量。
    它与全程变量的区别是: 全程变量可以再说明为外部变量(extern), 被其它源文件使用, 而静态全程变量却不能再被说明为外部的, 即只能被所在的源文件使用。

   3.静态变量只是在第一次使用的时候初始化,如果是全局变量,则加static与否结果相同。如果是局部变量,则其他模块访问不到。

   4.静态函数只有在本编译文件中才能被调用。其他c文件则不能调用。因此在其他文件中可以申明同名函数,而不互相影响。

   5.全局变量使用方便,但副作用的隐患巨大。如果你定义一个全局变量,我就可以在任何地方修改。OS一般是写成库函数提供的,
就是自己用编成.LIB也比在项目中添一堆源文件要方便。问题是,你怎么告诉用户你用了那些全局变量,让他们别改动呢?或你自己
要怎样才能记住那么多用过的全局变量,绞尽脑汁起个不同的名字呢?设为静态全局变量,就是告诉编译器,这个变量是全局的但只
在此文件中有效,如果我在文件外定义同名变量不会影响文件内的全局变量。这样,一旦作成库后,用户和自己就可以随便使用,没有任何限制了。
SamPa
5楼-- · 2020-01-26 13:34
是啊,楼主加个注释啊,没有仔细看得完,就是那个矩阵的按键中keyline = 0x10,直接右移...菜鸟看着很是吃力,呵呵
yao1
6楼-- · 2020-01-26 16:56
 精彩回答 2  元偷偷看……

一周热门 更多>