|
介绍什么是矩阵键盘 矩阵键盘是单片机外部设备中所使用的排布类似于矩阵的键盘组,由于电路设计时需要更多的外部输入,单独的控制一个按键需要浪费很多的IO资源,所以就有了矩阵键盘,常用的矩阵键盘有4X4和8X8,其中用的最多的是4X4。
b0 ?, ]% R& i, ?& C矩阵键盘的原理矩阵键盘又称为行列式键盘,它是用4条I/O线作为行线,4条I/O线作为列线组成的键盘。
. d; z) P4 h5 F0 U在行线和列线的每一个交叉点上,设置一个按键。这样键盘中按键的个数是4×4个。1 z8 p: r. x4 `( e4 A# r
这种行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。由于单片机IO端口具有线与的功能,因此当任意一个按键按下时,行和列都有一根线被线与,通过运算就可以得出按键的坐标从而判断按键键值。
/ b. ~( C8 g3 ]原理如同矩阵数列的行列式。 8 s4 W2 o2 @# ~$ h$ D; ?7 G
9 |7 b" n% ^6 [) e4 w, ` 驱动电路图按4*4矩阵搭建的按键矩阵还是比较简单的,也有的人为了保证电路的稳定性,加上二极管保护和上拉电阻,但是一般要求不太高的电路就不需要加了,向下面设置的电路那样就可以了。 ' O) g# V6 D" |, B: `
1 X" w- O4 b( ?4 s4 s" u3 Z 软件程序实现在这里宏定义一些GPIO的信息。 KEY.h - #ifndef _KEY_H: V+ g1 l* x! j. p: `2 W
- #define _KEY_H' ~/ ?5 i; u& F
- #include "stm32f10x.h"* q$ I$ y$ H% {5 h
- //引脚% _9 h" |6 p P) Q' S6 e: C
- #define S0 GPIO_Pin_0
2 @; k. b' ?; k8 c% K; J& c/ X - #define S1 GPIO_Pin_1( ^ g( i7 G4 \5 P
- #define S2 GPIO_Pin_2
- B R1 A4 e( z" | - #define S3 GPIO_Pin_3
: u: }) \, x- y/ P - #define S4 GPIO_Pin_4
# E% n" U; \$ Y9 H' G - #define S5 GPIO_Pin_5& m9 E+ z5 ~3 x7 Z& p: ]
- #define S6 GPIO_Pin_6" D' o# s- P1 D0 V
- #define S7 GPIO_Pin_7" r* K4 o2 \. ~# g0 T; [( e6 K
- //GPIO寄存器( o% E1 `9 C3 Z- F, m; V
- #define KEY_PORT GPIOB
$ ]2 N" e5 S! a0 o1 @ - //时钟% A' e. a% }/ b' q: d) M8 ]
- #define RCC_APB2_KEY RCC_APB2Periph_GPIOB
$ D, e7 A: B& Y! H9 a; j% l - //函数定义
u7 I" t4 _# P) T) O6 I0 M - void InitKey(void);3 J- p7 ^, X: m( E$ p0 a$ K: g
- int NumKey(void);
2 z+ B! f, ^# V0 k0 ^ - //延时+ U) V" E4 z: b5 S L
- void Delay( uint32_t count )2 a. b6 t9 g5 G+ |; f0 ]' Y
- {
+ o! Z) e# u6 a+ F! ] - for(; count!=0; count--);# ?( f+ Z C7 ?
- }
N2 J& d$ C8 t" }- C. w" P% C - #endif /* _KEY_H */
复制代码 ( g7 }! O p* E0 p% D" i
在这里存放两个函数,一个是初始化矩形键盘GPIO口的函数,在函数里把前四个定义为推挽输出,后四个GPIO口定义为下拉输入。
" x" i0 t1 d% R0 r& o& s另一个函数是键盘扫描函数,通过函数返回值确定是举行键盘的哪一个按键被按下。
0 p/ f4 B1 P) k) v3 g' C
KEY.c - #include "KEY.h"! \" K2 U8 O" U. h4 L
- void InitKey(void)//初始化KEY的GPIO2 \' y1 ~: j( g
- {# g; s- R1 D& [# G$ R6 c2 b
- //打开GPIO时钟
2 R: n M, e5 _5 v- a0 }1 B* R - RCC_APB2PeriphClockCmd(RCC_APB2_KEY,ENABLE);
# e- O( }% s3 X2 t% Y - //把S0,S1,S2,S3配置为推挽输出2 v! d! r9 S2 A$ V- v
- GPIO_InitTypeDef GPIOInit;* M1 g, J" ~! ]$ r. ~; W
- GPIOInit.GPIO_Mode=GPIO_Mode_Out_PP;//推挽输出
) M5 i/ |" e6 M( N1 m* c - GPIOInit.GPIO_Speed=GPIO_Speed_50MHz;
( L8 Y5 N" }9 V% k - GPIOInit.GPIO_Pin=S0|S1|S2|S3;
0 Q: O7 j* Q0 K4 }9 M- l2 d0 o) H/ F - GPIO_Init(KEY_PORT,&GPIOInit);
- S' L; d9 v8 K6 y& c -
y# G6 m9 ?0 R" s: c& e - //把S4,S5,S6,S7配置为下拉输入7 i+ _% L9 y! G" v r# q( ^4 v: R
- GPIOInit.GPIO_Mode=GPIO_Mode_IPU;9 X) R) P$ w; o! I: H
- GPIOInit.GPIO_Pin=S4|S5|S6|S7;9 E. H% b+ a) E. A' F: n$ W
- GPIO_Init(KEY_PORT,&GPIOInit); 3 s% f" \0 v: S% V
-
$ o, h; q8 p$ u( F6 I3 Q9 o - //0--3输出高,4--7输出低
8 K0 E) J6 W7 Y P: N. k1 ? - GPIO_SetBits(GPIOC,GPIO_Pin_0|GPIO_Pin_1|GPIO_Pin_2|GPIO_Pin_3);* D1 @$ `7 y% Z1 m0 K, A
- GPIO_ResetBits(GPIOC,GPIO_Pin_4|GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7);
% c: }8 R. ]$ u - ) X6 ~7 E+ A; X$ f# D( Q
- }
# c( b5 x$ p, @& ]$ ~# B: k$ B- k - int NumKey(void) //扫描键值
1 E. g: |5 h) @* W - {
7 a8 h7 K/ B$ I( ^9 ]) T8 v7 u - int KeyVal=0; //键值,后面自己设定的,用来设置按键的序号
. u6 A* Z' p+ r& n$ r4 f - u16 KeyWrite=0; //写给GPIO的值 & g, L2 M2 F D: T. L9 G
- GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0 | 0xf));//0--3全部输出高
) |- ^9 ` _+ d5 t! Y Z - if((KEY_PORT->IDR&0x00f0)==0x0000) //如果4--7全为0,表示没有按键按下,返回值设置为-1
3 c' c3 J. B9 P W T0 Z5 X5 C# h$ g0 C - return -1;. {/ H2 o" t& Y
- 4 S6 U0 V8 G5 G4 O% ?& [
- else
8 _6 Q0 F' i' f b1 _ - {
! r+ l2 i5 L" P" R/ H - Delay(0xF);//消抖
0 x% q; E5 ~" p7 E/ S4 p - if((KEY_PORT->IDR&0x00f0)==0x0000) //如果4-7全为0,表示刚才是抖动造成的
8 g* w, z0 W$ S' S3 r( o& C0 ^8 e - return -1; : f# v+ {$ h1 s
- }( Q7 i. ^6 }* i$ N# J. N7 f
- GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x1));//让0-3输出0001
B/ E( a2 d+ s2 G& ]; i - ; l* P7 ~/ i4 b1 ~6 _" X$ I
- switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
1 i& ^5 K( t7 ~8 u - {4 H/ ]* O- s% `: ]4 D1 C
- case 0x0010: KeyVal=16;break;
# f! o! d! a6 d% N' e - case 0x0020: KeyVal=12;break;
6 M; H) X3 y- _ - case 0x0040: KeyVal=8; break;
& G4 j# C& [; f1 ] - case 0x0080: KeyVal=4; break; 3 E3 J' v+ S% |6 `1 [7 h# F+ Y; o B
- }
% A/ \; q0 B7 P) |3 | -
- D% C. k, \! [) h+ ~8 q# K - GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x2));//让0-3输出0010
" D9 Q+ d% G W( m+ i - switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
" m$ x F; e# \. B - {
7 A3 h$ m) h# ` M - case 0x0010: KeyVal=15;break;
, j, a+ E; G2 d, k) l - case 0x0020: KeyVal=11;break;
. W4 _- ?4 y8 b: k - case 0x0040: KeyVal=7; break;# K! d' r+ V; H5 a. s
- case 0x0080: KeyVal=3; break;
. }' b$ P* d, N0 m' O" r- h+ h - }
9 Z/ t O- D/ G& H! H8 O9 G5 V - GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x4));//让0-3输出0100
3 K7 _2 c. ?; k& X2 A - switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断$ E- i @- v# [& O! C. [
- {
# _1 k: a! z2 w - case 0x0010: KeyVal=14;break;
9 a; w% F4 r: [" q2 e - case 0x0020: KeyVal=10;break;6 v& D! f3 w0 s. L% @; h: h d
- case 0x0040: KeyVal=6; break;
, x7 i6 u! E$ h- V( \$ m - case 0x0080: KeyVal=2; break; 1 @$ w/ ?: L4 U) v4 v
- }$ C# D% b" Z) E
- GPIO_Write(KEY_PORT,(KEY_PORT->ODR & 0xfff0|0x8));//让0-3输出1000! l; m1 i2 U; E- ]# I
- switch(KEY_PORT->IDR&0x00f0)//对4--7进行判断
# e1 Q$ _& S* p$ @8 e" T - {
0 L0 m! |7 U! v - case 0x0010: KeyVal=13;break;# q- ~6 K9 q) t, n
- case 0x0020: KeyVal=9;break;
! ?7 W7 i- `/ b5 T9 ^8 _+ F8 n - case 0x0040: KeyVal=5; break;$ `4 U* |) E* H+ o8 b- b3 b& N
- case 0x0080: KeyVal=1; break;
3 z- L' N y- x, E2 \ v - }
0 Q* \, }5 G# F; R - return KeyVal;
' ^, Z$ p$ X+ D% U2 p# N/ ] - }
复制代码 1 b$ ~6 b2 d( e; }0 }% ]
& p0 J7 R% N/ L6 h' @
转载自: 跋扈洋
) D$ C4 [ R2 k! i+ C |