[原创]CH341A的使用几点心得!

在我阅读CH341A的PDF文档时,着实高兴了一阵子,因为觉得CH341A的使用太简单了,比菲利浦的PDIUSBD12简单得多(此前我一直用这个芯片做USB类产品),至少可以免写驱动,而且价格还很便宜。国内IC厂商能做出这样的产品,值得鼓励。于是上淘宝购了几片CH341A着手进行测试。

测试的第一天晚上,使用的是CH341A的EPP1.7模式,无论如何发数据,我的设备都不理。因为我的设备端有CRC16校验,数据出错就不予理睬,所以可以肯定是数据出错了。于是使用CH341EppWriteData,每次只发一个字节,通讯成功,然而这个速度真吃不消,大约100Bytes/s。为什么多个字节一起发就不行呢?研究了一下EPP1.7的PDF,发现我的程序时序没错,而可能是CH341A的EPP1.7模式,并不等待nWAIT拉高就自行结束EPP周期,所以数据象流水般发送,我们的程序无法同步:前面的数据并未接收,后面的数据就覆盖了它!这么说来,CH341A的EPP1.7可能是个貌似的EPP1.7,与标准的EPP1.7文档中的可能不一样。WCH的文档并没说明,我只是根据测试现象猜测。

第二天,采用CH341A的EPP1.9模式。我之所以不太乐意用EPP1.9,因为EPP1.9对WAIT信号很敏感,若数据写入之后的10ms内,WAIT不被外设拉低,则置位超时标志,强制结束EPP周期,而且需要人为清除超时标志,才能启动下一个EPP周期,所以对于响应不够快的设备,EPP1.9并不适合。因为我的设备是多任务的,通讯任务的优先级较低,50ms内都可能没时间去处理通讯中断。结果发现CH341A的EPP1.9竟然又是个貌似的EPP1.9,根本没有10ms时限控制。这一下歪打正着,恰好我就是不需要这个超时控制的!于是修改了程序的时序:设备初始化拉低CH341A的WAIT引脚 -> CH341A的DS引脚从高跳低的下降沿触发通讯中断->设备接收数据,然后拉高CH341A的WAIT引脚5us,通知CH341A结束当前EPP周期 -> 设备拉低CH341A的WAIT引脚,通知CH341A启动下一EPP周期。经过这样的时序匹配,CH341A才真正和我的设备通讯起来,速率可达220k/s左右。关于这点,WCH的文挡也没有说明,我是万不得已才采用EPP1.9模式试试,才发现没这个10ms时限控制!

可见,WCH的文档不够详细严密,否则就不要走这个弯路。大体上,我们对于EPP1.7和EPP1.9的了解,来自英文的标准文档。所以个人认为,与标准有所不同的地方,应着重在文档中申明。

但是,还是高兴得太早!众所周知,USB总线携带的数据包,带有CRC16校验。所以当数据发送到CH341A时,理论上应该是准确无误的,而CH341A在PCB上,与PCB上的CPU的距离不到1cm,完全就是CPU一个片外扩展器件,若这么短的距离内通讯,还出错的话,那CPU和片外所有的器件通讯,都要出错,所以出错应该在USB传输层。但我发现CH341A发送到CPU的数据还是很多错的。为了验证这个问题,我在设备的PCB上加了个指示灯,每检测到一个数据包的CRC16校验码错误,就闪烁一次指示灯。结果我所看到的情况是指示灯不停地闪(我的数据量一般在几M字节以上,发送几十字节几k字节可能观察不到)!USB传输层的错误,我们还能有什么办法?芯片对我们而言是黑盒子的,驱动和应用层API也对我们是黑盒子。但办法总还是有的:对要发送的数据,先自己封包,把封好的包使用CH341EppWriteData发出去,设备端再检测包的正确性,错了通知应用程序重发。我的包是这样封的:握手的同步字符(2字节(我使用0xAA+0x55作为同步字符)) + 包号(2字节) + 数据流长度 1字节 + 数据流(最多255字节) + CRC16(2字节)。一次连续通讯最多65535个包,每包最多255字节,一次连续通讯可发16M数据,一般的应用可说足够了!经过这样处理后,CH341A终于和我们的设备可准确无误地通讯。准确到什么程度呢?即使正在通讯时,我把USB电缆不断地拔出、插入,人为破坏其通讯,99%的情况下还能正确完成通讯。我使用Bus hound总线监控软件,可以清楚地看到错包重发的现象,很爽。看到这里,觉得问题是不是应该解决了?可是——

还是有一个问题:CH341A频繁随机断线问题!CH341A断线之后,必须拔出USB电缆再插入,才能重新连接上。前面说过,我改进的通讯机制,已经不怕通讯时拔出电缆再插入电缆。问题是,很多设备是工作于无人值守的情况下,不可能专门安排个人去监视设备的通讯。这个问题的解决办法其实并不复杂:控制CH341A的Reset In引脚。但目前的CH341A不够方便,因为它没有一个引脚通知CPU说它断线了,只能判断多久没有通讯事件发生,确定是否是断线了,这会造成失误。PDIUSBD12有个重连功能,当断线发生时,GoodLink会熄灭,根据GoodLink的电平高低,就能知道是否断线,这点非常适合无人值守的设备!若CH341A能内置断线重连功能,它的应用范围就宽了不少。目前,它只适合于一般性应用,比方在无人值守的工业控制产品方面,根本就无法用。

应该说,CH341A在数据量不大时,通讯还是蛮可靠的,我测试了数据量在10k以下时的通讯质量,很少会出错。仅这点,做做下载线等一般性应用就很方便。但是,在数据量较大时,不经过应用层的严密处理,就几乎没法用。

CH341A的应用,简单不?

现在遗留两个问题: 1、开机不管插不插带CH341A的设备,都弹出找到新硬件向导! 2、频繁随机断线的问题。虽然可控制CH341A的RESET引脚重连,但毕竟如何知道断线了呢?

经验证,控制CH341A的RESET IN引脚,可引起重连的效果(PC会响一声,表示有设备插入),但有时实际上并没有重连,因为应用程序有时不能收到CH341_DEVICE_ARRIVAL消息,不知何故。有时却能收到


USB协议里面规定是要有CRC校验的,这个是有底层硬件来控制的,在一个传输事务(是USB中不能再分割的单位)中分3个阶段,令牌(IN/OUT/SETUP)+数据(可选)+握手(ACK/NAK/STALL),如果有数据传输的话,并且我们假设数据出现错误,那么另一端在接受到数据出错的话肯定不是应答ACK。 主机读数据: 主机(PC)发IN令牌,设备(341A)发数据(假如数据出错),主机发现数据出错什么也不发,设备发现没有握手,继续发数据,设备3次发都不成功进超时一般会进STALL,主机在没收到数据的ACK会一直发IN。设备进STALL,主机清端点,然后重新开始上述步骤传输数据。 主机写数据: 主机(PC)发OUT令牌,向设备发数据(假如数据出错),主机等待ACK确定,设备在发现数据出错的话,是不会发任何握手,这样主机会重复2次上面步骤(发OUT令牌,向设备发数据),设备发现3次数据都发送错误进STALL。 设备进STALL,同上。 上面是USB协议规定的,所以USB设备接受到的数据交给上层的时候是不会出现数据错误的,而你说的数据出错,应该是341并口与你的CPU之间出错的。


理论上应该如此。USB通讯携带的数据包在1024字节以内,使用的又是CRC16校验,基本不可能出错。但我这里测试,数据量较少时,基本都不会出错,而数据量达到数M时,我却没发现一次成功的通讯。若说是CPU和CH341A之间的通讯错误,那产品如何开发?总不能说CPU读写RAM芯片,都要进行校验吧?在USB传输层无错,那就可以理解为CH341A的引脚电平不稳定,否则没理由出错,因为CH341A离我的CPU也就1cm不到。

关于这个问题已经不很重要,因为如何保证通讯的绝对可靠,我已经解决了。稳定性已经允许通讯期间,随意拔插USB电缆了。

现在的问题是:如何知道CH341A断线了?CH341A断线了如何可靠地重新连接上?因为人工拔插的方法,太不招人喜欢,而且未必所有设备都是有人值守的。CH341A断线之后,Windows设备管理器里还在,只是应用程序无法和CH341A通讯了,拔插一下,马上就好了。

我试了两种方法:1、使用CH341ResetDevice函数,但这个函数只是简单地复位一下CH341A,却不能断线重连,恢复通讯。再说,真正断线了,API也无法访问CH341A了。 2、在硬件端检测CH341A的Active引脚,发现Active引脚被拉高,则拉高CH341A的RSTI引脚,产生复位。问题是,我发现CH341A的ACT引脚,断线了它也还是低电平(有时会是高电平)。这个不确定性,硬件端又无法做到重连。如果CH341A的引脚与PDIUSBD12的GoodLink引脚一样,那就好办得多了。


你留个电话,这样联系快点。


13588867730


你说的“现在的问题是:如何知道CH341A断线了?CH341A断线了如何可靠地重新连接上?因为人工拔插的方法,太不招人喜欢,而且未必所有设备都是有人值守的。CH341A断线之后,Windows设备管理器里还在,只是应用程序无法和CH341A通讯了,拔插一下,马上就好了。” 这个问题应该是干扰造成的,如果把这个问题解决了我们的芯片是不会频繁出现你说的断线问题,请查看下面的文档! /download/list.asp?id=2


因为我一直是做工控方面产品的,所以对于接口保护比较熟悉。现在的测试PCB上,我使用的是TVS管对D+、D-进行Rail-To-Rail保护。正式产品中,则可能用USB接口专用保护组件stf202。我所要说的是,保护只能增加稳定性和防止损坏,但不能杜绝。而我希望的是:在不能杜绝的情况下,若能用软方法产生拔插效果,基本就可杜绝了,除非PC系统除了问题——这就与我们的产品无关。而且,软方法拔插,不同于物理拔插,不会产生瞬变和尖锋电压。

做过工控产品开发的都知道,有的东西是无人值守地长年开着的。还比监控、安防产品,就拿云台的控制来说,基本是全年全天候运行,大多数时候无人值守。所以不仅仅是需要稳定性,还需要“万一出问题,自动恢复正常”这个功能。


用了很多时间。。CH341能用VB控制灯的开与关了。。。但频繁随机断线的问题。要按复位。。。基本是全年全天候运行,大多数时候无人值守。 哪个高手给个 用菲利浦的PDIUSBD12 用VB控制LED灯的电路图。。或给个网址。。。。


我用CH341A做了个USB转TTL串口的转换器,用于STC单片机程序下载,工作很稳定,速度能到14400kbps。


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