微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 嵌入式设计讨论 > MCU和单片机设计讨论 > 大牛帮忙看怪异问题:某些按键第三次按键会出错

大牛帮忙看怪异问题:某些按键第三次按键会出错

时间:10-02 整理:3721RD 点击:
第一次写51程序,芯片是STC89C52RC, 运行基本正常 就是按键控制很怪异,4个按键第一次按都对,第3个按键(K3),无论按几次 显示都对,
,第2个按键,第4个按键(K2, K4)第三次必定不对,不更新LCD显示,K1第二次就显示不更新,
开始还以为扫描键盘的代码有问题,更新后依旧。请问是哪里有问题呢?

#ifndef __MAIN_H__
#define __MAIN_H__

#include <reg52.h>
#include <intrins.h>
#include <stdio.h>
#include <string.h>
//LED IO设置
sbit LED1 = P2^0;
sbit LED2 = P2^1;
#define LED_PORT P2
sbit KEY1 = P3^2;
sbit KEY2 = P3^3;
sbit KEY3 = P3^4;
sbit KEY4 = P3^5;   
sbit CLK = P1^0;
sbit CW = P1^1;
sbit ENB = P1^2;
//函数或者变量声明
extern void Delay_ms(unsigned int n);
extern Delay_10us();
extern unsigned char Scan_Key();

#endif
//****************************************************
//****************************************************
#include "main.h"
#include "LCD1602.h"
void ShowState();
//正转值
#define RIGHT_RUN 1
//反转值
#define LEFT_RUN 0
char STATE_CW[]="CW";
char STATE_CCW[]="CCW";
float speed=1.0;        //速度因数
unsigned char RunState=RIGHT_RUN;  //运行状态
unsigned char temp = 0xfe;
unsigned char buf[18];
unsigned int  elapsedTime=0;
#define KEY_SEARCH_STATUS 0
#define KEY_ACK_STATUS 1
#define KEY_REALEASE_STATUS 2
#define KEY1  1
#define KEY2  2
#define KEY3  3
#define KEY4  4
//****************************************************
//按键扫描程序
//****************************************************
unsigned char Scan_Key()
{
    static unsigned char KeyStatus = KEY_SEARCH_STATUS,KeyCurPress=0;
    unsigned char KeyValue;
    unsigned char i=0;
    KeyValue = (~P3)&0x3c;
   
    switch(KeyStatus)
    {
      case KEY_SEARCH_STATUS:
      {
      if(KeyValue)
        KeyStatus=KEY_ACK_STATUS;
      return 0;
      }
      break;
      case KEY_ACK_STATUS:
      {
      if(!KeyValue)
        KeyStatus=KEY_SEARCH_STATUS;
      else
      {
        for(i=2;i<6;i++)
        {
          if(KeyValue & (1<<i))
          {
            KeyCurPress=KEY1+i-2;
            break;
          }
        }
       KeyStatus=KEY_REALEASE_STATUS;      
      }
      return 0;
      }
      break;
     case KEY_REALEASE_STATUS:
     {
       if(!KeyValue)
      {
        KeyStatus=KEY_SEARCH_STATUS;
        return KeyCurPress;
      }
      return 0;
     }
     default:
      break;
   }
   return 0;
}
                                
//定时器0中断程序:正转    用K1控制ENB 即按下待机
void t_0(void) interrupt 1
{
    TL0=0x86;    //(65536-(8616400/(speed*256)))%256;
    TH0=0x7c;   //(65536-(8616400/(speed*256)))/256;
    CLK=1;
    CW=1;
    Delay_ms(3);
    CLK=0; //产生脉冲  占空比10%
    elapsedTime++;
}

//定时器1中断:反转     用K2控制  interrupt 3 暂不使用,跟中断1有冲突
void invert(void)
{
    CLK=1;
    CW=0;
    RunState=LEFT_RUN;            
    Delay_ms(3);
    CLK=0; //产生脉冲  占空比10%
    ShowState();
}
//中断0:加速程序  用K3减少0.05倍
void SpeedUp()
{   
     if((speed>=1.0)&&(speed <=10.0))
        speed=speed+0.05;
     else
        speed=1.0;
    ShowState();                          
}
//中断1:减速程序   用K4增加0.05倍
void SpeedDowm()
{   
     if((speed<=1.0)&&(speed >=0.1))
        speed=speed-0.05;
     else
          speed=1.0;  
    ShowState();            
}
/* 显示(16*2): ..."/sec, CW, elapsed ...sec  */
void ShowState()    //显示状态与速度,运行时间          bug: 按键下去 显示上一次结果    !
{  
    LCD1602_write_com(0x1);  //clear screen
    Delay_ms(1);
    sprintf(buf, "%.04farc-s/sec", (speed*15.04));
    LCD1602_write_com(0x80);                        //指针设置到第一行
    LCD1602_write_word(buf);            //显示内容    16个字符
    LCD1602_write_com(0x80+0x40);                //指针设置到第二行
    sprintf(buf, "%s,ET %d sec", ((RunState==RIGHT_RUN)?STATE_CW:STATE_CCW), ((RunState==RIGHT_RUN)?((elapsedTime*34)/1000):0));        
    LCD1602_write_word(buf);                    //显示内容    16个字符   
}
void timer0_init()
{
   TMOD=0x01; //16位计数器方式
   TL0=0x86;
   TH0=0x7c;
   TR0=1;
   ET0=1;
   EA=1;        //全局中断
}
//****************************************************
//主函数
//****************************************************
void main()
{
    /* 定时器设置 */
    timer0_init();
    TL0=0x86;
    TH0=0x7c;
    Init_LCD1602();                                    //初始化LCD1602
    RunState=RIGHT_RUN;   
    while(1)
    {
      //refresh bug[16]
      switch(Scan_Key())
      {   
       case KEY1:                 //K1
       {
        ENB=1;
        RunState=RIGHT_RUN;   
        LED_PORT = 0X55;
        ShowState();
       }
       break;
       case KEY2:                //K2
       {
        invert();   
        LED_PORT = 0XAA;
       }
       break;
       case KEY3:          //K3
       {
        SpeedUp();   
        LED_PORT = 0X00;
       }
       break;
       case KEY4:          //K4
       {
        SpeedDowm();
        LED_PORT = temp;
        Delay_ms(300);
        temp = (temp << 1)|0x01;
        if(temp == 0xff)
          temp = 0xfe;        
       }
       break;  
       default:
         break;
      }
      ShowState();
   }            
}
//****************************************************
//MS延时函数(12M晶振下测试)
//****************************************************
void Delay_ms(unsigned int n)
{
    unsigned int  i,j;
    for(i=0;i<n;i++)
        for(j=0;j<123;j++);
}

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top