hrefspace

 找回密码
 立即注册
搜索
热搜: PHP PS 程序设计
查看: 480|回复: 0

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

[复制链接]

557

主题

557

帖子

1898

积分

版主

Rank: 7Rank: 7Rank: 7

积分
1898
发表于 2024-2-6 02:05:05 | 显示全部楼层 |阅读模式
下面是独立按键检测试验的完整程序代码。         程序主要实现的功能是:判断4个独立按键是否被按下,当有按键被按下后,判断是那个按键被按下,然后通过数码管显示被按下按键的编号。
        本程序中为了简单起见,没有进行按键释放的判断。
        程序中对于按键的处理使用了两个函数Key_Check();Key_Number()。其中Key_Check()函数主要用来检测是否有按键按下,其中包含了软件延时消除按键抖动的处理;Key_Number()函数同来判断哪个按键按下,如果想要增加按键释放的判断,可以在这个函数里面增加判断按键是否被释放的语句。
        void HC595_Send_Data(unsigned char byte);这个函数用来在数码管上显示被按下按键的编号。
  1. #include <[url=http://www.mcuzx.net]AVR[/url]/io.h> //io端口寄存器配置文件,必须包含#include <util/delay.h> //GCC中的延时函数头文件unsigned char Led_Disbuf[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; //共阳极unsigned char KeyNumber;//函数声明void HC595_Send_Data(unsigned char byte);void Delayus(unsigned int lus); //us延时函数void Delayms(unsigned int lms); //ms延时函数unsigned char Key_Check(void); // 检测是否有按键按下unsigned char Key_Number(void); //检测是哪个按键按下int main(void) //GCC中main文件必须为返回整形值的函数,没有参数{PORTB = 0Xff; //PORTB输出低电平,使LED熄灭 DDRB = 0XFF; //配置端口PB全部为输出口PORTG = 0x00;DDRG |= (1 << PG0) | (1 << PG1) | (1 << PG2) | (1 << PG4);PORTD = 0X00; //DDRD = 0Xf0; //四个按键分别接PD0、PD1、PD2、PD3设置为输入口KeyNumber = 0;while(1){if(Key_Check()){PORTB = Led_Disbuf[Key_Number()];HC595_Send_Data(0x01); //选通位选端口Delayms(20); //延时//HC595_Send_Data(0x00); //位选通关闭}}}//us级别的延时函数void Delayus(unsigned int lus){while(lus--){_delay_loop_2(4); //_delay_loop_2(1)是延时4个时钟周期,参数为4则延时16//个时钟周期,本实验用16M晶体,则16个时钟周期为16/16=1us}}//ms级别的延时函数void Delayms(unsigned int lms){while(lms--){Delayus(1000); //延时1ms}}// 检测是否有按键按下unsigned char Key_Check(void){if(!(PIND == 0x0f)){Delayms(20);if(!(PIND == 0x0f)){return 1;}elsereturn 0;}else return 0;}//检测是哪个按键按下 unsigned char Key_Number(void){unsigned char i;if(Key_Check()){i = PIND & 0x0f;switch(i){case 0x0f:{KeyNumber = 0;break;}case 0x0e:{KeyNumber = 1;break;}case 0x0d:{KeyNumber = 2;break;} case 0x0b:{KeyNumber = 3;break;}case 0x07:{KeyNumber = 4;break;}default :break;}}//else //{// KeyNumber = 0;//}return KeyNumber;}//发送一个字节void HC595_Send_Data(unsigned char byte){unsigned char i; for(i = 0;i < 8;i++){if(byte & 0x80){PORTG |= (1 << PG2); }else{PORTG &= ~(1 << PG2);}byte <<=1;PORTG |= (1 << PG0); //上升沿数据移位//Delayus(10);PORTG &= ~(1 << PG0); }PORTG |= (1 << PG1); //Delayus(10);PORTG &= ~(1 << PG1); }
复制代码
学习到现在,我们已经实现了单片机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|Archiver|手机版|小黑屋|hrefspace

GMT+8, 2024-11-1 11:33 , Processed in 0.064478 second(s), 21 queries .

Powered by hrefspace X3.4 Licensed

Copyright © 2022, hrefspace.

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