我只要简单的功能,按下一个按键,执行一个功能,如按下9,P30输出低电平。第二代码报错,第一个不会用。PS2读电脑键盘实验 数码管显示 只看楼主
* ID:487236 楼主
* 2019-8-7 20:50 查看1538 回复0 收藏
* /****************************************************************************************
* PS2 读电脑键盘实验 *
* 连接方法 : P0口与J12连接 拔开跳线帽用杜邦线连接左针与P3.2右针与P1.6连接 *
* 使用方法:用外部中断读取PS2键盘的数据 并在数码管上显示,此程序只处理数字键盘。 *
* *
* 其余按键功能用户可以自行扩展,为了程序简单便于阅读和学习,程序中没有使用奇偶校验, *
* 校验程序请自行添加。 * *
* *
* *****************************************************************************************/
*
* #include<reg52.h>
*
* sbit LS138A=P2^2;
* sbit LS138B=P2^3;
* sbit LS138C=P2^4;
*
* sbit BEEP = P1^5;
*
* sbit Key_Data = P1^6 ; //定义键盘引脚
* sbit Key_CLK = P3^2; //使用外部中断
*
* /******************************************************************/
* /* 函数声明 */
* /******************************************************************/
* void Decode(unsigned char ScanCode);//解码子程序
* void delay(unsigned int i); //函数声名
* void display();
* void beep();
*
*
* // 此表为 LED 的字模 // 0 1 2 3 4 5 6 7 8 9 A b c d E - L P U Hidden_ (20)
* unsigned char code Disp_Tab[] = { ~0xC0,~0xF9,~0xA4,~0xB0,~0x99,~0x92,~0x82,~0xF8,~0x80,~0x90,~0x88,~0x83,~0xC6,~0xA1,~0x86,~0xbf,~0xc7,~0x8c,~0xc1, ~0xff,~0xf7 };
* bit BF;
* unsigned char KeyV;
* unsigned char LedNumVal;
* int KEY_val,IntNum;
*
* /******************************************************************/
* /* 主函数 */
* /******************************************************************/
* void main()
* {
*
* IT1 = 0; //设外部中断1为低电平触发
* EA = 1; //外部中断开
* EX0 = 1; //开中断
*
* while(1)
* {
* if (BF)
* {
* if (KeyV != 240)beep();
*
* Decode(KeyV); //解码
*
* }
* else
* EA = 1; //开中断
* display();
* }
*
* }
*
* /******************************************************************/
* /* 外部中断读入信息 */
* /******************************************************************/
* void Keyboard_out(void) interrupt 0
* {
* if ((IntNum > 0) && (IntNum < 9))
* {
* KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
* if (Key_Data)
* KeyV = KeyV | 0x80; //当键盘数据线为1时到最高位
* }
* IntNum++;
* while (!Key_CLK); //等待PS/2CLK拉高
*
* if (IntNum > 10)
* {
* IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
* BF = 1; //标识有字符输入完了
* EA = 0; //关中断等显示完后再开中断
* }
*
* }
*
* /******************************************************************/
* /* 解码信息 */
* /******************************************************************/
* void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
* {
*
* switch (ScanCode)
* {
* case 0x70 : // 当收到0xF0,Key_UP置1表示断码开始
* KEY_val = 0;
* break;
*
* case 0x69 :
* KEY_val = 1;
* break;
*
* case 0x72 :
* KEY_val = 2;
* break;
*
* case 0x7A :
* KEY_val = 3;
* break;
*
* case 0x6B :
* KEY_val = 4;
* break;
*
* case 0x73 :
* KEY_val = 5;
* break;
*
* case 0x74 :
* KEY_val = 6;
* break;
*
* case 0x6c :
* KEY_val = 7;
* break;
*
* case 0x75 :
* KEY_val = 8;
* break;
*
* case 0x7d :
* KEY_val = 9;
* break;
*
* case 0x71 :
*
* // dot = 0X7F;
* break;
*
* }
*
*
* BF = 0; //标识字符处理完了
* }
*
*
* /***************************************************************************************/
* void display( )
* {
* unsigned char i;
* unsigned int LedOut[8];
*
* LedNumVal = KEY_val ;
*
* //显示键值
* LedOut[0]=Disp_Tab[KeyV%10000/1000];
* LedOut[1]=Disp_Tab[KeyV%1000/100];
* LedOut[2]=Disp_Tab[KeyV%100/10];
* LedOut[3]=Disp_Tab[KeyV%10];
*
* //显示对应的字符
* LedOut[4]=Disp_Tab[LedNumVal%10000/1000]; //千位
* LedOut[5]=Disp_Tab[LedNumVal%1000/100];//百位带小数点
* LedOut[6]=Disp_Tab[LedNumVal%100/10]; //十位
* LedOut[7]=Disp_Tab[LedNumVal%10]; //个位
*
*
* for( i=0; i<8; i++)
* { P0 = LedOut[i ];
*
* switch(i)
* {
* case 0:LS138A=0; LS138B=0; LS138C=0; break;
* case 1:LS138A=1; LS138B=0; LS138C=0; break;
* case 2:LS138A=0; LS138B=1; LS138C=0; break;
* case 3:LS138A=1; LS138B=1; LS138C=0; break;
* case 4:LS138A=0; LS138B=0; LS138C=1; break;
* case 5:LS138A=1; LS138B=0; LS138C=1; break;
* case 6:LS138A=0; LS138B=1; LS138C=1; break;
* case 7:LS138A=1; LS138B=1; LS138C=1; break;
*
* }
*
* delay(50);
* }
*
* }
*
* /***************************************************************************************
* 延时程序 *
* ****************************************************************************************/
* void delay(unsigned int i)
* {
* char j;
* for(i; i > 0; i--)
* for(j = 200; j > 0; j--);
* }
*
* /***************************************************************************************
* 蜂铃器发声 *
* ****************************************************************************************/
* void beep()
* {
* unsigned char i;
* for (i=0;i<255;i++)
* {
* delay(5);
* BEEP=!BEEP; //BEEP取反
* }
* BEEP=1; //关闭蜂鸣器
* }
*
单片机学习笔记(八)PS/2电脑键盘 只看楼主
* ID:108531 楼主
* 2016-3-12 16:47 查看3765 回复1 收藏
PS/2键盘是一种编码键盘,只需要一根数据线和一根时钟线就可以完成数据的输入。
实验程序设计为,按键盘上的"J"键,继电器闭合。
C语言源程序:
#include <reg52.h> //52单片机头文件包含
#include <intrins.h>//常用移位函数头文件包含
sbit key_data=P1^5; //定义键盘接口的数据脚
sbit key_clk=P3^2;//定义键盘接口的时钟脚
sbit JDQ=P2^4; //定义继电器连接引脚
bit BF=0; //定义位变量BF
unsigned char keyv=0; //定义无符号字符变量keyv并赋初值0
unsigned int intNum=0;//定义无符号整型变量intNum并赋初值0
unsigned char key_up=1;//定义无符号字符变量key_up并赋初值1
void ldedata(unsigned char scandata);//按键数据处理函数
void main() //主函数
{
EA=1; //打开总中断
EX0=1;//打开0号中断
IT0=1;//中断方式为下降沿触发方式
do{ //do-while循环
if(BF) //如果有键按下
ldedata(keyv);//处理按键数据
else
EA=1;//否则打开中断
}while(1); //总为真不断循环
}
void key_scan() interrupt 0 //中断函数键盘输入key_scan 中断入口0
{
if((intNum>0)&&(intNum<9)) //如果intNum>0并且intNum<9 就执行if里面的语句
{
keyv=keyv>>1; //将字符变量keyv右移一位
if(key_data) //判断key_data 是否为真 即是否有数据
keyv=keyv|0x80; //有就将keyv与0x80进行或运算再赋值给keyv
}
intNum++;//将intNum的值自加1
while(!key_clk)//键值是否处理完
if(intNum>10)//判断intNum是否大于10
{
intNum=0;//将intNum赋值为0
BF=1;//将BF赋值为1
EA=0;//关闭总中断
}
}
void ldedata(unsigned char scandata) //键盘数据处理函数
{
if(!key_up) //键盘松开时
{
switch(scandata){ //处理键盘数据
case 0xf0://没按下任何键
key_up=1;//按下
break;//跳出
case 0x12://左边SHIFT
break;//跳出
case 0x59://右边SHIFT
break;//跳出
default://缺省处理
P1=~scandata;//将按下的键码输出给P2口驱动灯亮,因发光二极采用共阳级,所以取反输出
if(scandata==0x3b)//当按下J键时
JDQ=0;//打开继电器
if(scandata==0x29){//当按下空格键时
JDQ=1;//关闭继电器
}
break;//跳出
}
}
else{ //否则
key_up=0;//按键按下
switch(scandata){//处理按键
case 0x12://左边SHIFT
break;//跳出
case 0x59://右边SHIFT
break;//跳出
}
}
BF=0;//标识字符表示处理完了
}
//实验结果 按下键盘j键继电器打开 按下空格键继电器关闭
|