矩阵按键
就是独立按键的重新组合。
注意此图中省略了上拉电阻,但实际电路中均含上拉电阻(上拉就是将不确定的信号通过一个电阻钳位在高电平,电阻同时起限流作用)
矩阵按键优点:节约IO口
矩阵按键原理
方法一:
逐行扫描:我们可以通过高四位轮流输出低电平来对矩阵键盘进行逐行扫描,当低四位接收到的数据不全为1的时候,说明有按键按下,然后通过接收到的数据是哪一位为0来判断是哪一个按键被按下。
方法二:
行列扫描:我们可以通过高四位全部输出低电平,低四位输出高电平。当接收到的数据,低四位不全为高电平时,说明有按键按下,然后通过接收的数据值,判断是哪一列有按键按下,然后再反过来,高四位输出高电平,低四位输出低电平,然后根据接收到的高四位的值判断是那一行有按键按下,这样就能够确定是哪一个按键按下了。
程序编写
1. #include "reg52.h" //此文件中定义了单片机的一些特殊功能寄存器
2.
3. typedef unsigned int u16; //对数据类型进行声明定义
4. typedef unsigned char u8;
5.
6. #define GPIO_DIG P0
7. #define GPIO_KEY P1
8.
9. sbit LSA=P2^2;
10. sbit LSB=P2^3;
11. sbit LSC=P2^4;
12.
13. u8 KeyValue; //用来存放读取到的键值
14.
15.
16. u8 code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
17. 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//显示0~F的值
18.
19. /*******************************************************************************
20. * 函 数 名 : delay
21. * 函数功能 : 延时函数,i=1时,大约延时10us
22. *******************************************************************************/
23. void delay(u16 i)
24. {
25. while(i--);
26. }
27.
28. /*******************************************************************************
29. * 函 数 名 : KeyDown
30. * 函数功能 : 检测有按键按下并读取键值
31. * 输 入 : 无
32. * 输 出 : 无
33. *******************************************************************************/
34. void KeyDown(void)
35. {
36. char a=0;
37. GPIO_KEY=0x0f;
38. if(GPIO_KEY!=0x0f)//读取按键是否按下
39. {
40. delay(1000);//延时10ms进行消抖
41. if(GPIO_KEY!=0x0f)//再次检测键盘是否按下
42. {
43. //测试列
44. GPIO_KEY=0X0F;
45. switch(GPIO_KEY)
46. {
47. case(0X07): KeyValue=0;break;
48. case(0X0b): KeyValue=1;break;
49. case(0X0d): KeyValue=2;break;
50. case(0X0e): KeyValue=3;break;
51. }
52. //测试行
53. GPIO_KEY=0XF0;
54. switch(GPIO_KEY)
55. {
56. case(0X70): KeyValue=KeyValue;break;
57. case(0Xb0): KeyValue=KeyValue+4;break;
58. case(0Xd0): KeyValue=KeyValue+8;break;
59. case(0Xe0): KeyValue=KeyValue+12;break;
60. }
61. while((a<50)&&(GPIO_KEY!=0xf0)) //检测按键松手检测
62. {
63. delay(1000);
64. a++;
65. }
66. }
67. }
68. }
69.
70.
71. /*******************************************************************************
72. * 函 数 名 : main
73. * 函数功能 : 主函数
74. * 输 入 : 无
75. * 输 出 : 无
76. *******************************************************************************/
77. void main()
78. {
79. LSA=0; //给一个数码管提供位选
80. LSB=0;
81. LSC=0;
82. while(1)
83. {
84. KeyDown(); //按键判断函数
85. GPIO_DIG=smgduan[KeyValue]; //
86. }
87. }
Scan为按键行列扫描函数
u8 KeyValue为按键返回值全局变量
8*8LED点阵
(原理如矩阵按键类似)
可以看到,阳极接到D0-D7,阴极接到P00-P07口,要让某个LED点亮,例如左上角第一个,只需让D7=1(高电平),D0-D6=0 。 P07=0(低电平),P00-P0^6=1即可(这里=0也可以,由于D0-D6=0,LED阳极方向低电平,电流总是不通)。 P0口可以直接控制,使P0=0x7f(0111 1111)即可
74HC595控制输出
1.595芯片只有一个输入口,即P34 I/O口,对应图中的SER,引脚号时14
2.P36,对应图中SRCLK,引脚号是11,它的作用是,每当它发生一次上升沿,则P34口的电平值会在位移寄存器中左移一位。当下一次上升沿发生时,移位寄存器的所有位都往左移一位。
3.P35,对应图中RCLK,引脚号12,当它发生一次上升沿,移位寄存器的值会输出到DA-DH(D0-D7),这里注意一下,D7是高位。
4.由于移位寄存器是一直往左移,那么第一个进入移位寄存器的就是最高位,所以,P34第一个值是高位
使用74HC595的优点是节省IO口,方便控制。
595芯片是通过P34,P35,P3^6进行输入输出。
同时一定要注意OE必须为低电平!!!!否则会出现整行整列全显示!!!!!!
程序编写(打印出CO)
ps:CO为我加入团队的名字
1. #include "reg51.h"
2. #include<intrins.h>
3.
4. typedef unsigned int u16;
5. typedef unsigned char u8;
6.
7. sbit SRCLK=P3^6;
8. sbit RCLK=P3^5;
9. sbit SER=P3^4;
10.
11. u8 ledduan[]={0x7e,0x81,0x81,0x00,0x7e,0x81,0x81,0x7e}; //段选
12. u8 ledwei[]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe}; //位选
13.
14. void delay(u16 i)
15. {
16. while(i--);
17. }
18.
19.
20. void Hc595SendByte(u8 dat)
21. {
22. u8 a;
23. SRCLK=0;
24. RCLK=0;
25. for(a=0;a<8;a++)
26. {
27. SER=dat>>7;
28. dat<<=1;
29.
30. SRCLK=1;
31. _nop_();
32. _nop_();
33. SRCLK=0;
34. }
35.
36. RCLK=1;
37. _nop_();
38. _nop_();
39. RCLK=0;
40. }
41.
42.
43. void main()
44. {
45. u8 i;
46. while(1)
47. {
48. P0=0x7f;
49. for(i=0;i<8;i++)
50. {
51. P0=ledwei[i];
52. Hc595SendByte(ledduan[i]);
53. delay(100);
54. Hc595SendByte(0x00);
55. }
56. }
57. }