*************************************************************************************
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。
否则将追究法律责任。http://blog.csdn.net/fulinus/article/details/15138735
*************************************************************************************
C51模拟PS2键盘程序,这是PS2协议程序头文件文件:
#ifndef __PS_2_H__ #define __PS_2_H__ #define PS2_DAT_H 1 #define PS2_DAT_L 0 #define PS2_CLK_H 1 #define PS2_CLK_L 0 sbit PS2_CLK = P0^0; sbit PS2_DAT = P0^1; void PS2_Send(unsigned char ch); unsigned char PS2_Rece(void); unsigned char PS2_Response(void); void MCU_To_PC(unsigned char Key_num); //void key_send(unsigned char key_value); //unsigned int key_scan(void); #endif
#include <C8051F310.h> // SFR declarations #include "PS_2.h" #include "delay.h" #include "Initialize.h" //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- // // Return Value : None // Parameters : // // This function // // // //----------------------------------------------------------------------------- void PS2_Send(unsigned char ch) { unsigned char i,temp,char_temp; unsigned char odd_flag=1; //if odd_flag is 1,then odd is true ,else is flase temp=ch; for(i=0;i<8;i++) //find the number of 1 in this uchar x iS odd or not { char_temp=temp&0x01; //奇效验,找出发送的数据中1的个数,如果为偶数,则置标志位为1,反之为0 if(char_temp==0x01) { odd_flag=!odd_flag; } temp=temp>>1; } temp=ch; char_temp=0; while(!PS2_CLK) { Delay_us(20); } PS2_DAT = PS2_DAT_L; //start bit 0 Delay_us(18); //从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒 PS2_CLK = PS2_CLK_L; Delay_us(35); for(i=0;i<8;i++) //send 8 bits LSB first { PS2_CLK = PS2_CLK_H; Delay_us(13); //从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒 char_temp=temp&0x01; if(char_temp==0x01) PS2_DAT = PS2_DAT_H; else PS2_DAT = PS2_DAT_L; char_temp = 0; Delay_us(22); PS2_CLK = PS2_CLK_L; Delay_us(36); temp=temp>>1; } PS2_CLK = PS2_CLK_H; Delay_us(13); //从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒 PS2_DAT = odd_flag; //send odd bit Delay_us(22); PS2_CLK = PS2_CLK_L; Delay_us(36); PS2_CLK = PS2_CLK_H; //send stop bit Delay_us(13); //从时钟脉冲的上升沿到一个数据转变的时间至少要有5微秒 PS2_DAT = PS2_DAT_H; Delay_us(22); PS2_CLK = PS2_CLK_L; Delay_us(36); PS2_CLK = PS2_CLK_H; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- // // Return Value : // Parameters : // // This function // // // //----------------------------------------------------------------------------- unsigned char PS2_Rece(void) { unsigned char i,dat=0x00; unsigned char ParityBit,oddSum=0; //数据校验计数器 if(!PS2_DAT) { Delay_us(10); if(PS2_DAT) return 0xCC; while(!PS2_CLK); Delay_us(40); PS2_CLK = PS2_CLK_L; for(i=0;i<8;i++) //read 8bit { Delay_us(35); PS2_CLK = PS2_CLK_H; Delay_us(36); PS2_CLK = PS2_CLK_L; dat=dat>>1; if(PS2_DAT) { dat|=0x80; oddSum++; //校验位计数器 } Delay_us(15); } Delay_us(35); PS2_CLK = PS2_CLK_H; Delay_us(36); PS2_CLK = PS2_CLK_L; if(PS2_DAT) ParityBit=1; //奇偶效验 else ParityBit=0; Delay_us(35); PS2_CLK = PS2_CLK_H; Delay_us(36); PS2_CLK = PS2_CLK_L; if(!PS2_DAT) //数据线仍旧为0吗 return 0xCC; Delay_us(15); PS2_DAT = PS2_DAT_L; Delay_us(20); PS2_CLK = PS2_CLK_L; //STOP BIT H_DATA 0 ERR Delay_us(36); PS2_CLK = PS2_CLK_H; //ACK bit Delay_us(15); PS2_DAT = PS2_DAT_H; oddSum += ParityBit; //数据位中1的个数加上校验为应为奇数 if(oddSum%2==0) return 0xCC; else return dat; } else return 0xCC; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- // // Return Value : // Parameters : // // This function // // // //----------------------------------------------------------------------------- unsigned char PS2_Response(void) //开机应答,使电脑能识别到键盘 { unsigned char PS2RecChar; //while(PS2RecChar != 0xFF) PS2RecChar = PS2_Rece(); if(PS2RecChar != 0xCC) switch(PS2RecChar) { Delay_ms(4); case 0xFF: //主机命令设备复位(0xff),设备必须应答0xfa后回复0xaa; PS2_Send(0xFA); Delay_ms(3); PS2_Send(0xAA); break; case 0xF2: // 主机请求获得设备ID命令(0xf2),设备必须应答0xfa后回复0xab,0x83; PS2_Send(0xFA); Delay_ms(3); PS2_Send(0xAB); Delay_ms(3); PS2_Send(0x83); // LED = 1; break; case 0xEE: //主机ECHO命令(0xee),设备直接回复0xee; PS2_Send(0xEE); break; case 0xEF: PS2_Send(0xFA); Delay_ms(3); PS2_Send(0xBF); Delay_ms(3); PS2_Send(0xB0); break; //除以上命令之外的其它命令,设备只要回复0xfa即可,当然要视设备的功能作相应的动作。 /*case 0xF5: PS2_Send(0xFA); break;*/ case 0xF3: PS2_Send(0xFA); break; case 0x00: PS2_Send(0xFA); break; case 0x02: PS2_Send(0xFA); break; case 0x20: PS2_Send(0xFA); break; case 0xED: PS2_Send(0xFA); break; case 0xF0: PS2_Send(0xFA); break; case 0xEC: PS2_Send(0xFE); break; case 0xFE: PS2_Send(0xFA); break; case 0xF1: PS2_Send(0xFA); break; case 0xF4: PS2_Send(0xFA); break; case 0xAA: PS2_Send(0xAA); break; default :break; } Delay_ms(4); return PS2RecChar; } //----------------------------------------------------------------------------- // //----------------------------------------------------------------------------- // // Return Value : // Parameters : // // This function // // // //----------------------------------------------------------------------------- /* void MCU_To_PC(unsigned char Key_num) { switch(Key_num) { case 1: //'f' PS2_Send(0x2B); Delay_ms(60); break; case 2: //L ARROW PS2_Send(0xE0); Delay_ms(4); PS2_Send(0x6B); Delay_ms(60); break; case 3: //'Enter' PS2_Send(0x5A); Delay_ms(60); break; default: break; } } */
*************************************************************************************
C51模拟PS2键盘(三):原文链接
程序包的位置在这里
*************************************************************************************