标题:
单片机状态机来扫描键盘程序 调时状态加减会出问题
[打印本页]
作者:
殿堂之上
时间:
2023-10-25 17:42
标题:
单片机状态机来扫描键盘程序 调时状态加减会出问题
用状态机来扫描键盘,有时按了会出现错乱,不知道哪里出问题了
单片机源程序如下:
#include <reg52.h>
#include <intrins.h>
#define SXLed_P P0
#define K5 0x07
#define K4 0x0b
#define K3 0x0d
#define K2 0x0e
unsigned int i;
unsigned char KeyValue,KeyValueTemp,StateNo,Flag_Time;
bit Flag_05s,Flag_1s,Flag_Change,Flag_Hide; //位标志
unsigned char SX[8]; //数码管数据缓存,位标志
unsigned char Hour,Minute,Second; //时分秒
sbit SXLed_W=P2^7; //数码管位选
sbit SXLed_D=P2^6; //数码管段选
sbit bp=P2^3;
unsigned char code Number[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7F,
0x6F,0x40,0x80,0x00}; //共阴极数码管0-9-.灭
void Delay(unsigned char ); //毫秒延时函数
void Init(void); //数据初始化函数
void T0_Init(void); //T0中断初始化函数
void SXLed (unsigned char location,unsigned char Num);//数码管显示函数
void Start_Screen(void); //开机显示画面函数
void Time(void); //时分秒进位函数
void Hex_BCD(void); //数据转换并送到数码管数缓存函数
void KeyScan(void); //按键扫描函数(状态机法)
void KeyProcess(void); //按键处理函数
void main(void)
{
Delay(100); //开机延时
Init(); //变量初始化
T0_Init(); //定时器T0初始化
Start_Screen(); //开机画面
// P1=0x00;
while(1)
{
if(Flag_05s==1) //0.5秒到了
{
Flag_05s=0;//0.5秒到状态清0
Hex_BCD();//数据转换并送到数码管数缓存
if(Flag_Change!=0)//调时状态
{
Flag_Hide=!Flag_Hide;//隐藏标志
if ((Flag_Hide==1)&&(Flag_Time==0))//调时状态时闪烁
{
SX[7]=12;
SX[6]=12;
}
if ((Flag_Hide==1)&&(Flag_Time==1))//调时状态分闪烁
{
SX[4]=12;
SX[3]=12;
}
if ((Flag_Hide==1)&&(Flag_Time==2))//调时状态秒闪烁
{
SX[1]=12;
SX[0]=12;
}
}
}
}
}
void Init(void)
{
i=0;
Hour=23;
Minute=59;
Second=50;
Flag_05s=0;
Flag_1s=0;
Flag_Change=0;
Flag_Hide=0;
StateNo=1;
KeyValue=0;
KeyValueTemp=0;
Flag_Time=0;
}
void T0_Timer(void) interrupt 1
{
TH0=0xf8; //定时2毫秒高四位初值重装
TL0=0xcd; //定时2毫秒高四位初值重装
SXLed(i%8,SX[i%8]); //数码管扫描显示
i++;
if(!(i%5)) KeyScan(); //按键扫描
if(!(i%250)) //0.5秒到了
{
// P1=~P1; //指示灯0.5秒交替闪烁
Flag_05s=1; //0.5秒标志置1
Flag_1s=!Flag_1s; //1秒标志置取反
if(Flag_1s==0) //1秒到了
if(Flag_Change==1) //是否调时状态
_nop_(); //是,啥也不干
else
Time(); //否,时间变动
}
}
void KeyProcess(void)
{
switch (KeyValue)
{
case K2:
if(Flag_Change==1)
{
Flag_Time++;
if(Flag_Time==3)Flag_Time=0;
}
break;
case K3:
if(Flag_Change==1)
{
if(Flag_Time==0)
{
Hour++;
if(Hour==23)Hour=0;
}
if(Flag_Time==1)
{
Minute++;
if(Minute==59)Minute=0;
}
if(Flag_Time==2)
{
Second++;
if(Second==59)Second=0;
}
}
break;
case K4:
if(Flag_Change==1)
{
if(Flag_Time==0)
{
Hour--;
if(Hour==0)Hour=23;
}
if(Flag_Time==1)
{
Minute--;
if(Minute==0)Minute=59;
}
if(Flag_Time==2)
{
Second--;
if(Second==0)Second=59;
}
}
break;
case K5:
if(Flag_Change==0)
Flag_Change=1;
else
Flag_Change=0;
break;
default:
Flag_Change=0;
break;
}
}
void KeyScan(void)
{
P3=P3|0x0f;
if (StateNo==1)
{
if ((P3&0x0f)!=0x0f)
StateNo=2;
else
StateNo=1;
}
else if (StateNo==2)
{
if ((P3&0x0f)!=0x0f)
{
KeyValueTemp=P3&0x0f;
StateNo=3;
}
else
StateNo=1;
}
else if (StateNo==3)
{
if ((P3&0x0f)==0x0f)
{
KeyValue=KeyValueTemp;
StateNo=4;
}
else
{
;
}
}
else if (StateNo==4)
{
KeyProcess();
StateNo=1;
}
else
StateNo=1;
}
void Hex_BCD(void)
{
SX[0]=Second%10;
SX[1]=Second/10;
SX[2]=10;
SX[3]=Minute%10;
SX[4]=Minute/10;
SX[5]=10;
SX[6]=Hour%10;
SX[7]=Hour/10;
}
void Time(void)
{
Second++;
if (Second==60)
{
Second=0;
Minute++;
if(Minute==60)
{
Minute=0;
Hour++;
if(Hour==24)Hour=0;
}
}
}
void T0_Init(void)
{
TMOD|=0x01; //定时器T0工作在16位定时模式
EA=1; //开总中断
ET0=1; //开定时器中断
TR0=1; //启动定时器
TH0=0xf8; //定时2毫秒高四位初值重装
TL0=0xcd; //定时2毫秒高四位初值重装
}
void SXLed (unsigned char location,unsigned char Num)//location显示位置,num显示数字
{
SXLed_P=0xff; //消影
SXLed_W=1; //打开位选锁存器
SXLed_P=~(0x80>>location); //送位码
SXLed_W=0; //锁存位选数据
SXLed_D=1; //打开段选锁存器
SXLed_P=Number[Num]; //送段码
SXLed_D=0; //锁存段选数据
}
void Start_Screen(void) //开机显示画面
{
unsigned char k,j;
for (k=0;k<11;k++)
{
for (j=0;j<8;j++)
if(k==0)
SX[j]=10;
else
SX[j]=k-1;
Delay(1000);
}
}
void Delay(unsigned char ms) //@11.0592MHz延时
{
unsigned char data i, j;
while(ms--)
{
_nop_();
i = 2;
j = 198;
do
{
while (--j);
} while (--i);
}
}
复制代码
作者:
wulin
时间:
2023-10-25 21:01
void KeyProcess(void)
{
switch(KeyValue)
{
case K2:/* */break;
case K3:/* */break;
case K4:/* */break;
case K5:/* */break;
}
KeyValue=0x00;//键值用后要清0
}
void KeyScan(void)
{
P3=0x0f;
if(P3!=0x0f)
KeyValue=P3;
KeyProcess();
}
作者:
殿堂之上
时间:
2023-10-26 15:31
wulin 发表于 2023-10-25 21:01
void KeyProcess(void)
{
switch(KeyValue)
你这样就不是用状态机的方式了,我找到原因了,是值设置的不对,还有调时进去时默认改时。
case K3:
if(Flag_Change==1)
{
if(Flag_Time==0)
{
Hour++;
if(Hour==
24
)Hour=0;
}
if(Flag_Time==1)
{
Minute++;
if(Minute==
60
)Minute=0;
}
if(Flag_Time==2)
{
Second++;
if(Second==
60
)Second=0;
}
}
break;
case K4:
if(Flag_Change==1)
{
if(Flag_Time==0)
{
Hour--;
if(Hour==
255
)Hour=23;
}
if(Flag_Time==1)
{
Minute--;
if(Minute==
255
)Minute=59;
}
if(Flag_Time==2)
{
Second--;
if(Second==
255
)Second=59;
}
}
break;
case K5:
if(Flag_Change==0)
{
Flag_Change=1;
Flag_Time=0;
}
else
Flag_Change=0;
break;
、、、、、、、、、、、、、、、、、、、、、、、、、、、
作者:
圣博朗西斯
时间:
2023-10-27 09:27
大体看了一下你的代码框架,写8位机思路是对的,但是按键的处理是不建议放中段处理的,你中断定时到了后,在While大循环里去刷新按键进行消抖
keytemp=0;
if(pin_adkey==0) // adckeyvolt<=20
{
keytemp=1;
}
直接向上面给出键值而后对键值进行定时刷新
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1