这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » MCU » 分享一个基于状态机的矩阵按键程序(源码)

共7条 1/1 1 跳转至

分享一个基于状态机的矩阵按键程序(源码)

工程师
2019-07-12 23:05:47     打赏


支持抬起识别。可以修改支持短按按下识别,短按抬起识别,长按按下识别,长按抬起识别。

支持任何微处理器(MCU、ARM等)


先看电路图:


以下是源码:

void MatrixKeyScan(unsigned char ucKeyValue[4][4])

{

        static unsigned char ucKeyState[4][4] = {KEY_STATE_0, KEY_STATE_0, KEY_STATE_0, KEY_STATE_0};

        static unsigned char ucKeyTime[4][4] = {0, 0, 0, 0};

        unsigned char ucKeyPress[4], i = 0, j = 0;

        

          for(j = 0; j < 4; j++)

          {

                LineOutCtrl(j, SET);

                  for(i = 0; i < 4; i++)

                  {

                        ColumnScan(i, ucKeyPress);

                        //printf("\r\n %d %d %d", j, i, ucKeyPress[i]);

                        

                        switch (ucKeyState[j][i])

                        {

                                case KEY_STATE_0:

                                if (!ucKeyPress[i])

                                {

                                        ucKeyState[j][i] = KEY_STATE_1;

                                }

                                break;


                                case KEY_STATE_1:

                                if (!ucKeyPress[i])

                                {

                                        ucKeyTime[j][i] = 0;

                                        ucKeyState[j][i] = KEY_STATE_2;

                                }

                                else

                                {

                                        ucKeyState[j][i] = KEY_STATE_0;

                                }

                                break;


                                case KEY_STATE_2:

                                if(ucKeyPress[i])

                                {

                                        ucKeyState[j][i] = KEY_STATE_0;

                                }

                                else

                                {

                                        ucKeyTime[j][i]++;

                                        if(ucKeyTime[j][i] == 1)

                                        {

                                                ucKeyState[j][i] = KEY_STATE_3;

                                        }

                                }

                                break;

                                case KEY_STATE_3:

                                if (ucKeyPress[i])

                                {

                                        ucKeyValue[j][i] = (i + j * 4 + 1);

                                        ucKeyState[j][i] = KEY_STATE_0;

                                }

                                else

                                {

                                }

                                break;

                                default:

                                break;

                        }

                  }

                LineOutCtrl(j, RESET);

          }

}



void ColumnScan(U8 Index, U8 *KeyPress)

{

        switch(Index)

        {

                case 0:

                        if(GPIO_ReadInputDataBit(KEYIN1_PORT, KEYIN1_PIN) == RESET)

                        KeyPress[Index] = 0;//按下

                        else

                        KeyPress[Index] = 1;//抬起

                break;

                case 1:

                        if(GPIO_ReadInputDataBit(KEYIN2_PORT, KEYIN2_PIN) == RESET)

                        KeyPress[Index] = 0;

                        else

                        KeyPress[Index] = 1;

                break;

                case 2:

                        if(GPIO_ReadInputDataBit(KEYIN3_PORT, KEYIN3_PIN) == RESET)

                        KeyPress[Index] = 0;

                        else

                        KeyPress[Index] = 1;

                break;

                case 3:

                        if(GPIO_ReadInputDataBit(KEYIN4_PORT, KEYIN4_PIN) == RESET)

                        KeyPress[Index] = 0;

                        else

                        KeyPress[Index] = 1;

                break;

                default:

                break;

        }

        //printf("\r\n %d %d", Index, KeyPress[Index]);

}


void LineOutCtrl(U8 Index, U8 en)

{

        switch(Index)

        {

                case 0:

                        if(!en)

                        GPIO_SetBits(KEYOUT1_PORT, KEYOUT1_PIN);

                        else

                        GPIO_ResetBits(KEYOUT1_PORT, KEYOUT1_PIN);

                break;

                case 1:

                        if(!en)

                        GPIO_SetBits(KEYOUT2_PORT, KEYOUT2_PIN);

                        else

                        GPIO_ResetBits(KEYOUT2_PORT, KEYOUT2_PIN);

                break;

                case 2:

                        if(!en)

                        GPIO_SetBits(KEYOUT3_PORT, KEYOUT3_PIN);

                        else

                        GPIO_ResetBits(KEYOUT3_PORT, KEYOUT3_PIN);

                break;

                case 3:

                        if(!en)

                        GPIO_SetBits(KEYOUT4_PORT, KEYOUT4_PIN);

                        else

                        GPIO_ResetBits(KEYOUT4_PORT, KEYOUT4_PIN);

                break;

                

                default:

                break;

        }

        

}


#define KEYOUT1_PORT                        GPIOA

#define KEYOUT1_PIN                                GPIO_Pin_0

#define KEYOUT2_PORT                        GPIOA

#define KEYOUT2_PIN                                GPIO_Pin_1

#define KEYOUT3_PORT                        GPIOA

#define KEYOUT3_PIN                                GPIO_Pin_2

#define KEYOUT4_PORT                        GPIOA

#define KEYOUT4_PIN                                GPIO_Pin_3


#define KEYIN1_PORT                                GPIOA

#define KEYIN1_PIN                                GPIO_Pin_4

#define KEYIN2_PORT                                GPIOA

#define KEYIN2_PIN                                GPIO_Pin_5

#define KEYIN3_PORT                                GPIOA

#define KEYIN3_PIN                                GPIO_Pin_6

#define KEYIN4_PORT                                GPIOA

#define KEYIN4_PIN                                GPIO_Pin_7


#define KEY_STATE_0 0

#define KEY_STATE_1 1

#define KEY_STATE_2 2

#define KEY_STATE_3 3

#define KEY_STATE_4 4


#define N_KEY       0xFE


void Task_10ms(void)

{

        static U8 ucCount = 0;

        U8 ucKeyValue[4][4] = {

        {N_KEY, N_KEY, N_KEY, N_KEY},

        {N_KEY, N_KEY, N_KEY, N_KEY},

        {N_KEY, N_KEY, N_KEY, N_KEY},

        {N_KEY, N_KEY, N_KEY, N_KEY}

        }, i = 0, j = 0;


        MatrixKeyScan(ucKeyValue);

        for(j = 0; j < 4; j++)

        {

                for(i = 0; i < 4; i++)

                {

                        if(ucKeyValue[j][i] != N_KEY)

                        {

                                printf("\r\n ucKeyValue 测试计数:%d %d",ucCount++, ucKeyValue[j][i]);

                        }

                }

        } 

}





关键词: 状态机          矩阵按键     源码    

工程师
2019-07-12 23:26:29     打赏
2楼

程序通俗易懂,还是不错哦!


助工
2019-07-12 23:28:17     打赏
3楼

谢谢楼主的源码


工程师
2019-07-12 23:30:06     打赏
4楼

太用心啦


菜鸟
2019-07-12 23:34:22     打赏
5楼

学习一下


工程师
2019-07-12 23:36:48     打赏
6楼

对比了楼主的程序,才发现我之前写的程序太LOW了,膜拜一下!

我还要多学习才行!


工程师
2019-07-12 23:54:17     打赏
7楼

之前看到到安福莱的类似程序,单个按键驱动改一下按键的的扫描函数,可支持短按,长按,连发,弹起。


共7条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]