📄 hello.c
字号:
/*------------------------------------------------------------------------------
KB.C
说明:此程序为一简单键盘模拟程序.适用于8051系列单片机
扫描码标准为国际第二通用扫描码,无任何粘连键及扩展键.
Copyright 2006 chuangxin
------------------------------------------------------------------------------*/
/* for the intended 8051 derivative */
#include <stdio.h> /* prototype declarations for I/O functions */
#include <AT89X51.h>
#define CLK P1_2
#define DATA P1_1
unsigned char Code = 0x00;
int enCode =0; //按键扫描成功标记
int realse =0;
unsigned char error = 0;
unsigned char RCode = 0x00;
unsigned char test = 0;
/*-----------------------------------------------
函数声明部分
------------------------------------------------*/
void ScanCode();
void Delay10ms();
void SendByte(unsigned char a );
void KBClk();
void DelayNus(unsigned char i);
unsigned char RecieveByte();
unsigned char C_Command();
/*------------------------------------------------
The main C function. Program execution starts
here after stack initialization.
------------------------------------------------*/
void main () {
//扫描码
int Command = 0; //命令输出标志
//TMOD = 0x61;//0x20; //定时器1定时方式2
SCON = 0x50;
//TCON = 0x40; //定时器1开始计数
//TH0 = 65490/256;//0xD7; //计数32us 此位保存TL1初始值
// TL0 = 65490%256;//0xD //起动定时器
CLK =1;
DATA =1;
P1_4 =0;
SendByte(0xAA); //键盘自检完毕
while (1) {
if(C_Command()){
RCode =RecieveByte();
switch(RCode){
case 0xF2:
SendByte(0xFA);
SendByte(0xAB);
SendByte(0x83);
break;
case 0xEE:
SendByte(0xEE);
break;
case 0x00:
SendByte(0xFA);
P1_4 = 1; //关掉指示灯
break;
case 0x02:
SendByte(0xFA);
P1_4 =0; //打开指示灯
break;
case 0xFF:
SendByte(0xFA);
SendByte(0xAA);
break;
case 0xFE:
SendByte(0xFA);
SendByte(Code);
break;
default:
SendByte(0xFA);
break;
}
}
enCode = 0;
if(CLK & DATA){
ScanCode();
if(enCode)
{
SendByte(Code);
}
if(realse){
SendByte(0xF0);
SendByte(Code);
realse = 0;
}
}
}
}
/*-----------------------------------------------
unsigned char ScanCode()
说明:按键扫描函数
参数:无
返回:unsigned char
功能:返回按键编码
------------------------------------------------*/
void ScanCode(){
unsigned char i =0;
Code = 0x1C; //A键的扫描码因为只用一个K3按键
P3_4 = 1;
if(P3_4 == 0){ //如果有键按下
Delay10ms(); //延时10ms
if(P3_4 == 0) //确定有键按下
{
enCode = 1; //可以发送数据了
Delay10ms(); //等待10ms让释放按键
realse = 1;
}
else
return ;
}
return ;
}
/*-----------------------------------------------
void DelayNms()
说明:延时程序
参数:无
返回:无
功能:延时
------------------------------------------------*/
void Delay10ms(){
unsigned char dly1 = 1;
unsigned char dly2 = 215;
while(dly1++){
while(dly2++);
}
}
void Delay40us(){
unsigned char i;
for(i = 59;i >0; i--);
}
void Delay20us(){
unsigned char i;
for(i = 30;i >0; i--);
}
void Delay50us(){
unsigned char i;
for(i = 74;i >0; i--);
}
void Delay5us(){
unsigned char i;
for(i = 8;i >0; i--);
}
void Delay15us(){
unsigned char i;
for(i = 23;i >0; i--);
}
/*-----------------------------------------------
void KBClk()
说明:键盘时钟脉冲生成函数
参数:无
返回:无
功能:生成键盘时钟脉冲,高40us,低40us
------------------------------------------------*/
void KBClk() interrupt 1 using 1 {
unsigned int edgeCg = 1;
unsigned char a =1;
CLK = !CLK;
TH0 = 65490/256;//0xD7; //计数32us 此位保存TL1初始值
TL0 = 65490%256;
}
/*-----------------------------------------------
void SendByte(unsigned char ScanCode)
说明:键盘发送一个字节
参数:unsigned char
返回:无
功能:键盘发送数据
------------------------------------------------*/
void SendByte(unsigned char scanCode){
int i;
int ood;
CLK =1;
wait: while(!CLK);
//等待时钟为高
Delay50us();
if(!CLK)
goto wait;
if(!DATA) //数据线不为高就退出
return;
Delay20us(); //延时20us
DATA =0;
Delay20us();//延时20us
if(!CLK)
return ; //主机阻止发送
CLK =0; //输出起始位
Delay40us();//延时40us
CLK =1;
Delay20us();//延时20us
for(i = 0; i < 8; i++){ //循环输出八位数据
while(CLK){
if(scanCode&0x01)
{ DATA =1; ood++;}
else
DATA =0;
scanCode >>=1;
Delay20us();//延时20us
if(!CLK)
return ; //主机阻止发送
CLK =0;
Delay40us();//延时40us
}
CLK =1; //输出脉冲
Delay20us();//延时20us
} //八位输出完毕
if(ood%2) //奇校验位如果有偶数个1则输出为1
DATA = 1;
else
DATA =0; //输出脉冲
Delay20us();//延时40us
if(!CLK)
return ; //主机阻止发送
CLK =0;
Delay40us();//延时40us
CLK = 1;
Delay20us();//延时20us
DATA =1; //输出结束位
Delay20us();//延时20us
CLK = 0;
Delay40us();//延时40us
CLK =1;
Delay20us();//延时20us
Delay15us(); //延时30us
Delay15us();
return;
}
/*-----------------------------------------------
unsigned char ReceieveByte()
说明:键盘接收一个字节
参数:无
返回:unsigned char
功能:键盘接收数据
------------------------------------------------*/
unsigned char RecieveByte(){
unsigned char recieveData =0x00;
unsigned char i;
unsigned char ood;
unsigned char oodRight;
while(!CLK); //等待时钟为高
if(DATA) //等待数据为低
{return 0xfe;}
/*DelayNus(30); //延时20us
CLK = 0; // 将时钟线拉低
DelayNus(59); //延时40us
CLK =1; //释放时钟线
DelayNus(30); //延时20us
//接收起始位 */
for(i = 0;i <8;i++){
Delay20us(); //延时20us
CLK = 0; // 将时钟线拉低
Delay40us(); //延时40us
CLK =1; //释放时钟线
Delay20us(); //延时20us
recieveData>>=1;
/*读八位数据*/
if(DATA){
recieveData = recieveData | 0x80;
ood++;
}
else
recieveData = recieveData &0x7F;
if(!CLK)
return 0xfe;
}
Delay20us(); //延时20us
CLK = 0; // 将时钟线拉低
Delay40us(); //延时40us
CLK =1; //释放时钟线
Delay20us(); //延时20us
if(ood == DATA)
oodRight =1;
else
oodRight =0; //接收校验位
if(!CLK)
return 0xfe;
Delay20us(); //延时20us
CLK = 0; // 将时钟线拉低
Delay40us(); //延时40us
CLK =1; //释放时钟线
Delay20us(); //延时20us
//接收结束位
if(!DATA)
return 0xfe;
// if(!DATA) //如果数据线还为0高,等待主机拉高
// return 0; //发生了错误
//发送应答位
Delay15us(); //延时15us
DATA =0; //把数据线拉低
Delay5us(); //延时5us
CLK =0;
Delay40us(); // 延时40us
CLK =1;
Delay5us(); //延时5us
DATA =1;
/*检验校验位是否正确,不正确就产生一个错误*/
if(!oodRight)
error = 1;
Delay40us(); //延时45us
Delay5us();
return recieveData;
}
/*-----------------------------------------------
unsigned char C_Command()
说明:判断主机是否要发送命令
参数:无
返回:unsigned char
功能:判断主机是否要发送命令
--------------------------------------------------*/
unsigned char C_Command(){
DATA =1;
CLK =1;
if(!DATA)
return 1;
else
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -