沁恒USB2.0使用指北

遇到反馈最多的问题是收不了数据,发不了数据。

 

多半是不清楚USB数据收发的机制导致。这里不做教学,只讲怎么用起来。

以CH554EVT.ZIP为代码基础,寄存器说明参考CH554DS1.PDF

文中所有提到的代码均以伪代码形式,便于理解。

 

先总结:

 

USB设备片面的理解是“被动的”。USB主要就是上传(IN事务,DEVICE->HOST)和下传(OUT事务,HOST->DEVICE)。上传的被动体现在设备准备好需要上传的数据之后,等着主机来将数据取走。下传的被动体现在设备需要准备好空闲的缓冲区,等着主机将数据发下来。数据什么时候流动,流动方向是什么,完全取决于主机,主机怎么控制数据流,取决于协议(这个协议包括标准USB CLASS协议,还有用户自定交互流程)。

 

因为这个被动,就会产生问题:

1、什么时候才表示主机将数据取走了、什么时候主机已经把数据发下来了。

2、上传数据不能够在主循环中拼命执行,因为可能上一包数据并没有成功发送。





一、上传

参考CH554EVT中CompatibilityHID.C

代码功能是Ep2InKey为0就上传固定数据,Ep2InKey为0就是P1.5接地。

为了实现稳定上传,引入了Endp2Busy这一个全局变量(全局标志),该标志必须使用

image.png

原因:USB是有应答的,USB设备作为“被动的”一方,需要等主机把数据取走了之后才能发送下一包数据。所以在调用Enp2BlukIn();的同时置位标志,防止这次的上传还没有结束,下一

次循环又处理了缓冲区数据。


image.png

在USB中断函数中的case UIS_TOKEN_IN | 2:   处将标志清除,也就是USB外设产生中断,并且成功进入这个case就表示2号端点的IN事务完成。

且代码131行处,可以看到将端点2的发送(设备->主机)响应状态改成了NAK,这样可以防止非主动的数据上传。直到数据准备好,我们会在主循环中调用Enp2BulkIn( ),将响应状态改成ACK,然后等着主机将数据取走。



二、下传

1、参考CH554EVT中VendorDefinedDev.C

2、代码功能:主循环判断从串口收一字节数据,对数据处理后通过端点1上传。端点2可以接收USB主机下发的数据,对收到的数据取反然后上传。即:

?

①由代码实现的,端点2支持且支持:下传上传下传上传下传上传下传上传

因为USB设备是“被动的”,所以只能等着主机在某个时候下传数据,需要提前准备好。初始化完确保UEP2_CTRL 寄存器对OUT事务的应答状态为“ACK”。只有响应状态为ACK,此时电脑尝试下传数据才能成功。?

端点应答状态的寄存器说明见下图。

image.png

第一包数据主机下发成功之后,才会进到USB中断函数。


第一包数据下传之后,下一包数据的上传在下图红框处处理:

先是将数据填充到Ep2Buffer[MAX_PACKET_SIZE]处

然后将上传数据包长度填到UEP2_T_LEN寄存器

最后将UEP2_CTRL寄存器的IN事务响应状态改成“ACK”

执行完以上操作,接下来就是等着下一次进USB中断,正常情况下下一次进USB中断函数会进入case UIS_TOKEN_IN | 2:???? 进入这里表示完成了一次IN事务。

image.png

这样的交互流程一定程度上做到了“同步”,也能够保证持续的传输。所以,一发一收的流程绝对不能乱,不然就可能传输卡住。

image.png

②由代码实现的,端点1支持且支持:上传上传上传上传上传上传上传上传

这个端点1上传功能类似CompatibilityHID.C中的上传,但是这里没有加上全局标志,只要getkey()函数有返回值,就一直会刷新Ep1Buffer。所以这个上传可能会出现上一包还没有被电脑取走,下一包数据就又填到缓冲区里了,导致类似数据出错、错位的问题。

image.png


①端点2支持且支持:下传上传下传上传下传上传下传上传

这个手册中有说明吗?这样的特性是不是意味着设备不能连续2次进行IN操作,进行一次IN操作后要主机触发一次OUT操作,才能进行下一下IN操作? 我看cdc例程就是用的端点2,也就是设备端不能连续给PC发送报文是吧?

怎么改善呢,CDC例程中使用其他端点可行吗? 我用的芯片是CH571/573,感谢答复!!!!


代码实现效果,并非芯片硬件特性


只有登录才能回复,可以选择微信账号登录