基于51单片机的PS2键盘的单片机编程

合集下载

天狼星51AVR课上程序代码

天狼星51AVR课上程序代码

51篇51单片机第二十课PS2键盘键值解码所属类别: 课程代码发布日期: 2011-03-05 点击量: 383#include<>#define uchar unsigned char#define uint unsigned intsbit psdata=P3^0;sbit psclk=P3^2;uchar numbit;uchar keyv;uchar key[3];uchar keynum;uchar m,n;unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};//************************************************//延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}//************************************************//延时函数,在12MHz的晶振频率下//大约50ms的延时//************************************************void delay_50ms(uint t){uint j;for(;t>0;t--)for(j=6245;j>0;j--);}void main(){IT0=1; //外部中断下降沿触发EX0=1; //打开外部中断0EA=1; //打开总中断while(1){if(keynum==3){keynum=0; //0x1cn=key[0]/16;m=key[0]%16;}P1=smg_du[m];P2=smg_we[0];delay_50us(20);P1=smg_du[n];P2=smg_we[1];delay_50us(20);}}void int0 () interrupt 0{if((numbit>0)&&(numbit<9)) //>>{keyv=keyv>>1; //001000000if(psdata)keyv=keyv | 0x80; //} //01numbit++; //0if(numbit>10){numbit=0;key[keynum]=keyv;keynum++;}}51单片机第二十三课实时时钟芯片DS1302的读写所属类别: 课程代码发布日期: 2011-03-05 点击量: 531#include<>#include <>#define uchar unsigned char#define uint unsigned intsbit sck=P1^0;sbit io=P1^1;sbit rst=P3^6;sbit smgen=P2^3;unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00,0x10};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};uchar time_data[7]={10,6,4,17,11,58,30}; //年周月日时分秒uchar write_add[7]={0x8c,0x8a,0x88,0x86,0x84,0x82,0x80};uchar read_add[7]={0x8d,0x8b,0x89,0x87,0x85,0x83,0x81};uchar disp[8];void write_ds1302_byte(uchar dat);void write_ds1302(uchar add,uchar dat);uchar read_ds1302(uchar add);void set_rtc(void);void read_rtc(void);void time_pros(void);void display(void);//************************************************//延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}//************************************************//延时函数,在12MHz的晶振频率下//大约50ms的延时//************************************************void delay_50ms(uint t)uint j;for(;t>0;t--)for(j=6245;j>0;j--);}void write_ds1302_byte(uchar dat) {uchar i;for(i=0;i<8;i++){sck=0;io=dat&0x01;dat=dat>>1;sck=1;}}void write_ds1302(uchar add,uchar dat) {rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);write_ds1302_byte(dat);rst=0;_nop_();io=1;sck=1;}uchar read_ds1302(uchar add){uchar i,value;rst=0;_nop_();sck=0;_nop_();rst=1;_nop_();write_ds1302_byte(add);for(i=0;i<8;i++)value=value>>1;sck=0;if(io)value=value|0x80;sck=1;}rst=0;_nop_();sck=0;_nop_();sck=1;io=1;return value;}void set_rtc(void){uchar i,j;for(i=0;i<7;i++){j=time_data[i]/10;time_data[i]=time_data[i]%10;time_data[i]=time_data[i]+j*16;}write_ds1302(0x8e,0x00); //去除写保护for(i=0;i<7;i++){write_ds1302(write_add[i],time_data[i]); }write_ds1302(0x8e,0x80); //加写保护}void read_rtc(void){uchar i;for(i=0;i<7;i++){time_data[i]=read_ds1302(read_add[i]); }}void time_pros(void)disp[0]=time_data[6]%16;disp[1]=time_data[6]/16;disp[2]=16;disp[3]=time_data[5]%16;disp[4]=time_data[5]/16;disp[5]=16;disp[6]=time_data[4]%16;disp[7]=time_data[4]/16;}void display(void){uchar i;for(i=0;i<8;i++){P1=smg_du[disp[i]];P2=smg_we[i];delay_50us(20);}}void main(void){set_rtc();delay_50us(20);while(1){smgen=0;rst=1;read_rtc();rst=0;time_pros();smgen=1;display();smgen=0;}}51单片机第二十四课数字温度传感器DS18B20测温所属类别: 课程代码发布日期: 2011-03-05 点击量: 506#include<>#define uchar unsigned char#define uint unsigned intsbit DQ=P2^2;sbit smg1=P2^4;sbit smg2=P2^5;sbit smg3=P2^6;uchar temp;unsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};void init_ds18b20(void);void delay(uint t);void write_byte(uchar dat);uchar read_byte(void);uchar readtemperature(void);void display(void);//************************************************//延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}void main(void){while(1){temp=readtemperature();display();}}void delay(uint t){while(t--);}void init_ds18b20(void) {uchar n;DQ=1;delay(8);DQ=0;delay(80);DQ=1;delay(8);n=DQ;delay(4);}void write_byte(uchar dat) {uchar i;for(i=0;i<8;i++){DQ=0;DQ=dat&0x01;delay(4);DQ=1;dat>>=1;}delay(4);}uchar read_byte(void) {uchar i,value;for(i=0;i<8;i++){DQ=0;value>>=1;DQ=1;if(DQ)value|=0x80;delay(4);}return value;}uchar readtemperature(void){uchar a,b;init_ds18b20();write_byte(0xcc); //跳过ROMwrite_byte(0x44); //启动温度测量delay(300);init_ds18b20();write_byte(0xcc);write_byte(0xbe);a=read_byte();b=read_byte();b<<=4;b+=(a&0xf0)>>4;return b;}void display(void){smg3=0;smg2=0;smg1=0;P1=smg_du[temp%10];delay_50us(20);smg2=0;smg1=1;P1=smg_du[temp/10];delay_50us(20);}51单片机第二十一课红外遥控解码程序设计所属类别: 课程代码发布日期: 2011-03-05 点击量: 504#include<>#define uchar unsigned char#define uint unsigned intunsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};uchar irtime;uchar startflag;uchar irdata[33];uchar bitnum;uchar irreceok;uchar ircode[4];uchar irprosok;uchar disp[8];//************************************************//延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}//************************************************//延时函数,在12MHz的晶振频率下//大约50ms的延时//************************************************void delay_50ms(uint t){uint j;for(;t>0;t--)for(j=6245;j>0;j--);}void timer0init(void){TMOD=0x02;TH0=0x00;TL0=0x00;ET0=1;EA=1;TR0=1;}void int0init(void){IT0=1;EX0=1;EA=1;}void irwork(void){disp[0]=ircode[0]/16; disp[1]=ircode[0]%16; disp[2]=ircode[1]/16; disp[3]=ircode[1]%16; disp[4]=ircode[2]/16; disp[5]=ircode[2]%16; disp[6]=ircode[3]/16; disp[7]=ircode[3]%16;}void display(void){uchar i;for(i=0;i<8;i++){P1=smg_du[disp[i]]; P2=smg_we[i];delay_50us(20);}}void irpros(void) //0x1c {uchar k,i,j;uchar value;k=1;for(j=0;j<4;j++)for(i=0;i<8;i++){value=value>>1; //7if(irdata[k]>6) //8{value=value | 0x80;}k++;}ircode[j]=value;}irprosok=1;}void main(){timer0init();int0init();while(1){if(irreceok){irpros();irreceok=0;}if(irprosok){irwork();irprosok=0;}display();}}void timer0 () interrupt 1 {irtime++; //255}void int0 () interrupt 0if(startflag){if(irtime>32) //检测引导码{bitnum=0;}irdata[bitnum]=irtime;irtime=0;bitnum++;if(bitnum==33){bitnum=0;irreceok=1;}}else{startflag=1;irtime=0;}}51单片机第十六课串口数据收发实验所属类别: 课程代码发布日期: 2011-03-05 点击量: 358 #include <>unsigned char a;unsigned char flag;void main(){TMOD=0x20; //设置定时器1为方式2TH1=0xfd; //装入初值TL1=0xfd;TR1=1; //启动定时器1SM0=0;SM1=1; //设置串口为方式1REN=1; //接受使能EA=1; //打开总中断开关ES=1; //打开串口中断开关while(1)if(flag==1){ES=0;flag=0;SBUF=a;while(!TI); //等待数据发送结束TI=0;ES=1;}}}void serial() interrupt 4{a=SBUF;P1=a;RI=0;flag=1; //标志位}51单片机第十七课字符液晶LCD1602显示所属类别: 课程代码发布日期: 2011-03-05 点击量: 436 #include<>#define uchar unsigned char#define uint unsigned intsbit rs=P2^4;sbit rw=P2^5;sbit e=P2^6;uchar table1[]=" ";uchar table2[]="LCD1602 test ok!";//************************************************ //延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************ void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}//************************************************ //延时函数,在12MHz的晶振频率下//大约50ms的延时//************************************************ void delay_50ms(uint t){uint j;for(;t>0;t--)for(j=6245;j>0;j--);}void write_com(uchar com){e=0;rs=0;rw=0;P0=com;delay_50us(10);e=1;delay_50us(20);e=0;}void write_data(uchar dat){e=0;rs=1;rw=0;P0=dat;delay_50us(10);e=1;delay_50us(20);e=0;}void init(void){delay_50us(300);write_com(0x38);delay_50us(100);write_com(0x38);delay_50us(100);write_com(0x38);write_com(0x38);write_com(0x08);write_com(0x01);write_com(0x06);write_com(0x0c);}void main(){uchar j;init();write_com(0x80);for(j=0;j<16;j++){write_data(table1[j]);delay_50us(10);}write_com(0x80+0x40);for(j=0;j<16;j++){write_data(table2[j]);delay_50us(10);}while(1);}51单片机第十三课矩阵键盘扫描实验所属类别: 课程代码发布日期: 2011-03-05 点击量: 343#include<>#define uchar unsigned char#define uint unsigned intunsigned char code smg_du[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71,0 x00};unsigned char code smg_we[]={0x08,0x18,0x28,0x38,0x48,0x58,0x68,0x78};//************************************************//延时函数,在12MHz的晶振频率下//大约50us的延时//************************************************void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}//************************************************ //延时函数,在12MHz的晶振频率下//大约50ms的延时//************************************************ void delay_50ms(uint t){uint j;for(;t>0;t--)for(j=6245;j>0;j--);}void main(){uchar key_l,key_h;uchar key;while(1){P3=0xf0;key_l=P3;key_l=key_l&0xf0;if(key_l!=0xf0){delay_50us(100);if(key_l!=0xf0){key_l=P3&0xf0; //key_l=key_l|0x0f;//P3=key_l;key_h=P3;key_h=key_h&0x0f;//00001110key_l=key_l&0xf0;//key=key_h+key_l; ////20//06//26}}switch (key){case 0xee:P1=smg_du[0];break; case 0xde:P1=smg_du[1];break; case 0xbe:P1=smg_du[2];break; case 0x7e:P1=smg_du[3];break; case 0xed:P1=smg_du[4];break; case 0xdd:P1=smg_du[5];break; case 0xbd:P1=smg_du[6];break; case 0x7d:P1=smg_du[7];break; case 0xeb:P1=smg_du[8];break; case 0xdb:P1=smg_du[9];break; case 0xbb:P1=smg_du[10];break; case 0x7b:P1=smg_du[11];break; case 0xe7:P1=smg_du[12];break; case 0xd7:P1=smg_du[13];break; case 0xb7:P1=smg_du[14];break; case 0x77:P1=smg_du[15];break;}}}Avr篇lesson 4-1#include <>#include <>void delay(void){unsigned char a,b;for(a=0;a<240;a++)for(b=0;b<240;b++);}void main(void){DDRB=0xff;PORTB=0xff;DDRA=0xff; PORTA=0xff;while(1){PORTA &=~0x80; delay();PORTA |=0x80; delay();}}lesson 4-2#include <>#include <>void delay(void){unsigned char a,b; for(a=0;a<240;a++) for(b=0;b<240;b++); }void main(void){DDRB=0xff; PORTB=0xff;DDRA=0xff; PORTA=0xff;while(1){PORTA ^=BIT(7);//PORTA ^=0x80; delay();}}lesson 4-3#include <>#include <>void main(void){DDRB=0xff;PORTB=0xff;DDRA=0xff;PORTA=0xff;DDRD=0;PORTD=0xff;while(1){if(PIND & 0x04) //00000100PORTA |=BIT(7);elsePORTA &=~BIT(7);}}lesson 5-1#include <>#include <>#define uchar unsigned charuchar table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};void delay(void){uchar a,b;for(a=0;a<240;a++)for(b=0;b<240;b++);}void main(void){uchar i;DDRB=0xff;PORTB=0xff;DDRA=0xff;PORTA=0xff;while(1){for(i=0;i<8;i++){PORTA=table[i];delay();}}}lesson 5-2#include <>#include <>#define uchar unsigned charuchar table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};void delay(void){uchar a,b;for(a=0;a<240;a++)for(b=0;b<240;b++);}void main(void){uchar i;DDRB=0xff;PORTB=0xff;DDRA=0xff;PORTA=0xff;while(1){for(i=0;i<8;i++){PORTA &=~BIT(i);delay();PORTA |=BIT(i);}}}lesson 5-3#include <>#include <>#define uchar unsigned charuchar table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; void delay(void){uchar a,b;for(a=0;a<240;a++)for(b=0;b<240;b++);}void main(void){uchar i;DDRB=0xff;PORTB=0xff;DDRA=0xff;PORTA=0xff;while(1){for(i=0;i<8;i++){// PORTA ^=BIT(i);PORTA ^=(1<<i);delay();PORTA ^=BIT(i);//DDRA |=BIT(DDRA);//a=PINA;}}}lesson 6-1#include <>#define uchar unsigned char#define uint unsigned intunsigned char table[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; void delay(void){uchar a,b;uchar c;for(c=0;c<12;c++)for(a=0;a<200;a++)for(b=0;b<200;b++);}void main(){uchar i;DDRB=0xff;PORTB=0xff;DDRA=0xff;PORTA=0xff;while(1){for(i=0;i<8;i++){PORTA=table[i];//delay();}// P0=0xfd;//}lesson 6-2#include <>#include <>#define uchar unsigned char#define uint unsigned int#define smgen_set PORTC |=BIT(3)#define smgen_clr PORTC &=~BIT(3)#define rs_set PORTD |=BIT(6)#define rs_clr PORTD &=~BIT(6)//sbit smgen=P2^3; ////sbit rs=P3^6; //unsigned char table1[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c}; unsigned char table2[]={0x00,0x10,0x20,0x30,0x40,0x50,0x60,0x70};void delay(unsigned int a)uchar b;for(b=0;b<10;b++){while(a--);}}void main(){unsigned char i; // rs=0;DDRB=0xff;PORTB=0;DDRC=0xff;PORTC=0;DDRD=0xff;PORTD=0;rs_clr;while(1){for(i=0;i<8;i++){PORTC=table2[i];//smgen=1;smgen_set;PORTB=table1[i];delay(200);}}lesson 6-3#include <>#include <>#define uchar unsigned char#define uint unsigned int#define en1_set PORTC |=BIT(3) #define en1_clr PORTC &=~BIT(3)#define en2_set PORTC |=BIT(0)#define en2_clr PORTC &=~BIT(0)#define rs_set PORTD |=BIT(6)#define rs_clr PORTD &=~BIT(6)//sbit en1=P2^3; ////sbit en2=P2^0; ////sbit rs=P3^6; //uchar table1[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f}; uchar table2[]={0x00,0x00,0x3e,0x41,0x41,0x41,0x3e,0x00};void delay(uint a){while(a--);}void main(){uchar i;DDRA=0xff; PORTA=0xff;DDRB=0xff; PORTB=0xff;DDRC=0xff; PORTC=0xff;DDRD=0xff; PORTD=0xff;en1_set;//en1=1;en2_set;//en2=1;rs_clr;//rs=0;while(1){for(i=0;i<8;i++){PORTA=table1[i];PORTB=table2[i];delay(100);}}PS/2键盘按键检测在单片机系统中,经常使用的键盘都是专用键盘,此类键盘一般都是单独设计制作的,成本高,使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出。

用单片机实现PC键盘输入

用单片机实现PC键盘输入

ACALL DELA10
RRC A RET
与主控机的异步串行通讯基于RS-232总线标准。为了使接口具有更好的兼容性和工作稳定性,我们用MAX232E作为数据传送器。MAX232E是专为RS-232通讯而设计,低功耗,外接电容小,抗干扰能力强,管脚有ESD保护并且能支持到120k波特率的数据传输,能很好地解决PC机和单片机电平不匹配问题。同时它增强了数据驱动能力,能支持12米的串行线。
CLR CLOCK ;同步信号产生一个脉冲
CLR KEY ;数据线置0 ACALL DELAY30
PC机复位键盘过程:先发复位命令FFH,单片机收到以FAH应答,PC机收到后,置时钟线和数据线为高电平,单片机检测到此状态开始内部自测试,测试完成发送AAH表示自检结束,否则发FDH表自检出错。
3.编码格式
实际的标准键盘在有按键按下时,键盘向PC机发送两行编码,一组为键稳定闭合时的扫描码,一组为闭合健断开时的断开码。具体各键的扫描码可以查询有关资料,断开码为两个字节,等于F0H+该键的扫描码。主控机通过通讯接口向受控机进行模拟键盘输入时,向串行口发送的编码单片机提取后发送给受控机的PS/2口,因此主控机向串行口发送的编码应符合下列格式:
摘 要:在某些特殊控制场合,需要通过主控机的串行口和受控机的PS/2键盘口,实现主控机对受控机的模拟键盘输入。本文介绍了串行口和键盘口的通讯接口的软、硬件设计方法。
关键词:串行口 PS/2键盘口 通讯 单片机
键盘作为微机的基本输入设备,是微机不可缺的一部分。但在某些特殊的场合,我们要对受控机进行程序设计的特殊输入控制,则需要一接口实现串行口和PS/2键盘口通讯,这样在主控机上通过对串行口的编程就能实现对受控机的模拟键盘输入。笔者开发的该接口以MCS-51单片机为核心,原理图如图1所示,利用MCS-51的全双工异步串行I/O口实现与主控机的异步串行通讯,而和受控机PS/2键盘口的同步串行通讯则通过双向数据I/O口控制同步时钟和数据位。

基于51单片机的数码管及键盘程序

基于51单片机的数码管及键盘程序

/*本程序功能:4*4按键,其中四个按键组成独立键盘,有加一减一和定时功能;另外十二个按键组成矩阵键盘,显示相应的编号。

*/#include<reg52.h>#define uchar unsigned char#define uint unsigned intuchar code duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; uchar code wei[]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};/*sbit key7=P3^7;sbit key6=P3^6;sbit key5=P3^5;sbit key4=P3^4;sbit key3=P3^3;sbit key2=P3^2;sbit key1=P3^1;sbit key0=P3^0;*/uchar temp,num,shi,ge;void delay(uint tms){uint i,j;for(i=tms;i>0;i--)for(j=110;j>0;j--);}void display(){shi=num/10;ge=num%10;P2=wei[2];P0=~duan[shi];P2=wei[3];P0=~duan[ge];delay(2);}/*void keyscan() //法①{key0=0;if(key4==0)P0=~duan[0];else if(key5==0)P0=~duan[4];else if(key6==0)P0=~duan[8];else if(key7==0)P0=~duan[12];delay(2);key0=1;key1=0;if(key4==0)P0=~duan[1];else if(key5==0)P0=~duan[5];else if(key6==0)P0=~duan[9];else if(key7==0)P0=~duan[13];delay(2);key1=1;if(key4==0)P0=~duan[2];else if(key5==0)P0=~duan[6];else if(key6==0)P0=~duan[10];else if(key7==0)P0=~duan[14];delay(2);key2=1;key3=0;if(key4==0)P0=~duan[3];else if(key5==0)P0=~duan[7];else if(key6==0)P0=~duan[11];else if(key7==0)P0=~duan[15];delay(2);key3=1;//这一句很重要,不要漏写}*/void init_t0()//法二{TMOD=0x01;TH0=(65536-46083)/256;TL0=(65536-46083)%256;EA=1;ET0=1;//TR0=1;}void timer0() interrupt 1{uchar count;TH0=(65536-46083)/256;TL0=(65536-46083)%256;count++;if(count==20){count=0;num++;if(num==60)num=0;}}void keyscan(){P1=0xfe;temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;temp=temp&0xf0;delay(10);if(temp!=0xf0){temp=P1;switch(temp){case 0xee:num++;/* while(temp==0xee){temp=P1;}*/ //这几条语句也可用于检测按键是否释放;若没有temp=P1,则不正确break;case 0xde:if(num==0)num=60;num--;// while(temp!=0xde);break;case 0xbe:num=0;// while(temp!=0xbe);break;case 0x7e:TR0=~TR0;// while(temp==0x7e);break;}while(temp!=0xf0){temp=P1;temp=temp&0xf0;}}}P1=0xfd;temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xed:num=1;break;case 0xdd:num=5;break;case 0xbd:num=9;break;case 0x7d:num=13;break;}}P1=0xfb;temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xeb:num=2;break;case 0xdb:num=6;break;case 0xbb:num=10;break;case 0x7b:num=14;break; }}P1=0xf7;temp=P1;temp=temp&0xf0;if(temp!=0xf0){temp=P1;switch(temp){case 0xe7:num=3;break;case 0xd7:num=7;break;case 0xb7:num=11;break;case 0x77:num=15;break; }}}void main(){init_t0();while(1){keyscan();display();}}。

PS2鼠标与51系列单片机的软硬件接口

PS2鼠标与51系列单片机的软硬件接口

钮状态发生变化,即主动向主机发送状态报告。
当鼠标加电后处于复位模式时,如果收到主机
的启动命令,就进入增量流模式,也就是进入了
正常工作状态。关于PS/2鼠标的命令集的详
细解释见文献[1—2]。
1.2接口规范
PS/2鼠标采用6针微型DIN接插件,但
只使用了其中的4个引脚,如图1所示。主机
通过接口为鼠标提供+5 V电源,数据及时钟
鼠标刚刚加电后,处于待机状态,主机必须 向其发送启动命令(0F4H),然后鼠标才进入增 量流模式,即正常的工作状态。这时,每移动超 过一个最小步距或按钮状态发生变化,鼠标将 向上发送一个3个字节的信息组,主机收到该 信息组后,通过处理即可控制信息使用。
2 鼠标接口程序设计
由于PS/2鼠标接口采用5 V工作电压, 且兼容TTL逻辑电平,因此8051单片机本身 具备直接接口能力,同时51系列的准双向I/0 口满足集电极开路条件,因此采用图5所示的 硬件连接方案。需要说明的是,由于正常工作 时,上行信息的发送是随机的,因此为了保证快 速的响应,CLK引脚必须采用中断输入,即接 到P3.2(1NTO),而DATA则可以接到任何一 根准双向引脚,这里就近接到了P3.3。
第16卷第3期 2008年9月
北京石油化工学院学报 Journal of Beijing Institute of
Petro—chemical Technology
V01.16 No.3 Sep.2008
PS/2鼠标与5 1系列单片机的软硬件接口
于 静 张立新
(北京石油化工学院,北京102617)

Software and Hardware Interface Between PS/2 Mouse and 5 1 Series SCM

用单片机来模拟ps2电脑键盘的程序

用单片机来模拟ps2电脑键盘的程序

用单片机来模拟ps2电脑键盘的程序//本程序可实现用单片机来代替ps2键盘来给电脑输入数据.//您只需从单片机上引出2根线到电脑的ps/2接口就可实现//本程序在51hei-5开发板上测试通过//跳线设置:默认//晶振:6M#include<reg51.h> //包含单片机寄存器的头文件#include<intrins.h> //包含_nop_()函数定义的头文件//#include"51hei.h"/************************************************************** *****************以下是引脚定义*************************************************************** ****************/sbit PS2CLK=P3^5;sbit PS2DAT=P2^7;/*****************************************************函数功能:延时1ms(3j+2)*i=(3×33+2)×10=1010(微秒),可以认为是1毫秒***************************************************/void delay1ms(){unsigned char i,j;for(i=0;i<10;i++)for(j=0;j<33;j++);}//===================================== =================================//2051模拟PS2键盘和PC机通讯程序 6M下发送程序代码//程序的完整版本及hex文件下载地址://===================================== =================================PS2keytohost(unsigned char vale){unsigned char h = 0;unsigned char i = 8;unsigned char J;unsigned char t;bit bparity =0 ;ACC = vale;//获取字节的奇偶信息if(!P) //ACC中偶数时,P为0,但是PS2中时奇校验( 字节中的1的个数+校验位 = 奇数){ bparity = 1; }if(PS2CLK&&PS2DAT) //发送前检测PS2总线{for(J = 12 ;J > 0;J--) {;}//6M,大约延时40uS后再检测if(PS2CLK)//时钟线空闲{if(PS2DAT)//数据线空闲{//for(t = 10;t > 0;t--){;} //6M,大约延时20uSfor(J = 11;J > 0;J--) //1共11个数据{if(h == 0) // 送起始位{PS2DAT = 0;h++;}else if(h == 1)//送8位数据位{PS2DAT = vale & 0x01;//先LSB开始vale >>= 1;i--;if(i == 0) //发送完成{ h++; }}else if(h == 2)//送校验位{PS2DAT = bparity;h++;}else{ PS2DAT = 1; } //送停止位for(t = 12;t > 0;t--){;} //6M,大约延时40uS PS2CLK = 0;//拉低时钟线,主机接收for(t = 12;t > 0;t--){;} //6M,大约延时40uS PS2CLK = 1;//拉高时钟线,设备发送if(!PS2CLK) //检测到时钟线变低{ //主机不要这次通讯 (很罕见)return(0);//返回 0}for(t = 6;t > 0;t--){;} //6M,大约延时20uS}//for(J = 11;J > 0;J--)for(t = 12;t >0;t--){;}return(1);//返回 1}//if(PS2DAT)}//if(PS2CLK)}//if(PS2CLK&&PS2DAT)}//end/***************************************************** 函数功能:主函数***************************************************/ void main(void){PS2keytohost(0X1C);while(1){delay1ms(); }}。

51单片机控制PS2键盘头文件

51单片机控制PS2键盘头文件

51单片机控制PS2键盘头文件51单片机控制PS2键盘是DM51的一个有用接口,光盘中程序给出了调试过的,如果有用户丢失了头文件,请将下面文件存为ps2.h转载请注明出处。

//===========================ps2.h头文件=============================// #ifndef PS2_H#define PS2_Hsbit keydata=P1^7;sbit clk=P3^2;unsigned char times=0;unsigned char i=0;unsigned char keycode=0,ps2_key; //ps2_key用于存放接收到的键码static unsigned char BF=0; //标识是否有字符被收到unsigned char code noshift[80][2]={1 , 8,// { f9 }3 , 4,// { f5 }4 , 2,// { f3 }5 , 0,// { f1 }6 , 1,// { f2 }7 ,11,// { f12 }9 , 9,// { f10 }13 ,25,// { tab }20 ,27,// { ctrl }41 ,29,// { space } 31 ,30,// { win } 12 , 3,// { f4 }11 , 5,// { f6 }10 , 7,// { f8 }14 ,96,// { ` }22 ,49,// { 1 }28 ,97,// { a }30 ,50,// { 2 }33 ,99,// { c }38 ,51,// { 3 }37 ,52,// { 4 }46 ,53,// { 5 }47 ,31,// { winright} 54 ,54,// { 6 }61 ,55,// { 7 }62 ,56,// { 8 }50 ,98,// { b }35 ,100,// { d }36 ,101,// { e }43 ,102,// { f }52 ,103,// { g }51 ,104,// { h }59 ,106,// { j }58 ,109,// { m }49 ,110,// { n }21 ,113,// { q }45 ,114,// { r }27 ,115,// { s }60 ,117,// { u } 42 ,118,// { v }29 ,119,// { w } 34 ,120,// { x }53 ,121,// { y }26 ,122,// { z }65 ,44,// { , }66 ,107,// { k }67 ,105,// { i }68 ,111,// { o }69 ,48,// { 0 }70 ,57,// { 9 }73 ,46,// { . }74 ,47,// { / }75 ,108,// { l }76 ,59,// { ; }77 ,112,// { p }78 ,45,// { - }82 ,39,// { ' }85 ,61,// { = }84 ,91,// { [ }91 ,93,// { ] }88 ,26,// { caps } 93 ,92,// { \ }90 ,32,// { enter } 120,10,// { f11 } 102,12,// { back } 224,13,// { home } 105,14,// { end }125,15,// { pageup }122,16,// { pagedown }117,17,// { up }114,18,// { down }107,19,// { left }116,20,// { right }113,21,// { del }112,22,// { insert }225,23,// { pause }118,24,// { esc }131, 6,// { f7 }};unsigned char code addshift[47][2]= {14,126, // { ~ }22, 33, // { ! }30, 64, // { @ }38, 35, // { # }37, 36, // { $ }46, 37, // { % }54, 94, // { ^ }61, 38, // { & }62, 42, // { * }70, 40, // { ( }69, 41, // { ) }78, 95, // { _ }85, 43, // { + }93,124, // { | }84,123, // { { }76, 58, // { : } 82, 34, // { " } 65, 60, // { < } 73, 62, // { > } 74, 63, // { ? } 28 ,65,// { a } 50 ,66,// { b } 33 ,67,// { c }35 ,68,// { d }36 ,69,// { e } 43 ,70,// { f } 52 ,71,// { g } 51 ,72,// { h } 67 ,73,// { i } 59 ,74,// { j } 66 ,75,// { k } 75 ,76,// { l } 58 ,77,// { m } 49 ,78,// { n } 68 ,79,// { o } 77 ,80,// { p } 21 ,81,// { q } 45 ,82,// { r } 27 ,83,// { s } 44 ,84,// { t } 60 ,85,// { u } 42 ,86,// { v } 29 ,87,// { w } 34 ,88,// { x }26 ,90,// { z }};unsigned char getchar(unsigned char k) //转换键码为ASCII码{unsigned char j;if(!i)for(j=0;j<80;j++){if(noshift[j][0]==k){ps2_key=noshift[j][1];return 1;}}elsefor(j=0;j<47;j++){if(addshift[j][0]==k){ps2_key=addshift[j][1];return 1;}}return 0;}void Keyboard_out(void) interrupt 0{if(times<9){keycode=keycode>>1; //因键盘数据是低>>高,结合上一句所以右移一位if(keydata) keycode=keycode | 0x80; //当键盘数据线为1时为1到最高位 }times++;if(times>10){times=0;if(keycode==0xe0 || keycode==0xf0){}//return;}else if((keycode==18 || keycode==89) && i==0){i=1;}else if((keycode==18 || keycode==89) && i==1){i=0;}else {EX0=0;BF=1;} //关中断等显示完后再开中断//当中断11次后表示一帧数据收完,清变量准备下一次接收//(注:如这里不用BF和关中断直接调Decode()//则所Decode中所调用的所有函数要声明为再入函数)}// while(!clk); //等待PS/2CLK拉高}#endif。

51单片机读取PS2键盘

51单片机读取PS2键盘

void main(void)
{
unsigned char TempCyc;
unsigned char KEY=0;
Delay5Ms(); // 延时片刻(可不要)
if (UnShifted[TempCyc][0] == ScanCode)
KeyChar=UnShifted[TempCyc][1];
DisNum++;
}
else //按下SHIFT
} while (IntNum<11); //51fuzi更正 原为 while Num<12);
return (Decode(KeyV)); // 键盘解码
}
return 0;
}
unsigned char Decode(unsigned char ScanCode)
{
for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
if (Shifted[TempCyc][0] == ScanCode)
KeyChar=Shifted[TempCyc][1];
DisNum++;
}
break;
}
}
else
{
Key_UP = 0;
switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理
{
case 0x12 : // 左 SHIFT
{
unsigned char KeyV=0;

单片机与PS2键盘接口程序

单片机与PS2键盘接口程序
(void *)PS2KpKeyPush + 0x2e62, //功能键Kp压键事件处理
/*---------------------------------------------
2个放键事件处理(集中管理)
----------------------------------------------*/
PS2Buffers.PS2Keyco u* nt = 0;//脉冲计数归零
if (PS2DATA){//高电平是停止位
if (key == 0xe0){//本次是扩展键
PS2Buffers.PS2KeyExtFlage = 0xe0;//置扩展键标志(小键盘只有回车键)
}
else if (key == 0xf0){//本次是键断码,键释放
void int1proc() interrupt IE1_VECTOR using 1
{
unsigned ch* ar i, key;
code unsigned ch* ar PS2TAB[] = {//20键PS2小键盘键码表
0x70,//0
0x69,//1
0x72,//2
0x7a,//3
计数器清零
PS2CLOCK = 1;//释放PS2时钟总线
}
}
}
else PS2Buffers.PS2KeyPopError = 0xed;//置停止位错误号0xed
}
else PS2Buffers.PS2Keyco u* nt = 0;//PS2键盘出错
}
/*------------------------------------------------------------------
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

PS2键盘的单片机编程在单片机系统中,经常使用的键盘都是专用键盘.此类键盘为单独设计制作的,成本高、使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出.与此相比,在PC系统中广泛使用PS/2键盘具有价格低、通用可靠,且使用连接线少(仅使用2根信号线)的特点,并可满足多种系统的要求.因此在单片机系统中应用PS/2键盘是一种很好的选择.文中在介绍PS/2协议和PS/2键盘工作原理与特点的基础上,给出了一个在单片机上实现对PS/2键盘支持的硬件连接与驱动程序设计实现.该设计实现了在单片机系统中对PS/2标准104键盘按键输入的支持.使用Keil C51开发的驱动程序接口和库函数可以方便地移植到其他单片机或嵌入式系统中.所有程序在Keil uVision2上编译通过,在单片机AT89C51上测试通过.1 PS/2协议目前,PC机广泛采用的PS/2接口为mini-DIN 6pin的连接器,如图1所示.PS/2设备有主从之分,主设备采用Female插座,从设备采用Male插头.现在广泛使用的PS/2键盘鼠标均在从设备方式下工作.PS/2接口的时钟与数据线都是集电极开路结构,必须外接上拉电阻(一般上拉电阻设置在主设备中).主从设备之间数据通信采用双向同步串行方式传输,时钟信号由从设备产生.1.1 从设备到主设备的通信当从设备向主设备发送数据时,首先检查时钟线,以确认时钟线是否为高电平.如果是高电平,从设备就可以开始传输数据;反之,从设备要等待获得总线的控制权,才能开始传输数据.传输的每一帧由11位组成,发送时序及每一位的含义如图2所示.每一帧数据中开始位总是为0,数据校验采用奇校验方式,停止位始终为1.从设备到主设备通信时,从设备总是在时钟线为高时改变数据线状态,主设备在时钟下降沿读人数据线状态.1.2 主设备到从设备的通信主设备与从设备进行通信时,主设备首先将时钟线和数据线设置为“请求发送”状态,具体方式为:首先下拉时钟线至少100us抑制通信,然后下拉数据线“请求发送”,最后释放时钟线.在此过程中,从设备在不超过10us的间隔内必须检查这个状态,当设备检测到这个状态时,它将开始产生时钟信号.此时数据传输的每一帧由12位构成,其时序和每一位含义如图3所示.与从设备到主设备通信相比,其每帧数据多了一个ACK位.这是从设备应答接收到字节的应答位,由从设备通过拉低数据线产生,应答位ACK总是为0.主设备到从设备通信过程中,主设备总是在时钟线为低电平时改变数据线的状态,从设备在时钟上升沿读人数据线状态.2 PS/2键盘的编码与命令集2.1 PS/2键盘的编码目前,PC机使用的PS/2键盘都默认采用第2套扫描码集.扫描码有两种不同的类型:“通码(make code)”和“断码(break code)”.当一个键被按下或持续按住时,键盘会将该键的通码发送给主机;而当一个键被释放时,键盘会将该键的断码发送给主机.根据键盘按键扫描码的不同,可将按键分为3类:第1类按键通码为一个字节,断码为0xF0+通码形式.如A键,其通码为0x1C;断码为0xF0 0x1C.第2类按键通码为两字节0xE0+0xXX形式,断码为0xE0+0xF0+0xXX形式.如Right Ctrl键,其通码为0xE0 0x14;断码为0xE0 0xF0 0x14.第3类特殊按键有两个,Print Screen键,其通码为0xE0 0x12 0xE0 0x7C;断码为0xE0 0xF0 0x7C 0xE0 0xF0 0x12.Pause键,其通码为0xE1 0x14 0x77 0xE1 0xF0 0xl4 0xF0 0x77;断码为空.组合按键扫描码的发送是按照按键发生的次序,如按下面顺序按左Shift十A 键:① 按下左Shift键;② 按下A键;③ 释放A键;④ 释放左Shift键,那么计算机上接收到的一串数据为0x12 0x1C 0xF0 0x1C 0xF0 0x12.在文中的驱动程序设计中,就是根据按键的分类对其分别进行处理.2.2 PS/2键盘的命令集主机可通过向PS/2键盘发送命令对键盘进行设置或者获得键盘的状态等操作.每发送一个字节,主机都会从键盘获得一个应答0xFA(“重发resend”和“回应echo”命令例外).驱动程序在键盘初始化过程中所用的指令:0xED,主机在该命令后跟随发送一个参数字节,用于指示键盘上Num Lock,Caps Lock,Scroll Lock Led的状态;0xF3,主机在这条命令后跟随发送一个字节参数定义键盘机打的速率和延时;0xF4,用于当主机发送0xF5禁止键盘后,重新使能键盘.3 PS/2键盘与单片机的连接电路PS/2键盘与AT89C51单片机的连接方式如图4所示.P1.0接PS/2数据线;P3.2(INT0)接PS/2时钟线.因为单片机的P1,P3口内部是带上拉电阻的,所以PS/2的时钟线和数据线可以直接与单片机的P1,P3相连接.4 驱动程序设计驱动程序的开发使用Keil C51语言以及KeiluVision2编程环境.PS/2 104键盘驱动程序主要任务是实现单片机与键盘间PS/2通信,同时将接收到的按键扫描码转换为该按键的键值KeyVal,提供给系统上层软件使用.4.1 单片机与键盘间PS/2通信的程序设计在PS/2通信过程中,主设备(文中是单片机)是在时钟信号为低时发送和接收数据信号.因为单片机向键盘发送的是指令,需要键盘回应,所以这部分程序采用查询方式;而单片机接收键盘数据时,数据线上的信号在时钟为低时已经稳定,所以这部分程序采用中断方式,且不需要在程序中加入延时程序.单片机向PS/2键盘发送数据程序代码为:void ps2_sentchar(unsigned char sentchar){//ps2主设备向从设备发送数据unsigned char sentbit_cnt= 0x00;unsigned char sentchar_chk = 0x00;EX0=0; //关外部中断0//发起一个传送,发起始位PS2_SGN_CLOCK = 0; //将时钟线拉低并保持100 usdelay100us();PS2_SGN_DATA= 0; //起始位PS2_SGN_CLOCK = 1;//发送DATA0-7for(sentbit_cnt=0;sentbit_cnt< 8;sentbit_cnt++){while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变为低PS2_SGN_DATA = sentchar& 0x01;//发送数据if(PS2_SGN_DATA) sentchar_chk++; //计算校验while(!PS2_SGN_CL0CK) _nop_(); //等待时钟线变高sentchar>>=1; //待发送数据右移一位}//发送校验位while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低switch(sentchar_chk){case 0:case 2:case 4:case 6:PS2_SGN_DATA =1;break;//奇校验case 1:case 3:case 5:case 7:PS2_SGN_DATA = 0;break;//奇校验default;break;)while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低PS2_SGN_DATA =1;//发送停止位,停止位总为1while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高while(PS2_SGN_CLOCK) _nop_(); //等待时钟线变低//接收ACK//if(PS2_SGN_DATA) error();//ACK信号由键盘发出,总为低电平while(!PS2_SGN_CLOCK) _nop_(); //等待时钟线变高EX0= 1; //开外部中断0}单片机由PS/2键盘接收数据程序:外部中断0设置为下降沿触发void int0() interrupt 0 using 0 {//EX0=0; //关外部中断0switch(ps2_revchar_cnt){case 1:……case 8:mcu_revchar<<=1;if(PS2_SGN_DATA) mcu_revchar |= 0x01;ps2_revchar_cnt++;break;case 0:ps2_revchar_cnt++;break; //开始位,case 9:ps2_revchar_cnt++;break; //校验位,可添加校验程序case 10: _nop_();//停止位ps2_revchar_cnt= 0;revchar_flag=1;//置接收到数据标识位break;default:break;}EX0=1;//开外部中断0}4.2 键盘扫描码转换程序设计由于键盘扫描码无规律可循,因此由键盘扫描码获得相应按键的键值(字符键为其ASCII值,控制键如F1,Ctrl等为自定义值),只能通过查表的方式获得.由于按键的3种类型及部分按键对应着两个键值(如A键的键值根据Caps和Shift键状态有0x41(A)和0x61(a)两种),因此综合考虑查表转换速度和资源消耗,设计中使用4个键盘表:键盘扫描码转换基本集和切换集(kb_plain_map[NR_KEYS]与kb_shift_map[NR_KEYS]);包含E0前缀的键盘扫描码转换基本集和切换集(kbeO_plain_map[NR_KEYS]与kbe0_shiftmap[NR_KEYS]).PS/2 104键盘按键扫描码最大值为0x83,所以设置NR_KEYS为132.所有4个键盘表的定义均为如下形式:KB_MAP[MAKE CODE]=KEYVAL,如果扫描码对应的按键为空(如KB_MAP[0x00]),则定义相应键值为NULL_KEY(0x00).以下是键盘扫描码基本集的部分代码实例: kb_plain_map[NR_KEYS]={……NULL_KEY;0x2C;0x6B;0x69;0x6F;0x30;0x39;NULL_KEY; //扫描码0x40~0x47//对应按键空,逗号,K,I,O,0,9,空//对应键值0x00,',','k','i','o','O','9',0x00…… };如此设计键盘转换表的另一个好处在于,以后如需扩展支持有ACPI、Windows多媒体按键键盘时,只需要将键表中相应处修改即可,如ACPIPower按键通码为0xE0 0x37,修改kbe0_plain_map[0x37]=KB_ACPI_PWR即可. 特殊按键Pause使用单独程序处理,如果接收到0xE1就转入这段程序.而Print Screen键则将其看作是两个通码分别为0xE0 0x12和0xE0 0x7C的“虚键”的组合键处理.在驱动程序中设定如下全局变量:led_status记录Scroll Lock Led,Num Lock Led和Caps Lock Led的状态(关为0,开为1);agcs_status记录左右Shift Ctrl Gui Alt状态,相应键按下则对应位为1,释放为0.E0_FLAG接到0xE0置1;E1_FLAG接收到0xE1置1;F0_FLAG接收到0xF0置1.按键键值通过KeyVal提供上层程序使用.PS/2键盘扫描码键值转换程序ps2_codetrans()流程框架如图5所示.第1类按键的扫描码键值转换程序代码。

相关文档
最新文档