打印
[AVR单片机]

PS2键盘扫描代码中的“&&”运算符 应该不是逻辑运算符?

[复制链接]
900|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
bxtinglove|  楼主 | 2015-3-14 22:03 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
本帖最后由 bxtinglove 于 2015-3-14 22:37 编辑

/*******************************************
  文件:PS2_KB.C
  环境:编译为ICC AVR6.25A,仿真为AVR Studio4.10
  硬件:ATMEGA16芯片
  日期:2006年12月10日
  功能:驱动开发板上的PS2接口,实现PS2键盘(支持第2套扫描码)
  备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)
/******************************************/
#include <iom16v.h>   //包含型号头文件
#include <macros.h>   //包含"位"操作头文件
#include <stdio.h>   //标准输入输出头文件
#include <AVR_PQ1A.h>  //包含自定义常量头文件
#include "YJ1602.C"

#pragma interrupt_handler Int0:2 //外部中断0中断函数声明     
#pragma data:code        //将译码表放在FLASH
const uchar unshifted[][2]=   //shift键没按下译码表
{  
  0x0e,'`',
  0x15,'q',
  0x16,'1',
  0x1a,'z',
  0x1b,'s',
  0x1c,'a',
  0x1d,'w',
  0x1e,'2',
  0x21,'c',
  0x22,'x',
  0x23,'d',
  0x24,'e',
  0x25,'4',
  0x26,'3',
  0x29,' ',
  0x2a,'v',
  0x2b,'f',
  0x2c,'t',
  0x2d,'r',
  0x2e,'5',
  0x31,'n',
  0x32,'b',
  0x33,'h',
  0x34,'g',
  0x35,'y',
  0x36,'6',
  0x39,',',
  0x3a,'m',
  0x3b,'j',
  0x3c,'u',
  0x3d,'7',
  0x3e,'8',
  0x41,',',
  0x42,'k',
  0x43,'i',
  0x44,'o',
  0x45,'0',
  0x46,'9',
  0x49,'.',
  0x4a,'/',
  0x4b,'l',
  0x4c,';',
  0x4d,'p',
  0x4e,'-',
  0x52,'\'',
  0x54,'[',
  0x55,'=',
  0x5b,']',
  0x5d,'\\',
  0x61,'<',
  0x69,'1',
  0x6b,'4',
  0x6c,'7',
  0x70,'0',
  0x71,'.',
  0x72,'2',
  0x73,'5',
  0x74,'6',
  0x75,'8',
  0x79,'+',
  0x7a,'3',
  0x7b,'-',
  0x7c,'*',
  0x7d,'9',
  0,0
};
const uchar shifted[][2]=      //shift键按下译码表
{
  0x0e,'~',
  0x15,'Q',
  0x16,'!',
  0x1a,'Z',
  0x1b,'S',
  0x1c,'A',
  0x1d,'W',
  0x1e,'@',
  0x21,'C',
  0x22,'X',
  0x23,'D',
  0x24,'E',
  0x25,'$',
  0x26,'#',
  0x29,' ',
  0x2a,'V',
  0x2b,'F',
  0x2c,'T',
  0x2d,'R',
  0x2e,'%',
  0x31,'N',
  0x32,'B',
  0x33,'H',
  0x34,'G',
  0x35,'Y',
  0x36,'^',
  0x39,'L',
  0x3a,'M',
  0x3b,'J',
  0x3c,'U',
  0x3d,'&',
  0x3e,'*',
  0x41,'<',
  0x42,'K',
  0x43,'I',
  0x44,'O',
  0x45,')',
  0x46,'(',
  0x49,'>',
  0x4a,'?',
  0x4b,'L',
  0x4c,':',
  0x4d,'P',
  0x4e,'_',
  0x52,'"',
  0x54,'{',
  0x55,'+',
  0x5b,'}',
  0x5d,'|',
  0x61,'>',
  0x69,'1',
  0x6b,'4',
  0x6c,'7',
  0x70,'0',
  0x71,'.',
  0x72,'2',
  0x73,'5',
  0x74,'6',
  0x75,'8',
  0x79,'+',
  0x7a,'3',
  0x7b,'-',
  0x7c,'*',
  0x7d,'9',
  0,0
};
#pragma data:data   //将以后的变量放在RAM
void Decode(uchar scancode);//声明函数原型
uchar edge, bitcount,ascii=' ';  //edge为0下降沿中断,为1上升沿中断
            //bitcount为位计数值
         //ascii为翻译后的ASCII码,初值为空格

/*******************************************
函数名称: Init_kb
功    能: 初始化PS2函数
参    数: 无
返回值  : 无
/********************************************/
void Init_kb(void)
{   
MCUCR = 2;       //设置INT0为下降沿触发中断
edge = 0;        //0为下降沿中断标志,1为上升沿中断标志
bitcount = 11;   //每次11位数据,一个起始位(0),8个数据位,一个奇偶校验位,一个停止位(1)
DDRD&=~BIT(PD2); //配置中断管脚为输入
PORTD|=BIT(PD2); //使能中断管脚的上拉
DDRA&=~BIT(PA0); //配置键盘数据输入口为输入
PORTA|=BIT(PA0); //使能数据输入管脚的上拉
SREG|=BIT(GLOBAL);//打开全局中断
GICR|=BIT(EXTINT0);
}
/*******************************************
函数名称: Disp_ascii
功    能: 在1602液晶上显示键盘上的ASCII码
参    数: ascii--将要显示的ASCII码
返回值  : 无
/********************************************/
void Disp_ascii(uchar ascii)   
{
LCD1602_gotoXY(1,2);
LCD1602_sendstr("KEY_ASCII:");
LCD1602_sendbyte(iDat,ascii);
}
/*******************************************
函数名称: Int0
功    能: 外部中断0的中断服务函数,下降沿中断读入11位数据,上升沿调用解码程序,这样符合PS2的时序图,程序效率更高
参    数: 无
返回值  : 无
/********************************************/
void Int0(void)
{
static uchar data;   // 声明局部静态变量来保存扫描码
if (!edge)       // 如果是下降沿触发中断,下降沿从键盘读取数据
{
  if(bitcount < 11 && bitcount > 2)    //3到10位是数据,起始位,校验位和停止位忽略
  {
   data = (data >> 1);           //右移保存数据
if(PINA&0x01)
{
   data|=0x80;        //存储一个'1'
}
  }
  MCUCR=3;     //设置INT0为上升沿触发中断
  edge=1;     //设置上升沿中断标志
}
else       //如果是上升沿触发中断,上升沿单片机开始译码
{
  MCUCR=2;     //设置INT0为下降沿触发中断
  edge=0;     //设置下降沿中断标志
  if(--bitcount==0)   //如果11位全部接收完毕
  {
   Decode(data);  //将扫描码翻译成ASCII码   
   bitcount = 11;   //重新设为11位数据
  }
}
}
/*******************************************
函数名称: Decode
功    能:
参    数: scancode--需要翻译的扫描码
返回值  : 无
/********************************************/
void Decode(uchar scancode)
{
static uchar up=0,shift=0; //up为通、断码标志,shift为shift键按下标志
uchar i;
if (!up)       //已接收的11位数据是通码(up为0)
{
  switch (scancode)//开始翻译扫描码
  {
   case 0xF0:    //键盘释放标志(随后的一个字节是断码)
     up=1;    //设置up为断码标志
     break;
   case 0x12:    //左shift键按下
     shift=1;   //设置shift为按下标志
     break;
   case 0x59:    //右shift键按下
     shift=1;   //设置shift为按下标志
     break;   
   default:        
     if(!shift)     //如果shift键没有按下
  {        //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
       for(i=0;unshifted[0]!=scancode&&unshifted[0];i++);
       if(unshifted[0]==scancode)
       {
         ascii=unshifted[1];
       }
  }
  else       //如果shift键按下
  {        //查找shifted表
       for(i=0;shifted[0]!=scancode&&shifted[0];i++);
       if(shifted[0]==scancode)
       {
         ascii=shifted[1];
       }
  }   
     break;
  }
}
else        //已接收的11位数据是断码(up为1)
{
  up = 0;         //将断码标志复位
  switch (scancode)  //检测shift键释放
  {
   case 0x12 :      //左shift键
     shift = 0;
     break;
   case 0x59 :   //右shift键
     shift = 0;
     break;
   default:
     break;
  }
}
}
/*******************************************
函数名称: main
功    能: 实现PS2键盘的驱动,在1602液晶上显示键盘上的ASCII码
参    数: 无
返回值  : 无
/********************************************/
void main(void)
{
Board_init( );       //初始化开发板
LCD1602_initial( );   //初始化1602
Init_kb();       //初始化PS2键盘接口
while(1)
{
  Disp_ascii(ascii);    //显示翻译后的ASCII码
}
}







for(i=0;unshifted[0]!=scancode&&unshifted[0];i++);

这行代码中的&&是逻辑运算吗?

相关帖子

发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

2

主题

3

帖子

0

粉丝