深圳市英锐恩科技有限公司:台湾麦肯单片机(Micon MDT单片机)亚太地区A级代理商
QLdsPIC3] PS2协议 {C30+dsPIC30F6014A]
//实验目的:熟悉MCU与PS2设备通信
//软件规划:
// 1,采用查询的方法检测PS2设备发送过来的时钟和数据
// 2,软件只检测字母(小写)数字(左边键盘)和数字键的通码,暂时不能检测断码。
// 3,不检测组合键盘
// 4,扫描按键结果送LCD1602显示
//硬件要求:
// 1,拨码开关S4全部置ON端
// 2,连接好键盘
// 3,跳线J18全部接通
#include //dsPIC30F6014标准头文件
_FOSC(0x0ffe5); //XT振荡,4倍频晶振.
_FWDT(WDT_OFF); //关闭看门狗定时器
_FBORPOR(PBOR_OFF & MCLR_EN); //掉电复位禁止,MCLR复位使能。
_FGS(CODE_PROT_OFF); //代码保护禁止
unsigned char __attribute__((address(0x900))) recdata1; //按键结果缓存单元1
unsigned char __attribute__((address(0x902))) recdata2; //按键结果缓存单元2
unsigned char __attribute__((address(0x904))) result; //按键的ASCII码保存单元
unsigned char __attribute__((address(0x906))) result1;
unsigned char __attribute__((address(0x908))) count; //循环次数
unsigned int __attribute__((address(0x90a))) temp; //临时单元
unsigned char __attribute__((address(0x9a0))) loop; //LCD显示次数计数器
#define rs LATBbits.LATB4 //定义LCD控制位(注意这里只能用LATB寄存器,不能直接用PORTB寄存器)
#define rw LATBbits.LATB5 //定义LCD的RW控制信号
#define e LATBbits.LATB6 //定义LCD的使能信号E
unsigned char const noshift[80][2]= //shift键不按下时按键的键码与ASCII对应表
{
//键盘码 ASCII码
22 ,49, // { 1 }
30 ,50, // { 2 }
38 ,51, // { 3 }
37 ,52, // { 4 }
46 ,53, // { 5 }
54 ,54, // { 6 }
61 ,55, // { 7 }
62 ,56, // { 8 }
70 ,57, // { 9 }
69 ,48, // { 0 }
28 ,97, // { a }
50 ,98, // { b }
33 ,99, // { c }
35 ,100, // { d }
36 ,101, // { e }
43 ,102, // { f }
52 ,103, // { g }
51 ,104, // { h }
67 ,105, // { i }
59 ,106, // { j }
66 ,107, // { k }
75 ,108, // { l }
58 ,109, // { m }
49 ,110, // { n }
68 ,111, // { o }
77 ,112, // { p }
21 ,113, // { q }
45 ,114, // { r }
27 ,115, // { s }
44 ,116, // { t }
60 ,117, // { u }
42 ,118, // { v }
29 ,119, // { w }
34 ,120, // { x }
53 ,121, // { y }
26 ,122, // { z }
84 ,91, // { [ }
91 ,93, // { ] }
76 ,59, // { ; }
82 ,39, // { ' }
65 ,44, // { , }
73 ,46, // { . }
74 ,47, // { / }
78 ,45, // { - }
85 ,61, // { = }
93 ,92, // { \ }
14 ,96, // { ` }
90 ,32, // { enter }
5 ,0, // { f1 }
6 ,1, // { f2 }
4 ,2, // { f3 }
12 ,3, // { f4 }
3 ,4, // { f5 }
11 ,5, // { f6 }
131 ,6, // { f7 }
10 ,7, // { f8 }
1 ,8, // { f9 }
9 ,9, // { f10 }
120 ,10, // { f11 }
7 ,11, // { f12 }
102 ,12, // { back }
224 ,13, // { home }
105 ,14, // { end }
125 ,15, // { pageup }
122 ,16, // { pagedown }
117 ,17, // { up }
114 ,18, // { down }
107 ,19, // { left }
116 ,20, // { right }
113 ,21, // { del }
112 ,22, // { insert }
225 ,23, // { pause }
118 ,24, // { esc }
13 ,25, // { tab }
88 ,26, // { caps }
20 ,27, // { ctrl }
17 ,28, // { alt }
41 ,29, // { space }
31 ,30, // { win }
47 ,31, // { winright
};
unsigned char const addshift[47][2]= //shift键按下时按键的键码与ASCII对应表
{
14 ,126, // { ~ }
22 , 33, // { ! }
30 , 64, // { @ }
38 , 35, // { # }
37 , 36, // { $ }
46 , 37, // { % }
54 , 94, // { ^ }
61 , 38, // { & }
62 , 42, // { * }
70 , 40, // { ( }
69 , 41, // { ) }
78 , 95, // { _ }
85 , 43, // { + }
93 ,124, // { | }
84 ,123, // { { }
91 ,125, // { } }
76 , 58, // { : }
82 , 34, // { " }
65 , 60, // { < }
73 , 62, // { > }
74 , 63, // { ? }
28 ,65, // { a }
50 ,66, // { b }
33 ,67, // { c }
35 ,68, // { d }
36 ,69, // { e }
43 ,70, // { f }
52 ,71, // { g }
51 ,72, // { h }
67 ,73, // { i }
59 ,74, // { j }
66 ,75, // { k }
75 ,76, // { l }
58 ,77, // { m }
49 ,78, // { n }
68 ,79, // { o }
77 ,80, // { p }
21 ,81, // { q }
45 ,82, // { r }
27 ,83, // { s }
44 ,84, // { t }
60 ,85, // { u }
42 ,86, // { v }
29 ,87, // { w }
34 ,88, // { x }
53 ,89, // { y }
26 ,90, // { z }
};
void init(); //I/O口初始化函数
void getkey(); //读取按键键码函数
void judge(); //键码转换成ASCII码
void lcd_display(unsigned char res); //LCD显示函数
void lcd_init(); //申明LCD初始化函数
void write_web(); //申明显示公司web地址函数
void write(unsigned int x); //申明显示1字节数据函数
void lcd_enable(); //申明LCD显示设置函数
void delay(); //申明延时函数
//************************初始化函数**************************
void init()
{
TRISC=0X0018;
TRISB=0X0000; //设置B口为输出
TRISD=0X0000; //设置D口为输出
result=0;
result1=0;
}
//********************读取按键键码函数*************************
void getkey()
{
unsigned char i;
temp=0;
for(count=1;count<21;count++) //循环20次(第1字节的1bit起始位,8bit数据,1bit校验位,1bit停止位,第2字节的1bit起始位和8bit数据,忽略校验位和停止位)
{
while(PORTCbits.RC4); //等待低电平
while(!PORTCbits.RC4) //低电平
{
for(i=0;i<15;i++); //延时一定时间,保证下降沿足够时间
if(count<10|count>12) //只读取数据位,忽略起始位和校验位,停止位
{
temp=temp>>1; //读取的数据右移1位(传输时低位在前)
if(PORTCbits.RC3) temp=temp|0x8000; //若为高,最高位加1
else temp=temp&0x7fff; //若为低,最高位清0
}
while(!PORTCbits.RC4); //等待恢复为高电平(下降沿读取数据)
}
}
recdata1=0;
recdata2=0;
recdata1=(unsigned char)temp&0x00ff; //按键码低8位
recdata2=(unsigned char)((temp>>8)&0x00ff); //按键码高8位
}
//*********************按键码转ASCII码**************************
void judge()
{
unsigned char i;
if(!(recdata1==0xf0)) //若按键码低8位为0XF0,则是按键的断码
{
if(recdata1==0x12) //shift有按下
{
if(recdata2=0xf0) return; //若只有shift按下,则返回
for(i=0;i<47;i++) //查找shift按下时按键的ASCII码
{
if(addshift[i][0]==recdata2)
{
result=addshift[i][1]; //返回读取的ASCII码
break;
}
}
}
else //shift键没有按下
{
for(i=0;i<80;i++)
{
if(noshift[i][0]==recdata1)
{
result=noshift[i][1];
break;
}
}
}
}
}
//*******************LCD初始化函数*******************************
void lcd_init()
{
PORTD=0X1; //清除显示
lcd_enable();
PORTD=0X38; //8位2行5*7点阵
lcd_enable();
PORTD=0X0e; //显示开,光标开,闪烁
lcd_enable();
PORTD=0X06; //文字不动,光标右移
lcd_enable();
PORTD=0X80; //产品名字显示地址
lcd_enable();
}
//*********************LCD显示函数*******************************
void lcd_display(unsigned char res)
{
unsigned char j;
if(loop<16) //一行只显示16字符
{
write(res); //写一个字节数据函数送LCD显示
loop++;
for(j=0;j<5;j++) //延时一段时间(主要是为了控制显示的速度)
{
delay();
}
}
else
{
loop=0;
PORTD=0X80; //重头开始显示
lcd_enable();
write(res); //写一个字节数据函数送LCD显示
}
}
//*****************写一个字节数据函数***************************
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void write(unsigned int x)
{
PORTD=x; //待显示数据送PORTD口
delay();
rs=1; //该字节数据为数据,而不是命令
delay();
rw=0; //此次操作为写,而不是读
delay();
e=0; //拉低使能信号
delay(); //保持使能信号为低一段时间
e=1; //拉高使能信号,建立LCD操作所需要的上升沿
delay();
}
//******************LCD显示设置函数*****************************
//在电平发生改变后需要插入一段延时时间,否则LCD反应不过来。
void lcd_enable()
{
delay();
rs=0; //该字节数据为命令,而不是数据
delay();
rw=0; //此次操作为写,而不是读
delay();
e=0; //拉低使能信号
delay(); //保持使能信号为低一段时间
e=1; //拉高使能信号,建立LCD操作所需要的上升沿
delay();
}
//**********************延时函数*********************************
void delay()
{
unsigned int i;
for(i=0;i<100;i++);
}
//**********************主函数***********************************
int main(void)
{
unsigned char m, k=0;
delay();
delay();
delay();
delay();
delay(); //延时一段时间,保证键盘,LCD等工作稳定
init(); //调用I/O口初始化函数
lcd_init(); //调用LCD初始化函数
while(1)
{
getkey(); //调用读取按键码函数
judge(); //调用按键码转ASCII码函数
if(recdata1!=0x12) lcd_display(result); //如按下键不为shift则送LCD显示
for(m=0;m<100;m++) //延长一段时间
{
delay();
delay();
}
}
}