标题:
基于状态机的单个按键长按,短按实现复用
[打印本页]
作者:
hmf
时间:
2017-4-11 11:23
标题:
基于状态机的单个按键长按,短按实现复用
开博第一文。希望再次记录学习的过程。
按
键扫描,单片机里面再基础不过的程序了。但对于初学者来说,用好按键也不是一件简单的事情。在毛老师的介绍下,第一次知道了状态机的思想也可以用于单片机的程序设计,感觉很是新奇。看了老师给发的几个文档后对状态机编程的概念有了一些初步的认识,于是试着用状态机的思想写了一个实现单个按键长按短按的小程序。
贴个代码试试....
//文件名:单个按键的复用
//作者:CWM
//修改日期:2011-06-15
//版本:V1.0
//功能描述:基于状态机的思想 实现单个按键的复用
//根据按键持续时间的不同,在数码管上分别显示0 1 2 3四个数字
001
#include <reg52.h>
002
003
#define key_state_0 0
//表示没有按下
004
#define key_state_1 1
//表示按键按下
005
#define key_state_2 2
//计时1
006
#define key_state_3 3
//计时2
007
#define key_state_4 4
//计时3
008
sbit
KEY
=
P1
^
0
;
009
sbit
LED
=
P1
^
1
;
010
unsigned
char
code
LED7Code
[]
=
{
~
0x3F
,
~
0x06
,
~
0x5B
,
~
0x4F
,
011
~
0x66
,
~
0x6D
,
~
0x7D
,
~
0x07
,
~
0x7F
,
~
0x6F
,
012
~
0x77
,
~
0x7C
,
~
0x39
,
~
0x5E
,
~
0x79
,
~
0x71
};
//数码管码值表
013
014
int
key_stime_counter
,
time_counter
;
//中断计时用
015
bit
time_1s_ok
,
key_stime_ok
;
//时间标志
016
017
void
system_Ini
()
018
{
019
TMOD
|=
0x00
;
020
TH1
=
0x1c
;
//12.000M
021
TL1
=
0x18
;
//定时器1工作在方式0下 定时1ms
022
IE
=
0x8A
;
023
TR1
=
1
;
024
}
025
026
char
read_key
()
027
{
028
static
char
key_state
=
0
,
key_time
=
0
;
029
static
char
key_press
,
key_return
=
0
;
030
031
key_press
=
KEY
;
032
switch
(
key_state
)
033
{
034
case
key_state_0
:
//无按键按下
035
if
(
!
key_press
)
key_state
=
key_state_1
;
036
break
;
037
case
key_state_1
:
//有按键按下
038
if
(
!
key_press
)
039
{
040
key_state
=
key_state_2
;
041
key_time
=
0
;
042
}
043
else
044
{
045
key_state
=
key_state_0
;
046
//key_return=0;
047
}
048
break
;
049
case
key_state_2
:
//计时1
050
if
(
key_press
)
//按键松开
051
{
052
key_state
=
key_state_0
;
053
}
055
else
if
(
++
key_time
>=
10
)
056
{
057
key_state
=
key_state_3
;
//计时满一秒
058
key_time
=
0
;
059
key_return
=
1
;
//输出1 数码管显示1
060
}
061
break
;
062
case
key_state_3
:
//计时2
063
if
(
key_press
)
//按键松开
064
{
065
key_state
=
key_state_2
;
//此时按键已经持续了一秒了 故数码管仍然显示1
066
//key_return=1;
067
}
068
else
if
(
++
key_time
>=
10
)
069
{
070
key_state
=
key_state_4
;
//此时已经按键持续超过2秒
071
key_time
=
0
;
072
key_return
=
2
;
//数码管显示2
073
}
074
break
;
075
case
key_state_4
:
076
if
(
key_press
)
077
{
078
key_state
=
key_state_3
;
//此时按键已经持续了二秒了 故数码管仍然显示2
079
//key_return=2;
080
}
081
else
if
(
++
key_time
>=
10
)
082
{
083
key_state
=
key_state_0
;
//按键松开
084
key_time
=
0
;
085
key_return
=
3
;
//数码管显示3
086
}
087
break
;
088
}
089
return
key_return
;
090
}
091
092
093
void
main
()
094
{
095
int
result
;
096
system_Ini
();
097
while
(
1
)
098
{
099
if
(
key_stime_ok
)
100
{
101
key_stime_ok
=
0
;
102
switch
(
read_key
())
103
{
104
case
0
:
105
P0
=
LED7Code
[
0
&
0x7f
;
//无按键或者按键时间少于1s 显示0
106
break
;
107
case
1
:
108
P0
=
LED7Code
[
1
&
0x7f
;
//按键时间大于1s 显示1
109
break
;
110
case
2
:
111
P0
=
LED7Code
[
2
&
0x7f
;
//按键时间大于2s 显示2
112
break
;
113
case
3
:
114
P0
=
LED7Code
[
3
&
0x7f
;
//按键时间大于3s 显示3
115
break
;
116
default:
break
;
117
118
}
119
}
120
}
121
122
}
123
124
void
Timer1
(
void
)
interrupt
3
125
{
126
127
TH1
=
0x1c
;
//12.000
128
TL1
=
0x18
;
129
if
(
++
key_stime_counter
>=
10
)
//到达10ms
130
{
131
key_stime_counter
=
0
;
132
key_stime_ok
=
1
;
133
134
}
135
}
比较凌乱的说...
只是作为一个学习过程的记录吧!没什么技术含量。
作者:
ryang
时间:
2017-7-29 10:58
谢谢楼主的分享
作者:
yinds5092
时间:
2021-12-12 17:14
51hei有你更精彩
欢迎光临 (http://www.51hei.com/bbs/)
Powered by Discuz! X3.1