SOS!我在使用CH340G(外置晶振)时,初始化时芯片的输出电平会有相应变化(而控制系统是不希望这样的),后来厂家升级了驱动程序,这个问题解决了。可是当我采用CH340C(无外置晶振)时,这个问题又出现了,该如何解决呢?请厂家提供解决方案。谢谢了!有高手也望不吝指教!拜托了!顺祝节日快乐!
您好,请问具体所指信号变化是否为DTR和RTS变化。如果是该2个信号在USB插入时变化,则是因为驱动版本未更新至最新版本所致,请从如下链接中下载驱动:http://www.wch.cn/downloads/CH341SER_EXE.html
谢谢TECH39的回复!确实是DTR和RTS信号的变化,CH340C插入USB时DTR和RTS没有变化,当驱动加载后这两个信号就动作了,而这时操作DTR和RTS的命令并没有下达。当芯片为CH340G时,通过升级CH341SER.EXE可以解决。而当芯片为CH340C时,这个方法不起作用了。链接下载的驱动日期为2019/1/30,版本为3.5.2019.1。也就是说:这个版本不能解决问题。症结在哪里呀?还求TECH39继续指导为盼!
您好,可以添加我微信单独确认下问题仍然存在的原因。已私信您联系方式。
您好!如何添加呀?您的微信号是啥?盼告。谢谢!
我的微信号:lichenyin2017,EMAIL:个人信息保护,已隐藏
您好,已添加微信。您可以将如上包含个人信息回帖删除,以免收到广告信息等。
官网CH341A驱动程序无法适配 ubuntu 5.11.0-37-generic 系统,驱动版本过旧,无法编译,需要如何修改驱动程序源代码!
您好,请单独mail给我,我将资料包发送过去,有问题及时沟通。我的邮箱地址:zhangj@wch.cn
1、利用CH341对I2C从站进行写操作,代码如下,结果成功完成。
CH341OpenDevice(0);
CH341StreamI2C(0, 18, tx_buf, 0, rx_buf); // 写入16字节的数据到指定存储器
CH341CloseDevice(0);
2、对从站进行读操作,代码如下:
CH341OpenDevice(0);
IIC_IssueStart(0); // start
IIC_OutByteCheckAck(0, 0x80); // 从站地址=0x40
IIC_OutByteCheckAck(0, 0x04); // 读取命令
IIC_IssueStart(0); // start
IIC_OutByteCheckAck(0, 0x81); // 0x40<<1 + 1
IIC_InBlockByAck(0, 15, rx_buf); // 前15个字节由主机ACK
IIC_InByteNoAck(0, temp); // 最后一个字节由主机NACK
rx_buf[15] = temp;
IIC_IssueStop(0);
CH341CloseDevice(0);
从站是一个MCU,通过监视可以正常接收到IIC_OutByteCheckAck发送的数据,但返回给主机的数据只发送了2个字节(应该发送16个字节的),而通过CH341这边接收到的数据又全部是0xFF。
以上程序是调用CH341DLL.DLL在VC#环境下编制的,以前采用其它厂家的USB/I2C转换器都完全调试通过了的,因此I2C从站设备是不会有问题的,现在就是针对IIC_InBlockByAck和IIC_InByteNoAck这两个功能块有所怀疑,请帮助分析一下,谢谢!
您好,如上提到的功能函数IIC_InBlockByAck、IIC_InByteNoAck等具体是什么实现,可以把这部分的代码发给我们确认下。排查I2C的读写问题主要有如下几个点:
1、CH341的读I2C,默认API在写完设备+寄存器地址后没有delay,要求设备准备数据足够快;(若来不及,可以先通过CH341SetStream设置为100Khz的I2C);
2、CH341默认是忽略I2C设备的ACK状态的,即设备是ACK或NACK,不影响API返回结果;
提到的返回给主机的数据只发送2个字节(应该16字节):关于这段话,主机读取的字节是主机决定,不是设备决定,读取16字节CH341StreamI2C中的读长度设置为16即可。
1、已被验证可正确执行的3个子程序:
public bool IIC_IssueStart(UInt32 iIndex)
{
byte[] mBuffer = new byte[3];
UInt32 mLength;
mBuffer[0] = mCH341A_CMD_I2C_STREAM;
mBuffer[1] = mCH341A_CMD_I2C_STM_STA;
mBuffer[2] = mCH341A_CMD_I2C_STM_END;
mLength = 3;
return (CH341WriteData(iIndex, mBuffer, ref mLength));
}
public bool IIC_IssueStop(UInt32 iIndex)
{
byte[] mBuffer = new byte[3];
UInt32 mLength;
mBuffer[0] = mCH341A_CMD_I2C_STREAM;
mBuffer[1] = mCH341A_CMD_I2C_STM_STO;
mBuffer[2] = mCH341A_CMD_I2C_STM_END;
mLength = 3;
return (CH341WriteData(iIndex, mBuffer, ref mLength));
}
public bool IIC_OutByteCheckAck(UInt32 iIndex, byte iOutByte)
{
byte[] mBuffer = new byte[10];
UInt32 mLength, mInLen;
mBuffer[0] = mCH341A_CMD_I2C_STREAM;
mBuffer[1] = mCH341A_CMD_I2C_STM_OUT;
mBuffer[2] = iOutByte;
mBuffer[3] = mCH341A_CMD_I2C_STM_END;
mLength = 4;
mInLen = 0;
if (CH341WriteRead(iIndex, mLength, mBuffer, 32, 1, ref mInLen, mBuffer) == true)
{
if ((mInLen > 0) && ((mBuffer[mInLen-1] & 0x80) == 0))
return (true);
}
return (false);
}
2、执行结果不正确的2个子程序:
public bool IIC_InBlockByAck(UInt32 iIndex, UInt32 iInLength, byte[] oInBuffer)
{
byte[] mBuffer = new byte[40];
UInt32 mLength, mInLen;
if ((iInLength == 0) || (iInLength > 32))
return (false);
mBuffer[0] = mCH341A_CMD_I2C_STREAM;
mBuffer[1] = (byte)(mCH341A_CMD_I2C_STM_IN |iInLength);
mBuffer[2] = mCH341A_CMD_I2C_STM_END;
mLength = 3;
mInLen = 0;
if(CH341WriteRead(iIndex, mLength, mBuffer, 32, 1, ref mInLen, mBuffer)==true)
{
if (mInLen == iInLength)
{
for (int i = 0; i < iInLength; i++)
oInBuffer[i] = mBuffer[i];
return (true);
}
}
return(false);
}
public bool IIC_InByteNoAck(UInt32 iIndex, ref byte oInByte)
{
byte[] mBuffer = new byte[4];
byte[] nBuffer = new byte[40];
UInt32 mLength, mInLen;
mBuffer[0] = mCH341A_CMD_I2C_STREAM;
mBuffer[1] = mCH341A_CMD_I2C_STM_IN;
mBuffer[2] = mCH341A_CMD_I2C_STM_END;
mLength = 3;
mInLen = 0;
if(CH341WriteRead(iIndex,mLength,mBuffer,32,1,ref mInLen,nBuffer)==true)
{
if(mInLen > 0 )
{
oInByte = nBuffer[mInLen-1];
return(true);
}
}
return(false);
}
从机只发送了2个字节是这样的:从机MCU是通过中断来发送数据的,每中断一次增加一次发送计数器,目前这个指令(0x04)执行后已经把要发送的数据放到了发送缓冲区(0x3F,0x9D,0x70,0xA4,.....)共16个字节,但响应完指令后发送计数器=2,上位机接收到的数据为:0x1F,0xFF,0xFF,0xFF,.....共16个字节。
当发送缓冲区数据=0x40,....共16个字节时,已发送的字节还是=2,但上位机收的数据为:0x20,0xFF,0xFF,...16个字节,感觉像数据错位或时钟过快。
IIC_IssueStart(0); // start
IIC_OutByteCheckAck(0, 0x80); // 从站地址=0x40
IIC_OutByteCheckAck(0, 0x04); // 读取命令
(CH341的读I2C,因为写完设备+寄存器地址后没有delay,要求设备准备数据足够快;
那我在这里加入一条延时语句,是否有用?)
IIC_IssueStart(0); // start
IIC_OutByteCheckAck(0, 0x81); // 0x40<<1 + 1
IIC_InBlockByAck(0, 15, rx_buf); // 前15个字节由主机ACK
IIC_InByteNoAck(0, temp); // 最后一个字节由主机NACK
rx_buf[15] = temp;
IIC_IssueStop(0);
您好,因为I2C的读操作需要Repeat Start,进行读操作的时候需要先Write设备地址(有寄存器地址),如果是采用单独的 IIC_OutByteCheckAck函数再读,则会没有Repeat Start信号。您可以发邮件给我,我整理下Code发您。此外,有逻辑分析仪的话可以同步抓下I2C时序,定位问题会更便捷些。