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

📄 main.c

📁 已经调通了PS2键盘程序。想学习的也许能帮上用处的。
💻 C
字号:
#include<iom16v.h>
#include<macros.h>
#include"Delay_nms.h"
#include "scancodes.h"

#define uchar unsigned char 
#define uint  unsigned int

#define XTAL 8

#define LED_G0  (PORTB&=~(1<<PB3))
#define LED_G1  (PORTB|=1<<PB3)
#define LED_Y0  (PORTB&=~(1<<PB4))
#define LED_Y1  (PORTB|=1<<PB4)
#define FM_0    (PORTA&=~(1<<PA4))
#define FM_1    (PORTA|=1<<PA4)
#define K1      (PINB&0x01)
#define K2      (PINB&0x02)
#define K3      (PINB&0x04)

//定义Keyboard引脚
#define Key_Data 3 //数据引脚
#define Key_CLK  2 //外部INT0中断,PD2或PD3
#define Key_Data_1 PORTD|=1<<Key_Data
#define Key_Data_0 PORTD&=~(1<<Key_Data)
#define Key_CLK_1  PORTD|=1<<Key_CLK
#define Key_CLK_0  PORTD&=~(1<<Key_CLK)
#define Key_Data_bit (PIND&(1<<Key_Data)) 
#define Key_CLK_bit  (PIND&(1<<Key_CLK))
unsigned char IntNum=0; //中断次数计数
unsigned char KeyV=0;       //键值
unsigned char BF=0;     //标识是否有字符被收到
unsigned char Key_UP=0;   //Key_UP是键松开标识,
unsigned char Shift =0;  //Shift是Shift键按下标识
unsigned char Dis_bit =0;
unsigned char KEY_data=0;   //处理好的键盘数据

const uchar str[]={"-KeyKboard test-"};
const uchar str1[]={"                "};

void Decode(unsigned char ScanCode);
void ps2_sentchar(unsigned char sentchar);

//端口初始化
void PORT_INT(void)
 {
    PORTA = 0xfe;
	DDRA  = 0xFe;
	PORTB = 0xff;
	DDRB  = 0xff;
    PORTC = 0x00;
	DDRC  = 0xff;
	DDRD  = 0x02;
	PORTD = 0xff;
 }
 
/***************串行口初始化********************/
void uart0_int(void)
 {
  UCSRB = 0X00;//禁止UART发送和接收
  UCSRA = 0X02;//倍速
  UCSRC = 0X06;//8位数据位
  UBRRL = 0X67;//波特率9600B/S
  UBRRH = 0X00;//
  UCSRB = 0X18;//允许UART发送和接收
 }
 
/***************发送1个字符子函数*****************/
void uart0_send(uchar data)
 {
  while(!(UCSRA&(1<<UDRE)));//等待发送缓冲区为空
  UDR=data;//发送一个字符
 }

/***************发送一串字符子函数*****************/
void uart_strsend(char *str)
 {
  while(!(UCSRA&(1<<UDRE)));//等待发送缓冲区为空
  while(*str)
   { 
    uart0_send(*str);
	str++;
   }
 }
 
//INT0中断,键盘数据接收
#pragma interrupt_handler int0_isr: 2
void int0_isr(void)
 {
    if ((IntNum > 0) && (IntNum < 9))
      {
       KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
       if (Key_Data_bit) {KeyV = (KeyV | 0x80);} //当键盘数据线为1时为1到最高位
       }
    IntNum++;
    while(!Key_CLK_bit); //等待PS/2CLK拉高
    if (IntNum > 10)
      {
       IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
       BF = 1; //标识有字符输入完了
       SREG=0x00; //关中断等显示完后再开中断 (注:如这里不用BF和关中断直接调Decode()则所Decode中所调用的所有函数要声明为再入函数)
      }
 }

 
void main(void)
 {  
 
    uchar i=0,j=0,k=0,p=0;
    
	SREG = 0x80;
	MCUCR = 0x00;
	GICR = 0x40;
	
	PORT_INT();       // 端口初始化
	uart0_int();
	Delay_nms(10,XTAL);
	InitLcd();

	eputstr(0,0,str);
	
   while(1)
    {
	  
	  if(BF==1)
	   {uart0_send(KeyV);
	    Decode(KeyV);
		SREG=0x80;
	   }
	  if(Dis_bit==1)
		{
		  if(KEY_data==0x7f)
		    {
              if(k>0)
			  {
			   Displayonechar(--i,1,0x20);
			   LcdWriteCommand(0x10,1);
			   --k;
			  }
			}
		  else if(k<16) {Displayonechar(i,1,KEY_data);k++;i++;}
		Dis_bit=0;
		} 
    }
  }


//键盘数据处理
void Decode(unsigned char ScanCode) 
//注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,
//也就是说shift的通码+G的通码+shift的断码+G的断码
 {  
    unsigned char TempCyc;
    if (! Key_UP) //当键盘松开时
       {
       switch (ScanCode)
        {
        case 0xF0 :Key_UP = 1;break;// 当收到0xF0,Key_UP置1表示断码开始
        case 0x12 :Shift  = 1;break;// 左 SHIFT
        case 0x59 :Shift  = 1;break;// 右 SHIFT
        default: if(!Shift) //如果SHIFT没按下
                  {
                   for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(UnShifted[TempCyc][0]!=0xff); TempCyc++); //查表显示
                   if (UnShifted[TempCyc][0] == ScanCode) 
					   KEY_data=UnShifted[TempCyc][1];//如果SHIFT没按下
                       //Displayonechar(15,1,KEY_data);//
					   Dis_bit=1; 
				 
                   }
                 else //按下SHIFT
                   {
                     for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(Shifted[TempCyc][0]!=0xff); TempCyc++); //查表显示
                     if (Shifted[TempCyc][0] == ScanCode) 
						 KEY_data=Shifted[TempCyc][1];//SHIFT按下
                         //Displayonechar(15,1,KEY_data);//
					     Dis_bit=1;
                    }break;
        }
      }
  
   else
       {
	    Key_UP = 0;
        switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
         {
		  case 0x12 : Shift = 0;break; // 左 SHIFT
          case 0x59 : Shift = 0;break;// 右 SHIFT
         }
        }
  BF = 0; //标识字符处理完了
   }

//ps2主设备向从设备发送数据
void ps2_sentchar(unsigned char sentchar)
   {
    unsigned char sentbit_cnt= 0x00;
    unsigned char sentchar_chk = 0x00;
    SREG = 0x00;//关外部中断0
    //发起一个传送,发起始位
    Key_CLK_0;//将时钟线拉低并保持100 us
    //delay100us();
    Key_Data_0;//Key_Data_0 = 0;起始位
    Key_CLK_1;//Key_Clk_1 = 1;
    //发送DATA0-7
    for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++)
	 {
      while(Key_CLK_bit) _NOP(); //等待时钟线变为低
	  if(sentchar & 0x01){Key_Data_1;}
	  else {Key_Data_0;}//发送数据
      if(sentchar & 0x01) sentchar_chk++; //计算校验
      while(!Key_CLK_bit) _NOP(); //等待时钟线变高
      sentchar>>=1; //待发送数据右移一位
     }
    //发送校验位
    while(Key_CLK_bit) _NOP(); //等待时钟线变低
    switch(sentchar_chk)
	  {
      case 0:
      case 2:
      case 4:
      case 6:Key_Data_1;break;//奇校验
      case 1:
      case 3:
      case 5:
      case 7:Key_Data_0;break;//奇校验
      default:break;
      }
    while(!Key_CLK_bit) _NOP(); //等待时钟线变高
    while(Key_CLK_bit) _NOP(); //等待时钟线变低
    Key_Data_1;//发送停止位,停止位总为1
    while(!Key_CLK_bit) _NOP(); //等待时钟线变高
    while(Key_CLK_bit) _NOP(); //等待时钟线变低
    //接收ACK
    //if(Key_Data_bit) error();
    //ACK信号由键盘发出,总为低电平
    while(!Key_CLK_bit) _NOP(); //等待时钟线变高
    SREG = 0x80; //开外部中断0
  }

⌨️ 快捷键说明

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