大牛帮忙看怪异问题:某些按键第三次按键会出错
时间: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++);
}
,第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++);
}