圣龙扬特-AVR电子
标题:
PS2接口键盘的ICC解码程序
[打印本页]
作者:
铜河
时间:
2013-2-28 20:01
标题:
PS2接口键盘的ICC解码程序
/********************************
* 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码
}
}
作者:
铜河
时间:
2013-2-28 20:02
LCD函数:
/****************************************
* LCD1602操作函数,8位数据联接关系: *
* LCD1602
B0-DB7 M16
C0-PC7 *
* LCD1602:RS M16
B4 *
* LCD1602:E M16
B2 *
* LCD1602:R/W M16
B5 *
* 作 者:tonghe *
* 日 期:2008年08月25日 *
****************************************/
#include <iom16v.h>
#include <macros.h>
#include "delay.h"
//LCD相关端口定义
#define RS1602 PB4 //RS接在PORTB4上
#define CLR_RS PORTB&=~(1<<RS1602) //RS清0
#define SET_RS PORTB|=1<<RS1602 //RS置1
#define E1602 PB2 //E接在PORTB2上
#define CLR_E PORTB&=~(1<<E1602) //E清0
#define SET_E PORTB|=1<<E1602 //E置1
#define RW1602 PB5 //RW接在PORTB5上
#define CLR_RW PORTB&=~(1<<RW1602) //RS清0
#define SET_RW PORTB|=1<<RW1602 //RS置1
#define DATA_1602 PORTC
//简化宏定义
#define uchar unsigned char
#define uint unsigned int
/*************************************
* LCD1602操作函数组 *
*************************************/
//写数据到LCD的函数:入口data,需写入的显示数据
void lcd_da(uchar data)
{
SET_RS; //RS置高,写数据
delay_ms(1);
// SET_E;
DATA_1602 = data; //数据送端口
SET_E;
delay_ms(1);
CLR_E; //E下降沿写入数据
delay_ms(1); //延时1MS
}
//写指令到LCD的函数:入口data,需写入的控制指令
void lcd_comm(uchar data)
{
CLR_RS; //RS清0,写指令
delay_ms(1); //延时1MS
// SET_E;
DATA_1602 = data; //指令送端口
SET_E;
delay_ms(1);
CLR_E; //E下降沿写入指令
delay_ms(1); //延时1MS
}
//LCD1602初始化函数
void lcd_init(void)
{
CLR_RW;
delay_ms(5);
lcd_comm(0x38); //写指令:8位数据、2行显示、5*8点阵
delay_ms(5);
lcd_comm(0x06); //写指令:自左向右显示
delay_ms(5);
lcd_comm(0x0C); //写指令:显示开
delay_ms(5);
lcd_comm(0x14); //写指令:移动
delay_ms(5);
lcd_comm(0x80); //写指令:第1行地址
delay_ms(5);
lcd_comm(0x01); //写指令:CLS
delay_ms(5);
}
//清屏指令函数
void cls(void)
{
lcd_comm(0x01);
delay_ms(5);
}
//定位指令函数
void locate(uchar a,uchar b)
{
uchar x;
if(a==1)
x=0x80+b-1;
if(a==2)
x=0xC0+b-1;
lcd_comm(x);
delay_ms(1);
}
/***********************************
* 显示一个字符串函数 *
* 入 口:待显示的字符串 *
***********************************/
void lcd(char *s)
{
while(*s)
{
lcd_da(*s);
s++;
}
}
作者:
铜河
时间:
2013-2-28 20:03
完整的工程项目文件:
欢迎光临 圣龙扬特-AVR电子 (http://avr.cnta.net/)
Powered by Discuz! X2.5