MJKDZ PS2手柄控制OskarBot小车(二):硬件连接与通信时序
【目录】
- 1、PS2硬件连接
- 1.1 硬件连接原理图
- 1.2 硬件接口关系对比
- 2、通信协议
- 2.1 PS2通信硬件接口与信号
- 2.2 PS2通信时序
- 2.3 PS2手柄各数据的意义
- 2.4 PS2手柄数据与MJKDZ手柄:传送数据对比
- 3、PS2手柄代码
- 3.1 PS2手柄按键处理主要内容
- 3.2 手柄命令处理函数的主要修改点
【目标】:OskarBot遥控,原来连接的是PS2手柄控制器,遵循PS2手柄协议,为模拟的SPI通信。
现改为MJKDZ的2.4GHz无线串口模块(BK2461),为串口通信。采用串口2接收MJKDZ手柄的数据,加入原PS2手柄的按键处理程序中。
【参考】:
(1)亚博智能 - 实验十四:C51单片机平台--PS2控制智能小车综合实验
https://www.yahboom.com/build.html?id=1095&cid=161
(2)YFRobot - PS2解码通讯及例程V1.8.zip
http://yfrobot.com/thread-11561-1-1.html
采购信息:OskarBot 奥斯卡机器人舵机小车
小车:
https://item.taobao.com/item.htm?spm=a1z09.2.0.0.67002e8dCycmQ8&id=570479397628&_u=qefkhaj6c7e
STM32控制板: https://item.taobao.com/item.htm?spm=2013.1.0.0.7b9274f8qfCjqB&id=565040857054
1、PS2手柄硬件连接
1.1 硬件连接原理图
(1)PS2接收底座与芯片的管脚连接
(2)MJKDZ的无线串口模块与芯片连接(串口2)
1.2 硬件接口关系对比
(1)引脚功能对比
(2)改造方案
方案1、继续沿用PS2接口的模拟SPI通信,找两个端口当做CLK:硬件太复杂,放弃。
方案2、改用串口通信,修改代码,接收MJKDZ手柄传来的数据,移植到原PS2手柄处理的代码上(这些代码比较复杂,可以后期再优化精简)。
选择方案2.
(3)PS2手柄按键对应关系
2、通信协议
2.1 PS2通信硬件接口与信号
DI/DAT:信号流向,从手柄到主机,此信号是一个 8bit 的串行数据,同步传送于时钟的下降沿。信号的读取在时钟由高到低的变化过程中完成。
DO/CMD:信号流向,从主机到手柄,此信号和 DI 相对,信号是一个 8bit 的串行数据,同步传送于时钟的下降沿。
NC:空端口;
GND:电源地;
VDD:接收器工作电源,电源范围 3~5V;
CS/SEL:用于提供手柄触发信号。在通讯期间,处于低电平;
CLK:时钟信号,由主机发出,用于保持数据同步;
NC:空端口;
ACK:从手柄到主机的应答信号。此信号在每个 8bits 数据发送的最后一个周期变低并且 CS 一直保持低电平,如果 CS 信号不变低,约 60 微秒 PS 主机会试另一个外设。在编程时未使用 ACK 端口。
当主机想读手柄数据时,将会拉低 CS 线电平,并发出一个命令“0x01”;
手柄会回复它的 ID“0x41=模拟绿灯,0x73=模拟红灯”;
在手柄发送 ID 的同时,主机将传送 0x42,请求数据;
随后手柄发送出 0x5A,告诉主机“数据来了”。
2.2 PS2通信时序
时钟频率 250KHz(4us),如果接收数据不稳定,可以适当的增加频率。在通讯过程中,
一串数据通讯完成后 CS 才会由低转高,不是 1 个字节通讯完成后就由低转高,在通讯期间,
一直处于低电平。
在时钟下降沿时,完成数据(1bit)的发送与接收,发送和接收是同时完成的。
(1)当单片机想读手柄数据或向手柄发送命令时,将会拉低 CS 线电平,并发出一个命令“0x01”;
(2)手柄会回复它的 ID“0x41=绿灯模式,0x73=红灯模式”;
(3)在手柄发送 ID 的同时,单片机将传送 0x42,请求数据;
(4)随后手柄发送出 0x5A,告诉单片机“数据来了”。
(5)手柄正式发送数据;
(6)一个通讯周期有 9 个字节(8 位),这些数据是依次按位传送。
idle:数据线空闲,该数据线无数据传送。
2.3 PS2手柄各数据的意义
(1)PS2手柄数据格式
当有按键按下,对应位为“0”,其他位为“1”,例如当键“SELECT”被按下时,Data[3]=1111 1110 B。
MODE 灯的意义?
A:因手柄的供应商不同,模式灯有所区别。现有手柄 MODE 灯意义如下:
1、模式灯是“绿灯模式”和“红灯模式”;
2、ID 值没有改变,“0x41=红灯模式,0x73=绿灯模式”;
红灯模式时:左右摇杆发送模拟值,0x00~0xFF 之间,且摇杆按下的键值值 L3、R3 有效;
绿灯模式时:左右摇杆模拟值为无效,推到极限时,对应发送 UP、RIGHT、DOWN、LEFT、△、○、╳、□,按键 L3、R3 无效。
2.4 PS2手柄数据与MJKDZ手柄:传送数据对比
(1)主机发送数据
PS2手柄,需要主机发送请求,手柄才会传输数据。
而MJKDZ手柄,采用串口中断模式,只要按键值有更新,就发送数据。
Q:后期优化代码:MJKDZ手柄,收到发送请求,发送当前按键值。
(2)主机接收到的数据
PS2手柄发送数据固定:当有按键按下,对应位为“0”,其他位为“1”;
MJKDZ手柄发送数据,可自定义,修改后可保持与PS2手柄的数据一致;
Q:后期优化代码:MJKDZ手柄,追加发送数据的情况:
(1)按键值有更新,发送按键值,摇杆模拟量;
(2)按键值不变,摇杆值更新,不会单独发送数据(PS2手柄支持)。->临时替代方案:需要摇杆数据时,先改摇杆,再将R1键按下。后期再优化。
(3)两个按键同时按下,PS2手柄的按键值可正常响应,而MJKDZ手柄会识别成先后两个键按下。->此使用场景,是否有需求?
PS2手柄,单键按下,只有4个数字:7(0111)、B(1011)、D(1101)、E(1110);PS2双键按下,有多种数字组合。
MJKDZ手柄,双键按下,如何读取数值?
注意事项:
1)都是发送8个字节(8位)数据;
2)头2个字节数据不同:PS2手柄为工作模式,数据Ready;MJKDZ手柄为自定义数据校验码1(0x73),校验码2(0x5A)被当做尾校验;
->数据处理,代码中增加首尾字符校验。
3)PS2手柄遍历所有按键(16个),需占用2个字节,才知道哪个按键被按下。按下的键位0,未按下为1。
MJKDZ手柄,一个字节,就知道哪个键被按下,按键代表的数值为自定义0x00~0x0F;
3、PS2手柄代码
3.1 PS2手柄按键处理主要内容
获取按键值,响应储存数据,处理命令
20ms读一次按键值
3.2 手柄命令处理函数的主要修改点
原PS2按键响应函数只需要赋值给下一步消息处理的函数,
现在需要增加判断一帧数据(MJKDZ发的8位数据)接收完毕,赋值给数组psx_buf[8](原来为psx_buf[9])。
数组的顺序与原来不同,但处理消息函数 收到的数据要保持不变 void parse_psx_buf(unsigned char *buf, unsigned char mode)