⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyboard.c

📁 AVR单片机程序,可以直接使用,PS/2键盘,可以直接用,还可以修改为查询方式,用在产品设计中!还可以定义按键弹起和功能键!
💻 C
字号:
#include <mega16.h>
// Standard Input/Output functions
#include <stdio.h>      
bit F_DATA;
void Decode1(unsigned char scancode);
/*******************************************
  文件:KeyBoard.C
  环境:编译为CodeVision AVR
  11.0592M日工晶振,串口通信速率为9600 
  硬件:ATMEGA16芯片
  功能:实现PS2键盘(支持第2套扫描码)
  备注:参考《AVR系列单片机C语言编程与应用实例》(清华大学出版社)    
  PD.2,INT0为时钟信号输入脚,PD.3为数据输入脚?  作者:邹家义
  日期:2008年11月8日,15点29整理
  使用扫描做
/******************************************/
		  
const unsigned char unshifted[65][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
};
flash unsigned char shifted[65][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
} ;  
		  

unsigned char  edge, bitcount,ascii1=' ';		//edge为0下降沿中断,为1上升沿中断
	  						 		//bitcount为位计数值
									//ascii为翻译后的ASCII码,初值为空格

/*******************************************
函数名称: Init_kb
功    能: 初始化PS2函数
参    数: 无
返回值  : 无
/********************************************/
void Init_kb()
{ 	 
DDRA=0xff;
DDRB=0xff;
DDRD=0xff; 
 edge = 0;        //0为下降沿标志,1为上升沿标志
 bitcount = 11;	  //每次11位数据,一个起始位(0),8个数据位,一个奇偶校验位,一个停止位(1)
 DDRD.2=0; //配置中断管脚为输入
 PORTD.2=1; //使能中断管脚的上拉    正常为高电平
 DDRD.3=0; //配置键盘数据输入口为输入
 PORTD.3=1; //使能数据输入管脚的上拉
} 

/*******************************************
函数名称: Decode
功    能: 
参    数: scancode--需要翻译的扫描码
返回值  : 无
/********************************************/
void Decode1(unsigned char scancode)
{
 static unsigned char up=0,shift=0;	//up为通、断码标志,shift为shift键按下标志
 unsigned char  i;
 if (!up)	  	   //已接收的11位数据是通码(up为0)
 {
  switch (scancode)//开始翻译扫描码
  {
   case 0xF0:	   //键盘释放标志(随后的一个字节是断码)
   		up=1;	   //设置up为断码标志
   		break;
   case 0x12:	   //左shift键按下
   		shift=1;   //设置shift为按下标志                   //如果CAPLOCK键按下,按下shift键后,读到的为unshift码,小写字母
   		break;
   case 0x59:	   //右shift键按下
   		shift=1;   //设置shift为按下标志
   		break;   
   default:        
   		if(!shift)			  //如果shift键没有按下
		{ 					  //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
	  	   for(i=0;unshifted[i][0] !=scancode&&unshifted[i][0];i++);          //当i>64时,即查完后scancode&&unshifted[i][0]==0,
	  	   if(unshifted[i][0]==scancode)                                                      //且unshifted[i][0]==0,就会跳出循环//理解错误,本身就是这个意思?	  	   {                                                                                                     //此句可用unshifted[i][0] !=scancode&&(unshifted[i][0]==0);
	   	   	ascii1=unshifted[i][1];                                                              //或unshifted[i][0] !=scancode&&(i<65);
	   	   	printf("%c",ascii1);                           //可以在这里设置一个标志,有数据输入了,主程序中读ASCII1即可
	  	   }
		} 
		else 				  //如果shift键按下
		{	 				  //查找shifted表
	  	   for(i=0;shifted[i][0] != scancode && shifted[i][0];i++);
	  	   if(shifted[i][0]==scancode) 
	  	   {
	   	   	ascii1=shifted[i][1]; 
	   	   	printf("%c",ascii1);
	  	   }
		}   
   		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码
参    数: 无
返回值  : 无
/********************************************/             
KEY_CHULI()
{  static unsigned char data1;   // 声明局部静态变量来保存扫描码  
if (!edge)   				// 如果是下降沿触发中断
 {
  if(bitcount < 11 && bitcount > 2)    //3到10位是数据,起始位,校验位和停止位忽略
  { 
  	data1 = (data1 >> 1);		   	 	   //右移保存数据
	if(PIND.3)
	{
	  data1|=0x80;					   //存储一个'1',如果传输的是“1”,最高位置1
	}                                       //因为PS2协议是从低位到高位传输的,所以每传输一位,都放在最左边,传输之前先右移
  }
 // MCUCR=3;				 //设置INT0为上升沿触发中断
  edge=1;				 //设置上升沿中断标志
 } 
 else 					 //如果是上升沿触发中断,11位传完后要解码
 { 
 // MCUCR=2;				 //设置INT0为下降沿触发中断   
 if(PIND.2==1)
  edge=0;				 //设置下降沿中断标志 
  if(--bitcount==0)		 //如果11位全部接收完毕
  {
   Decode1(data1);	 //将扫描码翻译成ASCII码   
   bitcount = 11;		 //重新设为11位数据
  }
 }
 }     
/*******************************************
函数名称: main
功    能: 实现PS2键盘的驱动,在1602液晶上显示键盘上的ASCII码
参    数: 无
返回值  : 无
/********************************************/
void main(void)
{
 F_DATA=1;

// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud rate: 9600
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x47;

 Init_kb();		  			//初始化PS2键盘接口        
 printf("OK,GOOD!\n");
 while(1)
 {
//  Disp_ascii(ascii1);    //显示翻译后的ASCII码      
if(PIND.2!=F_DATA)  
 {
  F_DATA=PIND.2;  
  KEY_CHULI();
  }
 }
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -