单片机型号说明:IAP15F2K61S2
新建工程时单片机型号选择STC15F2K60S2
键盘的分类
- 键盘分编码键盘和非编码键盘。键盘上闭合件的识别由专用的硬件编码器实现,并产生键编码号或者键值的成为编码键盘,如计算机键盘,而靠软件变成来识别的称为非编码键盘。
- 在单片机组成的各种系统中,用的最多的是非编码键盘,也有用到编码键盘的。
- 非编码键盘又分为:独立键盘和行列式(又称矩阵式)键盘。
- 键盘在单片机中是很好的人机交互工具
按键选择
蓝桥杯单片机开发板按键选择
左下角,按键旁边的跳线帽(位号J5)接到右边,是独立按键,四个独立按键是第一列,PCB丝印层框选出的部分
跳线帽(位号J5)接到左边,是矩阵按键
按键抖动
按键在闭合和断开是,触点会存在抖动现象:
参考51单片机中独立按键的写法
先用最原始的方法写个按键检测
按键按下,对应LED亮起,松手即灭
1. #include <STC15F2K60S2.H> 2. 3. void Delay_ms(int xms) //15单片机 4. { 5. int i; 6. long a; 7. for (i = xms; i > 0; i --) 8. for(a = 810; a > 0; a --); 9. } 10. 11. void anjian(void) 12. { 13. unsigned char a; 14. if(P30 == 0) 15. { 16. Delay_ms(10); 17. if(P30 == 0) 18. { 19. P00 = 0; 20. } 21. } 22. else 23. P00 = 1; 24. 25. if(P31 == 0) 26. { 27. Delay_ms(10); 28. if(P31 == 0) 29. { 30. P01 = 0; //按键点灯 31. } 32. } 33. else 34. P01 = 1; 35. } 36. 37. void main() 38. { 39. P2 = 0xA0; P0 = 0x00; P2 = 0x80; P0 = 0xFF; //初始化 40. while(1) 41. { 42. anjian(); 43. } 44. }
完善按键:松手检测 +while循环等待
1. #include <STC15F2K60S2.H> 2. 3. unsigned char num = 0; 4. 5. void Delay_ms(int xms) //15单片机 6. { 7. int i; 8. long a; 9. for (i = xms; i > 0; i --) 10. for(a = 810; a > 0; a --); 11. } 12. 13. void anjian(void) 14. { 15. 16. if(P30 == 0) 17. { 18. Delay_ms(10); //消抖延时 19. if(P30 == 0) 20. { 21. num++; 22. P0 = ~num; //按键显示二进制 23. } 24. while(!P30); //按住就卡在这,松手跳出函数 25. } 26. else 27. P00 = 1; 28. 29. // if(P31 == 0) 30. // { 31. // Delay_ms(10); 32. // if(P31 == 0) 33. // { 34. // P01 = 0; //按键点灯 35. // } 36. // while(P31 == 0); //按住就卡在这 37. // } 38. // else 39. // P01 = 1; 40. 41. } 42. 43. void main() 44. { 45. P2 = 0xA0; P0 = 0x00; P2 = 0x80; P0 = 0xFF; //初始化 46. while(1) 47. { 48. anjian(); 49. } 50. }
独立按键控制8个LED实现二进制显示
上面这段程序是用按键显示二进制,但是上面的程序,15单片机的L1不能保持常亮起,只有按下的时候亮,不知道代码哪里出了bug
而且将控制函数写在了按键函数了,这样不美观,写项目的时候会更乱,所以把按键用函数封装一下
1. unsigned char Duli_Anjian(void) 2. { 3. unsigned char Keynumber = 0; 4. if(P30 == 0) {Delay_ms(20); while(P30 == 0); Delay_ms(20); Keynumber = 7;} 5. if(P31 == 0) {Delay_ms(20); while(P31 == 0); Delay_ms(20); Keynumber = 6;} 6. if(P32 == 0) {Delay_ms(20); while(P32 == 0); Delay_ms(20); Keynumber = 5;} 7. if(P33 == 0) {Delay_ms(20); while(P33 == 0); Delay_ms(20); Keynumber = 4;} 8. return Keynumber; 9. }
思路:置标志位Keynumber,将这个变量作为返回值返回出去,放在while(1)里循环检测
显示二进制的程序
二进制对应的LED状态
0x01 = 0000 0001 = 灭灭灭灭 灭灭灭亮
0x02 = 0000 0010 = 灭灭灭灭 灭灭亮灭
0x03 = 0000 0011 = 灭灭灭灭 灭灭亮亮
……
0xFF = 1111 1111 = 亮亮亮亮 亮亮亮亮
二进制表示形式中,“1”代表亮起,让LED亮起来模拟二进制的效果
但是LED是低电平驱动,给0是亮,所以赋值的时候,直接取反再赋值给P0端口,就可以了
按键7按下num+1,按键6按下num-1
将按键封装好,重写显示二进制的代码
1. #include <STC15F2K60S2.H> 2. 3. unsigned char Keynum; 4. unsigned char num = 0; 5. 6. void Delay_ms(int xms) //15单片机延时函数 7. { 8. int i; 9. long a; 10. for (i = xms; i > 0; i --) 11. for(a = 810; a > 0; a --); 12. } 13. 14. unsigned char Duli_Anjian(void) 15. { 16. unsigned char Keynumber = 0; 17. if(P30 == 0) {Delay_ms(20); while(P30 == 0); Delay_ms(20); Keynumber = 7;} 18. if(P31 == 0) {Delay_ms(20); while(P31 == 0); Delay_ms(20); Keynumber = 6;} 19. if(P32 == 0) {Delay_ms(20); while(P32 == 0); Delay_ms(20); Keynumber = 5;} 20. if(P33 == 0) {Delay_ms(20); while(P33 == 0); Delay_ms(20); Keynumber = 4;} 21. return Keynumber; 22. } 23. 24. void main() 25. { 26. P2 = 0xA0; P0 = 0x00; P2 = 0x80; P0 = 0xFF; //初始化 27. while(1) 28. { 29. Keynum = Duli_Anjian(); //调用按键检测函数 30. if(Keynum == 7) //第一个按键 31. { 32. num++; //实现二进制加法 33. P0 = ~num; 34. } 35. else if(Keynum == 6) //第二个按键 36. { 37. num--; //减法 38. P0 = ~num; 39. } 40. } 41. } 42.
烧录程序,用按键7和按键6实际操作,这次将上面的bug解决了
Keynum = Duli_Anjian(); //调用按键检测函数
if (Keynum == 7) { ... }
else if (Keynum == 6) { ... }
else if (Keynum == 5) { ... }
else if (Keynum == 4) { ... }
主程序不断检测按键数值
如果是**按键按下,就执行**操作了,主程序清晰明了~
用if ...... else if ......结构,程序运行速率更高
假设按下按键7,就不用判断按键6,但是这样的代码,一次只能检测一个按键键码,不能检测两个按键同时按下,有利有弊,根据实际需求修改代码
后续会研究用少量按键实现多个功能,比如两个按键同时按下,长按短按,双击三击,
之前在玩51单片机鼓捣过按键的长按短按