当前位置:   article > 正文

蓝桥杯模块学习6——矩阵键盘(深夜学习——单片机)_蓝桥杯单片机矩阵键盘

蓝桥杯单片机矩阵键盘

目录

一、硬件部分:

1、原理图:

 二、矩阵键盘:

1、代码思路:

2、参考代码:

(1)宏定义:


一、硬件部分:

1、原理图:

(1)由独立按键的文章我们可以知道J5要接1、2,电路才会变成矩阵键盘电路

(2)如果学过矩阵的人应该都知道,矩阵中的位置是由行列标号决定,所以我们确定按下按键的行列就能确定按下哪个按键,这时候我们就要用到按键扫描

(3)按键扫描:我们的思路是,按键是连接行和列的桥梁,如果往某行或者某列输入低电平,其他行或列为高电平,我们只需要检测所有列或者行是否有低电平即可。

 二、矩阵键盘

        实现功能:用16个按键控制数码管第一个显示0-F

1、代码思路:

        通过观察可以发现通过P30-P33有利于保存数据,所以我们往每列逐次输入低电平,检测行并记录数据。

2、参考代码:

(1)宏定义

  1. #ifndef _PUBLIC_H
  2. #define _PUBLIC_H
  3. #include "STC15F2K60S2.H"
  4. #define u8 unsigned char
  5. #define u16 unsigned int
  6. void Delay_1ms(u16 num);
  7. void Close_All(void);
  8. void Delay_10us(u16 num);
  9. #endif
  1. #include "Public.h"
  2. // 延时函数(最小约1ms@12MHz)
  3. void Delay_1ms(u16 num)
  4. {
  5. unsigned int i;
  6. while(num--)
  7. for(i=0; i<628; i++);
  8. }
  9. /*
  10. 输入变量:无
  11. 输出变量:无
  12. 功能:关闭蜂鸣器和继电器
  13. */
  14. void Close_All(void)
  15. {
  16. //关闭蜂鸣器和继电器
  17. P0 = 0x00;
  18. P2 = (P2 & 0x1f) | 0xA0;
  19. P2 &= 0x1f;
  20. //关闭LED灯
  21. P0 = 0xff;
  22. P2 = (P2 & 0x1F) | 0x80;
  23. P2 &= 0x1f;
  24. }
  25. void Delay_10us(u16 num)
  26. {
  27. u16 i;
  28. while(num--)
  29. for(i=0; i<3; i++);
  30. }

(2)主函数:

  1. // 使用程序前,将J13调整为IO模式(2-3脚短接)
  2. #include "Public.h"
  3. u8 M_Buttun();
  4. //定义一个数组存放从1-f对应的16进制数
  5. //code 关键字的作用是我定义的数据要存放到ROM区,写入后不可以被改变
  6. u8 code transistor_positive[]=
  7. {
  8. 0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,
  9. 0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e
  10. };
  11. //带小数点
  12. u8 code transistor_positive_point[]=
  13. {
  14. 0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,
  15. 0x00,0x10,0x08,0x03,0x46,0x21,0x06,0x0e
  16. };
  17. void Transistor_Show(u8 num,u16 PIS);
  18. // 主函数
  19. void main(void)
  20. {
  21. u8 temp;
  22. Close_All();
  23. while(1)
  24. {
  25. temp = M_Buttun();
  26. if(temp)
  27. {
  28. Transistor_Show(transistor_positive[temp-4],0x01);
  29. }
  30. }
  31. }
  32. /*
  33. 输入变量:无
  34. 输出变量:检测到的按键,如果返回0代表没有检测到任何按键按下
  35. 功能:矩阵键盘按键检测
  36. */
  37. u8 M_Buttun()
  38. {
  39. u16 temp=0;
  40. // u8 i,j;
  41. u8 i;
  42. u16 sign = 0x8000;
  43. //往每行中输入低电平
  44. //L1:P44 L2:P42 L1:P44 L3:P35 L4:P34
  45. P44=0;P42=1;P35=1;P34=1;//第一列
  46. temp = temp | (P3&0x0f);//只保存低四位数据
  47. P44=1;P42=0;P35=1;P34=1;//第二列
  48. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  49. P44=1;P42=1;P35=0;P34=1;//第三列
  50. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  51. P44=1;P42=1;P35=1;P34=0;//第四列
  52. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  53. for(i=0;i<16;i++)
  54. {
  55. if((~temp) == (sign>>i))//从最高位检测到最低位
  56. return i+4;
  57. }
  58. return 0;
  59. }
  60. /*
  61. 输入变量:num,显示数字;PIS,显示位置
  62. 输出变量:无
  63. 功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用
  64. 注意:需要把存放从1-f对应的16进制数数组也移植
  65. */
  66. void Transistor_Show(u8 num,u16 PIS)
  67. {
  68. //改变数据
  69. P0 = num;
  70. P2 = (P2 & 0x1f) | 0xE0;
  71. P2 &= 0x1f;
  72. //改变显示位置
  73. P0 = PIS;
  74. P2 = (P2 & 0x1f) | 0xC0;
  75. P2 &= 0x1f;
  76. }

更新:经过定时器的学习和小工程的尝试后,由于单线程的缺点,我们不得不利用定时器把不同的任务在不同时间完成,来实现多线程

(3)主函数(优化):

  1. // 使用程序前,将J13调整为IO模式(2-3脚短接)
  2. #include "Public.h"
  3. #include "stdio.h"
  4. u8 SEG_COT[9];
  5. u8 SEG_Code[8];
  6. u8 temp1;
  7. u8 key_old,SEG_POS,key_delay,seg_delay;
  8. void Key_Proc();
  9. void Timer_0_Init(u16 time);
  10. void SEG_TSL(u8 *input,u8 *output);
  11. void SEG_Proc();
  12. // 主函数
  13. void main(void)
  14. {
  15. Close_All();
  16. Timer_0_Init(1000);//1ms
  17. while(1)
  18. {
  19. Key_Proc();
  20. SEG_Proc();
  21. }
  22. }
  23. /********************数码管********************************/
  24. /*
  25. 输入变量:input,输入字符数组;output:输出16进制数数组
  26. 输出变量:无
  27. 功能:将字符串转化为对应数码管显示的16进制数
  28. */
  29. void SEG_TSL(u8 *input,u8 *output)
  30. {
  31. //j一定要赋值
  32. u8 i=0,temp=0,j=0;
  33. for(i=0;i<8;i++,j++)
  34. {
  35. switch(input[j])
  36. {
  37. case '0': temp = 0xc0; break;
  38. case '1': temp = 0xf9; break;
  39. case '2': temp = 0xa4; break;
  40. case '3': temp = 0xb0; break;
  41. case '4': temp = 0x99; break;
  42. case '5': temp = 0x92; break;
  43. case '6': temp = 0x82; break;
  44. case '7': temp = 0xf8; break;
  45. case '8': temp = 0x80; break;
  46. case '9': temp = 0x90; break;
  47. case 'A': temp = 0x88; break;
  48. case 'B': temp = 0x83; break;
  49. case 'C': temp = 0xc6; break;
  50. case 'D': temp = 0xA1; break;
  51. case 'E': temp = 0x86; break;
  52. case 'F': temp = 0x8E; break;
  53. case 'H': temp = 0x89; break;
  54. case 'L': temp = 0xC7; break;
  55. case 'N': temp = 0xC8; break;
  56. case 'P': temp = 0x8c; break;
  57. case 'U': temp = 0xC1; break;
  58. case '-': temp = 0xbf; break;
  59. case ' ': temp = 0xff; break;
  60. default: temp = 0xff;
  61. }
  62. if(input[j+1] == ".")
  63. {
  64. temp &= 0x7f;
  65. j++;
  66. }
  67. output[i] = temp;
  68. }
  69. }
  70. /*
  71. 输入变量:num,要显示数据;PIS,显示位置,从左到右分别为0-7
  72. 输出变量:无
  73. 功能:操作138译码器,4-7分别对应Y4-Y7,其余都会使译码器不起作用
  74. 注意:需要把存放从1-f对应的16进制数数组也移植
  75. */
  76. void SEG_Show(u16 num,u16 PIS)
  77. {
  78. //消影
  79. P0 = 0xff;
  80. P2 = (P2 & 0x1f) | 0xE0;
  81. P2 &= 0x1f;
  82. //改变显示位置
  83. P0 = 0x01<<PIS;
  84. P2 = (P2 & 0x1f) | 0xC0;
  85. P2 &= 0x1f;
  86. //改变数据
  87. P0 = num;
  88. P2 = (P2 & 0x1f) | 0xE0;
  89. P2 &= 0x1f;
  90. }
  91. void SEG_Proc()
  92. {
  93. if(seg_delay) return;
  94. seg_delay = 1;
  95. sprintf(SEG_COT, "%02u",(u16)temp1);
  96. SEG_TSL(SEG_COT,SEG_Code);
  97. }
  98. /*****************按键*******************/
  99. /*
  100. 输入变量:无
  101. 输出变量:检测到的按键,如果返回0代表没有检测到任何按键按下
  102. 功能:矩阵键盘按键检测
  103. */
  104. u8 M_Buttun()
  105. {
  106. u16 temp = 0;
  107. u8 i = 0;
  108. u16 sign = 0x8000;
  109. //往每行中输入低电平
  110. //L1:P44 L2:P42 L1:P44 L3:P35 L4:P34
  111. P44=0;P42=1;P35=1;P34=1;//第一列
  112. temp = temp | (P3&0x0f);//只保存低四位数据
  113. P44=1;P42=0;P35=1;P34=1;//第二列
  114. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  115. P44=1;P42=1;P35=0;P34=1;//第三列
  116. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  117. P44=1;P42=1;P35=1;P34=0;//第四列
  118. temp = temp<<4 | (P3&0x0f);//只保存低四位数据
  119. for(i=0;i<16;i++)
  120. {
  121. if((~temp) & (sign>>i))//从最高位检测到最低位
  122. return i+4;
  123. }
  124. return 0;
  125. }
  126. void Key_Proc()
  127. {
  128. u8 key_now,key_down,key_up;
  129. //延时一段时间消抖,同时节省CPU资源
  130. if(key_delay) return;
  131. key_delay = 1;
  132. //读取按键按下的编号
  133. key_now = M_Buttun();
  134. //按键按下:通过判断按键状态是否发生变化,并且变化后状态是否为按下
  135. key_down = key_now & (key_old ^ key_now);
  136. //按键抬起
  137. key_up = ~key_now & (key_old ^ key_now);
  138. //记录当前状态为下一次检测做准备
  139. key_old = key_now;
  140. if(key_down)//按键按下
  141. {
  142. temp1 = key_now;
  143. }
  144. }
  145. /**************定时器**************************/
  146. /*
  147. 输入变量:定时时长___us
  148. 输出变量:无
  149. 功能:配置并开启定时器0
  150. */
  151. void Timer_0_Init(u16 time)
  152. {
  153. //12T模式
  154. AUXR &= 0x7f;
  155. //定时器0 模式0
  156. TMOD &= 0xf0;
  157. //设置初值
  158. TH0 = (65536-time)/256;
  159. TL0 = (65536-time)%256;
  160. //打开中断
  161. ET0 = 1;
  162. EA = 1;
  163. //开始计数
  164. TR0 = 1;
  165. }
  166. void Timer_0_IT(void) interrupt 1
  167. {
  168. //按键10ms检测一次
  169. if(++key_delay == 10) key_delay = 0;
  170. //数码管500ms检测一次
  171. if(++seg_delay == 500) seg_delay = 0;
  172. SEG_Show(SEG_Code[SEG_POS],SEG_POS);
  173. if(++SEG_POS == 8)SEG_POS = 0;
  174. }

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/560764
推荐阅读
相关标签
  

闽ICP备14008679号