键盘接口实验
一、 实验目的:1、了解IO口的结构;
2、熟悉键盘的程序原理;
3、掌握键盘的使用。
二、实验仪器: MEGA16实验板 一块
PC机 一台
三、 实验原理:在AVR 单片机中,当I/O方向设置为输入,电平被设置为高电平时,一旦外部接入低电平,端口电平被拉低,电平变化会反映相应端口PINX寄存器中,利用这一特点,在键盘中采用设置行所对IO口为输出,高电平,列所对IO口为输入,高电平。对行所对IO口电平逐个设置为低电平,此时列线上某列电平被拉低。通过读取列线上电平,计算出所按键值。
四 实验程序
#include <iom16v.h>
#include <macros.h>
/延时///
void delay_us( int t) //us
{
do
t--;
while(t>1);
}
void delay_ms(unsigned int t) //ms
{
while(t!=0)
{
delay_us(1142);
t--;
}
}
unsigned char led[]={ 0X 3F ,/*0*/ //七段译码表
0X06,/*1*/
0X5B,/*2*/
0X 4F ,/*3*/
0X66,/*4*/
0X6D,/*5*/
0X7D,/*6*/
0X07,/*7*/
0X 7F ,/*8*/
0X 6F ,/*9*/
0X77,/*A*/
0X 7C ,/*b*/
0X39,/*C*/
0X5E,/*d*/
0X79,/*E*/
0X71,/*F*/
}; //显示符0,1,2,3,4,5,6,7,8,9,
unsigned char led_buff[]={0x 3f ,0x 3f ,0x 3f ,0x 3f ,0x 3f ,0x 3f }; //显示缓冲区
unsigned char scan_key(void) //不做按键释放检查的键盘扫描函数
{
unsigned char i,temp;
DDRD=0X 0F ; //设置D口的高四位为输入,低四位为输出
PORTD=0XFf; //D口输出高电平
for(i=0;i<4;i++)
{
PORTD=~(1<<i); //第i为值为低电平
delay_us(500);
temp=PIND&0XF0; //temp取D口高四位的值
if(temp!=0xf0) //如有键按下,延时15ms
{
delay_ms(15); //延时用来消除显示抖动
temp=PIND&0xf0; //再读键盘
if(temp!=0xf0)
{
temp&=0xf0;
switch (temp) //计算键值
{
case 0x70:temp=15-(3-i)*4;break;
case 0xb0:temp=14-(3-i)*4;break;
case 0xd0:temp=13-(3-i)*4;break;
case 0xe0:temp=12-(3-i)*4;break;
default:temp=0x 7f ;
}
return temp; //返回temp
}
}
PORTD=0xff;
}
return 0x 7f ;
}
void port_init(void) //初始化IO
{
DDRA=0xff;
PORTA=0xff;
DDRC=0xff;
PORTC=0Xff;
DDRD=0x 0f ;
PORTD=0xff;
}
void display(void) //六位数码管显示
{
unsigned int i=0;
for(;i<6;i++)
{
PORTA=led_buff[i]; //PA口为段选
PORTC=(1<<i); //PC口为位选
delay_us(1000);
PORTC=0X00;
}
}
void main(void)
{
unsigned char key1,key2;
unsigned char i;
port_init();
for(;;)
{
key1=scan_key(); //键盘扫描
if (key1!=0x 7f )
{
do
{
key2=scan_key();
display();
}
while(key1==key2);
for (i=0;i<5;i++) //显示
led_buff[5-i]=led_buff[4-i]; //按下一次移一次
led_buff[0]=led[key1]; //做led显示转换
}
display(); //显示
}
}