|
STM32 按键输入 |V1.0.0 LED灯的程序已经差不多了,咱们接下来可以写写别的一些东西了,比如按键的采集。 说到这个按键输入呀,我一直觉得挺难做的。实际运用的时候,真的比学的时候难多了。 大家想想呀,按键,有单击,双击,甚至三击,多击。单击,又分短按,长按。 其中,除了单击,其他的都需要计算时间,双击的间隔多少时间才合适,短按和长按的时间也需要考虑。细想起来,这个按键采集真的不是简单的事。 今天呢,就从简单的单击开始设计。 一个键的单击功能,我想大家基本也知道该怎么写,就是读IO口的电平,IO有信号了,就处理相应的程序。 IO初始化时,我们需要将IO口的模式设置为输入模式,并需要定时去读取该IO的信号。 同样的,咱们依然用正点原子的硬件,这次咱们只用一个按键。 按键的硬件 按键挂载的IO口 从硬件上就知道,按键按下,IO口就是低电平,由于外部电路没有上拉电阻,我们要把IO口模式设为上拉输入。 - //按键初始化函数
3 ]' _7 \% u8 u" R% c7 F8 \6 n' ^ - void KEY_Init(void) //IO初始化- N3 ^ D' N5 {2 @
- {
2 x* K! `0 B. y0 A$ j - GPIO_InitTypeDef GPIO_InitStructure;
$ ~$ A3 d& ]1 X5 T+ { - / b# y2 V2 ^# H) Y& `6 X& g! P
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);//使能PORTE时钟% z2 [+ E! ]( l
9 w) N: {7 O. P4 t6 r- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;//KEY04 ~- A# p5 ^0 P$ I
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //设置成上拉输入# H: ~: \# L' ~ [* W) I$ a- L
- GPIO_Init(GPIOE, &GPIO_InitStructure);//初始化GPIOE4
" ? v( V$ Y+ z, o5 B* k3 w - }
复制代码 & f0 ]$ A7 K+ r/ x' v7 n$ c6 S
还有,读取IO的值,有信号输入时,输出1, - /** @brief 读键值
4 u4 Y4 m, K H( s - * @param[in] 无
; K* @! \# `% x. ?% K0 V1 J. i - * @param[out] 无# {6 }0 }* ]$ V, P( {2 M- R
- * @retval 类型
( Q( e" H& j4 r4 `& w - * @note 10ms
& @; P9 ?, _# s% E: Q - */5 v' s4 y: R; h8 C2 c
- u8 sKEY_GetValue(void)
$ g: C# }, _+ `+ J! G: N) R1 S* N2 D - {' h0 H4 k( \; T2 r
- u8 data = 0; 2 Q. }% m# b& a2 u+ p- e& ?/ A
- + z6 O1 m2 w9 {' U
- if(KEY0 == 0)" i1 d' o4 V) M4 Y4 r9 A7 o
- data |= 0x01;& S( m0 g/ U" [6 U. H
- return data;9 h- R& |$ a+ C- }
- }
复制代码
+ I; x* f5 z- K" o( v* l* f2 {) f 然后,咱们设置一个循环函数,按一下按键,切换一次LED的模式。 我们把这个函数放在10ms的循环里,这样,就相当于每10ms读一次IO口的值,可以不需要延时来防抖。 - /** @brief KEY循环
: g1 ?/ O6 q: Y- }. Y - * @param[in] 无; ^8 |$ B$ Z3 U7 t! q
- * @param[out] 无) I" M: _1 T. m. ^/ e$ {, A9 g
- * @retval 类型; v6 u3 c$ t+ k. I$ m
- * @note 10ms
# S- [1 v+ E0 C/ j- J0 W# q - */
! L! e: V" H5 | o8 H4 {4 l' m - void sKEY_Loop(void)
1 w* a7 A( a2 A/ Y* [8 B2 a D - {
, }8 g/ v8 s0 u8 a9 D. h - static u8 LastValue;7 t0 u) [" e- I# }# s; k
- static u8 LedType = 0;# R7 r# y* U8 O/ e+ b. \; n
-
$ [2 \. W6 l, ], L( s8 T4 X - if( sKEY_GetValue() & 0x01 )( I' B* }1 @3 z- S2 [! @
- {0 }* v& \6 t2 e! Q4 O
- if(LastValue == 0): [( n* O U+ b% `0 O$ L* ]: z
- {
1 O& g0 C8 Q# v$ G8 E! W& z8 K2 _ - LastValue = 1;' v2 n2 B$ X$ s% F& w
-
E: ~7 e8 v$ ]5 P" ~ - LedType = (LedType +1) % 3;
; O* a- p1 J4 B+ u K - sLED_SetType(LedType);. `# Z$ B& t, G' L6 L* n
- }
& u3 P; f1 W% t6 ?( _& m4 E - }# Y, g: V3 z6 g, j/ n
- else2 k& w/ L0 t2 }( y5 B' f8 \
- LastValue = 0;& C& A$ J8 v# K( i c
- }
复制代码
1 D1 Q/ p. F: z- } k3 W8 h1 B/ F 当然,主函数也是要做相应的修改的,加入KEY的初始化函数,以及KEY的循环函数。 我们先设置LED使能,并设置LED的故障码为5。然后开始执行程序。 - int main(void)/ [6 [) [: h( ^/ _) b
- {
. A. F7 u5 i# P - delay_init(); //延时函数初始化 ' B( g, x( `2 N; \
- NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); //设置NVIC中断分组2:2位抢占优先级,2位响应优先级
6 S, S$ t; z* ~7 ]/ O. i& ?6 e - LED_Init(); //LED端口初始化
( [& |% A' y7 A& I, n - KEY_Init();+ O( b/ i) u3 a6 P
- TIM3_Int_Init(99,7199); //10Khz的计数频率,计数到100为10ms; j' X% k4 i9 B* A' ]
-
& w3 f# Q9 V# B( f; X4 O- ]! m- c
$ z- S# ~' L" [$ |" x6 _-
3 I8 g( z! q0 A: I+ Q/ v( g+ H - while(1)
) p, H: @- q. c" h: X! E - { x- N: S. |2 Z& d
- sLED_Enable(ENABLE);2 U/ y4 f: |6 z% N0 |
- sLED_SetErrNum(5);
0 g" @8 O2 z& L6 X4 e -
3 Z1 p9 t# X9 \" v; d- ]& j$ h - if(GetTimerFlag()) //10ms
& r. }( D4 @9 a, ~* y9 j - {
7 I% L4 a. k% [" x' @! p* J - sLED_Loop();7 i3 E5 d5 r. k6 I2 h( \
- sKEY_Loop();
( C w9 J, r8 Y, G) Y - }
9 M- G, b7 j+ M - }
# L% u/ l3 u/ F* O - }
复制代码 + ^* y9 i. h" o7 C8 T/ s; l
这样就可以了。 今晚就不放视频了,先到这里,明天见。 文章出处: Yue無缺
/ ?7 @2 X: s5 t |