单片机
返回首页

PS2键盘的设计---C51程序

2016-11-09 来源:eefocus

#include

#define Frequence 11   //晶振频率单位是MHZ
#define DELAY 10*Frequence/6 //发送程序延时
#define SLEEP 8*Frequence/6   //发送程序延时
sbit KBCLK='P3'^0; //键盘时钟线
sbit KBDATA='P3'^1; //键盘数据线

bit bat(void);   //基本保证测试无错误返回0,有错返回1
unsigned char buf_length(); //返回缓冲区数据个数
bit command_s(); //键盘命令检查,有命令要接受返回1
void clr_buf(void); //清键盘缓冲区
void del_head(); //删除缓冲区头
unsigned char exist(unsigned char); 
//检查键盘缓冲区中是否有与参数相等数,有则返回位置,无则返回255

//bit emputy(); //检查键盘缓冲区是否空,是返回1
unsigned char get_head(); //取键盘缓冲区头,头指针不变

unsigned char get_head_f();
//取缓冲区头对应标记,标记为0表示对应键已经松下

bit insert(unsigned char,unsigned char);
//插入缓冲区,并设置对应标记,成功则返回1

void ini_timer01(); //定时器初始化
void receive_process(); //接收键盘命令并处理
void reset(); //软件复位
unsigned char scankb(unsigned char); //扫描第N行,返回列直
void send_buf();    //发送缓冲区扫描码

bit send_code(unsigned char _KeyNo,bit flag); 
//发送按键扫描码,flag=0发送断开码,flag=1发送接通码

bit send(unsigned char); //发送数据

void set_default(); //设置缺省值
void set_timer1(); //复位定时器1

void set_scan_v(unsigned char); //设置扫描速度(拍发速率、延迟时间)
void set_flag(unsigned char); //设置缓冲区对应标记
void set_led(unsigned char); //设置LED
void secret(unsigned char);
void scan(void);
unsigned char get_end();
bit emputy(void);

//-----------------------函数声明,变量定义--------------------------------------------------------
#include
#define KEY P1
unsigned char key_code;           //键值
unsigned char key_buf[8];         //按键缓冲区
unsigned char key_COUNT;          //按键计数器
unsigned char COUNT_TI;           //定时中断计数
//-----------------------变量声明---------------------------------------------------------------------
void system_init(void );         //初始化,设置定时器0的工作方式,供主程序调用
void TIMER0_SCANkey();           //定时器0中断处理函数
bit judge_hitkey();              //判断是否有键按下,有返回1,没有返回0
unsigned char scan_key();             //扫描键盘,返回键值(高四位代表行,低四位代表列)
void key_manage(unsigned char keycode); //按键处理
//...........每个按键对应一个处理程序
//--------------------------------------------------------------------------------------------------
// 函数名称: scan_key
// 函数功能: 扫描键盘,返回键值(高四位代表行,低四位代表列)
//            无键按下返回0
//--------------------------------------------------------------------------------------------------
unsigned char scan_key()              //扫描键盘,返回键值(高四位代表行,低四位代表列)
{
   unsigned char scancode,keycode,keycode_line,keycode_row;
   scancode='0xF0';                      //列置低,行置高
   KEY='scancode';                       //输入扫描码,扫描行
   keycode_line=KEY;
   scancode='0xF0';                        //列置高,行置低
   KEY='scancode';                       //输入扫描码,扫描列
   keycode_row=KEY;
   keycode=(((keycode_line<<4)&0xF0)|(keycode_row&0x0F));
   return(keycode);
   }
//--------------------------------------------------------------------------------------------------
// 函数名称: Timer0_init()
// 函数功能: 初始化设置
//            设定INT0的工作方式
//--------------------------------------------------------------------------------------------------
void Timer0_init(void ) 
             {
              TMOD='0x20'; //定时器0工作在方式2的定时模式
              ET0=1;     //定时器0中断允许
              TH0=0;
              TL0=0;
              TR0=1;     //定时器0开始计数
              EA='1';      //系统中断允许
              }
//--------------------------------------------------------------------------------------------------
// 函数名称: TIMER0_intrupt
// 函数功能: 定时器0中断处理程序 按键定时查询
//--------------------------------------------------------------------------------------------------
void TIMER0_SCANkey() interrupt 1 using 1
              {
               EA='0';                        //系统中断禁止
      if((++COUNT_TI)%30==0)
      {
      switch(COUNT_TI/30)
      {
       case 1:if(scan_key()==0) 
               COUNT_TI=0;          //无键按下,计数值归零
        break;
       case 2:break;
       case 3:if(scan_key()==0)
              COUNT_TI=0;           //无键按下,计数值归零,上次按键未扰动
        else 
        key_code=scan_key(); //又有效建,获取键值
       break;
          default:if(scan_key()==0)    //等待按键释放
              key_manage(key_code); //有一个有效按键,调用按键处理程序
        }
     }
   EA=1;
      }
//--------------------------------------------------------------------------------------------------
// 函数名称: key_manage
// 函数功能: 有效按键处理
//            按键计数器加1,缓存区数据后移1位
//--------------------------------------------------------------------------------------------------
void key_manage(unsigned char keycode)
      {
      unsigned char i;
   for(i=7;i>=0;i--)
   {
    key_buf[i]=key_buf[i-1];       //缓冲区内数据后移1位
   }
   key_buf[0]= keycode;            //将键值送入缓冲区
      key_COUNT++;                   //按键计数器加一
   }

 

//-----------------------函数声明,变量定义--------------------------------------------------------
#include
#define KEY P1
sbit DATA='P3'^1;       //数据线
sbit CLK='P3'^2;        //时钟线
unsigned char key_buf[8];         //按键缓冲区
unsigned char key_COUNT;          //按键计数器
//--------------------------------------------------------------------------------------------------
// 函数名称: delay
// 入口参数: N
// 函数功能:延时子程序,实现(16*N+24)us的延时 
// 系统采用11.0592MHz的时钟时,延时满足要求,其它情况需要改动
//--------------------------------------------------------------------------------------------------
void delay(unsigned int N) 
{
int i; 
for(i=0;i }
//--------------------------------------------------------------------------------------------------
// 函数名称: CAL_jiaoyan
// 函数功能: 计算校验位
//--------------------------------------------------------------------------------------------------
bit CAL_jiaoyan(unsigned char byte_data)
   {
   //
    }
//--------------------------------------------------------------------------------------------------
// 函数名称: SEND_byte
// 函数功能: 发送一子节数据
//--------------------------------------------------------------------------------------------------
void SEND_byte(unsigned char byte_data)
      {
unsigned char i,temp;
   if(CLK==0)             //时钟线为低

   temp='byte'_data;
   CLK='1';
   DATA='0';
   delay(0);
   CLK='0';           //发送起始位
   for(i=0;i<8;i++)
      {
            delay(0);
         CLK='1'; 
    DATA=(temp&0x01); //发送数据
            byte_data=byte_data>>1; 
    delay(0);
    CLK=0; 
    }
      delay(0);
         CLK='1'; 
    DATA=CAL_jiaoyan(byte_data); //发送校验位
         delay(0);
    CLK=0; 
             delay(0);
         CLK='1'; 
    DATA=1;                     //发送结束位
         delay(0);
    CLK=0; 
   }
//--------------------------------------------------------------------------------------------------
// 函数名称: RECEIVE_byte
// 函数功能: 接收一子节数据
//--------------------------------------------------------------------------------------------------
unsigned char RECEIVE_byte()
      {
     unsigned char byte_data,i;
   CLK='0';
   delay(0);
   CLK='1';                   //接收起始位,丢弃
   for(i=0;i<8;i++)
      {
            delay(0);
         CLK='0'; 
    delay(0);
    CLK=1;
    byte_data=byte_data>>1;
    if(DATA=1)
            byte_data=byte_data|0x80;
    else 
    byte_data=byte_data&0x7F; //接收8位数据
     }
   for(i=0;i<2;i++)
      {
            delay(0);         //接收校验位和结束位
         CLK='0'; 
    delay(0);
    CLK=1;
   }   
   return(byte_data);
}
//--------------------------------------------------------------------------------------------------
// 函数名称: manage
// 函数功能: 主机命令处理函数
//--------------------------------------------------------------------------------------------------
void manage(unsigned char rec_data)
    {
}
//--------------------------------------------------------------------------------------------------
// 函数名称: SEND_keydata
// 函数功能: 发送按键值到主机
//--------------------------------------------------------------------------------------------------
void SEND_keydata()
     {
unsigned char ASCII_code;       //
// ASCII_code=judge_key(key_buf[key_COUNT]); //判断键值,按键编码成ASCII码
SEND_byte(ASCII_code);
key_COUNT--;
}
//--------------------------------------------------------------------------------------------------
// 函数名称: 主程序
// 函数功能: 循环查询主机状态
//--------------------------------------------------------------------------------------------------
void main()
    {
unsigned char rec_data;
while(1)
{
if(CLK==0&&DATA==0)
    {
rec_data=RECEIVE_byte();       //接收主机键盘
    manage(rec_data);              //指令处理函数
}
if(key_COUNT!=0&&CLK==1)     //有按键等待处理
                                       //线路空闲
   SEND_keydata();
    }
}

进入单片机查看更多内容>>
相关视频
  • RISC-V嵌入式系统开发

  • SOC系统级芯片设计实验

  • 云龙51单片机实训视频教程(王云,字幕版)

  • 2022 Digi-Key KOL 系列: 你见过1GHz主频的单片机吗?Teensy 4.1开发板介绍

  • TI 新一代 C2000™ 微控制器:全方位助力伺服及马达驱动应用

  • MSP430电容触摸技术 - 防水Demo演示

精选电路图
  • 家用电源无载自动断电装置的设计与制作

  • 短波AM发射器电路设计图

  • 带有短路保护系统的5V直流稳压电源电路图

  • 如何调制IC555振荡器

  • 基于ICL296的大电流开关稳压器电源电路

  • 基于TDA2003的简单低功耗汽车立体声放大器电路

    相关电子头条文章