




免费预览已结束,剩余20页可下载查看
下载本文档
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
学习51单片机与PS2鼠标程序 滚轮识别,显示3D坐标简介:PS2鼠标,具有滚轮识别,LCD1602显示3D坐标,有LED指示灯,等等其实发现学起来也很简单。由于在网上找不到51单片机可以识别鼠标带滚轮的完整可用程序,也就是3D,X,Y,Z;轴功能的程序,笔者花了很长时间尝试,终于整出来了,特拿出来与所有单片机菜鸟分享。第一步:PS/2接口和协议简介1 PS/2接口和协议1.1 接口的物理特性 PS/2接口用于许多现代的鼠标和键盘,由IBM最初开发和使用物理上的PS/2接口有两种类型的连接器:5脚的DIN和6脚的mini-DIN图1就是两种连接器的引脚定义使用中,主机提供+5V电源给鼠标,鼠标的地连接到主机电源地上1.2 接口协议原理 PS/2鼠标接口采用一种双向同步串行协议即每在时钟线上发一个脉冲,就在数据线上发送一位数据在相互传输中,主机拥有总线控制权,即它可以在任何时候抑制鼠标的发送方法是把时钟线一直拉低,鼠标就不能产生时钟信号和发送数据在两个方向的传输中,时钟信号都是由鼠标产生,即主机不产生通信时钟信号 如果主机要发送数据,它必须控制鼠标产生时钟信号方法如下:主机首先下拉时钟线至少100s抑制通信,然后再下拉数据线,最后释放时钟线通过这一时序控制鼠标产生时钟信号当鼠标检测到这个时序状态,会在10ms内产生时钟信号如图3中 A 时序段主机和鼠标之间,传输数据帧的时序如图2图3所示2.2 数据包结构在主机程序中,利用每个数据位的时钟脉冲触发中断,在中断例程中实现数据位的判断和接收在实验过程中,通过合适的编程,能够正确控制并接收鼠标数据但该方案有一点不足,由于每个CLOCK都要产生一次中断,中断频繁,需要耗用大量的主机资源2 PS/2鼠标的工作模式和协议数据包格式2.1 PS/2鼠标的四种工作模式 PS/2鼠标的四种工作模式是:Reset模式,当鼠标上电或主机发复位命令 0xFF给它时进入这种模式;Stream模式鼠标的默认模式,当鼠标上电或复位完成后,自动进入此模式,鼠标基本上以此模式工作;Remote模式,只有在主机发送了模式设置命令 0xF0后,鼠标才进入这种模式;Wrap模式,这种模式只用于测试鼠标与主机连接是否正确 PS/2鼠标在工作过程中,会及时把它的状态数据发送给主机发送的数据包格式如表1所示Byte1中的Bit0Bit1Bit2分别表示左右中键的状态,状态值0表示释放,1表示按下Byte2和Byte3分别表示X轴和Y轴方向的移动计量值,是二进制补码值Byte4的低四位表示滚轮的移动计量值,也是二进制补码值,高四位作为扩展符号位这种数据包由带滚轮的三键三维鼠标产生若是不带滚轮的三键鼠标,产生的数据包没有Byte4 其余的相同第二步:11.3 PS/2鼠标原理目前最常见的鼠标有PS/2鼠标和USB鼠标。本章介绍PS/2鼠标。PS/2鼠标有4种工作模式,具体如下:(1)复位模式。当上电后或接收到复位命令FF后鼠标即处于此模式。鼠标进行自检和初始化,再向主机发送0xFA,0xAA和0x00,一些参数将恢复到默认值,即采样率为100sample/s非自动流速、流模式、分辨率为4计数/mm、禁止状态。(2)流模式。如果有按键或滚轮动作,即向系统发送信息,最大发送速率就是可编程的采样率。(3)遥控模式。只有主机发送了模式设置指令0xF0后,鼠标才进入这种模式。(4)这种模式只用于检测鼠标与主机是否连接正确,在该模式下鼠标收到什么就返回什么,除非收到退出卷绕指令0xEC或复位指令0xFF。流模式是默认模式。大多数应用系统使用流模式,鼠标的任何动作都会报告给主机。也可以使用遥控模式,主机使用0xEB命令请求数据,鼠标进行应答。标准的PS/2协议数据格式为3字节,如表11-4所示。鼠标的按键和滚动信息都采用这种格式汇报给主机。表11-4 标准的PS/2协议数据格式YOverflowXOverflowYSignXSign1MiddleButtonRightButtonLeftButtonX movementY movement标准鼠标指支持左右移动和三个鼠标键。微软智能鼠标支持滚轮。当主机向鼠标发送魔幻序列0xF3 0xC8 0xF3 0x64 0xF3 0x50后,鼠标进入滚轮模式。此时读取鼠标ID返回0x03。此后通信过程使用如表11-5所示的4字节协议。表11-5 字节的PS/2协议数据格式YOverflowXOverflowYSignXSign1MiddleButtonRightButtonLeftButtonX movementY movementZH movementZL movement其中ZH和ZL都采用二进制补码表示,范围为-87。此外,鼠标还有只能IE鼠标和台风(Typhoon)鼠标,通信协议与上述还有不同。目前最常见的鼠标就是这两种。主机和鼠标之间的通信命令有很多。主机向鼠标发出的每一个字节和命令鼠标都必须采用0xFA应答,但是重传命令0xFE除外。如果鼠标接收的命令或数据是错误的,鼠标发送0xFE表示NACK,如果下一个字节重复错误,鼠标使用0xFC表示连续错误。0xD0表示读扩展ID,可最长达256字节。0xD10xDF是提供商特定命令,如0xD1是Logitech PS/2+命令。0xE1表示读取第二个ID。0xE2表示IBM TrackPoint。0xE6表示设置鼠标比例为原始比例1:1,即X movement和Y movement都以原始值发送。0xE7表示设置鼠标比例为原始比例2:1,即如果X movement或Y movement大于等于6,则乘以2后发送;如果小于6,则0,1,2,3,4,5分别被放大到0,1,1,3,6,9。0xEA表示设置鼠标到流模式。0xEB表示读取鼠标数据,即读取一个3字节或4字节的包。0xEC清除卷绕模式。0xEE表示设置鼠标到卷绕模式。0xF0表示设置鼠标到遥控模式。0xF2表示读取鼠标ID。0xF3表示设置鼠标采样率。0xF4表示设置鼠标使能。0xF5表示设置鼠标停止。0xF6表示设置鼠标到默认值。0xFE表示请求重新发送。0xFF表示复位。鼠标还有一些其他的更加复杂的命令,读者可参考有关文献。第三步:/* XXXX.C部分*/#include#includemouse.h#includeLCD1602_4.h#includeDELAY52.hsbit beep=P37;void main()LCD1602_Init();/初始化液晶1602CLEARSCREEN;/清屏Init_mouse();delayms(500); num(0,2,mouse_byte);/x坐标值 delayms(500); host_to_mouse(0xf3);num(0,2,mouse_byte);num(0,10,1);delayms(500);delay10us(1);host_to_mouse(0xc8);num(0,2,mouse_byte);num(0,10,2);delayms(500);delay10us(1);host_to_mouse(0xf3);num(0,2,mouse_byte);num(0,10,3);delayms(500);host_to_mouse(0x64);num(0,2,mouse_byte);num(0,10,4);delayms(500);host_to_mouse(0xf3);num(0,2,mouse_byte);num(0,10,5);delayms(500);host_to_mouse(0x50);num(0,2,mouse_byte);num(0,10,6);delayms(50);delay10us(1); host_to_mouse(0xf2);num(0,2,mouse_byte);num(0,10,7);delayms(50);if(mouse_byte=0x03) LCD1602_write_string(0,0,OK);delayms(500); elseLCD1602_write_string(0,0,DE);delayms(500);delayms(500);while(1)led=1;CLEARSCREEN;/清屏LCD1602_write_string(0,0,x:);num(0,2,move_x);/x坐标值LCD1602_write_string(0,8,y:);num(0,10,move_y);/y坐标值 LCD1602_write_string(1,8,z:); num(1,10,move_z);/y坐标值if(mouse_data0&0x01)/如果点下左键beep=0;LCD1602_write_string(1,0,left);else if(mouse_data0&0x02)/如果点下右键beep=0;LCD1602_write_string(1,0,right);else if(mouse_data0&0x04)/如果点下中键beep=0;LCD1602_write_string(1,0,middle);elsebeep=1;LCD1602_write_string(1,0,nothing); delayms(50);/*XXX.H文件部分*/#ifndef MOUSE_H#define MOUSE_H#includeDELAY52.h#includeLCD1602_4.h#define delay10 _nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_(); #define delay100 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10 delay10;sbit mouse_SDA=P34;/数据线P3_5计数器0输入端口sbit mouse_CLK=P33;/时钟线P3_3 外部中断1输入端口sbit led=P36;bit pp=0; bit ACK=0; uchar recv=0; uchar bdata mouse_byte; /接收字节 bdata-可寻址的片内RAMsbit mouse_byte_bit0=mouse_byte0;/mouse_byte第0位sbit mouse_byte_bit1=mouse_byte1;/mouse_byte第1位sbit mouse_byte_bit2=mouse_byte2;/mouse_byte第2位sbit mouse_byte_bit3=mouse_byte3;/mouse_byte第3位sbit mouse_byte_bit4=mouse_byte4;/mouse_byte第4位sbit mouse_byte_bit5=mouse_byte5;/mouse_byte第5位sbit mouse_byte_bit6=mouse_byte6;/mouse_byte第6位sbit mouse_byte_bit7=mouse_byte7;/mouse_byte第7位uchar bdata mouse_fuction;/功能信息字节 uchar mouse_buffer11;/接收位数据缓冲区uchar mouse_buffer_bit=0;/mouse_buffermouse_buffer_bituchar mouse_data4;/接收鼠标数据缓冲区,分别存放:功能信息字节,x位移量,y位移量uchar mouse_data_bit=0;/mouse_datamouse_data_bituint move_x=10000;/存放横坐标uint move_y=10000;/存放纵坐标uchar move_z=0;void Init_mouse(void) / TCON=0x00;/中断触发方式0 EA=1; /开放中断 EX1=1;/允许外部中断1 / ET0=0x01;/允许全局中断,允许设定时器/计数器0溢出中断 开定时器中断0 PX1=1;/设置中断优先级 设外部中断1为最高优先级别 /*发送数据*/void host_to_mouse(uchar cmd) uchar i; EX1=0; mouse_CLK=0; delay100; delay100; ACC=cmd; pp=P; /获得奇偶校验位 mouse_SDA=0; mouse_CLK=1; for(i=0;i=1; while(mouse_CLK=0); while(mouse_CLK=1); mouse_SDA=pp; /发送奇偶校验位 while(mouse_CLK=0); while(mouse_CLK=1); mouse_SDA=1; while(mouse_CLK=0); while(mouse_CLK=1); ACK=mouse_SDA; /接收应答位 while(mouse_CLK=0); EX1=1; /* 奇校检*/uchar Checkout(void)ACC=mouse_byte;if(P=mouse_buffer9)return 1;elsereturn 0; /* 数据分析及处理*/void data_analyse(void)/将收到的11位信号中截取8位数据放进mouse_bytemouse_byte_bit0=mouse_buffer1;mouse_byte_bit1=mouse_buffer2;mouse_byte_bit2=mouse_buffer3;mouse_byte_bit3=mouse_buffer4;mouse_byte_bit4=mouse_buffer5;mouse_byte_bit5=mouse_buffer6;mouse_byte_bit6=mouse_buffer7;mouse_byte_bit7=mouse_buffer8;if(Checkout()/如果校验正确if(mouse_data_bit4) mouse_datamouse_data_bit+=mouse_byte; if(mouse_data_bit=4)mouse_data_bit=0;if(mouse_data0&0x10)/如果X sign bit为1,表示鼠标向左移move_x-=(256-mouse_data1);/x坐标减elsemove_x+=mouse_data1;/x坐标加if(mouse_data0&0x20)move_y-=(256-mouse_data2);/y坐标减elsemove_y+=mouse_data2;/y坐标加if(mouse_data3&0x08) move_z-=(16-(mouse_data3&0x0f);else mouse_data3=mouse_data3&0x0f; move_z+=mouse_data3; /Z坐标加 /* 外部中断1*/void ReceiveData(void) interrupt 2led=0;if(mouse_buffer_bit=10) while(mouse_CLK=0);/等待设备拉高时钟线mouse_buffermouse_buffer_bit+=mouse_SDA;/接收数据if(mouse_buffer_bit=10)data_analyse();/数据分析及处理mouse_buffer_bit=0; #endif/*XXX.H文件部分*/#ifndefLCD1602_4_H#define LCD1602_4_H#include #includeDELAY52.h#define LCD1602_DATA P0#define CLEARSCREEN LCD1602_write_cmd(0x01)sbit LCD1602_RS=P25;sbit LCD1602_RW=P26; sbit LCD1602_EN=P27;/*void LCD1602_Init(void);/液晶初始化void LCD1602_write_cmd(uchar command);/写命令void LCD1602_write_data(uchar temp);/写数据void LCD1602_set_xy(uchar x, uchar y);/设置坐标void LCD1602_write_char(uchar x,uchar y,uchar dat);/写一个字符到第x行y列void LCD1602_write_string(uchar x,uchar y,uchar *s);/写字符串到第x行y列void LCD1602_Read_BF(void);/读忙信号void num(uchar x,uchar y,uint n);/在第x行,第y列显示整型数字n/*void LCD1602_Init(void) LCD1602_write_cmd(0x28);LCD1602_write_cmd(0x28);LCD1602_write_cmd(0x28);/设置4位数据传输模式LCD1602_write_cmd(0x0C);LCD1602_write_cmd(0x80); CLEARSCREEN;void LCD1602_Read_BF(void)LCD1602_RW=1;/RW 1LCD1602_RS=0;/RS 0LCD1602_EN=1;/EN 1Read BF LCD1602_DATA=LCD1602_DATA&0x0F|0xf0;while(LCD1602_DATA&0x80);LCD1602_EN=0;void LCD_en_write(void) /EN端产生一个高电平脉冲,写LCD LCD1602_EN=1;_nop_(); LCD1602_EN=0; /*void LCD1602_write_cmd(uchar command)LCD1602_Read_BF();LCD1602_RS=0; /RS 0 LCD1602_RW=0;/RW 0 LCD1602_DATA&=0x0F;LCD1602_DATA=command&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();command=command4; LCD1602_DATA&=0x0F;LCD1602_DATA=command&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();/*void LCD1602_write_data(uchar dat)LCD1602_Read_BF();LCD1602_RS=1; /RS 1 LCD1602_RW=0; /RW 0 LCD1602_DATA &=0x0F;LCD1602_DATA=dat&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();dat=dat4;LCD1602_DATA &=0x0F;LCD1602_DATA=dat&0xf0 | LCD1602_DATA&0x0f;LCD_en_write();/*void LCD1602_set_xy(uchar x,uchar y)uchar address;y&=0x0f;if(!x)address=0x80+y;else address=0xc0+y;LCD1602_write_cmd(address); /*void LCD1602_write_char(uchar x,uchar y,uchar dat)LCD1602_set_xy(x,y); LCD1602_write_data(dat);/*void LCD1602_write_string(uchar x,uchar y,uchar *s)LCD1602_set_xy(x,y); while(*s) LCD1602_write_data(*s); s+;void num(uchar x,uchar y,uint n)uchar i,length,a6=0,0,0,0,0,0;uint nx=n;if(n=0)LCD1602_write_char(x,y,0);return;for(i=0;i=1)length+;nx/=10;nx=n;for(;length0;length-)alength-1=nx%10+48;nx/=10;LCD1602_write_string(x,y,a);#endif/*XXX.H文件部分*/#ifndef DELAY52_H#define DELAY52_H#define uchar unsigned char#define uint unsigned int#include/起始值delayus(1)=27us,间隔9.9usvoid delay10us(uint t)while(t-);void delayms(uint t)uint i;uchar j;for(i=0;it;i+)for(j=0;j125;j+);#endif整个程序完!先按上面接口连接,然后即可编译下载,测试然后在修改成自己的代码。6.3.3 定时计数器的控制寄存器定时器/计数器的工作方式 1定时器/计数器的工作方式0(1)电路逻辑结构当图6-7中的计数器=13位(TH的8位与TL低5位)即得方式0的逻辑电路图。(2)工作方式0的特点两个定时器/计数器T0、T1均可在方式0下工作;是13位的计数结构,其计数器由TH全部8位和TL的低5位构成(高3位不用);当产生计数溢出时,由硬件自动给计数溢出标志位TF0(TF1)置1,由软件给TH,TL重新置计数初值。应说明的是,方式0采用13位计数器是为了与早期的产品兼容,计数初值的高8位和低5位的确定比较麻烦,所以在实际应用中常由16位的方式1取代。2定时器/计数器的工作方式1(1)电路逻辑结构方式1是16位计数结构的工作方式,计数器由TH全部8位和TL全部8位构成。其逻辑电路如图6-11所示。(2)工作方式1的特点两个定时器/计数器均可在方式1下工作;是16位的计数结构,其计数器由TH的全部8位和TL的全部8位构成;当产生计数溢出时,由硬件自动给计数溢出标志位TF0(TF1)置1,由软件给TH,TL重新置计数初值。(3)计数/定时的范围在方式1下,当为计数工作方式时,由于是16位的计数结构,所以计数范围是:165536。当为定时工作时,其定时时间=(216-计数初值)机器周期,例如:设单片机的晶振频率f=12MHz,则机器周期为1s,从而定时范围:1s65536s。因为80C51单片机的定时计数器是可编程的。因此,在利用定时/计数器进行定时计数之前,先要通过软件对他进行初始化,初始化一般应进行如下工作:设置工作方式,即设置TMOD中的各位GATE、C/T、M1M0。计算加1计数器的计数初值COUNT,并将计数初值COUNT 送入TH、TL中。计数方式:计数值 = 2n COUNT ,计数初值:COUNT= 2n 计数值。定时方式:定时时间 =(2n COUNT)机器周期,计数初值COUNT = 2n 定时时间/机器周期。其中n=13、16、8、8分别对应方式0、1、2 、3。启动计数器工作,即将TR置1。T0、T1开中断例6-5 T0工作于:定时方式1,定时时间T=2ms,系统主频fosc=8MHz,允许中断,对T0进行初始化编程。解:由于,T0工作于定时方式,T0工作方式1。因此, =0,GATE=0,M1M0=01。T1不用,故TMOD=0000 0001=01H。系统主频fosc=8M时,时钟周期T=1/8s,机器周期=12T=12/8=1.5s。加1计器初值COUNT =216 2000/1.5 =10000H535H=FACBH,初始化程序如下: MOV SP ,#50H MOV TMOD,#01H MOV TH0,#0FAH MOV TL0,#0CBH SETB TR0 SETB ET0 SETB EA例6-6 定时计器T0工作于计数方式,计数值=1,使用方式1,允许中断,初始化编程。解:由于,T0工作于计数方式,T0工作方式1。因此, =1,GATE=0, T0工作方式1,M1M0=01。T1不用,故TMOD=0000 0101=05H计数器初值COUNT=2161 = 1111 1111 1111 1111=FF FFH MOV TMOD,#05H ;设置T0工作计数方式1。 MOV TH0,#0FFH ;加1 计数器高8位TH0赋初值FFH MOV TL0,#0FFH ;加1 计数器高8位TL0赋初值FFH SETB TR0 ;打开T0启动开关 SETB ET0 ;T0开中断 SETB EA ;CPU开中断3定时器/计数器的工作方式2工作方式0和工作方式1的最大特点是产生计数溢出后,需要由软件重新给计数器赋初值.这样不但影响定时精度,而且也给程序设计带来不便。方式2在计数溢出后自动重装计数器初值。其逻辑结构如下。(1)逻辑结构如图6-8所示(2)工作方式2的特点 两个定时器/计数器均可在方式2下工作; 把计数器分成两部分TH和TL,在开始计数(定时)时,把计数初值赋给TL的同时,也赋给TH,在TL发生计数溢出后,而是通过硬件自动把TH中的内容重新赋给TL。 是8位的计数结构TH:暂存器(用来暂时存放计数初值)。TL:计数器。(3)计数/定时的范围由于是8位的计数结构,所以,计数范围为1256,定时时间=(28-计数初值)机器周期。例6-7 T0工作于定时方式2,定时时间T=500s ,系统主频fosc=6 MHz 。进行初始化编程。解:由于,T0工作于定时方式,T0工作方式2。因此, =0,GATE=0,M1M0=10。T1不用,故TMOD=00000010=02H系统主频fosc=6M时,时钟周期T=1/6s,机器周期=12T=12/6=2s。 COUNT =28-500/2 =256250=06 MOV SP , #50H MOV TMOD,#02H MOV TH0,#06H MOV TL0,#06H SETB TR0 SETB ET0 SETB EA例6-8 设单片机频率为6MHz,使用定时器0以方式2产生周期为200s的连续等宽正方波脉冲,并由P1.0输出,以查询方式来完成。 计算计数初值要产生200s的连续等宽正方波脉冲,只需在P1.0端以100s为周期交替输出高低电平即可实现,从而定时时间为100s。f=6MHz、则机器周期为2s,100=(256-COUNT)2求得:计数初值COUNT=206=CEH。这样,把CEH装入TL0的同时,也装入TH0中暂存,即:(TH0)=(TL0)=CEH 确定TMOD寄存器的内容根据TMOD各位的含义,不难得出(TMOD)=02H。 程序由于工作方式2具有自动装载功能,因此计数初值只需设置一次,以后就不再需要软件重置。这是方式2与方式0、1的本质区别。4定时器/计数器的工作方式3在前面的三种工作方式中,两个定时器/计数器的设置和使用是完全相同的。但是在工作方式3下,两个定时器/计数器的设置和使用却不尽相同,下面分别介绍。(1)在工作方式3下的定时器/计数器0在工作方式3下,定时器/计数器0被拆成两个独立的8位计数器TL0和TH0。其中TL0既可以计数使用,又可以定时使用,定时器/计数器0的控制位和引脚信号全归它使用。其功能和操作方式0或方式1完全相同。而且逻辑电路结构也极其类似,如图6-9所示。与TL0的情况不同,对于定时器/计数器0的另一
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 2025版合同代理协议书范本
- 会计英语(第六版)课件 Lesson 4 LONG TERM ASSETS
- 2025林地流转合同样本
- 营销知识培训大纲课件
- 2025-2026学年七年级语文上册第五单元检测基础卷( 含答案)
- 2025-2026学年七年级语文上册第三单元检测培优卷(含答案)
- 2025年合同变更与解除管理规定的工程案例分析
- 2025年绿色金融产品创新与市场绿色金融产品创新驱动因素分析报告
- 2024人教版七年级生物上册第一、二单元共2套单元练习试卷(含答案)
- 2025设备租赁合同示范文本设备租赁合同
- GB/T 28714-2023取水计量技术导则
- 供应商纠正预防措施报告
- 蛋白质-能量营养不良课件
- 1输变电工程施工质量验收统一表式(线路工程)
- 市热电厂清洁生产审核报告
- GB/T 239.2-2023金属材料线材第2部分:双向扭转试验方法
- 四年级大庆精神铁人精神教案
- 《廉洁从业》企业文化培训课件
- 《教育魅力-青年教师成长钥匙》
- 《生物多样性公约》及国际组织课件
- 绪论(遗传学)课件
评论
0/150
提交评论