📄 ps2键盘(at45db011).c
字号:
}
case 0x03:
{
while(Send_1Byte_To_PS2_Port(0xe0)==0) {} //通码首字节
while(Send_1Byte_To_PS2_Port(0xf0)==0) {} //断码字节
while(Send_1Byte_To_PS2_Port(0x7c)==0) {}
while(Send_1Byte_To_PS2_Port(0xe0)==0) {}
while(Send_1Byte_To_PS2_Port(0xf0)==0) {}
while(Send_1Byte_To_PS2_Port(0x12)==0) {} //通码下1个字节
break;
}
default:
{
//while(Send_1Byte_To_PS2_Port(0x4a)==0) {}
Key_Send_Buffer_PlacPoint=0;
break;
}
}
}
//========================================放置键按下码================================================
void Find_OnKey_Position(unsigned char Key_SWitch)
{
if(First_Key_Number[2]==Key_SWitch)
{
//Shift_Store_Data(&First_Key_Number[0],Key_SWitch);
First_Key_Number[0]=First_Key_Number[1]; //如果当前按下键是上一次的继续,继续移位存放
First_Key_Number[1]=First_Key_Number[2];
First_Key_Number[2]=Key_SWitch;
return;
}
else if(Second_Key_Number[2]==Key_SWitch)
{
//Shift_Store_Data(&Second_Key_Number[0],Key_SWitch);
Second_Key_Number[0]=Second_Key_Number[1];
Second_Key_Number[1]=Second_Key_Number[2];
Second_Key_Number[2]=Key_SWitch;
return;
}
else if(Third_Key_Number[2]==Key_SWitch)
{
//Shift_Store_Data(&Third_Key_Number[0],Key_SWitch);
Third_Key_Number[0]=Third_Key_Number[1];
Third_Key_Number[1]=Third_Key_Number[2];
Third_Key_Number[2]=Key_SWitch;
return;
}
else if((First_Key_Number[0]==0xff)&&(First_Key_Number[1]==0xff)&&(First_Key_Number[2]==0xff) //如果该键未曾按下过,查找存放位置
&&(Second_Key_Number[0]==0xff)&&(Second_Key_Number[1]==0xff)&&(Second_Key_Number[2]==0xff)
&&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
{
//Shift_Store_Data(&First_Key_Number[0],Key_SWitch);
First_Key_Number[0]=First_Key_Number[1]; //如果当前按下键是上一次的继续,继续移位存放
First_Key_Number[1]=First_Key_Number[2];
First_Key_Number[2]=Key_SWitch;
}
else if(((First_Key_Number[0]!=0xff)||(First_Key_Number[1]!=0xff)||(First_Key_Number[2]!=0xff)) //如果该键未曾按下过,查找存放位置
&&(Second_Key_Number[0]==0xff)&&(Second_Key_Number[1]==0xff)&&(Second_Key_Number[2]==0xff)
&&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
{
//Shift_Store_Data(&Second_Key_Number[0],Key_SWitch);
Second_Key_Number[0]=Second_Key_Number[1]; //如果当前按下键是上一次的继续,继续移位存放
Second_Key_Number[1]=Second_Key_Number[2];
Second_Key_Number[2]=Key_SWitch;
}
else if((((First_Key_Number[0]!=0xff)||(First_Key_Number[1]!=0xff)||(First_Key_Number[2]!=0xff)) //如果该键未曾按下过,查找存放位置
&&((Second_Key_Number[0]!=0xff)||(Second_Key_Number[1]!=0xff)||(Second_Key_Number[2]!=0xff)))
&&(Third_Key_Number[0]==0xff)&&(Third_Key_Number[1]==0xff)&&(Third_Key_Number[2]==0xff))
{
//Shift_Store_Data(&Third_Key_Number[0],Key_SWitch);
Third_Key_Number[0]=Third_Key_Number[1]; //如果当前按下键是上一次的继续,继续移位存放
Third_Key_Number[1]=Third_Key_Number[2];
Third_Key_Number[2]=Key_SWitch;
}
}
//========================================放置键释放码================================================
void Find_OffKey_Position(unsigned char Key_SWitch)
{
if((First_Key_Number[0]==Key_SWitch)||(First_Key_Number[1]==Key_SWitch)||(First_Key_Number[2]==Key_SWitch))
{
//Shift_Store_Data(&First_Key_Number[0],0xff);
First_Key_Number[0]=First_Key_Number[1];
First_Key_Number[1]=First_Key_Number[2];
First_Key_Number[2]=0xff;
}
else if((Second_Key_Number[0]==Key_SWitch)||(Second_Key_Number[1]==Key_SWitch)||(Second_Key_Number[2]==Key_SWitch))
{
//Shift_Store_Data(&Second_Key_Number[0],0xff);
Second_Key_Number[0]=Second_Key_Number[1];
Second_Key_Number[1]=Second_Key_Number[2];
Second_Key_Number[2]=0xff;
}
else if((Third_Key_Number[0]==Key_SWitch)||(Third_Key_Number[1]==Key_SWitch)||(Third_Key_Number[2]==Key_SWitch))
{
//Shift_Store_Data(&Third_Key_Number[0],0xff);
Third_Key_Number[0]=Third_Key_Number[1]; //这条指令占用3个字节
Third_Key_Number[1]=Third_Key_Number[2];
Third_Key_Number[2]=0xff; //这条指令占用3个字节
}
}
//=====================================移位存数函数===================================
//注意:创建这个函数需要40个字节,很不划算。
/*
void Shift_Store_Data(unsigned char *StoreAddr,unsigned char StoreData)
{
StoreAddr[0]=StoreAddr[1];
StoreAddr[1]=StoreAddr[2];
StoreAddr[2]=StoreData;
}
*/
//========================装载键定义处理函数=======================================================
//返回值说明:
// 0x0 = 无键定义
// 0x1 = 有键定义且是单字节单键 须发断码
// 0x2 = 有键定义且是双字节单键 须发断码
// 0x3 = 有键定义且是四字节Prnt Scrn单键 须发断码
// 0x4 = 有键定义且是Pause单键或复合建 不发断码
unsigned char Load_TKey_Define(unsigned char Key_Num)
{
unsigned char i;
unsigned char k;
ReadOnePageToBuffer(Key_Num); //读该键的定义码到Buffer2,整页读
k=ReadByteFromBuffer(0x00);
if(k==0xe0) //如果是0xe0打头
{
Nop_Key_Flag=1; //有键
for(i=1;;)
{
k=ReadNextFromBuffer();
if((k==0)||(k==0xff)) break;
i++;
}
SPI45DB041_CS=1;
if(i==1)
{
Nop_Key_Flag=0;
return(0x00); //错误键定义
}
else if(i==2)
{
Key_Send_Buffer_PlacPoint=0;
return(0x02); //如果是0xe0打头且只是2个字节,说明是
//双字节特殊功能键,释放时须发断码
}
else if(i==4)
{
k=ReadByteFromBuffer(0x01);
SPI45DB041_CS=1;
if(k!=0x12)
{
Key_Send_Buffer_PlacPoint=i;
return(i);
}
k=ReadByteFromBuffer(0x02);
SPI45DB041_CS=1;
if(k!=0xe0)
{
Key_Send_Buffer_PlacPoint=i;
return(i);
}
k=ReadByteFromBuffer(0x03);
SPI45DB041_CS=1;
if(k!=0x7c)
{
Key_Send_Buffer_PlacPoint=i;
return(i);
}
return(0x03);
}
else
{
Key_Send_Buffer_PlacPoint=i;
return(0x04); //
}
}
else if((k==0)||(k==0xff))
{
SPI45DB041_CS=1;
Nop_Key_Flag=0;
return(0x0); //说明无键定义
}
Nop_Key_Flag=1; //有键
for(i=1;;)
{
k=ReadNextFromBuffer();
if((k==0)||(k==0xff)) break;
i++;
}
SPI45DB041_CS=1;
if(i==1) return(0x01);
else
{
Key_Send_Buffer_PlacPoint=i;
return(0x04);
}
}
//========================蜂鸣器鸣响启动函数=======================================================
void Drived_Buzz(unsigned int HLen)
{
Buzz_Rs232_Flag=1; //设为Buzz模式
Buzz_Timer=0; //这个定时就取T1中断的次数,因为T0已经关闭
TR0=0;
TR1=1;
while(Buzz_Timer<HLen) {} //经过测定,所用蜂鸣器在f=3.125KHz时比较合适,这个值已反复调试,勿改
//示波器测得f=3.125KHz
TR1=0;
TR0=1;
BUZZ=1;
Buzz_Rs232_Flag=0;
Buzz_Timer=0;
}
//========================上电/复位初始化键盘======================================================
void Ini_KeyBoard(void)
{
unsigned char k;
ReadOnePageToBuffer(SYSTEM_PARA_PAGE_FLASH);
k=ReadByteFromBuffer(KEYCODED_TABLE);
SPI45DB041_CS=1;
if(k==0x0) Keycoded_Table=0;
else Keycoded_Table=1;
System_Status_Reg=(~ReadByteFromBuffer(SYSYTEM_STATUS_BYTE));
SPI45DB041_CS=1;
}
//============================限时读PS2口=========================================================
//规定时间内读到返回1,没读到返回0
bit TRead_PS2_Port(unsigned char RDPS2Time)
{
Code_Reci_Data_Timing=0;
while(1)
{
if(PS2_RXD==0) break;
if(Code_Reci_Data_Timing > RDPS2Time) return(0);
}
if(Read_PS2_Port()==0) return(0);
return(1); //
}
//========================从PS2口读一个字节========================================================
//正确读到数据时返回1,数据在Key_Reciver_Buffer中
//
bit Read_PS2_Port(void)
{
bit cp;
unsigned char i;
cp=0;
i=0;
//while(PS2_RXD==1) //等待主机拉低数据线提出发送请求
while(PS2_TXD==0) {} //等待主机释放时钟线
//开始读
TR0=0;
Delay_uS_Time(15); //维持高40微妙
for(i=0;i<8;i++)
{
Key_Reciver_Buffer=Key_Reciver_Buffer>>1;
PS2_TXD=0; //拉低时钟,主机发送第1个数据位
Delay_uS_Time(15); //维持低电平40微妙
PS2_TXD=1; //拉高通告主机,设备已读取数据
if(PS2_RXD==1) Key_Reciver_Buffer=(Key_Reciver_Buffer|0x80); //读数据位
if(Check_PC_Cancle_Send()==0)
{
TR0=1;
return(0);
}
}
PS2_TXD=0; //拉低时钟,主机发送校验位
Delay_uS_Time(15); //延迟20微妙
PS2_TXD=1;
if(PS2_RXD==1) cp=1; //读校验位
ACC=Key_Reciver_Buffer;
if(P!=(!cp))
{
TR0=1;
return(0);
}
if(Check_PC_Cancle_Send()==0)
{
TR0=1;
return(0);
}
PS2_TXD=0;
Delay_uS_Time(15); //延迟20微妙
PS2_TXD=1;
if(PS2_RXD==0) //等待主机拉高数据线,实际上是读停止位
{
TR0=1;
return(0);
}
Delay_uS_Time(7);
PS2_RXD=0; //送应答ACK位
Delay_uS_Time(7); //延迟40微妙
PS2_TXD=0;
Delay_uS_Time(15); //延迟40微妙
PS2_TXD=1; //释放时钟线
PS2_RXD=1; //释放数据线
while(PS2_RXD==0)
{
//PS2_TXD=0;
//Delay_uS_Time(15);
//PS2_TXD=1; //继续发脉冲等待主机释放时钟线
//Delay_uS_Time(15);
}
TR0=1;
Delay_uS_Time(30);
return(1);
}
//高点平期间检查主机是否放弃传送,放弃返回0
bit Check_PC_Cancle_Send(void)
{
unsigned char i;
for(i=0;i<19;i++)
{
if(PS2_TXD==0) return(0);
}
return(1);
}
//========================发送一个字节到PS2口======================================================
//A发送成功返回1,失败返回0
//=================================================================================================
bit Send_1Byte_To_PS2_Port(unsigned char SendData)
{
bit cp=0;
unsigned char i;
unsigned char h;
WDT_CONTR=0x37;
h=SendData;
Last_Send_To_Ps2_Word=h; //保存发送的字节以便重发
if((PS2_TXD==1)&&(PS2_RXD==1))
{
TR0=0; //关闭定时器,以免影响时序
PS2_RXD=0;
Delay_uS_Time(7); //
ACC=h;
if(P==0) cp=1; //如果数据位中包含偶数个1 校验位就会置1 如果数据位中
//包含奇数个1 校验位就会置0 数据位中1 的个数加上校验
//位总为奇数这就是奇校验这是用来错误检测
else cp=0;
/*
Code_Reci_Data_Timing=0;
while(1)
{
if((PS2_TXD==1)&&(PS2_RXD==1)) break;
if((Code_Reci_Data_Timing>20)||(PS2_RXD==0)||(PS2_TXD==0))
{
return(0); //20毫秒内主机无反应返回失败
}
}
*/
//PS2_RXD=0;
Send_1Bit_To_PS2_Port(0x00); //发送起始位
for(i=0;i<8;i++)
{
Send_1Bit_To_PS2_Port(h); //发送8位数据
h=h>>1;
}
if(cp==0) Send_1Bit_To_PS2_Port(0x0); //发校验位
else Send_1Bit_To_PS2_Port(0x01);
Send_1Bit_To_PS2_Port(0x01); //发停止位
TR0=1;
Delay_uS_Time(50); //
return(1);
}
return(0);
}
//========================发送一个bit到PS2口======================================================
void Send_1Bit_To_PS2_Port(unsigned char Send_Bit)
{
if((Send_Bit&0x01)!=0) PS2_RXD=1;
else PS2_RXD=0;
_nop_();
PS2_TXD=0;
Delay_uS_Time(14); //延迟40微妙
PS2_TXD=1;
Delay_uS_Time(12);
}
/********************************************************\
* 函数名:SPI45D041_ReadByte
作用域:本文件调用
* 功能: SPI_SCK下降沿数据有效,读一个字节数据
* 参数: 无
\********************************************************/
unsigned char SPI45D041_ReadByte(void)
{
unsigned char count,byte;
for(count=0;count<8;count++)
{
SPI45DB041_SCK=1;
byte<<=1;
SPI45DB041_SCK=0;
if(SPI45DB041_SO) byte++;
}
return(byte);
}
/********************************************************\
* 函数名:SPI45D041_WriteBits
作用域:本文件调用
* 功能: 对一个int型的数据(16位)依次右移,并放在FLASH的输入脚上
* 参数: byte 一个int的数
num_of_bits 针对上面的int型的数据,依次向右移出的bit数
* 返回值:无
SPI_SCK上升沿数据有效
针对bit的数据操作:通过SI口,写入一个字节的多少bit
\********************************************************/
void SPI45D041_WriteBits(unsigned int byte,unsigned char num_of_bits)
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -