深圳市英銳恩科技有限公司:臺灣麥肯單片機(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();
}
}
}