打印

怪异现象!按键未按下高电平时为何不是1而是8呢??

[复制链接]
964|5
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
hzocce|  楼主 | 2019-1-18 16:35 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 hzocce 于 2019-1-18 16:44 编辑

玩一个按键状态机扫描程序,PB3通过电阻上拉到VCC,按键按下后短路到GND。
PG1接了一个LED,通过亮灭来观察按键是否被单片机识别到。

本来按键功能就是按下后翻转IO电平,表现的现象为LED亮灭,也就是通过按键来控制LED亮灭。
但是发现了一个问题,就是按下一次后,LED再都不会翻转了。
后面终于知道了程序为什么不执行原因,用串口输出当时读取到得数值后,发现竟然是8,为何???
求高手指点,谢谢!


#include "stm8s.h"
#include "usart2.h"
#include "stm8s_tim1.h"

unsigned char Flag_10ms=0;
extern u8 RxBuffer[RxBufferSize];
extern u8 UART_RX_NUM;
void Delay(uint16_t nCount)
{
  while (nCount != 0)
  {   
    nCount--;
  }
}
//时钟配置
void CLK_Config(void)
{
    CLK_HSICmd(ENABLE);    //启动内部高速时钟
    CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1); //1分频
}


#define Key_Get               GPIO_ReadInputPin(GPIOB, GPIO_PIN_3)






#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 LONG_KEY_TIME       200     //长按的3秒时间
#define SINGLE_KEY_TIME     3       // 短按的消抖时间

#define  N_Key 0   //无键
#define  S_Key 1   //单键
#define  D_Key 2   //双键
#define  L_Key 10  //长键
#define  T_Key 3   //3次点击
#define  F_Key 4   //4次点击
#define  V_Key 5   //5次点击



#define KEY_ON           0
#define KEY_OFF           1
unsigned char Scan_key(void)
{
    static char key_state = 0;     //按键的状态
    unsigned char key_press=0;       //按键是否被按下
    unsigned char key_return = 0;
    key_press=0;
    key_press = Key_Get;         // 读按键I/O电平
    UART2_SendByte(key_press);//----------------------输出后发现读取到得竟然是8哎~~~~~~~~~~~~~~
    switch (key_state)
    {
        case KEY_STATE_0:                 // 按键初始态
              if(key_press==KEY_ON)//按下后为0,进入判断
              {
                  key_state = KEY_STATE_1;// 键被按下,状态转换到键确认态下一阶段
              }break;
                                
        case KEY_STATE_1:                   // 按键确认态
              if(key_press==KEY_ON)

              {
                  key_return = 1;         // 按键仍按下,按键确认输出为“1”
                  key_state = KEY_STATE_2;// 状态转换到键释放态
              }
              else
              {
                  key_state = KEY_STATE_0; // 按键已抬起,转换到按键初始态
              }
              break;
                                 
        case KEY_STATE_2:
           //if(key_press==KEY_OFF) //如果是判断1则永远都不会执行,为什么???????
                 if(key_press==8) //确认是否松开,若松开进入到初始
              {
                  key_state = KEY_STATE_0;//按键已释放,转换到按键初始态
              }
              break;
   }
return key_return;                            //返回按键值
}
void Do_Something_For_You(unsigned char Which)
{
     switch(Which)
     {
      case S_Key: GPIO_WriteReverse(GPIOG,GPIO_PIN_0);  //单击事件
                  break;
      case D_Key:   //双击事件
        GPIO_WriteReverse(GPIOG,GPIO_PIN_1);
                  break;
      case T_Key:   //三击事件
                  break;
      case F_Key:    //四击事件
                  break;
     case V_Key:   //五击事件
                  break;
     
     }


}
void Time1(void)
{
    TIM1_DeInit();
    TIM1_DeInit();                                                                //恢复为默认值
    //TIM1_TimeBaseInit(15, TIM1_COUNTERMODE_UP, 20000, 0x00); //不分频16MHz 计数值20000 80ms中断一次
    //TIM1_TimeBaseInit(15, TIM1_COUNTERMODE_UP, 5000, 0x00); //不分频16MHz 计数值5000 20ms中断一次
    TIM1_TimeBaseInit(15, TIM1_COUNTERMODE_UP, 10000, 0x00); //不分频16MHz 10ms中断一次
    TIM1_GenerateEvent(TIM1_EVENTSOURCE_UPDATE);    //手册里有说明,不设置的话就不会产生中断
    TIM1_ITConfig(TIM1_IT_UPDATE, ENABLE);                //配置更新中断
    TIM1_Cmd(ENABLE);                                                            //使能定时器  
}
unsigned char KEY_Function=0;
void main(void)
{

  // CLK_HSIPrescalerConfig(CLK_PRESCALER_HSIDIV1);  //使用内部高速时钟
    CLK_Config();
    Init_UART2();            //初始化串口2
    Time1();
    enableInterrupts();
    GPIO_Init(GPIOG, GPIO_PIN_0, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOG, GPIO_PIN_1, GPIO_MODE_OUT_PP_LOW_FAST);
    GPIO_Init(GPIOB, GPIO_PIN_3, GPIO_MODE_IN_PU_NO_IT);
   
    GPIO_WriteLow(GPIOG,GPIO_PIN_0);
    GPIO_WriteLow(GPIOG,GPIO_PIN_1);
    printf("\r\nHello%s\r\n"," Word!");

  while (1)
  {
   
     if(Flag_10ms)
    {   
        Flag_10ms=0;

        KEY_Function=Scan_key();
        Do_Something_For_You(KEY_Function);

    };

  }
  
}


INTERRUPT_HANDLER(TIM1_UPD_OVF_TRG_BRK_IRQHandler, 11)
{


    TIM1_ClearITPendingBit(TIM1_IT_UPDATE);
    Flag_10ms=1;
//    if(++Flag_10ms>=10)
//    {
//      Flag_10ms=0;
//      GPIO_WriteReverse(GPIOG,GPIO_PIN_1);
//    };


}

#ifdef USE_FULL_ASSERT

/**
  * @brief  Reports the name of the source file and the source line number
  *   where the assert_param error has occurred.
  * @param file: pointer to the source file name
  * @param line: assert_param error line source number
  * @retval : None
  */
void assert_failed(u8* file, u32 line)
{
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */

  /* Infinite loop */
  while (1)
  {
  }
}
#endif

/******************* (C) COPYRIGHT 2011 STMicroelectronics *****END OF FILE****/

相关帖子

沙发
hzocce|  楼主 | 2019-1-18 16:37 | 只看该作者

使用特权

评论回复
板凳
hzocce|  楼主 | 2019-1-18 16:39 | 只看该作者

改成判断是否为8的时候一切正常,判断为1的时候则不正常,这个怎么解释呢?

使用特权

评论回复
地板
hzocce|  楼主 | 2019-1-18 16:53 | 只看该作者
从stm8s_gpio.c文件中看到如下:


/**
  * @brief  Reads the specified GPIO input data pin.
  * @param  GPIOx : Select the GPIO peripheral number (x = A to I).
  * @param  GPIO_Pin : Specifies the pin number.
  * @retval BitStatus : GPIO input pin status.
  */
BitStatus GPIO_ReadInputPin(GPIO_TypeDef* GPIOx, GPIO_Pin_TypeDef GPIO_Pin)
{
    return ((BitStatus)(GPIOx->IDR & (uint8_t)GPIO_Pin));
}

使用特权

评论回复
5
ayb_ice| | 2019-1-18 17:02 | 只看该作者
PB3, 1<<3不是等于8吗
驱动没有转换成位变量
或判断 ==0, != 0

使用特权

评论回复
6
hzocce|  楼主 | 2019-1-21 09:08 | 只看该作者

似乎明白了一点。。。。谢谢指导~~~~~


可是我没有看到哪里是是1<<3哎,

那这样的话,所有的库函数操作的,只能判断0跟非0了,不能跟寄存器操作一样,单个位读取?
寄存器位操作的话,就是1跟0的区别。
PB3就是等于1哎~ 而不是8.

使用特权

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

本版积分规则

127

主题

561

帖子

4

粉丝