|
程序如下:
#include<reg52.h> //包含单片机寄存器的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
typedef unsigned char uint8 ;
typedef unsigned int uint16;
#define TURNON 1
#define TURNOFF 0
bit flag = TURNON;
//uint8 ctrl = 0x0;
static uint8 PS2RecChar1 = 0xCC;
/*******************************************************************************
以下是引脚定义
*******************************************************************************/
sbit PS2CLK1 = P1^4;
sbit PS2DAT1 = P3^2;
sbit ctrl0 = P1^5;
//sbit ctrl1 = P1^6;
//sbit ctrl2 = P1^7;
/*****************************************************
函数功能:延时
***************************************************/
void Delay_5us () //5.43us 晶振为11.0592M时调用一个函数要4个指令周期即4.34us,也就是说每多一个加一个指令周期(1/f)*12=1.085us
{ _nop_();
}
void Delay_10us () //
{ _nop_();_nop_();_nop_();_nop_();_nop_();
}
void Delay_20us () //19.53us
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();
}
void Delay_15us () //15.19us
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void Delay_13us () //13.02
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
}
void Delay_40us () //39.06
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();
}
void Delay_50us () //50.1
{
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();
_nop_();_nop_();_nop_();
}
void delay_ms ( uint16 t )
{
uint16 i,j;
for ( i = t; i > 0; i-- )
for ( j = 110; j > 0; j-- )
;
}
void init_serial()
{
T2CON = 0x34; //Set the Counter/Timer2 for the baud rate generator
RCAP2H = 0xFF; //T2 baud is 38400
RCAP2L = 0xF7;
SCON = 0x50; //Serial port in Mode 2
EA=1;
ES = 1; //Allow serial interrupt
}
//==================================================
// c51模拟PS2键盘和PC机通讯程序
// 发送程序代码
//==================================================
void OnPS2SendChar1 ( uint8 dat )
{
uint8 h = 0, j;
uint8 i = 8;
bit bparity = 0 ;
ACC = dat; //获取字节的奇偶信息
if ( !P ) //ACC中偶数时,P为0,但是PS2中时奇校验( 字节中的1的个数+校验位 = 奇数)
bparity = 1;
if( PS2CLK1 && PS2DAT1 ) //发送前检测PS2总线
{
Delay_50us (); //50us
if ( PS2CLK1 ) //时钟线空闲
{
if ( PS2DAT1 ) //数据线空闲
{
for (j = 11;j > 0;j--) //1共11个数据
{
if ( h == 0 ) // 送起始位
{
PS2DAT1 = 0;
h++;
}
else if ( h == 1 ) //送8位数据位
{
PS2DAT1 = dat & 0x01; //先LSB开始
dat >>= 1;
i--;
if (i == 0) //发送完成
h++;
}
else if ( h == 2 ) //送校验位
{
PS2DAT1 = bparity;
h++;
}
else
{ PS2DAT1 = 1; } //送停止位
//Delay_10us (); //10us
Delay_13us (); //数据改变后,到此处耗时6.51us
PS2CLK1 = 0; //拉低时钟线,设备发送
Delay_40us (); //40us
PS2CLK1 = 1;
Delay_5us (); //for循环到下一次DATA置1时程序本身要耗时约20us
if ( !PS2CLK1 ) //检测到时钟线变低
{ //主机不要这次通讯 (很罕见)
break; //return;
}
}
//Delay_15us (); //发送完一包后延迟30us
//Delay_15us ();
}//if(PS2DAT)
else
return; //主机发送命令,KB转入接收程序
}//if(PS2CLK)
}//if(PS2CLK&&PS2DAT)
}//end
//======================================================================
// c51模拟PS2键盘和PC机通讯程序
// 接收程序代码
//======================================================================
void OnPS2ReceChar1 ( )
{
bit bparity = 1 ; //奇偶校验错误,明天来确认。原来为0 改为1后进不了系统!
bit ParityBit = 0 ;
bit DATAFlag = 1;
uint8 dat = 0x0, i;
if ( !PS2DAT1 )
{
//标准键盘DATA线拉低250us后产生时钟,所以我在延迟约200us后再检测DATA
Delay_50us () ;
Delay_50us () ;
Delay_50us () ;
if ( !PS2DAT1 )
{ //data为低,则读取一个字节
for ( i = 0; i < 8; i ++ )//read 8bit
{
_nop_(); //1T
Delay_20us ();
PS2CLK1 = 0; //1T
Delay_40us ();
PS2CLK1 = 1; //1T
dat = dat >> 1; //4T
if ( PS2DAT1 ) //2T
{
dat|=0x80; //2T
bparity = ~bparity; //1T
}
else
{
_nop_();_nop_();_nop_();
}
if ( PS2CLK1 == 0 ) //2T
{ return; } //如果时钟被拉低,则有错误发生,发送0XFE报错
//OnPS2SendChar1 ( 0xfe );
} //6T
Delay_20us (); //读取校验位
PS2CLK1 = 0;
Delay_40us ();
PS2CLK1 = 1;
Delay_20us ();
if ( PS2DAT1 )
ParityBit = 1;
else
ParityBit = 0;
Delay_20us (); //越过停止位
PS2CLK1 = 0;
Delay_40us ();
PS2CLK1 = 1;
Delay_20us (); //STOP BIT H_DATA 0 ERR
/*
if ( !PS2DAT1 ) //如果DATA线为低,输出CLK直到DATA线为高
{
DATAFlag = 0;
Delay_20us ();
PS2CLK1 = 0;
Delay_40us ();
PS2CLK1 = 1;
Delay_20us ();
}
if ( DATAFlag == 0 )
OnPS2SendChar1 ( 0xfe );
*/
Delay_10us (); //协议中要求15us后
PS2DAT1 = 0; //ACK bit
Delay_10us (); //协议中要求5us后
PS2CLK1 = 0;
Delay_40us ();
PS2CLK1 = 1;
Delay_10us (); //协议中要求5us后,我发现5us时间太短,ASK上升沿会与CLK上升沿重合
PS2DAT1 = 1;
/*
Delay_40us ();
PS2CLK1 = 0;
Delay_40us ();
Delay_20us ();
PS2CLK1 = 1;
*/
if ( ParityBit == bparity )
PS2RecChar1 = dat;
else
OnPS2SendChar1 ( 0xfe ); //校验错误,请求重发,而不是报错0XFC
Delay_40us (); //延迟45us
Delay_5us ();
}
}
}
//======================================================================
// c51模拟PS2键盘和PC机通讯程序
// 开机自检程序代码
//======================================================================
void ProcessPS21 ( void )
{
if ( PS2RecChar1 != 0xCC )
{
switch ( PS2RecChar1 )
{
case 0xEE:
{
OnPS2SendChar1 ( 0xEE );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
case 0xFE: //7 //resend
{
PS2RecChar1 = 0xCC;
} break;
case 0xAA: //12
{
OnPS2SendChar1 ( 0xAA );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
case 0xEF: //5
{
OnPS2SendChar1 ( 0xFA );
//Delay_50us () ;
Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;
OnPS2SendChar1 ( 0xBF );
//Delay_50us () ;
Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;
OnPS2SendChar1 ( 0xB0 );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
case 0xF2:
{
OnPS2SendChar1 ( 0xFA );
//Delay_50us () ;
Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;
OnPS2SendChar1 ( 0xAB );
//Delay_50us () ;
Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;
OnPS2SendChar1 ( 0x83 );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
case 0xFF:
{
OnPS2SendChar1 ( 0xFA );
//Delay_50us () ;
Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;Delay_50us () ;
OnPS2SendChar1 ( 0xAA );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
default:
{
OnPS2SendChar1 ( 0xFA );
//Delay_50us () ;
delay_ms ( 1 );
PS2RecChar1 = 0xCC;
} break;
}
}
}
/*
void ProcessPS21 ( void )
{
if( PS2RecChar1 == 0xF3 )//1
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0x00 )//11
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0x02 )//111
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0x20 )//1111
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0xED )//2
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0xF0 )//3
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0xF2 )//4
{
OnPS2SendChar1 ( 0xFA );
// Delay30us();
OnPS2SendChar1 ( 0xAB );
// Delay30us();
OnPS2SendChar1 ( 0x83 );
PS2RecChar1 = 0xCC;
}
else if( PS2RecChar1 == 0xEF )//5
{
OnPS2SendChar1 ( 0xFA );
// Delay30us();
OnPS2SendChar1 ( 0xBF );
// Delay30us();
OnPS2SendChar1 ( 0xB0 );
PS2RecChar1 = 0xCC;
}
else if ( PS2RecChar1 == 0xF3 )//6
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if(PS2RecChar1==0xFE)//7 //resend
{
PS2RecChar1=0xCC;
}
else if(PS2RecChar1 == 0xEE)//8
{
OnPS2SendChar1 ( 0xEE );
PS2RecChar1 = 0xCC;
}
else if(PS2RecChar1 == 0xEE)//9
{
OnPS2SendChar1 ( 0xEE );
PS2RecChar1 = 0xCC;
}
else if (PS2RecChar1 == 0xF1)//10
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if (PS2RecChar1 == 0xF4)//11
{
OnPS2SendChar1 ( 0xFA );
PS2RecChar1 = 0xCC;
}
else if (PS2RecChar1 == 0xAA )//12
{
OnPS2SendChar1 ( 0xAA );
PS2RecChar1 = 0xCC;
}
else if ( PS2RecChar1 == 0xFF )//13
{
OnPS2SendChar1 ( 0xFA );
// Delay30us();
OnPS2SendChar1 ( 0xAA );
// Delay30us();
PS2RecChar1 = 0xCC;
}
else ;
}
*/
/********************************************************************************************************************/
// 主程序
/********************************************************************************************************************/
void main(void)
{
uint8 temp;
uint8 code table[]={0x1c,0x32,0x21,0x23,0x24,0x2b,0x34,0x33,0x43,0x3b}; // A,B,C,D,E,F,G,H,I,J
//PS2Init ( ); //开中断
ctrl0 = 0;
PS2DAT1 = 1;
PS2CLK1 = 1;
init_serial();
while(1)
{
if ( PS2DAT1 == 0 )
{
Delay_50us () ;
if ( PS2DAT1 == 0 )
{
OnPS2ReceChar1 ( );
}
}
if ( PS2RecChar1 != 0xCC )
{
TI=0;
SBUF = PS2RecChar1;
while( !TI );
TI = 0;
Delay_50us () ;
Delay_50us () ;
Delay_50us () ;
ProcessPS21 ( );
}
/*
if ( ctrl0 == 1 ) //不停的发q
{
OnPS2SendChar1 ( 0X15 ); //按下通码
delay_ms ( 2 );
OnPS2SendChar1 ( 0xF0 ); //抬起,断码
delay_ms ( 1 ); //每发一包数据后,时钟会拉低约200us,如果立刻发下一包数据,将被忽略
OnPS2SendChar1 ( 0X15 );
delay_ms ( 1000 );
}
*/
if ( ( ctrl0 == 1 ) && ( flag == TURNON ) ) //发送abcdefghij
{
flag = TURNOFF;
for ( temp = 0; temp < 10; temp ++ )
{
OnPS2SendChar1 ( table[temp] ); //按下通码
delay_ms ( 2 );
OnPS2SendChar1 ( 0xF0 ); //抬起,断码
delay_ms ( 1 ); //每发一包数据后,时钟会拉低约200us,如果立刻发下一包数据,将被忽略
OnPS2SendChar1 ( table[temp] );
delay_ms ( 500 );
}
}
}
}
|
阿莫论坛20周年了!感谢大家的支持与爱护!!
知道什么是神吗?其实神本来也是人,只不过神做了人做不到的事情 所以才成了神。 (头文字D, 杜汶泽)
|