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

自学AVR单片机十四(独立按键检测的程序实现)

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

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

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

×
下面是独立按键检测试验的完整程序代码。         程序主要实现的功能是:判断4个独立按键是否被按下,当有按键被按下后,判断是那个按键被按下,然后通过数码管显示被按下按键的编号。
        本程序中为了简单起见,没有进行按键释放的判断。
        程序中对于按键的处理使用了两个函数Key_Check();Key_Number()。其中Key_Check()函数主要用来检测是否有按键按下,其中包含了软件延时消除按键抖动的处理;Key_Number()函数同来判断哪个按键按下,如果想要增加按键释放的判断,可以在这个函数里面增加判断按键是否被释放的语句。
        void HC595_Send_Data(unsigned char byte);这个函数用来在数码管上显示被按下按键的编号。
  1. #include <AVR/io.h> //io端口寄存器配置文件,必须包含
  2. #include <util/delay.h> //GCC中的延时函数头文件
  3. unsigned char Led_Disbuf[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳极
  4. unsigned char KeyNumber;
  5. //函数声明
  6. void HC595_Send_Data(unsigned char byte);
  7. void Delayus(unsigned int lus); //us延时函数
  8. void Delayms(unsigned int lms); //ms延时函数
  9. unsigned char Key_Check(void); // 检测是否有按键按下
  10. unsigned char Key_Number(void); //检测是哪个按键按下
  11. int main(void) //GCC中main文件必须为返回整形值的函数,没有参数
  12. {
  13. PORTB = 0Xff; //PORTB输出低电平,使LED熄灭
  14. DDRB = 0XFF; //配置端口PB全部为输出口

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

  17. PORTD = 0X00; //
  18. DDRD = 0Xf0; //四个按键分别接PD0、PD1、PD2、PD3设置为输入口

  19. KeyNumber = 0;

  20. while(1)
  21. {
  22. if(Key_Check())
  23. {
  24. PORTB = Led_Disbuf[Key_Number()];
  25. HC595_Send_Data(0x01); //选通位选端口
  26. Delayms(20); //延时
  27. //HC595_Send_Data(0x00); //位选通关闭
  28. }
  29. }
  30. }
  31. //us级别的延时函数
  32. void Delayus(unsigned int lus)
  33. {
  34. while(lus--)
  35. {
  36. _delay_loop_2(4); //_delay_loop_2(1)是延时4个时钟周期,参数为4则延时16
  37. //个时钟周期,本实验用16M晶体,则16个时钟周期为16/16=1us
  38. }
  39. }
  40. //ms级别的延时函数
  41. void Delayms(unsigned int lms)
  42. {
  43. while(lms--)
  44. {
  45. Delayus(1000); //延时1ms
  46. }
  47. }
  48. // 检测是否有按键按下
  49. unsigned char Key_Check(void)
  50. {
  51. if(!(PIND == 0x0f))
  52. {
  53. Delayms(20);
  54. if(!(PIND == 0x0f))
  55. {
  56. return 1;
  57. }
  58. else
  59. return 0;
  60. }
  61. else
  62. return 0;
  63. }
  64. //检测是哪个按键按下
  65. unsigned char Key_Number(void)
  66. {
  67. unsigned char i;

  68. if(Key_Check())
  69. {
  70. i = PIND & 0x0f;
  71. switch(i)
  72. {
  73. case 0x0f:
  74. {
  75. KeyNumber = 0;
  76. break;
  77. }
  78. case 0x0e:
  79. {
  80. KeyNumber = 1;
  81. break;
  82. }
  83. case 0x0d:
  84. {
  85. KeyNumber = 2;
  86. break;
  87. }
  88. case 0x0b:
  89. {
  90. KeyNumber = 3;
  91. break;
  92. }
  93. case 0x07:
  94. {
  95. KeyNumber = 4;
  96. break;
  97. }
  98. default :
  99. break;
  100. }
  101. }
  102. //else
  103. //{
  104. // KeyNumber = 0;
  105. //}
  106. return KeyNumber;
  107. }
  108. //发送一个字节
  109. void HC595_Send_Data(unsigned char byte)
  110. {
  111. unsigned char i;

  112. for(i = 0;i < 8;i++)
  113. {

  114. if(byte & 0x80)
  115. {
  116. PORTG |= (1 << PG2);
  117. }
  118. else
  119. {
  120. PORTG &= ~(1 << PG2);
  121. }
  122. byte <<=1;

  123. PORTG |= (1 << PG0); //上升沿数据移位
  124. //Delayus(10);
  125. PORTG &= ~(1 << PG0);

  126. }
  127. PORTG |= (1 << PG1);
  128. //Delayus(10);
  129. PORTG &= ~(1 << PG1);
  130. }
复制代码

学习到现在,我们已经实现了单片机I/O口的输出控制和输入判断。下面我们来总结一下AVR单片机I/O口在进行输入输出操作时的注意事项:
  • AVR单片机的通用I/O口是有方向的,通过方向控制寄存器DDRx来控制I/O口是输入还是输出状态;使用AVR的I/O口时要先设置DDRx方向寄存器,然后才能进行I/O口的读写操作;
  • AVR单片机的I/O口在复位后的初始状态全部为输入工作方式,内部上拉电阻无效。所以此时I/O口呈现为高阻输入状态(I/O口的三态为:输入状态、输出状态、高阻状态);
  • 复位后要及时对系统中用到的I/O口进行初始化设置,根据系统需要设置用到的I/O口为输入或输出状态,当设定为输入状态时,还要考虑是否使用内部的上拉电阻;在电路设计中,如果能使用内部上拉电阻,可以节省外部的上拉电阻,从而简化电路设计、节省系统成本;
  • 对于系统中没有用到的I/O口,从考虑功耗和消除电路干扰的方面考虑,一般设置为输入状态,并使能内部上拉电阻;
  • I/O口用于输出时,应设置为DDRx=1(x为相应端口序号),然后用PORTx输出相应值;
  • I/O口用于输入时,应设置为DDRx=0(x为相应端口序号),然后用PORTx输出相应值; 用PINx读取外部电平状态 ;注意此时用PORTx设置内部上拉电阻是否有效,PORTx=1表示内部上拉电阻有效,PORTx=0表示内部上拉电阻无效;
  • 一旦将I/O口的工作方式由输出状态设置成输入状态后,必须等待一个时钟周期后才能正确的读取到I/O口的PINx的值。
*滑块验证:
您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

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

GMT+8, 2024-11-23 06:38 , Processed in 0.054760 second(s), 9 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

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