51单片机标准PS2键盘
天狼星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键盘按键检测在单片机系统中,经常使用的键盘都是专用键盘,此类键盘一般都是单独设计制作的,成本高,使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出。
独立式键盘程序
51单片机:键盘控制程序2009-11-14 16:12键盘控制1.功能说明:用八位指拨开关(DIP)作单片机的输入,控制输出端口连接的八只LED发光二极管。
如若DIP1开关为 ON(向右拨动)则LED1亮,其它开关作用同。
程序:LOOP: MOV A, P3 ; 从P3读入DIP开关值MOV P1, A ; 从P1输出03: JMP LOOP ; 无穷循环04: END ;程序结束2.功能说明:用DIP开关中的低4位作二进制的输入,控制输出端数码管显示器的输出。
程序:01: MOV DPTR,#TABLE ; 存表02: MOV P0, #0FFH ; LED全灭03: LOOP: MOV A, P3 ; 从P3口读入DIP开关值04: ANL A, #0FH ; 高4位清0,取低四位05: ACALL CHANG ; 转成七段显示码06: MOV P0, A ; 从P0输出07: JMP LOOP ; 转移LOOP处,循环08: CHANG: MOVC A,@A+DPTR ; 取码09: RET ; 返回转换显示码子程序10: TABLE: DB 0C0H, 0F9H, 0A4H, 0B0H ;11: DB 99H, 92H, 82H, 0F8H ;12: DB 80H, 90H, 88H, 83H ;13: DB 0C6H, 0A1H, 86H, 8EH ; 显示码表14: END ;程序结束3.功能说明:用两个按键开关K1和K2作输入,K1为电源指示灯开关,K2为工作指示灯开关。
分别控制电源指示灯(P1.0接的LED)和工作指示灯(P1.7接的LED)的接通和关闭。
接通电源时,电源指示灯是在亮的状态。
当按K2时,工作指示灯亮,电源指示灯灭。
按K1时,电源指示灯亮,工作指示灯灭。
程序:01: START: MOV P1, #11111110B ; P1.0所接LED亮02: JB P2.5 , $ ; 判断P2.5(K2键)是否为103: ON: MOV P1, #01111111B ; P1.7所接LED亮04: JNB P2.4, START ; 判断P2.4(K1键)是是否为005: JMP ON ; 未按K1键,则跳至ON06: END ;程序结束4.功能说明:由四个按键开关组成独立式键盘,控制灯左移、右移和闪烁。
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键盘与鼠标的接口定义针脚定义:原理PS/2鼠标接口采用一种双向同步串行协议。即每在时钟线上发一个脉冲,就在数据线上发送一位数据。在相互传输中,主机拥有总线控制权,即它可以在任何时候抑制鼠标的发送。方法是把时钟线一直拉低,鼠标就不能产生时钟信号和发送数据。在两个方向的传输中,时钟信号都是由鼠标产生,即主机不产生通信时钟信号。如果主机要发送数据,它必须控制鼠标产生时钟信号。方法如下:主机首先下拉时钟线至少100μs 抑制通信,然后再下拉数据线,最后释放时钟线。通过这一时序控制鼠标产生时钟信号。当鼠标检测到这个时序状态,会在10ms内产生时钟信号。如图3中A 时序段。主机和鼠标之间,传输数据帧的时序如图2、图3所示。2.2 数据包结构在主机程序中,利用每个数据位的时钟脉冲触发中断,在中断例程中实现数据位的判断和接收。在实验过程中,通过合适的编程,能够正确控制并接收鼠标数据。但该方案有一点不足,由于每个CLOCK都要产生一次中断,中断频繁,需要耗用大量的主机资源。PS/2鼠标的四种工作模式是:Reset模式,当鼠标上电或主机发复位命令0xFF给它时进入这种模式;Stream模式鼠标的默认模式,当鼠标上电或复位完成后,自动进入此模式,鼠标基本上以此模式工作;Remote模式,只有在主机发送了模式设置命令0xF0后,鼠标才进入这种模式;Wrap模式,这种模式只用于测试鼠标与主机连接是否正确。PS/2鼠标在工作过程中,会及时把它的状态数据发送给主机。发送的数据包格式如表1所示。Byte1中的Bit0、Bit1、Bit2分别表示左、右、中键的状态,状态值0表示释放,1表示按下。Byte2和Byte3分别表示X轴和Y轴方向的移动计量值,是二进制补码值。Byte4的低四位表示滚轮的移动计量值,也是二进制补码值,高四位作为扩展符号位。这种数据包由带滚轮的三键三维鼠标产生。若是不带滚轮的三键鼠标,产生的数据包没有Byte4 其余的相同。一.PS/2 鼠标键盘协议PC 键盘可以有6 脚的mini-DIN 或5 脚的DIN 连接器如果你的键盘是6 脚的mini-DIN 而你的计算机是5 脚的DIN 或者相反这两类连接器可以用上面提到的适配器来兼容具有6 脚mini-DIN 的键盘通常被叫做PS/2 键盘而那些有5 脚DIN 叫做AT 设备XT 键盘也使用5 脚DIN 但它们非常古老并且多年前就不生产了所有现代的为PC 建造的键盘不是PS/2,AT 就是USB 的这篇文章不适用于USB 设备它们使用了一种完全不同的接口。
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单片机按键-数码管显示
普中51单⽚机按键-数码管显⽰基于普中单⽚机按键-数码管显⽰简介1.硬件部分普中单⽚机开发板 数码管 独⽴按键2.软件部分keil软件硬件部分普中单⽚机开发板数码管独⽴按键(这些都是开发板的最基本的配置)软件部分#include "reg52.h" //此⽂件中定义了单⽚机的⼀些特殊功能寄存器typedef unsigned int u16; //对数据类型进⾏声明定义typedef unsigned char u8;/*端⼝引脚定义*/sbit LSA=P2^2;sbit LSB=P2^3;sbit LSC=P2^4;sbit KEY1 = P3^0;sbit KEY2 = P3^1;/*变量定义*/int number;unsigned char KeyNum=0; //被触发的按键编号unsigned char KeyLock1=0;unsigned char KeyLock2=0;unsigned int cnt;/*函数声明部分*/void KEY_Scan();void KEY_Action();void Light_Scan();void delay(u16 i);void Display();void Time0Iint();/*数码管码表*/unsigned char code smgduan[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};//共阴数码管显⽰0~F的值unsigned char LightBuf[]={0xFF,0xFF,0xFF,0xFF,0XFF};/******************************************************************************** 函数名 : delay* 函数功能 : 延时函数,i=1时,⼤约延时10us*******************************************************************************/void delay(u16 i){while(i--);}/******************************************************************************** 函数名 : Display* 函数功能 : 数码管显⽰部分*******************************************************************************/void Display(){LightBuf[0]=smgduan[number%10];LightBuf[1]=smgduan[number/10%10];LightBuf[2]=smgduan[number/100%10];LightBuf[3]=smgduan[number/1000%10];LightBuf[4]=smgduan[number/10000%10];}/******************************************************************************** 函数名 : Light_Scan()* 函数功能 : 数码管扫描函数,选择显⽰的位置*******************************************************************************/void Light_Scan(){u8 i;for(i=0;i<8;i++){switch(i) //位选,选择点亮的数码管,{case(0):LSA=0;LSB=0;LSC=0;P0=LightBuf[4];break;//显⽰第0位case(1):LSA=1;LSB=0;LSC=0;P0=LightBuf[3];break;//显⽰第1位case(2):LSA=0;LSB=1;LSC=0;P0=LightBuf[2];break;//显⽰第2位case(3):LSA=1;LSB=1;LSC=0;P0=LightBuf[1];break;//显⽰第3位case(4):LSA=0;LSB=0;LSC=1;P0=LightBuf[0];break;//显⽰第4位default: break;}delay(100); //间隔⼀段时间扫描P0=0x00;//消隐}}/******************************************************************************* * 函数名 : KEY_Scan()* 函数功能 : 按键扫描函数*******************************************************************************/ void KEY_Scan(){static unsigned char cnt1 = 0xFF;static unsigned char cnt2 = 0xFF;cnt1 =(cnt1<<1)|KEY1;cnt2 =(cnt2<<1)|KEY2;if(cnt1 != 0x00){KeyLock1 = 0;}else if(KeyLock1==0){KeyNum = 1;KeyLock1 = 1;}if(cnt2 != 0x00){KeyLock2 = 0;}else if(KeyLock2==0){KeyNum = 2;KeyLock2 = 1;}}/******************************************************************************* * 函数名 : KEY_Action()* 函数功能 : 按键执⾏操作部分*******************************************************************************/ void KEY_Action(){switch(KeyNum){case 1:number++; KeyNum = 0; break;case 2:number--; KeyNum = 0; break;default:break;}}/******************************************************************************* * 函数名 :Time0Iint* 函数功能 :定时器0配置,定时器初始化函数*******************************************************************************/ void Time0Iint(){EA=1;TH0 = (65536-2000)/256;//定时2msTL0 = (65536-2000)%256;TMOD &= 0xFC;TMOD = 0x01;ET0 = 1;TR0 = 1;}/******************************************************************************* * 函数名 :void InterruptT0() interrupt 1* 函数功能 : 定时器0中断执⾏部分*******************************************************************************/ void InterruptT0() interrupt 1{TH0 = (65536-2000)/256;//定时2msTL0 = (65536-2000)%256;Light_Scan();KEY_Scan();}/******************************************************************************* * 函数名 : main* 函数功能 : 主函数* 输⼊ : ⽆* 输出 : ⽆*******************************************************************************/ void main(){Time0Iint();while(1){Display();KEY_Action();}}参考资料。
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;
51单片机各针脚介绍
51单片机各针脚介绍51单片机是一款广泛应用于嵌入式系统中的微控制器,它在电子行业中具有重要的地位。
了解51单片机的各个针脚和其功能对于学习和应用它来说至关重要。
本文将为读者介绍51单片机的各个针脚以及它们的功能。
1. VCC和GND:VCC代表供电正极,GND代表接地。
这两个针脚是最基本的供电和接地连接,使用者需要将这两个引脚连接到电源,以提供电压和地线。
2. P0.0 - P0.7:P0口是51单片机最常用的8位通用I/O口之一。
每个引脚可以被配置为输入或输出,用于连接和控制外部设备。
3. P1.0 - P1.7:P1口也是一个8位通用I/O口,具有与P0口相同的功能。
P1口的特点是它具备上拉电阻功能,可以用于外部开关和按钮的输入控制。
4. P2.0 - P2.7:P2口也是一个8位通用I/O口,同样可以作为输入或输出引脚。
与P1口类似,P2口也具备上拉电阻功能。
5. P3.0 - P3.7:P3口是最后一个8位通用I/O口,同样可用作输入或输出引脚。
与P2口类似,P3口具备上拉电阻功能。
6. RST:RST是复位控制引脚,用于将51单片机重启至复位状态。
当对RST引脚施加低电平脉冲时,单片机将会重新启动,并执行初始化操作。
7. EA/VPP:EA/VPP引脚具有两个不同的功能。
在系统中,EA引脚必须连接到GND,以选择外部程序存储器;VPP引脚在烧录代码时使用,通常连接到12V电压。
8. ALE/PROG:ALE/PROG引脚也有两种功能,ALE用于地址锁存器的时钟输入,PROG用于编程电平切换。
在应用中,ALE通常用于与外部设备进行时序协调。
9. PSEN:PSEN引脚用于外部程序存储器的读取操作。
当进行指令获取或通信时,PSEN引脚连接到程序存储器并发送读取控制信号。
10. XTAL1和XTAL2:这两个引脚用于外部晶振或陶瓷谐振器的连接。
XTAL1接收晶振信号输入,XTAL2输出晶振信号。
51单片机按键电路
51单片机键盘接口电路(含源程序)键盘是由若干按钮组成的开关矩阵,它是单片机系统中最常用的输入设备,用户能通过键盘向计算机输入指令、地址和数据。
一般单片机系统中采和非编码键盘,非编码键盘是由软件来识别键盘上的闭合键,它具有结构简单,使用灵活等特点,因此被广泛应用于单片机系统。
按钮开关的抖动问题组成键盘的按钮有触点式和非触点式两种,单片机中应用的一般是由机械触点组成的。
在下图中,当开<键盘结构图>图1图2关S未被按下时,P1。
0输入为高电平,S闭合后,P1。
0输入为低电平。
由于按钮是机械触点,当机械触点断开、闭合时,会有抖动动,P1。
0输入端的波形如图2所示。
这种抖动对于人来说是感觉不到的,但对计算机来说,则是完全能感应到的,因为计算机处理的速度是在微秒级,而机械抖动的时间至少是毫秒级,对计算机而言,这已是一个“漫长”的时间了。
前面我们讲到中断时曾有个问题,就是说按钮有时灵,有时不灵,其实就是这个原因,你只按了一次按钮,可是计算机却已执行了多次中断的过程,如果执行的次数正好是奇数次,那么结果正如你所料,如果执行的次数是偶数次,那就不对了。
为使CPU能正确地读出P1口的状态,对每一次按钮只作一次响应,就必须考虑如何去除抖动,常用的去抖动的办法有两种:硬件办法和软件办法。
单片机中常用软件法,因此,对于硬件办法我们不介绍。
软件法其实很简单,就是在单片机获得P1。
0口为低的信息后,不是立即认定S1已被按下,而是延时10毫秒或更长一些时间后再次检测P1。
0口,如果仍为低,说明S1的确按下了,这实际上是避开了按钮按下时的抖动时间。
而在检测到按钮释放后(P1。
0为高)再延时5-10个毫秒,消除后沿的抖动,然后再对键值处理。
不过一般情况下,我们常常不对按钮释放的后沿进行处理,实践证明,也能满足一定的要求。
当然,实际应用中,对按钮的要求也是千差万别,要根据不一样的需要来编制处理程序,但以上是消除键抖动的原则。
51单片机引脚介绍(全)
51单片机引脚介绍(全)51单片机引脚介绍(全)单片机(Microcontroller)是一种集成了微处理器核心、存储器和各种输入输出控制电路的集成电路芯片,广泛应用于嵌入式系统中。
而51单片机(8051 Microcontroller)是最早被广泛使用的一款单片机型号,其引脚布局和功能十分重要。
本文将对51单片机的引脚进行详细介绍,以便更好地理解和应用。
1. 引脚简介51单片机共有40个引脚,编号为P0.0至P3.7,其中P0、P1、P2、P3为4个8位的I/O端口,分别对应于32个可编程的引脚。
此外,引脚还包括VCC(供电正极)、GND(接地)以及RESET(复位引脚)、PSEN(程序存储器使能引脚)、ALE/PROG(地址锁存/编程使能引脚)、EA/VPP(外部访问使能/编程电压),共计7个特殊功能引脚。
2. I/O口的功能P0口是可用的8位双向I/O口,可以用于与外设的数据传输。
P0口在模拟输入/输出工作状态下为双向I/O口,在数字输入/输出工作状态下为输出口。
P1口也是一个可用的8位双向I/O口,用于与外设的数据传输。
P2口是一个不可用的8位双向I/O口,它被用作外部总线的高8位数据总线。
P3口是一个可用的8位双向I/O口,用于与外设的数据传输。
3. 特殊功能引脚RESET引脚是用于复位单片机的引脚。
将RESET引脚拉低,即可使单片机复位。
PSEN引脚是用于访问外部程序存储器(EPROM或闪存)的引脚。
当PSEN为高时,表示访问的是程序存储器。
ALE/PROG引脚在T0(定时器0)的溢出和外部中断0激活时产生外部地址锁存信号。
在程序编程时,它与PSEN引脚一起用作编程使能信号,并提供编程电压。
EA/VPP引脚是用于控制单片机是否使用外部存储器。
当EA/VPP 为低时,表示单片机使用外部存储器;当EA/VPP为高时,表示单片机使用内部存储器。
4. 其他引脚VCC引脚是单片机的正电源引脚,需要接入正电源。
51单片机键盘数码管显示(带程序)
期中大作业学院:物理与电子信息工程学院课题:【利用8255和51单片机实现数码管显示按键数值的程序】要求:【4*4矩阵键盘,按0到15,数码管上分别显示0~9,A~F】芯片资料:8255:8255是Intel公司生产的可编程并行I/O接口芯片,有3个8位并行I/O口。
具有3个通道3种工作方式的可编程并行接口芯片(40引脚)。
其各口功能可由软件选择,使用灵活,通用性强。
8255可作为单片机与多种外设连接时的中间接口电路。
8255作为主机与外设的连接芯片,必须提供与主机相连的3个总线接口,即数据线、地址线、控制线接口。
同时必须具有与外设连接的接口A、B、C口。
由于8255可编程,所以必须具有逻辑控制部分,因而8255内部结构分为3个部分:与CPU连接部分、与外设连接部分、控制部分。
8255特性:1.一个并行输入/输出的LSI芯片,多功能的I/O器件,可作为CPU总线与外围的接口。
2.具有24个可编程设置的I/O口,即3组8位的I/O口,分别为PA口、PB口和PC 口。
它们又可分为两组12位的I/O口:A组包括A口及C口(高4位,PC4~PC7),B组包括B口及C口(低4位,PC0~PC3)。
A组可设置为基本的I/O口,闪控(STROBE)的I/O闪控式,双向I/O三种模式;B组只能设置为基本I/O或闪控式I/O两种模式,而这些操作模式完全由控制寄存器的控制字决定.引脚说明RESET:复位输入线,当该输入端处于高电平时,所有内部寄存器(包括控制寄存器)均被清除,所有I/O口均被置成输入方式。
CS:芯片选择信号线,当这个输入引脚为低电平时,即CS=0时,表示芯片被选中,允许8255与CPU进行通讯;CS=1时,8255无法与CPU做数据传输。
RD:读信号线,当这个输入引脚为低电平时,即CS=0且RD=0时,允许8255通过数据总线向CPU发送数据或状态信息,即CPU从8255读取信息或数据。
WR:写入信号,当这个输入引脚为低电平时,即CS=0且WR=0时,允许CPU将数据或控制字写入8255。
51单片机按键等控制代码
8 位立即数带进位加到累加器 累加器带借位减去寄存器内容 累加器带借位减去直接地址单元 累加器带借位减去间接 RAM 内容 累加器带借位减去 8 位立即数 累加器加 1 寄存器加 1 直接地址单元内容加 1 间接 RAM 内容加 1 DPTR 加 1 累加器减 1 寄存器减 1 直接地址单元内容减 1 间接 RAM 内容减 1 A 乘以 B A 除以 B 累加器进行十进制转换
3、 逻辑操作类指令 助记符 ANL A,Rn ANL A,direct ANL A,@Ri ANL A,#data8 ANL direct,A ANL direct,#data8 ORL A,Rn ORL A,direct ORL A,@Ri ORL A,#data8 ORL direct,A ORL direct,#data8 XRL A,Rn XRL A,direct XRL A,@Ri XRL A,#data8 XRL direct,A XRL direct,#data8 CLR A CPL A RL A RLC A RR A
进位位和直接地址位相“与”
ANL C,/bit
进位位和直接地址位的反码相“与”
ORL C,bit
进位位和直接地址位相“或”
ORL C,/bit
进位位和直接地址位的反码相“或”
MOV C,bit
直接地址位送入进位位
MOV bit,C
进位位送入直接地址位
字节数 1 2 1 2 1 2 2 2 2 2 2 2
功能说明 寄存器内容加到累加器 直接地址单元内容加到累加器 间接 RAM 内容加到累加器 8 位立即数加到累加器 寄存器内容带进位加到累加器 直接地址单元内容带进位加到累加器 间接 RAM 内容带进位加到累加器
字节数 1 2 1 2 1 2 1
用51单片机制作ps2接口的工业小键盘
用51单片机制作ps2接口的工业小键盘经过我的验证,是完全可行的。
#include <reg52.h>#include <intrins.h>#define uchar unsigned char#define SEM_FULL 1#define SEM_EMPTY 0uchar bdata ps2char;uchar bdata keystatus;uchar bdata parity_buf;uchar bdata s_buf,r_buf;uchar data last_s;sbit date=P3^0;sbit clock=P3^2;sbit key0=P2^0;sbit key1=P2^1;sbit key2=P2^2;sbit key3=P2^3;sbit key4=P2^4;sbit key5=P2^5;sbit key6=P2^6;sbit key7=P2^7;sbit s_buf0=s_buf^0;sbit r_buf7=r_buf^7;sbit parity_buf0=parity_buf^0;bit ps2_tx_sem=SEM_EMPTY;bit ps2_sendbyte(uchar c);void delayus(uchar us){while(--us);}void delayms(uchar ms){uchar i;while(ms--){for(i=0;i<120;i++);}}bit parity(){bit PARITY=1;uchar i;for(i=0;i<8;i++){PARITY^=parity_buf0;parity_buf=parity_buf>>1;}return PARITY;}void ps2_tx_sem_take(){ps2_tx_sem0:EA=0;if(ps2_tx_sem==SEM_FULL){EA=1;delayus(30);delayus(30);goto ps2_tx_sem0;}ps2_tx_sem=SEM_FULL;EA=1;return;}void ps2_tx_sem_give(){EA=0;ps2_tx_sem=SEM_EMPTY;EA=1;return;}void ps2_clk_check(){ps_tx_sem:EA=0;if(clock==0) // if PS2_CLK low, wait for 50us {EA=1;delayus(30);goto ps_tx_sem;}EA=1;return;}void ps2_send(uchar dat){ps2_tx_sem_take();ps2_clk_check();if(date==1)ps2_sendbyte(dat);ps2_tx_sem_give();}uchar ps2_recbyte() // Return receice data,Error return 0{uchar i;bit PARITY;r_buf=0;while(!clock); // Wait KBCLK Highdelayus(10);if(date) // KBDA TA shoud be low,mean received start bit{ps2_send(0xfe); // if KBDATA is High, return and send error status date(0xfe)return 0;}delayus(30);clock=0; // Device control the KBCLK signalfor(i=0;i<8;i++) // Rising edge of KBCLK, write data into r_buf7{delayus(30);clock=1;delayus(10);if(!clock) return 0; // if KBCLK pull down, mean Host cancelled this sendingr_buf7=date;if(i!=7)r_buf=r_buf>>1;delayus(10);clock=0;}delayus(30);clock=1;delayus(10);if(!clock) return 0; // if KBCLK pull down, mean Host cancelled this sendingPARITY=date; // Receive odd parity bitdelayus(10);clock=0;delayus(30);clock=1;delayus(10); // Receive Stop bit, should be highif(!date) // Otherwise,send error status date(0xfe){ps2_send(0xfe);return 0;}date=0; // Send ACK bit, mean have receive data done delayus(10);clock=0;delayus(30);clock=1; // Set KBCLK and KBDATA highdelayus(10);date=1;delayus(10);parity_buf=r_buf;if(PARITY==parity()) // Check Odd parity{return r_buf;}else{ps2_send(0xfe);return 0;}delayus(30);}bit ps2_sendbyte(uchar c) // Success return 1,Fail return 0{uchar i;bit PARITY;clock=1;if(!clock) // Host prevent Keyboard sending datareturn 0;parity_buf=c;PARITY=parity(); // Calculate value about sending data odd paritylast_s=c; // Save last sending datas_buf=c;if(!clock) // Host prevent Keyboard sending datareturn 0;if(!date) // Host prepared sending command data to keyboard return 0;date=0; // Falling edge of KBCLK send data, start bit 0 delayus(10);clock=0;for(i=0;i<8;i++) // First send LSB{delayus(10);clock=1;delayus(10);if(!clock) // if KBCLK is low,mean Hos prevent Keyboard sending datareturn 0;date=s_buf0;s_buf=s_buf>>1;delayus(10);clock=0;}delayus(10);clock=1;delayus(10);if(!clock) // if KBCLK is low,mean Hos prevent Keyboard sending datareturn 0;date=PARITY; // Sending odd parity bitdelayus(10);clock=0;delayus(10);clock=1;delayus(10);date=1; // Sending stop bitdelayus(10);clock=0;delayus(30);clock=1;delayus(30);delayus(10);return 1;}bit bat(){if(P2!=0xff)return 1;elsereturn 0;}void re_send ( ){ps2_send(last_s);}void reset(){date=1;while(!clock||!date); // Wait KBCLK and KBDATA highif(bat())ps2_send(0xfc); // Self-Check failedelseps2_send(0xaa); // Self-Check successed}bit Check_command ( ) // Keyboard receive host command,return 1 { clock=1;date=1;if(!clock&!date)return 1;elsereturn 0;}void receive_process(){uchar command;if(!Check_command()) return;command=ps2_recbyte();if(!command) return;switch(command){case 0xff: // reset commandps2_send(0xfa);reset();break;case 0xfe: // re-send commandps2_send(0xfa);re_send();break;case 0xf3: // Set Typematic Rate/Delayps2_send (0xfa);break;case 0xf2: // Read IDps2_send(0xfa);ps2_send(0xAB);ps2_send(0x83);break;case 0xee: // respond commandps2_send(0xee);case 0x00:ps2_send(0xfe);default:ps2_send(0xfa); // other command, just send a response of 0xFA break;}}void main(){P2=0xff;if(bat())ps2_send(0xfc);elseps2_send(0xaa);while(1){ if(Check_command())receive_process();key4=0;while(!key4){if(!key0){delayms(5);if(!key0){ps2_sendbyte(0x1C);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X1C);while(!key0);}}else if(!key1){delayms(5);if(!key1){ps2_sendbyte(0x32);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X32);while(!key1);}}else if(!key2){delayms(5);if(!key2){ps2_sendbyte(0x21);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X21);while(!key2);}}else if(!key3){delayms(5);if(!key3){ps2_sendbyte(0x23);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X23);while(!key3);}}else key4=1;}key5=0;while(!key5){if(!key0){delayms(5);if(!key0){ps2_sendbyte(0x24);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X24);while(!key0);}}else if(!key1){delayms(5);if(!key1){ps2_sendbyte(0x2B);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X2B);while(!key1);}}else if(!key2){delayms(5);if(!key2){ps2_sendbyte(0x34);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X34);while(!key2);}}else if(!key3){delayms(5);if(!key3){ps2_sendbyte(0x33);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X33);while(!key3);}}else key5=1;}key6=0;while(!key6){if(!key0){delayms(5);if(!key0){ps2_sendbyte(0x43);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X43);while(!key0);}}else if(!key1){delayms(5);if(!key1){ps2_sendbyte(0x3B);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X3B);while(!key1);}}else if(!key2){delayms(5);if(!key2){ps2_sendbyte(0x42);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X42);while(!key2);}}else if(!key3){delayms(5);if(!key3){ps2_sendbyte(0x4B);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X4B);while(!key3);}}else key6=1;}key7=0;while(!key7){if(!key0){delayms(5);if(!key0){ps2_sendbyte(0x3A);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X3A);while(!key0);}}else if(!key1){delayms(5);if(!key1){ps2_sendbyte(0x31);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X31);while(!key1);}}else if(!key2){delayms(5);if(!key2){ps2_sendbyte(0x44);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X44);while(!key2);}}else if(!key3){delayms(5);if(!key3){ps2_sendbyte(0x4D);delayms(5);ps2_sendbyte(0xF0);delayms(1);ps2_sendbyte(0X4D);while(!key3);}}else key7=1;}}}。
在51单片机上使用PC机ps2键盘
在51单片机上使用PC机ps/2键盘(附源码)本人弄了几天,终于在今天晚上,也就是刚才实验成功,心情特佳,特写出来以享大家。
单片机上应用非编码键盘,各书上均有介绍。
作为实验用,我想到了用PC机的ps/2键盘。
PC机键盘内部有单片机电路来完成编码和去抖动,它按照ps/2协议来发送扫描码。
因此在应用中,我们需要做的只是将扫描码与字符对应起来,大部分事情都由键盘自己完成了。
首先介绍一下键盘的接口,典型的几种接口如下图:其中第一种用于老式键盘(我原来的键盘就是),第二种便是现在的PS/2键盘,第三个不用去管它。
我的实验是按照最常用的PS/2(即第二种)来做的。
再略微介绍一下PS/2协议的相关内容。
PS/2的一个数据帧为11位,时序如下:PS/2帧的第一位是起始位,为0,然后是8位数据位,发送键盘扫描码的一个字节(扫描码为1-4个字节),然后是奇偶校验位,最后是停止位,为1。
这些是在数据线(即1号引脚线)上发送的。
无键按下时,数据线和始终线都保持为1。
当有键按下时,时钟线CLOCK 送出脉冲,同时数据线送出数据。
主机(此处是89c51 MCU)在始终脉冲的下降沿对数据线采样获得数据。
键盘扫描码包括通码和断码,当键按下时发送通码,抬起时发送断码。
更详细的内容可参考所附的《PS/2技术参考》。
根据上述原理,我这样设计了实验:将键盘的脉冲线接至89c51的外部中断输入口(INT0或INT1),当键按下和抬起时有脉冲产生,此脉冲引发MCU中断。
将键盘的DATA线连至89c51的输入口(如P1.0)。
在中断处理程序中,从输入口读入数据,然后通过循环移位对读进的数据位进行处理,1(起始位)、10(奇偶校验)、11(停止位)可抛弃,如不嫌麻烦也可将奇偶校验位加以应用。
当一个数据帧收完后,将处理后剩下的2-9位(即扫描码)通过串口发至PC机,通过PC机的串口监视软件(如“串口调试助手”)来查看。
硬件连线和源码如下:源码:ORG 0000HAJMP MAIN;转入主程序ORG 0003H ;外部中断P3.2脚INT0入口地址AJMP INT ;转入外部中断服务子程序;以下为主程序进行CPU中断方式设置MAIN:MOV SCON,#50H;设置成串口1方式MOV TMOD,#20H;波特率发生器T1工作在模式2上MOV PCON,#80H;波特率翻倍为2400x2=4800BPSMOV TH1,#0F3H;预置初值(按照波特率2400BPS预置初值)MOV TL1,#0F3H;预置初值(按照波特率2400BPS预置初值)SETB EA ;打开CPU总中断请求SETB IT0 ;设定INT0的触发方式为脉冲负边沿触发SETB EX0 ;打开INT0中断请求SJMP $INT: CLR EA ;暂时关闭CPU的所有中断请求CJNE R0,#0,L1L3: INC R0SJMP L5L1: CJNE R0,#9,L2SJMP L3L2: CJNE R0,#10,L4SETB TR1;启动定时器T1MOV SBUF,AMOV R0,#0L5: SETB EA ;允许中断RETI ;退出子程序L4: MOV C,P1.0RRC ASJMP L3END搞定后,当按下和释放键时,会在PC机上显示其扫描码。
51单片机控制ps2键盘设计说明
51接PS2键盘2008-09-20 16:02在这个周末,终于有时间做做试验了。
昨晚用AVR和MC9S12DG128驱动1602成功,今天突然想到PS2键盘的驱动,当时觉得PS2键盘与MCU接口很神秘,做了之后才觉得其实不然哈。
再传张键盘的扫描码的波形。
(协议规定:数据低位在前,采用奇校验数据格式(PS->MCU):1起始位为0,8数据位,1奇校验位,1停止位为1)'A'键(0x1C)的make code:代码:PS_2_KB.H//************write by zhouyong********* //************qq:510559254************** //************2008-9-20*****************#ifndef _PS_2_KB_H#define _PS_2_KB_H#include <AT89X51.H>#define KB_CLK P3_3#define KB_DATA P3_4uchar Get_Key(void);uchar Key_Scan(void);uchar Key_Scan(void){uchar i,key_temp;KB_CLK=1; //输入KB_DATA=1;key_temp=0;while(KB_CLK); //第一次为0for(i=0;i<8;i++){key_temp>>=1;while(!KB_CLK); //下沿,第一位while(KB_CLK);_nop_();if(KB_DATA){key_temp|=0x80; //低位在前}}while(!KB_CLK); //校验位while(KB_CLK);while(!KB_CLK); //停止位while(KB_CLK);while(!KB_CLK);return key_temp;}//由于make_code和第二个break_code一样,就取break_code第二个作为键码uchar Get_Key(void){uchar Key_Code;Key_Code=Key_Scan(); //make_codeKey_Code=Key_Scan(); //break_code 1Key_Code=Key_Scan(); //break_code 2switch(Key_Code){case 0x1c: return 'A';break;case 0x32: return 'B';break;case 0x21: return 'C';break;case 0x23: return 'D';break;case 0x24: return 'E';break;case 0x2b: return 'F';break;case 0x34: return 'G';break;case 0x33: return 'H';break;case 0x43: return 'I';break;case 0x3b: return 'J';break;case 0x42: return 'K';break;case 0x4b: return 'L';break;case 0x3a: return 'M';break;case 0x31: return 'N';break;case 0x44: return 'O';break;case 0x4d: return 'P';break;case 0x15: return 'Q';break;case 0x2d: return 'R';break;case 0x1b: return 'S';break;case 0x2c: return 'T';break;case 0x3c: return 'U';break;case 0x2a: return 'V';break;case 0x1d: return 'W';break;case 0x22: return 'X';break;case 0x35: return 'Y';break;case 0x1a: return 'Z';break;case 0x45: return '0';break;case 0x16: return '1';break;case 0x1e: return '2';break;case 0x26: return '3';break;case 0x25: return '4';break;case 0x2e: return '5';break;case 0x36: return '6';break;case 0x3d: return '7';break;case 0x3e: return '8';break;case 0x46: return '9';break;default: return 0xff; break;}}#endifLCD1602.H://************write by zhouyong*********//************qq:510559254**************//************2008-9-14*****************#ifndef _LCD1602_#define _LCD1602_#include <AT89X51.H>#include <string.h>#include <intrins.h>//--------------------------------------------------------------------#define E_1602 P3_7 //on falling edge enable data or command #define RW_1602 P3_6 //read or write control#define RS_1602 P3_5 //cmd or data register select#define DATA_1602 P2 //data port#define DATA 1 //select DATA register#define CMD 0 //select CMD register#define READ 1#define WRITE 0//--------------------------------------------------------------- void Delay_us(uchar t);void Delay_ms(uchar t);void Init_1602(void);void Write_Char_1602(uchar Data,bit CMD_DATA,bit Check);void Check_Busy_1602(void);void Write_String_1602(uchar *P);void Set_R_C(uchar R,uchar C);//void Clear_LCD_1602(void);//---------------------------------------------------------------- /*void Clear_LCD_1602(void){Write_Char_1602(0x01,CMD,1);//clear screen}*/void Delay_us_1602(uchar t){while(--t);}void Delay_ms_1602(uchar t){while(t--){Delay_us_1602(225);Delay_us_1602(227);}}void Init_1602(void){Delay_ms_1602(15);Write_Char_1602(0x38,CMD,0); //don't check busyDelay_ms_1602(5);Write_Char_1602(0x38,CMD,0);Delay_ms_1602(5);Write_Char_1602(0x38,CMD,0);Write_Char_1602(0x38,CMD,1);//8 wire,2 line display,5x10 charWrite_Char_1602(0x08,CMD,1);//close display,no cursor,don't blink Write_Char_1602(0x01,CMD,1);//clear screenWrite_Char_1602(0x06,CMD,1);//the cursor move from left to right,the text don't moveWrite_Char_1602(0x0c,CMD,1);//open display}void Write_Char_1602(uchar Data,bit CMD_DATA,bit Check){if(Check)Check_Busy_1602();RS_1602=CMD_DATA;RW_1602=WRITE;DATA_1602=Data;E_1602=1;_nop_();E_1602=0;}void Write_String_1602(uchar *P) //only can write from start to end {uchar i,len;len=strlen(P);Set_R_C(0,0);if(len>16){for(i=0;i<16;i++){Write_Char_1602(P[i],DATA,1);}Set_R_C(1,0);for(i=16;i<len;i++){Write_Char_1602(P[i],DATA,1);}}else{for(i=0;i<len;i++){Write_Char_1602(P[i],DATA,1);}}}void Set_R_C(uchar R,uchar C) //set row and column R=0/1;C=0~F {R&=0x01;C&=0x0f;if(R)Write_Char_1602(0x80+0x40+C,CMD,1);elseWrite_Char_1602(0x80+C,CMD,1);}void Check_Busy_1602(void){DATA_1602=0xff; //set as input portRS_1602=CMD;RW_1602=READ;E_1602=1;while(DATA_1602 & 0x80){E_1602=0; //这两句protues仿真必须加E_1602=1; //}E_1602=0;}#endifmain.c:#include <AT89X51.H>#include <intrins.h>#define uchar unsigned char#define uint unsigned int#include "PS_2_KB.h"#include "LCD1602.h"void main(void){ucharBuffer[]="";uchar Key_Code,Key_Count,i;Init_1602();Set_R_C(0,0);for(;;){Key_Code=Get_Key();if(Key_Code!=0xff) // 为0xff时视为无效键{Buffer[Key_Count]=Key_Code;Write_String_1602(Buffer);Key_Code=0;Key_Count++; //第n次按键,显示在第n位if(Key_Count==32){for(i=0;i<32;i++){Buffer[i]=' ';}Key_Count=0;}P1=~P1; //P1口接有LED,用于指示按键 }}}。
实例制作一个51单片机连接PS2键盘
实例制作的是用一个AT89C51单片机连接PS/2键盘接口和一个16x2的液晶显示屏,当敲击键盘时,字母可以显示在液晶显示屏上。
这个实例能启发你如何利用单片机来实现对PS/2接口的控制。
实例中提供的源代码修改后可以用到其他PS/2键盘制作项目中。
实例中提供的16x2字符型的液晶显示屏的驱动函数也可以其他项目。
电路原理主电路板中的AT89C51单片机(可以用AT89C52/S51/S52直接替换,如用AT89C2051/4051则需要改程序)组成了51最小化系统。
液晶显示屏于嗯了SMC1602A. 键盘通过PS/2六孔插座和主电路板。
PS/2设备的连接器使用mini-DIN连接器,正有6个引线,其中2个保留为用。
DATA和CLK是可双向通信的I/O线,也就是说通过这两根线,既可以把主机的数据发送到PS/2设备,有可以把设备的数据发向主机。
在无键按下是,DATA 和CLK一直处于高电平状态。
但有键按下时,键盘先检查CLK,看它是否处于高电平,如果是处在低电平,说明主机无空闲接收数据,这是键盘将会把数据放在自己的缓冲区(16Bytes).直到CLK重新被拉高。
键盘获得总线权,这是键盘产生始终信号在CLK上输出。
同时每一个时钟周期在DATA 线上输出一位数据。
第1位是起始位为0,第2-9位为一个八位二进制数据由地位到高位依次输出,第10位为奇偶校验位下面是电路原理图PS/2设备接口用于许多现代的鼠标和键盘,PS/2连接器上有四个管脚:电源地、+5V、数据和时钟。
Host(计算机)提供+5V并且键盘/鼠标的地连接到host的电源地上,数据和时钟都是集电极开路的这就意味着它们通常保持高电平而且很容易下拉到地(逻辑0)。
任何你连接到PS/2鼠标、键盘或host 的设备,在时钟和数据线上要有一个大的上拉电阻。
置“0”就把线拉低,置“1”就让线上浮成高。
从键盘/鼠标发送到主机的数据在时钟信号的下降沿(当时钟从高变到低的时候)被读取;从主机发送到键盘/鼠标的数据在上升沿(当时钟从低变到高的时候)被读取。
利用51单片机,8个按键,8路发光二级管构成一个独立式键盘系统,按下8个按键,点亮对应的灯。
电子信息工程学院电子设计应用软件训练任务【训练任务】:1、熟练掌握PROTEUS软件的使用;2、按照设计要求绘制电路原理图;3、能够按要求对所设计的电路进行仿真;【基本要求及说明】:1、按照设计要求自行定义电路图纸尺寸;2、设计任务如下:利用51单片机,8个按键,8路发光二级管构成一个独立式键盘系统,按下8个按键,点亮对应的灯。
3、按照设计任务在Proteus 6 Professional中绘制电路原理图;4、根据设计任务的要求编写程序,在Proteus下进行仿真,实现相应功能。
【按照要求撰写总结报告】指导教师年月日负责教师年月日学生签字年月日成绩评定表电子设计应用软件训练总结报告一.任务说明本次任务是利用51单片机、按键以及发光二极管设计一个独立式键盘系统,要求独立简单可控。
首先要明确51单片机的工作原理,在此基础上编写单片机程序,再载入到所连电路原理图中实现按键控制二极管亮灭。
此次任务需要完成电路原理图的绘制、单片机汇编语言的编程。
目的是通过本次设计熟悉Proteus软件的工作环境,掌握基本的操作及流程以及对单片机汇编语言的进一步学习,使之前的学习得到巩固。
二.原理图绘制说明总体而言,一个完善的系统最重要的是稳定,精确,设计简单,修护容易,成本低,体积小。
满足以上条件的系统我们都可以说是完善的系统。
因此,我在设计中选用了一些比较成熟的器件,这些器件都经过时间的考验,能稳定的工作,同时,价格也相对便宜。
下面对原理图中主要的硬件进行简单介绍。
2.1 AT89C51的基本概述AT89C5l单片机,是一种低功耗、高性能的、片内含有4KB Flash ROM的8位CMOS 单片机,工作电压范围为2.7~6V(实际使用+5V供电),8位数据总线。
它有—个可编程的全双工串行通信接口,能同时进行串行发送和接收。
AT89C51具有4K并行可编程的非易失性FLASH程序存储器,可实现对器件串行在系统编程ISP和在应用中编程(IAP)。
基于51单片机的PS2键盘1602显示24c02存储的密码锁设计(附程序)
基于51单片机的PS2键盘密码锁设计摘要:AT89S52是一种低功耗、高性能CMOS 8位微控制器,具有8K在系统可编程Flash 存储器,被广泛应用于各个领域。
LCD1602液晶显示器以其微功耗、体积小、超薄轻巧等诸多优点而备受人们喜爱。
本作品是以AT89S52作为主控芯片,LCD1602作为显示器,以PS2键盘作为输入设备的密码锁。
PS2键盘与AT89S52通过PS2接口协议进行通信,可以完成密码设置,密码重置及显示等诸多功能。
本作品还使用了24C02存储器来实现密码锁的掉电保存功能。
关键词:AT89S52;LCD1602;24C02;PS2键盘Abstract:AT89S52 is a low power,high performance CMOS 8 bit microcontroller, with 8K flash memory, is widely applied in various fields. LCD1602 liquid crystalDisplay with its low power consumption, small size, thin lightweight and many other advantages, is liked by people.This work is based on the AT89S52 as the main chip, the LCD1602 as display, PS2 keyboard as an input device of the cipher lock. PS2 keyboard and AT89S52 through PS2 interface protocolFor communication, can complete password, password reset and display and other functions. This work we also used the 24C02 memory to realize the password lock the power-down save function.Keywork: A T89C52; LCD1602; 24C02;PS/2 keyboard1 实验目的及意义在单片机系统中,经常使用的键盘都是专用键盘.此类键盘为单独设计制作的,成本高、使用硬件连接线多,且可靠性不高,这一状况在那些要求键盘按键较多的应用系统中更为突出.与此相比,在PC系统中广泛使用PS/2键盘具有价格低、通用可靠,且使用连接线少(仅使用2根信号线)的特点,并可满足多种系统的要求.因此在单片机系统中应用PS/2键盘是一种很好的选择.对于单片机初学者的我而言,AT89S52简单易学,非常适合我学习。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
*** MCU: STC89C52/AT89C52 部分C源码可以直接用于项目开发、欢迎复制共享、功德无量、没有版权 ***
*** 目标:用C语言写程序就这么简单、慧争祝你1天入门、10天学会、1年精通单片机与C语言、找个好工作 ***
***************************************************************************************************/
Decode(KeyV);
else
EA = 1; //开中断
}
while(1);
}
void Keyboard_out(void) interrupt 0
{
if ((IntNum > 0) && (IntNum < 9))
{
KeyV = KeyV >> 1; //因键盘数据是低>>高,结合上一句所以右移一位
HJ-1G 51单片机标准PS2键盘输入实验2009年08月15日 星期六 20:51/**************************************************************************************************
*** 慧净电子1天入门、10天学会、1年精通单片机与C语言视频教程配套程序源码 ***
ShowChar(DisNum,Shifted[TempCyc][1]);
DisNum++;
if(DisNum==32)
{
WriteCommand(0x01);//清屏
WriteCommand(0x01);//清屏
DisNum=0;//重头写数据
}
}
}
else //按下SHIFT
{
{
case 0x12 : // 左 SHIFT
Shift = 0;
break;
case 0x59 : // 右 SHIFT
Shift = 0;
break;
}
}
BF = 0; //标识字符处理完了
}
BF = 1; //标识有字符输入完了
EA = 0; //关中断等显示完后再开中断
}
}
void Decode(unsigned char ScanCode) //注意:如SHIFT+G为12H 34H F0H 34H F0H 12H,也就是说shift的通码+G的通码+shift的断码+G的断码
for(TempCyc = 0; (Shifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
if (Shifted[TempCyc][0] == ScanCode)
{
/*说明:此程序使用标准PS2键盘输入,LCD1602液晶屏输出显示。此样例仅作测试使用
晶振使用12M或者11.0592M,本键盘使用部分字母和数字测试,其他按键不能使用,用
户可以自行扩展。由于开发板和程序的各种参数,程序中没有使用奇偶校验,不保证没有
误码,校验程序请自行添加。
*/
//注意:接上标准PS2键盘后,按下键盘后,LCD1602才会显示出相关字母
if (UnShifted[TempCyc][0] == ScanCode)
{
ShowChar(DisNum,UnShifted[TempCyc][1]);
DisNum++;
if(DisNum==32)
{
*** 作者:慧净助学会员 网上收集整理 ***
*** 编译器:KEIL ***
DisNum=0;//重头写数据
}
}
}
break;
}
}
else
{
Key_UP = 0;
switch (ScanCode) //当键松开时不处理判码,如G 34H F0H 34H 那么第二个34H不会被处理 *** 交流空间:/HJMCU ***
*** 论坛交流: 欢迎来论坛一分钱不要下载配套的仿真电路 ***
sbit Key_CLK =P3^2; //使用中断
bit BF;
bit Shift; //定义上档键标志
bit Key_UP; //定义通码断码标志
unsigned char KeyV;
unsigned char IntNum;
unsigned char DisNum;
Shift = 1;
break;
case 0x59 : // 右 SHIFT
Shift = 1;
break;
default:
if(!Shift) //如果SHIFT没按下
{
for (TempCyc = 0;(UnShifted[TempCyc][0]!=ScanCode)&&(TempCyc<59); TempCyc++); //查表显示
#include <reg52.h> //包含头文件
#include "scancodes.h"
#include "LCD1602.h"
sbit Key_Data = P3^1;//定义Keyboard引脚
//sbit Key_CLK =P3^2; //使用中断
//sbit Key_Data = P3^1;//定义Keyboard引脚
{
unsigHale Waihona Puke ed char TempCyc;
if (!Key_UP) //当键盘按下时
{
switch (ScanCode)
{
case 0xF0 : // 当收到0xF0,Key_UP置1表示断码开始
Key_UP = 1;
break;
case 0x12 : // 左 SHIFT
void Decode(unsigned char ScanCode);//解码子程序
void main()
{
IT1 = 0; //设外部中断1为低电平触发
EA = 1; //外部中断开
EX0 = 1; //开中断
InitLcd();//初始化1602液晶屏
do
{
if (BF)
if (Key_Data)
KeyV = KeyV | 0x80; //当键盘数据线为1时到最高位
}
IntNum++;
while (!Key_CLK); //等待PS/2CLK拉高
if (IntNum > 10)
{
IntNum = 0; //当中断11次后表示一帧数据收完,清变量准备下一次接收
*** 配套的硬件学习板网址:/ ***
*** 日期:2008.8.8 ***