摘要:第二点和是同时完成的,这说明这是全双工通信。上表中的表示数据线空闲,没有数据传输。设置振动模式后,用于控制右侧小电机,指示关,其他值为开。微控制器发送给句柄,此时句柄会返回给微控制器,说明已经收到请求,很快就会返回数据。
1.硬件准备:战舰开发板,PS2手柄接收器,PS2手柄,连接线2根。硬件连接:PS2手柄接收器有6个引脚,与单片机的IO口连接,如下图所示:
接收器信号微控制器logndgndvcc 3.3 VDI/dat Pb 12 do/cmd Pb 13 CSP 14 clk Pb 15 III。PS2通信介绍通信顺序如下,感觉很像SPI,四线DI和DO是一对同时传输的8位串行数据。发射时,CS需要处于低电平,CLK由高变低。DO是单片机发送给接收器的信号。DI是接收器发送给单片机的信号。第一点:数据输出或输入时CS为低,所以我们要在数据传输时先拉高CS再拉低,在数据传输时再拉高CS。第二点:DI(数据输入)和DO(数据输出)同时完成,说明这是全双工通信。串口是全双工通信。IIC是半双工通信。第三点:时钟上升和下降时,DI和DO的数据相交,也就是说数据交换(数据只有0和1)。这时候我们就不能读写数据了,因为数据还不稳定,读取的数据不准确。时钟在下降沿的时候,数据已经稳定下来,这个时候我们开始读写数据。第四点:既然是从0到7,就可以知道有8位数据,从低位到高位读写。我们可以把数据放入一个数组。时钟传输一个数据位(也称为位0或位1)。
时钟频率为250KHZ(4us)。如果数据不稳定,可以适当增加频率。当微控制器发送0x01时,接收器会回复其ID“0x 41代表绿灯模式”,“0x73代表红灯模式”;手柄发送ID的同时,MCU会发送0X42,手柄发送0X5A,高速MCU数据来了。上表中的Idle表示数据线空闲,没有数据传输。因此,数据[0]、数据[1]和数据[2]不能用于存储PS2摇杆的键,数据[3]和数据[4]用于存储键的值,数据[5]、数据[6]、数据[7]和数据[8]用于存储摇杆的模拟量。
有按钮时,对应位为0,其他位为1。例如,当按下SELECT时,按下L3时Data[3]=1111 1110B,按下R3时data [3] = 1111 101b,按下START时Data[3]=1111 1011B,Data[3]=1111 0111B。按右时Data[3]=1110 1111B,按下时Data[3]=1101 1111B,按左时Data[3]=1011 1111B,Data[3]=0111 1111B。
手柄有两种模式,红灯模式(手柄上的红灯+绿灯)和绿灯模式(手柄上只有绿灯),按下模式键即可切换。红灯模式:1。有效按下L3/R3键;2.按下左右摇杆,可以根据不同的笔画输出0x 00-0x ff;3.有效按下L3/R3键;2.把左右摇杆推到上、下、右、左的极限值,右摇杆可以达到和△/x/一样的效果。
设置振动模式后:WW用于控制右边的小电机,0x00表示关,其他值为开。YY用于控制左边的大电机,0x40-0xff表示电机开启。值越大,振动越强。其他值表示电气机制。
4.代码分析1。配置IO口,设置PB12为下拉输入;PB13/14/15设置为推挽输出。
void PS2 _ Init(void){ GPIO _ Init typedef GPIO _ Init structure;//enter di-> Pb 12 RCC _ APB 2 periphclockcmd(RCC _ APB 2 periph _ gpio b,enable);//使能PORTB时钟gpio _ init结构。gpio _ pin = gpio _ pin _ 12GPIO_InitStructure。GPIO _ Speed = GPIO _ Speed _ 50MHzGPIO_InitStructure。GPIO _ Mode = GPIO _ Mode _ IN _ FLOATING;//设置为gpio _ init (gpiob,& gpio _ init结构),用于上拉、下拉和浮动输入;//输出do-> Pb 13 cs -> Pb 14 cl -> Pb 15 Pio _ init结构。gpio _ pin = gpio _ pin _ 13 | gpio _ pin _ 14 | gpio _ pin _ 15;GPIO_InitStructure。GPIO _ Speed = GPIO _ Speed _ 50MHzGPIO_InitStructure。GPIO _ Mode = GPIO _ Mode _ Out _ PP//设置为推挽输出gpio _ init (gpiob,& gpio _ init结构);} 2.定义3个数组
u8 Comd[2]={0x01,0x 42 };//开始命令。请求数据u8data [9] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x 00 };//数据存储数组//每个键对应一个值u16mask [] = {PSB _ select,PSB _ L3,PSB _ R3,PSB _ start,PSB _ pad _ up,PSB _ pad _ right,PSB _ pad _ down,PSB _ pad _ left,PSB _ L2。3.以宏观方式定义四个IO的状态,PB12/PB13/PB14/PB15。
# define dipbin(12)//Pb 12 input # define DO _ H Pb out(13)= 1//命令位高#define DO_L PBout(13)=0 //命令位低#define CS_H PBout(14)=1/ /CS上拉#define CS_L PBout(14)=0 //CS下拉#define CLK_H PBout(15)=1 //时钟上拉#define CLK_L PBout(15)=0 //时钟下拉4。微控制器向手柄发送命令。
//发送命令void PS 2 _ cmd(u8 cmd){ volatile u16ref = 0x 01;数据[1]= 0;for(ref = 0x 01;ref do _ H;//作为控制位输出} else DO _ L;CLK _ H;//生成时钟delay _ us(50);CLK _ L;delay _ us(50);CLK _ H;if(DI)Data[1]= ref | Data[1];} }//如果微控制器向接收器发送0x01=0000 0001B,接收器接收到0x01后向微控制器发送0x41 = 0100 0001b,ref = 0x01 = 0000 0001b数据[1]= 0;CMD=0000 0001BDI=0100 0001B/从低到高执行8个周期。第一个周期:ref=0000 0001Bif(ref&CMD)为真,输出PB13=1if(DI)为真。输出数据[1]= ref | data[1]= 0000 0001 | 0000 0001 = 0000 0001第二周期:ref=0000 0010Bif(ref&CMD)为假,输出PB13=0if(DI)为假,不执行操作第三周期:ref=输出PB13=0if(DI)为假,不操作第四周期:ref=0000 1000Bif(ref&CMD不操作第六个周期:ref=0010 0000Bif(ref&CMD)为假,输出PB13=0if(DI)为假,不操作第七个周期:ref=0100 0000Bif(ref&CMD)为假,输出PB13=0if(DI)为真。输出数据[1]= ref | data[1]= 0100 0000 | 0000 0001 = 0100 0001第八个周期:ref=1000 0000Bif(ref&CMD)为假,输出PB13=0if(DI)为假。不执行任何操作,因此最终结果是微控制器逐位发送0x01,接收器发送的数据0x41保存在Data[1]中。a…volatile修饰符可以保证ref从0x01开始,即0000 0001B b.ref = 0x01refvolatile u8字节= 0;易失性u16 ref = 0x01CS _ L;PS2 _ Cmd(Comd[0]);//启动命令0x 01 PS 2 _ Cmd(Comd[1]);//请求数据0x 42 for(byte = 2;byte clk _ H;CLK _ L;delay _ us(50);CLK _ H;if(DI)Data[byte]= ref | Data[byte];} delay _ us(50);} CS _ H;a .数据传输必须在CS被拉低期间进行。数据传输完成后,CS应拉回到高电平,以便进行下一次通信。b .微控制器向句柄发送0x01 0x42,句柄会向微控制器返回0x5A,表示已经收到请求,即将返回数据。所以Data[2]存储句柄返回的0x5A。下面的Data[3]-Data[8]全部返回按钮和操纵杆的状态信息。
6.检查钥匙状态
//处理读取的PS2数据,只处理关键部分。默认数据是红灯模式。//只按一个键的时候是0,不按的时候是1 u8 PS2 _数据键(){ u8 indexPS2 _ clear data();PS2 _ read data();Handkey=(Data[4]PSB_SELECT,PSB_L3,PSB_R3,PSB_START,PSB_PAD_UP,PSB_PAD_RIGHT,PSB_PAD_DOWN,PSB_PAD_LEFT,PSB_L2,PSB_R2,PSB_L1,PSB_R1,PSB_GREEN,PSB_RED,PSB_BLUE,PSB _ PINK };7.检查摇杆的状态。
# define PSS _ rx5 # define PSS _ ry6 # define PSS _ lx7 # define PSS _ ly8//获取一个摇杆的模拟范围从0到256u8ps2 _匿名数据(u8 button){返回数据[button];a .四个摇杆的反馈是模拟的,范围是0x00~0xFF,换算成十进制就是0-255。摇杆的值存储在数据[5]、数据[6]、数据[7]和数据[8]中。b .注意摇杆只在红灯模式下反馈模拟量,绿灯模式下不反馈。
8.其他功能8.1清除数据缓冲区
//清空数据缓冲区void PS2 _ Clear data(){ u8a;for(a = 0;aCS _ L;PS2 _ Cmd(0x 01);PS2 _ Cmd(0x 44);PS2 _ Cmd(0x 00);PS2 _ Cmd(0x 01);//analog = 0x 01;Digital=0x00软件设置发送模式PS2 _ Cmd(0x ee);//Ox03锁存设置,即不能按“MODE”键设置模式。//0xEE不锁存软件设置,但是可以通过按“MODE”来设置模式。PS2 _ Cmd(0x 00);PS2 _ Cmd(0x 00);PS2 _ Cmd(0x 00);PS2 _ Cmd(0x 00);CS _ H;delay _ us(16);}
评论前必须登录!
注册