打印

STM32 I/O矩阵扫描

[复制链接]
3183|14
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
lin34337151|  楼主 | 2012-12-28 19:01 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);
                                                                                                                                  
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //P0口普推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
          GPIO_Init(GPIOE, &GPIO_InitStructure);       

          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         //上拉输入
          GPIO_Init(GPIOE, &GPIO_InitStructure);       
                                                                                         
        GPIO_ResetBits(GPIOE, GPIO_Pin_0);
        GPIO_SetBits(GPIOE, GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
//
//        __TEMP=GPIO_ReadInputData(GPIOE);
//        GPIO_Write(GPIOE, ((__TEMP&0xffe0)|0X001e));
        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1e)!=0X1e)          //不等于有键按下
        {
                 LocalKey_COUNT1++;
                if((LocalKey_COUNT1>125)&&(LocalKey_FLAG1==0))  //15个循环周期去抖动
                {
                    LocalKey_FLAG1=1;
                //        SYSTICK_BUZZ_FUN(200);
                        ZONE_FLAG=1;                         //标志分区键按下
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1e;
                //        SYSTICK_KEY_WAIT_FUN(30000); //如果指有分区按键按下,30S秒还没功能键按下
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:          //分区1
                                    ZONE[0]|=0x01; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x1a:               //分区2
                                    ZONE[0]|=0x02;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x16:                   //分区3
                                        ZONE[0]|=0x04;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0e:                   //分区4
                                        ZONE[0]|=0x08;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                default:
                                        ZONE_FLAG=0;
                        }
                }               
        }
        else  //松开或者无按键
        {
                LocalKey_FLAG1=0;
                LocalKey_COUNT1=0;
        }          
//        delay(200);
//        LocalKey_PE1_Config();         
//        __TEMP=GPIO_ReadInputData(GPIOE);
//        GPIO_Write(GPIOE, ((__TEMP&0xffe0)|0X001d));
        GPIO_InitTypeDef GPIO_InitStructure;                                          
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);
                                                                                                                                  
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
          GPIO_Init(GPIOE, &GPIO_InitStructure);       

          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
          GPIO_Init(GPIOE, &GPIO_InitStructure);         

        GPIO_ResetBits(GPIOE,GPIO_Pin_1);
        GPIO_SetBits(GPIOE, GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);

        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1d)!=0X1d)          //不等于有键按下
        {
                 LocalKey_COUNT2++;
                if((LocalKey_COUNT2>125)&&(LocalKey_FLAG2==0))  //15个循环周期去抖动
                {       
                        LocalKey_FLAG2=1;
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1d;
                //        SYSTICK_KEY_WAIT_FUN(30000);//30s时间等待
                        ZONE_FLAG=1;
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:                          //分区5
                                        ZONE[0]|=0x10;SYSTICK_BUZZ_FUN(200);
                                        break;                          //分区6
                                case 0x19:
                                        ZONE[0]|=0x20; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x15:                          //分区7
                                        ZONE[0]|=0x40;SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0d:                          //分区8
                                        ZONE[0]|=80; SYSTICK_BUZZ_FUN(200);
                                        break;
                        }
                }       
        }
        else
        {
                LocalKey_FLAG2=0;
                LocalKey_COUNT2=0;
        }  
谁能帮我看一下,这个完整的矩阵键盘扫描
为什么我单独一组四个按键都能扫到,两个全部运行怎么就扫描不到了?
沙发
uet_cache| | 2012-12-28 19:51 | 只看该作者
看起好乱啊。眼都花了,,自己还是先整理下来吧。。

使用特权

评论回复
板凳
lin34337151|  楼主 | 2012-12-28 20:53 | 只看该作者
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);                                                                                                                           
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //P0口普推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
          GPIO_Init(GPIOE, &GPIO_InitStructure);       
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         //上拉输入
          GPIO_Init(GPIOE, &GPIO_InitStructure);                                                                                         
        GPIO_ResetBits(GPIOE, GPIO_Pin_0);
        GPIO_SetBits(GPIOE, GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);

        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1e)!=0X1e)          //不等于有键按下
        {
                 LocalKey_COUNT1++;
                if((LocalKey_COUNT1>125)&&(LocalKey_FLAG1==0))  //15个循环周期去抖动
                {
                    LocalKey_FLAG1=1;
                        ZONE_FLAG=1;                         //标志分区键按下
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1e;
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:          //分区1
                                    ZONE[0]|=0x01; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x1a:               //分区2
                                    ZONE[0]|=0x02;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x16:                   //分区3
                                        ZONE[0]|=0x04;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0e:                   //分区4
                                        ZONE[0]|=0x08;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                default:
                                        ZONE_FLAG=0;
                        }
                }               
        }
        else  //松开或者无按键
        {
                LocalKey_FLAG1=0;
                LocalKey_COUNT1=0;
        }
                 
        GPIO_InitTypeDef GPIO_InitStructure;                                          
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);                                                                                                                           
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
          GPIO_Init(GPIOE, &GPIO_InitStructure);       
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
          GPIO_Init(GPIOE, &GPIO_InitStructure);         
        GPIO_ResetBits(GPIOE,GPIO_Pin_1);
        GPIO_SetBits(GPIOE, GPIO_Pin_0|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);

        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1d)!=0X1d)          //不等于有键按下
        {
                 LocalKey_COUNT2++;
                if((LocalKey_COUNT2>125)&&(LocalKey_FLAG2==0))  //15个循环周期去抖动
                {       
                        LocalKey_FLAG2=1;
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1d;
                        ZONE_FLAG=1;
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:                          //分区5
                                        ZONE[0]|=0x10;SYSTICK_BUZZ_FUN(200);
                                        break;                          //分区6
                                case 0x19:
                                        ZONE[0]|=0x20; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x15:                          //分区7
                                        ZONE[0]|=0x40;SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0d:                          //分区8
                                        ZONE[0]|=80; SYSTICK_BUZZ_FUN(200);
                                        break;
                        }
                }       
        }
        else
        {
                LocalKey_FLAG2=0;
                LocalKey_COUNT2=0;
        }  

使用特权

评论回复
地板
lin34337151|  楼主 | 2012-12-28 20:53 | 只看该作者
请大侠指点一下,不知道哪里有问题

使用特权

评论回复
5
lin34337151|  楼主 | 2012-12-28 20:57 | 只看该作者
        LocalKey_PE0_Config();
        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1e)!=0X1e)          //不等于有键按下
        {
                 LocalKey_COUNT1++;
                if((LocalKey_COUNT1>125)&&(LocalKey_FLAG1==0))  //15个循环周期去抖动
                {
                    LocalKey_FLAG1=1;
                        ZONE_FLAG=1;                         //标志分区键按下
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1e;
                //        SYSTICK_KEY_WAIT_FUN(30000); //如果指有分区按键按下,30S秒还没功能键按下
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:          //分区1
                                    ZONE[0]|=0x01; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x1a:               //分区2
                                    ZONE[0]|=0x02;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x16:                   //分区3
                                        ZONE[0]|=0x04;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0e:                   //分区4
                                        ZONE[0]|=0x08;        SYSTICK_BUZZ_FUN(200);
                                        break;
                                default:
                                        ZONE_FLAG=0;
                        }
                }               
        }
        else  //松开或者无按键
        {
                LocalKey_FLAG1=0;
                LocalKey_COUNT1=0;
        }          
        LocalKey_PE1_Config();         
        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
        if((__ScanKey_temp&0x1d)!=0X1d)          //不等于有键按下
        {
                 LocalKey_COUNT2++;
                if((LocalKey_COUNT2>125)&&(LocalKey_FLAG2==0))  //15个循环周期去抖动
                {       
                        LocalKey_FLAG2=1;
                        __ScanKey_temp=(uint8_t)GPIO_ReadInputData(GPIOE);
                        __ScanKey_temp=__ScanKey_temp&0x1d;
                //        SYSTICK_KEY_WAIT_FUN(30000);//30s时间等待
                        ZONE_FLAG=1;
                        switch(__ScanKey_temp)
                        {
                                case 0X1c:                          //分区5
                                        ZONE[0]|=0x10;SYSTICK_BUZZ_FUN(200);
                                        break;                          //分区6
                                case 0x19:
                                        ZONE[0]|=0x20; SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x15:                          //分区7
                                        ZONE[0]|=0x40;SYSTICK_BUZZ_FUN(200);
                                        break;
                                case 0x0d:                          //分区8
                                        ZONE[0]|=80; SYSTICK_BUZZ_FUN(200);
                                        break;
                        }
                }       
        }
        else
        {
                LocalKey_FLAG2=0;
                LocalKey_COUNT2=0;
        }

使用特权

评论回复
6
lin34337151|  楼主 | 2012-12-28 20:58 | 只看该作者
void LocalKey_PE0_Config(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;
        RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOE, ENABLE);
                                                                                                                                  
          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;   //P0口普推挽输出
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
          GPIO_Init(GPIOE, &GPIO_InitStructure);       

          GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       
          GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;         //上拉输入
          GPIO_Init(GPIOE, &GPIO_InitStructure);       
                                                                                         
        GPIO_ResetBits(GPIOE, GPIO_Pin_0);
        GPIO_SetBits(GPIOE, GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4);
}

使用特权

评论回复
7
lin34337151|  楼主 | 2012-12-28 21:01 | 只看该作者
这里我有两个扫描两组按键,把其中一组屏蔽掉都可以正常运行,一起来就扫描不到按键

使用特权

评论回复
8
香如故| | 2012-12-28 21:21 | 只看该作者
最好每个io外接个几k的上拉电阻,内部上拉电阻不怎么可靠,受干扰性很大的

使用特权

评论回复
9
lin34337151|  楼主 | 2012-12-28 22:38 | 只看该作者
相如故,你好!我在每个I/O加了10K上拉电阻,我估计是我I/O设置的问题。比如我给一个I/O口赋值,从另外IO口读取数据,这个要怎么设置,以前用51单片机没有这个问题。

使用特权

评论回复
10
uet_cache| | 2012-12-29 09:49 | 只看该作者
本帖最后由 uet_cache 于 2012-12-29 09:56 编辑

你PE0/1配置切换完后加点延时再去读,不行,你可以单步仿真。。如果单步仿真运行,一般是需要点时间的。。

使用特权

评论回复
11
明月小厨| | 2012-12-29 10:55 | 只看该作者
这就是传说中的一次性代码;
项目完成后这些代码再也没有谁愿意看,就算想看也看不懂,不如重写,这就是一次性!

比我写的还要乱很多.

使用特权

评论回复
12
zztishan| | 2012-12-29 12:53 | 只看该作者
感觉整个程序的架构有点问题,很乱,为什么GPIO的两次初始化你不放两个函数里,按键去抖延时,你为什么不放一个函数里?你这样很乱,哪里出问题都不好找。整个逻辑就比较混乱,你要实现什么功能,通过哪些步骤可以实现,实现到哪一步了。你最好先画个流程图,然后根据流程图写函数实现,在调试,看看那个函数实现出问题了。再找原因,如果原因是流程图忽略了其他的条件,你的再重复上面的过程。我相信,你这样去做肯定找出问题,解决问题的。你要解决的这个项目,本身不难,问题出在是你把它搞乱,搞复杂了。

使用特权

评论回复
13
610095871| | 2012-12-29 14:58 | 只看该作者
struct io_port
{                                            
        GPIO_TypeDef *GPIO_x;                 
        unsigned short GPIO_pin;
};

static struct io_port key_output[4] =
{
        {GPIOD, GPIO_Pin_13}, {GPIOD, GPIO_Pin_14},
        {GPIOD, GPIO_Pin_15}, {GPIOC, GPIO_Pin_6}
};
static struct io_port key_input[7] =
{
        {GPIOC, GPIO_Pin_7}, {GPIOC, GPIO_Pin_8},
        {GPIOC, GPIO_Pin_9}, {GPIOA, GPIO_Pin_8},
        {GPIOA, GPIO_Pin_11}, {GPIOA, GPIO_Pin_12},
        {GPIOA, GPIO_Pin_13}
};
void update_key(void)
{
        u8 i=0, j=0;
        for(i = 0; i < 4; i++)             //i是输出口,依次置低电平
        {
                  GPIO_ResetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);
                OSTimeDly(20);          ///
        //        delay_ms(40);
                  for(j = 0; j < 7; j++)            //j是输入口,当键按下时导通被置为低电平  
                  {
                           if(GPIO_ReadInputDataBit(key_input[j].GPIO_x, key_input[j].GPIO_pin) == 0)
                           {

                            key[i][j] = 1;
                           }
                        else
                        {
                            key[i][j] = 0;
                           }
                        OSTimeDly(20);///
                //        delay_ms(40);
                  }
               
                  GPIO_SetBits(key_output[i].GPIO_x, key_output[i].GPIO_pin);
        }
}

我一般这样做矩阵扫描。

使用特权

评论回复
14
lin34337151|  楼主 | 2012-12-31 17:58 | 只看该作者
问题找到了,不是程序的问题,是我在按键两个脚之间加了个104电容引起的。谢谢各位指点。

使用特权

评论回复
15
guodongmei| | 2012-12-31 19:22 | 只看该作者
学习了,矩阵键盘

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

113

主题

285

帖子

3

粉丝