stm32_ps2键盘显示测试程序

本文介绍了一个基于STM32的PS2键盘测试程序,详细解释了如何通过STM32读取PS2键盘的扫描码并将其转换为ASCII码进行显示。程序能够处理大小写字母、数字及特殊字符的输入,并支持换行和Shift键操作。
//PS2键盘测试程序,可换行,按shift不放接着输入
//可输出大写,按下CAPS输出大写,再次按下输出小写
//此程序只用来测试,代码冗余,仅供参考,可根据需要自行删减
//PA13->PS2.CLK  PA15->PS2.DATA

#include <stm32f10x_lib.h>
#include "sys.h"
#include "usart.h"		
#include "delay.h"	
#include "led.h" 
#include "key.h"
#include "exti.h"
#include "wdg.h"
#include "timer.h"
#include "lcd.h"	   

const u8 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 u8 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
};

void Decode(u8 scancode);// 声明函数原型
u8 bitcount=11,ascii=' ';	// bitcount为位计数值;ascii为翻译后的ASCII码,初值为空格
u8 hang=0,lie=0;  //彩屏显示位置

int main(void)
{		
  Stm32_Clock_Init(9);//系统时钟设置
	delay_init(72);		//延时初始化
	uart_init(72,9600); //串口1初始化  
	EXTIX_Init();
	LED_Init();
 	LCD_Init();
	LCD_Clear(YELLOW);
	
	POINT_COLOR=RED;
	BACK_COLOR=YELLOW;
	
  while(1) 
	{			
		if(hang>=240) //换行
		{hang=0;lie+=16;if(lie>=320)lie=0;} 
		LCD_ShowChar(hang,lie,ascii,16,0);		// 显示键盘字符
	}											    
}

/*******************************************
函数名称: Decode
功    能: 
参    数: scancode--需要翻译的扫描码
返回值  : 无
********************************************/
void Decode(u8 scancode)
{
 static u8 up=0,shift=0;	//up为通、断码标志,shift为shift键按下标志
 u8 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;   
	 case 0x58:  //CAPS键按下处理
		  shift=(shift==0)?1:0;//shift取反
			break;
	 case 0x66:	// backspace键按下时处理
			//backspace键按下时处理
			break;
	 case 0x5a:// 回车键按下时处理:换行
			ascii=' ';
			hang=0;
			lie=lie+16;
			break;
   default:        
   		if(!shift)			  //如果shift键没有按下
		{ 					  //查找unshifted表,表中左列是扫描码,右列是对应的ASCII码
	  	   for(i=0;unshifted[i][0]!=scancode&&unshifted[i][0];i++);
	  	   if(unshifted[i][0]==scancode) 
	  	   {
	   	   	ascii=unshifted[i][1];
					 hang=hang+8;
	  	   }
		} 
		else 				  //如果shift键按下
		{	 				  //查找shifted表
	  	   for(i=0;shifted[i][0]!=scancode&&shifted[i][0];i++);
	  	   if(shifted[i][0]==scancode) 
	  	   {
	   	   	ascii=shifted[i][1];
					  hang=hang+8;
	  	   }
		}   
   		break;
  }
 } 
 else 		  			//已接收的11位数据是断码(up为1)
 {
  up = 0;   	  	 	//将断码标志复位
  switch (scancode)		//检测shift键释放
  {
   case 0x12 :	   		//左shift键
   		shift = 0;
   		break;
   case 0x59 :			//右shift键
   		shift = 0;
   		break;
   default:
   		break;
  }
 }
}

 

此外还需修改中断文件夹中的两个函数

void EXTIX_Init(void)
{
	RCC->APB2ENR|=1<<2;     //使能PORTA时钟
	JTAG_Set(JTAG_SWD_DISABLE);//关闭JTAG和SWD   

	GPIOA->CRL&=0XFFFFFFF0;//PA0设置成输入	  
	GPIOA->CRL|=0X00000008;   
	GPIOA->CRH&=0X0F0FFFFF;//PA13,15设置成输入	  
	GPIOA->CRH|=0X80800000; 				   
	GPIOA->ODR|=1<<13;	   //PA13上拉,PA0默认下拉
	GPIOA->ODR|=1<<15;	   //PA15上拉

	Ex_NVIC_Config(GPIO_A,0,RTIR); //上升沿触发
	//Ex_NVIC_Config(GPIO_A,13,FTIR);//下降沿触发
	Ex_NVIC_Config(GPIO_A,15,FTIR|RTIR);//下降、上升沿触发

	MY_NVIC_Init(2,2,EXTI0_IRQChannel,2);    //抢占2,子优先级2,组2
	MY_NVIC_Init(2,1,EXTI15_10_IRQChannel,2);//抢占2,子优先级1,组2	   
}

//外部中断15~10服务程序
void EXTI15_10_IRQHandler(void)
{			
	
	static u8 data;   // 声明局部静态变量来保存扫描码
  if (!PAin(15))   				// 如果是下降沿触发中断
  {
  if(bitcount < 11 && bitcount > 2)    //3到10位是数据,起始位,校验位和停止位忽略
  { 
  	data = (data >> 1);		   	 	   //右移保存数据
	if(PAin(13)&0x01)
	{
	  data|=0x80;					   //存储一个'1'
	}
  }
 } 
 else 					 //如果是上升沿触发中断
 { 
  if(--bitcount==0)		 //如果11位全部接收完毕
  {
   Decode(data);	 //将扫描码翻译成ASCII码   
   bitcount = 11;		 //重新设为11位数据
  }
 }
// 	delay_ms(10);    //消抖			 
// 	if(KEY0==0)      //按键0
// 	{
// 		LED0=!LED0;
// 	}else if(KEY1==0)//按键1
// 	{
// 		LED1=!LED1;
// 	}
// 	EXTI->PR=1<<13;     //清除LINE13上的中断标志位  
	EXTI->PR=1<<15;     //清除LINE15上的中断标志位  

}



 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值