- 阅读权限
- 150
- UID
- 7
- 帖子
- 140
- 精华
- 0
- 注册时间
- 2013-2-26
- 在线时间
- 20 小时
- UID
- 7
- 帖子
- 140
- 精华
- 0
- 注册时间
- 2013-2-26
- 在线时间
- 20 小时
|
/********************************
* PS2接口键盘实验 *
* 文件名称:main.c *
* 实验环境:阿贵的M16实验板 *
* 建立日期:2008年06月22日 *
* 版 本:V16.0.1 *
* 作 者:tonghe *
* 修改日期:2008年06月22日 *
* 功 能:实现PS2键盘 *
* (支持第2套扫描码) *
* 芯 片:ATMEGA16 *
* 时钟频率:7.3728MHZ *
* 编 译 器:ICCAVR6.31A *
********************************/
#include <iom16v.h>
#include <macros.h>
#include "delay.h"
#include "lcd1602_8.h"
#pragma data:code //将译码表放在FLASH
const unsigned char unshifted[][2]= //shift键没按下译码表
{
0x0e,'`', 0x15,'q', 0x16,'1', 0x1a,'z',
0x1b,'s', 0x1c,'a', 0x1d,'w', 0x1e,'2',
0x21,'c', 0x22,'x', 0x23,'d', 0x24,'e',
0x25,'4', 0x26,'3', 0x29,' ', 0x2a,'v',
0x2b,'f', 0x2c,'t', 0x2d,'r', 0x2e,'5',
0x31,'n', 0x32,'b', 0x33,'h', 0x34,'g',
0x35,'y', 0x36,'6', 0x39,',', 0x3a,'m',
0x3b,'j', 0x3c,'u', 0x3d,'7', 0x3e,'8',
0x41,',', 0x42,'k', 0x43,'i', 0x44,'o',
0x45,'0', 0x46,'9', 0x49,'.', 0x4a,'/',
0x4b,'l', 0x4c,';', 0x4d,'p', 0x4e,'-',
0x52,'\'', 0x54,'[', 0x55,'=', 0x5b,']',
0x5d,'\\', 0x61,'<', 0x69,'1', 0x6b,'4',
0x6c,'7', 0x70,'0', 0x71,'.', 0x72,'2',
0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+',
0x7a,'3', 0x7b,'-', 0x7c,'*', 0x7d,'9',
0,0
};
const unsigned char shifted[][2]= //shift键按下译码表
{
0x0e,'~', 0x15,'Q', 0x16,'!', 0x1a,'Z',
0x1b,'S', 0x1c,'A', 0x1d,'W', 0x1e,'@',
0x21,'C', 0x22,'X', 0x23,'D', 0x24,'E',
0x25,'$', 0x26,'#', 0x29,' ', 0x2a,'V',
0x2b,'F', 0x2c,'T', 0x2d,'R', 0x2e,'%',
0x31,'N', 0x32,'B', 0x33,'H', 0x34,'G',
0x35,'Y', 0x36,'^', 0x39,'L', 0x3a,'M',
0x3b,'J', 0x3c,'U', 0x3d,'&', 0x3e,'*',
0x41,'<', 0x42,'K', 0x43,'I', 0x44,'O',
0x45,')', 0x46,'(', 0x49,'>', 0x4a,'?',
0x4b,'L', 0x4c,':', 0x4d,'P', 0x4e,'_',
0x52,'"', 0x54,'{', 0x55,'+', 0x5b,'}',
0x5d,'|', 0x61,'>', 0x69,'1', 0x6b,'4',
0x6c,'7', 0x70,'0', 0x71,'.', 0x72,'2',
0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+',
0x7a,'3', 0x7b,'-', 0x7c,'*', 0x7d,'9',
0,0
};
#pragma data:data //将以后的变量放在RAM
unsigned char edge, bitcount,ascii=' '; //edge为0下降沿中断,为1上升沿中断
//bitcount为位计数值
//ascii为翻译后的ASCII码,初值为空格
void port_init(void)
{
PORTA = 0x00;
DDRA = 0x00;
PORTB = 0x00;
DDRB = 0xFF;
PORTC = 0x00;
DDRC = 0xFF;
PORTD = 0x44;
DDRD = 0x00;
}
/************************************
* 初始化PS2接口函数 *
************************************/
void Init_kb(void)
{
MCUCR = 2; //设置INT0为下降沿触发中断
edge = 0; //0为下降沿中断标志,1为上升沿中断标志
bitcount = 11; //每次11位数据,一个起始位(0),8个数据位,
//一个奇偶校验位,一个停止位(1)
GICR = 0x40;
SEI(); //打开全局中断
}
/************************************
* 扫描码翻译函数 *
* 入口参数: 需要翻译的扫描码 *
************************************/
void Decode(unsigned char scancode)
{
static unsigned char up=0,shift=0;//up为通、断码标志,shift为shift键按下标志
unsigned char i;
if (!up) //已接收的11位数据是通码(up为0)
{
switch (scancode) //开始翻译扫描码
{
case 0xF0: //键盘释放标志(随后的一个字节是断码)
up=1; //设置up为断码标志
break;
case 0x12: //左shift键按下
shift=1; //设置shift为按下标志
break;
case 0x59: //右shift键按下
shift=1; //设置shift为按下标志
break;
default:
if(!shift) //如果shift键没有按下
{ //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
for(i=0;unshifted[i][0]!=scancode&&unshifted[i][0];i++);
if(unshifted[i][0]==scancode)
{
ascii=unshifted[i][1];
}
}
else //如果shift键按下
{ //查找shifted表
for(i=0;shifted[i][0]!=scancode&&shifted[i][0];i++);
if(shifted[i][0]==scancode)
{
ascii=shifted[i][1];
}
}
break;
}
}
else //已接收的11位数据是断码(up为1)
{
up = 0; //将断码标志复位
switch (scancode) //检测shift键释放
{
case 0x12 : //左shift键
shift = 0;
break;
case 0x59 : //右shift键
shift = 0;
break;
default:
break;
}
}
}
/************************************
* 外部中断0函数 *
* 功 能: 数据时钟输入端,上升沿 *
* 中断读入11位数据,下降 *
* 沿调用解码程序 *
************************************/
#pragma interrupt_handler Int0:2
void Int0(void)
{
static unsigned char data; // 声明局部静态变量来保存扫描码
if (!edge) // 如果是下降沿触发中断
{
if(bitcount < 11 && bitcount > 2)//3到10位是数据,起始位,校验位和停止位忽略
{
data = (data >> 1); //右移保存数据
if(PIND&(1<<PD6))
{
data|=0x80; //存储一个'1'
}
}
MCUCR=3; //设置INT0为上升沿触发中断
edge=1; //设置上升沿中断标志
}
else //如果是上升沿触发中断
{
MCUCR=2; //设置INT0为下降沿触发中断
edge=0; //设置下降沿中断标志
if(--bitcount==0) //如果11位全部接收完毕
{
Decode(data); //将扫描码翻译成ASCII码
bitcount = 11; //重新设为11位数据
}
}
}
/********************************
* 主函数名称 *
********************************/
void main(void)
{
port_init(); //初始化
delay_ms(100);
lcd_init(); //初始化1602
delay_ms(100);
Init_kb(); //初始化PS2键盘接口
locate(1,2);
lcd("KEY_ASCII:");
while(1)
{
locate(1,13);
lcd_da(ascii); //显示翻译后的ASCII码
}
}
|
|