找回密码
 注册会员
更新自动建库工具PCB Footprint Expert 2024.04 Pro / Library Expert 破解版

自学AVR单片机十六(4X4矩阵键盘的程序设计)

[复制链接]
慧龙 发表于 2010-5-6 17:01:43 | 显示全部楼层 |阅读模式

本文包含原理图、PCB、源代码、封装库、中英文PDF等资源

您需要 登录 才可以下载或查看,没有账号?注册会员

×
下面我们来动手编写4X4矩阵键盘的程序,按键检测程序如下
程序中我们先设置连接矩阵键盘的PD口的高四位为输出口(作为行线),低四位为输入口(作为列线),然后先控制第一根行线输出低电平(其余行线输出高电平),逐列检测4根列线的电平状态,如果其中一根列线为低电平,那么这根列线与设置为输出低电平的行线交叉出的按键就是被按下的按键,计算出按键编码。如果这一行所有列线都为高电平,说明该行没有按键按下,那么接下来控制第二根行线输出低电平继续检测,直到设置第四根行线为低电平。

  1. unsigned char i,j;
  2. DDRD = 0xf0;           //设置PD高四位为输出口,低四位为输入口
  3. PORTD = 0x00;         // 初始运行输出全为0
  4. if((PIND & 0x0f) == 0x0f) return 16;   // 判断有无按键动作,没有,返回0     
  5. else
  6. {
  7.   Delayms(20);                     //按键消抖
  8.   if((PIND & 0x0f) == 0x0f) return 16;      //再次判断是否有按键动作
  9.   else
  10.   {
  11.    for(i = 4;i < 8;i++)                //逐行输出0
  12.    {
  13.     PORTD = ~(1 << i) | 0x0f;      //第i行输出0
  14.     for(j = 0;j < 4;j++)
  15.     {
  16.      if((PIND & (1 << j)) == 0)        //逐列检测
  17.      KeyNumber = (i - 4) * 4 + j;      //计算键值
  18.     }
  19.    }
  20.   return KeyNumber;       //
复制代码

完整代码

  1. #include <AVR/io.h> //io端口寄存器配置文件,必须包含
  2. #include <util/delay.h> //GCC中的延时函数头文件
  3. unsigned char Led_Disbuf[17]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
  4. 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xff}; //共阳极
  5. unsigned char KeyNumber;
  6. //函数声明
  7. void HC595_Send_Data(unsigned char byte);
  8. void Delayus(unsigned int lus); //us延时函数
  9. void Delayms(unsigned int lms); //ms延时函数
  10. unsigned char Read_Key(void); // 读取键值
  11. int main(void) //GCC中main文件必须为返回整形值的函数,没有参数
  12. {
  13. PORTB = 0X00; //PORTB输出低电平,使LED熄灭
  14. DDRB = 0XFF; //配置端口PB全部为输出口

  15. PORTG = 0x00;
  16. DDRG |= (1 << PG0) | (1 << PG1) | (1 << PG2) | (1 << PG4);

  17. KeyNumber = 16; //开始没有按键按下,不显示

  18. while(1)
  19. {
  20. if(!(Read_Key() == 16))
  21. {
  22. PORTB = Led_Disbuf[KeyNumber];
  23. HC595_Send_Data(0x01); //选通位选端口
  24. Delayms(20); //延时
  25. //HC595_Send_Data(0x00); //位选通关闭
  26. }//读取键值


  27. }
  28. }
  29. //us级别的延时函数
  30. void Delayus(unsigned int lus)
  31. {
  32. while(lus--)
  33. {
  34. _delay_loop_2(3); //_delay_loop_2(1)是延时4个时钟周期,参数为3则延时12
  35. //个时钟周期,本实验用12M晶体,则12个时钟周期为12/12=1us
  36. }
  37. }
  38. //ms级别的延时函数
  39. void Delayms(unsigned int lms)
  40. {
  41. while(lms--)
  42. {
  43. Delayus(1000); //延时1ms
  44. }
  45. }
  46. //4*4矩阵键盘扫描,PD高四位为行输出口,低四位为列输入口
  47. unsigned char Read_Key(void)
  48. {
  49. unsigned char i,j;
  50. DDRD = 0xf0; //设置PD高四位为输出口,低四位为输入口
  51. PORTD = 0x00; // 初始运行输出全为0
  52. if((PIND & 0x0f) == 0x0f) return 16; // 判断有无按键动作,没有,返回0
  53. else
  54. {
  55. Delayms(20); //按键消抖
  56. if((PIND & 0x0f) == 0x0f) return 16; //再次判断是否有按键动作
  57. else
  58. {
  59. for(i = 4;i < 8;i++) //逐行输出0
  60. {
  61. PORTD = ~(1 << i) | 0x0f; //第i行输出0
  62. for(j = 0;j < 4;j++)
  63. {
  64. if((PIND & (1 << j)) == 0) //逐列检测
  65. KeyNumber = (i - 4) * 4 + j; //计算键值
  66. }
  67. }
  68. return KeyNumber; //
  69. }
  70. }
  71. }
  72. //发送一个字节
  73. void HC595_Send_Data(unsigned char byte)
  74. {
  75. unsigned char i;

  76. for(i = 0;i < 8;i++)
  77. {

  78. if(byte & 0x80)
  79. {
  80. PORTG |= (1 << PG2);
  81. }
  82. else
  83. {
  84. PORTG &= ~(1 << PG2);
  85. }
  86. byte <<=1;

  87. PORTG |= (1 << PG0); //上升沿数据移位
  88. //Delayus(10);
  89. PORTG &= ~(1 << PG0);

  90. }
  91. PORTG |= (1 << PG1);
  92. //Delayus(10);
  93. PORTG &= ~(1 << PG1);
  94. }
复制代码
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

QQ|手机版|MCU资讯论坛 ( 京ICP备18035221号-2 )|网站地图

GMT+8, 2024-12-23 13:05 , Processed in 0.052924 second(s), 10 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表