原创 51 PS2键盘控制LCD12864 实验(二十一)

2008-5-12 11:45 4877 6 7 分类: MCU/ 嵌入式

点击下载


这个实验利用键盘控制单片机,然后把实验结果显示到lcd12864上,详情见附件


平台:FDR-1 51 开发板


主程序代码:


#include
#include"led.h"                //该头文件包含数码管显示数字驱动
#include"tg12864p.h"                                                  //该头文件包含lcd12864驱动   


sbit dat =P3^2;//DATA IN


#define uchar unsigned char                                            // 即 uchar等同与unsigned char
#define uint unsigned int                  
uchar sp2key_scan();  
/*****************常量声明区******************************************/
uchar code key_table[47]={
                     '0','1','2','3','4','5','6','7','8','9',        
                     'a','b','c','d','e','f','g','h','i','j',
      'k','l','m','n','o','p','q','r','s','t',   //说明:存放键盘上按键的as2码值
      'u','v','w','x','y','z',' ','-','=',']',
                      ';','"',',','.','/','[',' '         //作用:方便日后传值到液晶上
       };  


 /****************全局变量声明区************************************/
uchar key="0";       //用于存放键盘解码函数的解码结果
uchar key_temp=0;              
bit   BF="0";     //接收到通码的标志位
uchar key_count=0; //记录键盘传任一个数据时传来时钟脉冲个数 
uchar key_buffer[5]={0,0,0,0,0};//接收键盘传来数据的缓冲区
uchar key_num=0;//一个按键动作,键盘会发出通码,段吗,这用于记录收到编码个数。
                //可以参考附带的ps2.pdf第54页
 
/*************        键盘接收解码程序    *******************************
这是本程序的核心函数,用于键盘解码。建议读者参考附带的pse.pdf第54页
了解键盘ps2协议,理解通码、断码概念以及发送编码个数。
******************************************************************/   
void  key_dec() interrupt 2 using 0
{    
 if ((key_count>0)&&(key_count<9))
 {   
  key_temp>>=1; 
  if (dat==1)key_temp|=0x80;  
 }
 key_count++;   
 if (key_count>10) 
 {                    
  key_buffer[key_num]=key_temp; //将获得的数据写入缓冲区
  key_temp=0;
  key_num++;
  key_num%=5;         //不会超过五个码
  if(key_buffer[0]<0xe0) //收到通码或结束码
  {
   if(key_num==1) //若是通码
   {
    if(!BF)    
    {  //置标志位
     BF=1; //清空缓冲区,准备接收下一个按键发来的码
     key=key_buffer[0];
    }
   }
   if(key_num>1&&key_buffer[key_num-1]==key_buffer[0])key_num=0;  //收到结束码
  }
  else
  {
   if(key_num==2) //收到通码或结束码
   {    
    if(!BF) //若是通码               
    {         //置标志位若置标志位是通码
     BF=1;         //清空缓冲区,准备接收下一个按键发来的码
     key=key_buffer[1];
    }
   }
   if(key_num>2&&key_buffer[key_num-1]==key_buffer[1])key_num=0;//收到结束码
  }
  key_count=0;  
 }        
}


/****************   键盘初始化函数 ***********************/


void init_keyboard()
{
 TCON=0x04;                 //外部中断低电平触发
 IE  =132;              //开启外部中断1
                                                          //不修改当前的优先级  
}
    
  /**********************       键值转换函数   **********************
  主要用于将接收到的编码量化键值,以备以后分类处理。
  返回数据:  量化后的键值
  *******************************************************************/ 
 
  
uchar sp2key_scan() 
{
    unsigned char temp2,k=255;
    if(BF==1)      //如果收到
    {     //清除接收到通码的标志位,键盘可以继续接收数据
       BF="0";                                     
         temp2=key;
        switch ( temp2 ) 
     {    
      case 0x45: k="0";  break; //0
      case 0x16: k="1";  break; //1
      case 0x1e: k="2";  break; //2
      case 0x26: k="3";  break; //3
      case 0x25: k="4";  break; //4
      case 0x2e: k="5";  break; //5                          
      case 0x36: k="6";  break; //6
      case 0x3d: k="7";  break; //7
      case 0x3e: k="8";  break; //8
      case 0x46: k="9";  break; //9
      case 0x1c: k="10"; break; //a
      case 0x32: k="11"; break; //b
      case 0x21: k="12"; break; //c
      case 0x23: k="13"; break; //d
      case 0x24: k="14"; break; //e
      case 0x2b: k="15"; break; //f
      case 0x34: k="16"; break; //g
      case 0x33: k="17"; break; //h
      case 0x43: k="18"; break; //i
      case 0x3b: k="19"; break; //j
      case 0x42: k="20"; break; //k
      case 0x4b: k="21"; break; //l
      case 0x3a: k="22"; break; //m
      case 0x31: k="23"; break; //n
      case 0x44: k="24"; break; //o
      case 0x4d: k="25"; break; //p
      case 0x15: k="26"; break; //q
      case 0x2d: k="27"; break; //r
      case 0x1b: k="28"; break; //s
      case 0x2c: k="29"; break; //t
      case 0x3c: k="30"; break; //u
      case 0x2a: k="31"; break; //v
      case 0x1d: k="32"; break; //w
      case 0x22: k="33"; break; //x
      case 0x35: k="34"; break; //y
      case 0x1a: k="35"; break; //z     
      case 0x0e: k="36"; break; //~
      case 0x4e: k="37"; break; //-
      case 0x55: k="38"; break; //=     
      case 0x29: k="46"; break; //SPACE
      case 0x66: k="47";break; //del
      case 0x5b: k="39";break; //]  
      case 0x4c: k="40";break;//;
      case 0x52: k="41";break;// '
      case 0x41: k="42"; break; //,
      case 0x49: k="43";break;//.
      case 0x4a: k="44";break; // / 
            case 0x54: k="45"; break; //[ 
   case 0x58: k="49"; break; //cap
   case 0x5a: k="48"; break; //回车键


   case 112 : k="0" ; break; //小键盘部分
   case 105 : k="1" ; break;
   case 114 : k="2" ; break;
   case 122 : k="3" ; break;
   case 107 : k="4" ; break; 
   case 115 : k="5" ; break;
   case 116 : k="6" ; break;
   case 108 : k="7" ; break;
   case 117 : k="8" ; break;
   case 125 : k="9" ; break;
   case 113 : k="43" ; break;;


      default : k="255";
    }
   
 }
 return k;        
}  
/************************* 输入显示函数****************************************
                  将输入数据显示在12864上
      data 输入字符的asc2码值,
      positon   是当前坐标
*******************************************************************************/
void input(uchar dat,uchar position)
{
 switch(position)
 {    
  case 16:Location_xy_12864(1,0); break;
  case 32:Location_xy_12864(2,0); break;
  case 48:Location_xy_12864(3,0); break;
 }
 Write_Char_12864(dat);
}
void  main()
{
 uchar t="0",
 temp=0,
 pos=0,            //记录输入光标位置 ,输入一个字母或数字,光标加一
 cap=0;
 temp=200; 
 while(temp--); 
 init_keyboard();
 Init_12864();
 delay10us(1000); 
 while(1)
 {  
  temp=sp2key_scan();
  if(temp!=255)
  {
   t=temp;
   if(t<48) //输入为字母或其他符号                                          
   {   
    if(pos==64)
    {
     pos=0;
     LcmClearTXT(); 
    }
    if(t==47)     //删除
    {
     if(pos)
     {      
      Lcm_clear_char(pos);
      if((pos%2))pos-=1;
      if(pos)pos--;
     }  
    } 
    else              
    {   
     temp=key_table[t];
     if(t>9&&t<36)temp-=cap*32; //如果输入为字符,根据cap 令显示为大写或小写  
     input(temp,pos);
     pos++;        
    }  
   }
   if(t==48)                                                        //换行
   {                 
    if(pos<48)
    {
     pos+=16;
     Location_xy_12864(pos/16,(pos%16)/2);
    }
    else
    {
     LcmClearTXT();
     pos=0;
    } 
   }
   if(t==49)cap=!cap;//cap:大小写转换
  }                        
 }  

PARTNER CONTENT

文章评论1条评论)

登录后参与讨论

用户31424 2010-3-25 09:58

请问能发下“建议读者参考附带的pse.pdf第54页”这个pdf文件到我邮箱吗?liangzanyao06@163.com
相关推荐阅读
正点原子 2013-05-17 23:47
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十一章 战舰STM32开发板综合实验(标准例程终结篇)
   第六十一章 战舰STM32开发板综合实验        前面已经给大家讲了55个实例了,本章将设计一个综合实例,作为本指南的最后一个实验 ,该实验向大家展示了STM...
正点原子 2013-05-03 23:02
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第六十章 UCOSII实验3-消息队列、信号量集和软件定时器
   第六十章 UCOSII实验3-消息队列、信号量集和软件定时器   上一章,我们学习了UCOSII的信号量和邮箱的使用,本章,我们将学习消息队列、信号量集和软件定时器...
正点原子 2013-05-03 20:42
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
第五十七章 ENC28J60网络实验   本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块...
正点原子 2013-05-01 23:00
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十九章 UCOSII实验2-信号量和邮箱
第五十九章 UCOSII实验2-信号量和邮箱      上一章,我们学习了如何使用UCOSII,学习了UCOSII的任务调度,但是并没有用到任务间的同步与通信,本章我们将学习两个最基本的...
正点原子 2013-04-30 10:55
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十八章 UCOSII实验1-任务调度
  第五十八章 UCOSII实验1-任务调度      前面我们所有的例程都是跑的裸机程序(裸奔),从本章开始,我们将分3个章节向大家介绍UCOSII(实时多任务操作系...
正点原子 2013-04-26 23:16
【连载】【ALIENTEK 战舰STM32开发板】STM32开发指南--第五十七章 ENC28J60网络实验
 第五十七章 ENC28J60网络实验  本章,我们将向大家介绍ALIENTEK ENC28J60网络模块及其使用。本章,我们将使用ALIENTEK ENC28J60网络模块和uIP 1...
我要评论
1
6
关闭 站长推荐上一条 /3 下一条