OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7168|回复: 6

按键响应太慢了,求助

[复制链接]

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2012-11-30
在线时间
0 小时
发表于 2013-6-2 21:56:50 | 显示全部楼层 |阅读模式
 主要问题是,功能都能按我的预期实现,但是对按键按下的响应太慢了,比如按了其中一个按键,过好几秒才出现象(使用的是原子哥的战舰STM32开发板)
代码如下:
1)key.h文件:
# ifndef KEY_H_
# define KEY_H_

# include "sys.h"

//自己写的宏:读取某组I/O口某个引脚的电平
# define ReadA(n) GPIO_ReadInputDataBit(GPIOA, (uint16_t)(0x0001 << n))
# define ReadE(n) GPIO_ReadInputDataBit(GPIOE, (uint16_t)(0x0001 << n))

# define KEY_UP 1
# define KEY_LEFT 2
# define KEY_DOWN 3
# define KEY_RIGHT 4

void Key_Init(void);
u8 Key_Scan(void);

# endif
2)key.c文件:(仅列出和原子哥很不类似的函数而已,其中I/O口的使能等都是差不多的
u8 Key_Scan(void)
{
if(ReadA(0) || !ReadE(2) || !ReadE(3) || !ReadE(4))
{
delay_ms(10); //消抖
if(ReadA(0))
{
while(ReadA(0)) //松手检测,下同
continue;
return KEY_UP;
}
else if(!ReadE(2))
{
while(!ReadE(2))
continue;
return KEY_LEFT;
}
else if(!ReadE(3))
{
while(!ReadE(3))
continue;
return KEY_DOWN;
}
else if(!ReadE(4))
{
while(!ReadE(4))
continue;
return KEY_RIGHT;
}
}   

return 0; //无按键按下
}
3)main.c文件:
# include "led.h"
# include "sys.h"
# include "delay.h"
# include "beep.h"
# include "key.h"

int main(void)
{
delay_init();
LED_init();
Beep_Init();
Key_Init();

while(1)
{
switch(Key_Scan())
{
case KEY_UP:
GPIO_ResetBits(GPIOB, GPIO_Pin_5); //灯亮
GPIO_ResetBits(GPIOE, GPIO_Pin_5); //灯亮
GPIO_ResetBits(GPIOB, GPIO_Pin_8); //不响
break;
case KEY_LEFT:
GPIO_SetBits(GPIOB, GPIO_Pin_5);   //不亮
GPIO_SetBits(GPIOE, GPIO_Pin_5);   //不亮
GPIO_SetBits(GPIOB, GPIO_Pin_8); //响
break;
case KEY_DOWN:
GPIO_ResetBits(GPIOB, GPIO_Pin_5); //亮
GPIO_SetBits(GPIOE, GPIO_Pin_5);   //不亮
GPIO_ResetBits(GPIOB, GPIO_Pin_8); //不响
break;
case KEY_RIGHT:
GPIO_SetBits(GPIOB, GPIO_Pin_5); //不亮
GPIO_ResetBits(GPIOE, GPIO_Pin_5); //亮
GPIO_ResetBits(GPIOB, GPIO_Pin_8); //不响
break;
}
}
}

看了开发指南(库函数版本),很好的资料(顶下),看了就自己能操作那些I/O口了,都是自己看着外围电路来写的代码,写完后再看原子哥的标准例程(库函数版本)
不过有一点不大明白,CRL或者CRH寄存器不是每4位设置一个I/O口的输入输出模式了吗,为什么GPIOMode_TypeDef这个枚举是8位的,见下图





        希望大家帮我解决上面2个问题
嘿嘿,开发板上一年就买了,因为某些事,去给人弄一些纯软件的项目,现在才拿出来学习,硬件编程和硬件不是很懂,如果有哪些地方说的不够详细,请指出
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

57

主题

431

帖子

1

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
886
金钱
886
注册时间
2011-12-25
在线时间
12 小时
发表于 2013-6-2 22:57:57 | 显示全部楼层
/**
  * @brief  Initializes the GPIOx peripheral according to the specified
  *         parameters in the GPIO_InitStruct.
  * @param  GPIOx: where x can be (A..G) to select the GPIO peripheral.
  * @param  GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that
  *         contains the configuration information for the specified GPIO peripheral.
  * @retval None
  */
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
  uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00;
  uint32_t tmpreg = 0x00, pinmask = 0x00;
  /* Check the parameters */
  assert_param(IS_GPIO_ALL_PERIPH(GPIOx));
  assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));
  assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));  
  
/*---------------------------- GPIO Mode Configuration -----------------------*/
  currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);
  if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
  { 
    /* Check the parameters */
    assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
    /* Output mode */
    currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed;
  }
/*---------------------------- GPIO CRL Configuration ------------------------*/
  /* Configure the eight low port pins */
  if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)
  {
    tmpreg = GPIOx->CRL;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = ((uint32_t)0x01) << pinpos;
      /* Get the port pins position */
      currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding low control register bits */
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << pinpos);
        }
        else
        {
          /* Set the corresponding ODR bit */
          if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
          {
            GPIOx->BSRR = (((uint32_t)0x01) << pinpos);
          }
        }
      }
    }
    GPIOx->CRL = tmpreg;
  }
/*---------------------------- GPIO CRH Configuration ------------------------*/
  /* Configure the eight high port pins */
  if (GPIO_InitStruct->GPIO_Pin > 0x00FF)
  {
    tmpreg = GPIOx->CRH;
    for (pinpos = 0x00; pinpos < 0x08; pinpos++)
    {
      pos = (((uint32_t)0x01) << (pinpos + 0x08));
      /* Get the port pins position */
      currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos);
      if (currentpin == pos)
      {
        pos = pinpos << 2;
        /* Clear the corresponding high control register bits */
        pinmask = ((uint32_t)0x0F) << pos;
        tmpreg &= ~pinmask;
        /* Write the mode configuration in the corresponding bits */
        tmpreg |= (currentmode << pos);
        /* Reset the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD)
        {
          GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
        /* Set the corresponding ODR bit */
        if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU)
        {
          GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08));
        }
      }
    }
    GPIOx->CRH = tmpreg;
  }
}
楼主把这个理解懂了就解决你的问题,小小提示

typedef enum
{ GPIO_Mode_AIN = 0x0,    //输入的 第5位都是0
  GPIO_Mode_IN_FLOATING = 0x04,
  GPIO_Mode_IPD = 0x28,
  GPIO_Mode_IPU = 0x48,
  GPIO_Mode_Out_OD = 0x14,  //输出的  第5位都是1
  GPIO_Mode_Out_PP = 0x10,
  GPIO_Mode_AF_OD = 0x1C,
  GPIO_Mode_AF_PP = 0x18
}GPIOMode_TypeDef;
程序有说明,,输入输出 2bit,,(输出模式)速度2bit..
很喜爱电子行业
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-6-2 23:16:34 | 显示全部楼层
按键模式设置没对吧,导致在while里面停了太久.
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2012-11-30
在线时间
0 小时
 楼主| 发表于 2013-6-2 23:47:25 | 显示全部楼层
回复【3楼】正点原子:
---------------------------------
void Key_Init(void)
{
GPIO_InitTypeDef Init;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA |
RCC_APB2Periph_GPIOE, ENABLE);
Init.GPIO_Pin = GPIO_Pin_0;
Init.GPIO_Speed = GPIO_Speed_50MHz;
Init.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GPIOA, &Init);

Init.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4;       //之前忘了加这句
Init.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOE, &Init);
}
嘿嘿,我发现之前的代码没有加注释的那句,现在加上就OK了,不过新问题又来了,
如果没有那句的话,不是仅仅初始化GPIOE第0个引脚而已吗,这样子也能ReadInputDataBits函数读取每一个引脚的状态?
回复 支持 反对

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2012-11-30
在线时间
0 小时
 楼主| 发表于 2013-6-2 23:48:31 | 显示全部楼层
回复【2楼】冰是睡着的水:
---------------------------------
嗯嗯,谢啦
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165540
金钱
165540
注册时间
2010-12-1
在线时间
2117 小时
发表于 2013-6-2 23:48:41 | 显示全部楼层
回复【4楼】YS晓:
---------------------------------
不加就是一个都不初始化了...
我是开源电子网www.openedv.com站长,有关站务问题请与我联系。
正点原子STM32开发板购买店铺http://openedv.taobao.com
正点原子官方微信公众平台,点击这里关注“正点原子”
回复 支持 反对

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
92
金钱
92
注册时间
2012-11-30
在线时间
0 小时
 楼主| 发表于 2013-6-2 23:49:53 | 显示全部楼层
回复【6楼】正点原子:
---------------------------------
结构体变量Init前面已经有一个Init.GPIO_Pin = GPIO_Pin_0了,初始化GPIOA的第0个引脚
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-7-19 01:49

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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