文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>MEGA32+CH375实现USB鼠标的一些笔记

MEGA32+CH375实现USB鼠标的一些笔记

时间:2010-06-24  来源:Etual

CH375外置固件模式和 CH372完全兼容 数据线D0~D7,nRD ,nWR,nCS,nINT,A0=1写命令,A0=0写数据。
可以采取MCS-51的总线模式直接驱动,也可以用模拟IO的方式
(1)首先必须实现的是两个最基本的函数,写数据和写命令
注意时序的要求,不过一般来说,先nWR是最后使能也是最先退出,这个应该参考时序图
void CH375_WR_CMD_PORT(uint8_t cmd);
void CH375_WR_DAT_PORT(uint8_t data);
uint8_t CH375_RD_DAT_PORT(void);
(2)有了两个基本函数就可以写命令了,首先初始化芯片,先发送一个复位命令,等待40ms,然后发送一个 CMD_CHECK_EXIST
看看返回的是否已经取反了的数据,如果正确的话,那么CH375基本就已经正常了。其实,每个WR的低电平脉冲,就写入一个命令
或者数据,每个低电平的RD脉冲就读出一个数据,所以数据是不会丢的。
 CH375_WriteCMD(CMD_RESET_ALL);   //复位全部
 CH375_DelayNms(50);    //延时40ms
 
 CH375_WriteCMD(CMD_CHECK_EXIST);  //检查芯片是否存在
 CH375_WriteDAT(0x55);    //填数据0x55 取反为0xaa
 if(CH375_ReadDAT() != 0xaa)
 {
  return 1;
 }//不存在则退出
(3)接着比较重要的是设置USB模式,可以发送命令 CMD_SET_USB_MODE 设置,例如使用USB从机外部固件模式,则发送个1过去 (4)这个时候CH375已经正常工作了,如果有事件发生,那么会引起nINT的中断信号,可以通过
        CH375_WR_CMD_PORT(CMD_GET_STATUS);  /* 获取中断状态并取消中断请求 */
 InterruptStatus =CH375_RD_DAT_PORT();
读出具体的状态来做出反应。接着是根据USB的协议来办事了。
(5)CH375中对3个重要的端点的操作,EP0 控制端点,EP1 中断端点,EP2 批量传输端点
其中端点0,1 是8字节,端点2是64字节双缓冲
外部固件模式需要设置端点,可以通过命令
EP0_OUT   SET_ENDP2
EP0_IN    SET_ENDP3
将数据发送到 EP0缓冲区传到主机,则通过
WR_USB_DATA3 写到EP0缓冲
WR_USB_DATA5 写到EP1缓冲
WR_USB_DATA7 写到EP2缓冲
CMD_RD_USB_DATA  则是从 EP0 中读取数据
CH375 对 USB_INT_EP0_OUT 可以不响应,因为SETUP事物有专用的 USB_INT_EP0_SETUP
可以通过 CMD_RD_USB_DATA 读取需要的数据
当USB插入,那么先进行3次的USB总线复位,产生 USB_INT_BUS_RESET 中断状态,然后是 USB_INT_EP0_SETUP,表示 EP0 收到了
SETUP 事务包,这个时候应该根据需要返回描述符,如果没有返回,那么USB主机会将前面的步骤进行3次,如果都没有正确响应
那么最后windows提示"USB设备无法识别"
首先读取的是接着的数据包的长度,如果是USB设备请求(USB DEVICE REQUEST)的话肯定是8个字节,因为USB要求每个设备的 EP0
控制端点必须至少能接收8字节的数据。那么CH375可以通过 CMD_RD_USB_DATA 命令读取第一个数据,判断是否为8,是的正确,然后
连续读取8个字节的设备请求,CMD_RD_USB_DATA 命令只需要发一次就OK了。
对于这8个字节,参考CH375官方的程序,比较好的办法是用一个联合体
union UsbSetupPacket
{
 struct DevReq_tag{
  uint8_t bmRequestType;
  uint8_t bRequest;
  uint16_t wValue;
  uint16_t wIndex;
  uint16_t wLength;
 } DevReq;
 uint8_t PacketBuffer[8];
};
union UsbSetupPacket upack; 访问可以通过buf来逐个字节去访问 upack.PacketBuffer[i]
也可以通过结构体里面的成员去访问 upack.DevReq.bmRequestType
bmRequestType 的bit7是指示方向,其实可以不理,因为对应的 bRequest不同就可以区分是上传还是下载
bit 5 ,6 用来区分请求的类型,比较常用的是 标准请求
通常
bmRequestType == 0x80 是一个标准的设备请求
bRequest == 6  这是一个 GET_DESCRIPTOR 的请求,那么根据需要返回设备描述符
然后判断 wValue 的高字节的,也就是 buf[3] ,这个就是描述符的类型,第一个当然是 1,设备描述符了。
根绝圈圈书本上的解释返回设备描述符,注意的是第一次要求返回的描述符其实是不完整的,只需要8个字节
接着就是 SET_ADDRESS 请求,这个使用 CH375 的 SET_USB_ADDR 命令然后设置具体的地址,这个地址是从
主机传过来的,保存在 wValue 的低字节当中,然后EP0返回一个0长度的包表示 ACK应答。然后在接着的EP0_IN
中断中判断是否 SET_ADDRESS 请求,如果是的话再用 CMD_SET_USB_ADDR 命令设置USB的新地址。说实话,这
让我很无语......为什么不是直接设置了就生效而非要这样做?....
成功设置地址之后,USB主机以新地址发送 GET_DESCRIPTOR ,这是就需要将完整的 Device Descriptor 返回。 接着是返回配置描述符,这个没什么,按照圈圈的书的代码直接copy进去,其中以后可能会修改的部分就是
端点描述符
然后USB主机发来一个 DEF_USB_SET_CONFIG 的请求,wValue 里面的数值为 1 ,表示1个configuration被采用了
一般来说可以在这里设置一个标志,当这个标志有效表示已经可以操作 EP1_IN 了。可以在这里设置一个标志,当
主程序检测到这个标志的时候就可以写报告到 EP1了
然后主机请求 HID 描述符,最后将HID描述符成功返回之后,window提示新硬件已经正确安装可以使用
这个时候枚举已经完成
Product Descriptor 发现新硬件的时候显示的字符串,在设备描述符的时候设置编号,然后在字符串描述符的时候返回
设备范例Id
VID 在设备描述符里面设置
PID 在设备描述符里面设置
serial 字符串
兼容 Id
在接口描述符里面设置的USB类
Etual
2010-6-24
相关阅读 更多 +
排行榜 更多 +
辰域智控app

辰域智控app

系统工具 下载
网医联盟app

网医联盟app

运动健身 下载
汇丰汇选App

汇丰汇选App

金融理财 下载