CH341中关于CH341WriteRead的I2C时序

1. 在检查CH341StreamI2C的部分源码后,好像是需要手动发START/STOP的,但是之前打电话询问的时候,给我的答案是CH341WriteRead可以自动产生START/STOP位,无需手动发送。

不知道哪种调用CH341WriteRead,需要在手动的产生START/STOP(就是在写buffer里面增加START/STOP的内容)?

2. CH341WriteRead的iReadStep参数是否可以为指定的读写长度,而非mCH341A_CMD_I2C_STM_MAX?

3. CH341WriteRead回传到指定读buffer的内容是纯粹的I2C帧内容,还是有带其他的USB帧的内容?例如读长度为0byte(实际上是用于写的ACK检查)就回读一个byte包含ACK内容。但是如果是从I2C上面读10byte,回读到buffer里面的内容是纯粹的I2C总线回传的数据,还是有带USB帧的封装包其他数据?

1-我们推荐您使用CH341StreamI2C来处理I2C数据流,CH341StreamI2C是通过调用CH341WriteRead来写、读指定的i2c命令来产生i2c时序


之前的帖子http://wch.cn/bbs/View.asp?T=1&S=101&I=52582 不是说CH341StreamI2C不支持ACK回复吗?


那你应该使用该帖子的方法实现i2c通讯 请使用下面的函数替换 /* ********************************************************************************************** */ /* 例子:兼容IIC总线的通用操作时序 */

BOOL WINAPI IIC_IssueStart( ULONG iIndex ) // 指定CH341设备序号 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG 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, &mLength ) ); // 写出数据块 }

BOOL WINAPI IIC_IssueStop( ULONG iIndex ) // 指定CH341设备序号 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG 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, &mLength ) ); // 写出数据块 }

BOOL WINAPI IIC_OutBlockSkipAck( // 输出数据块,不检查应答 ULONG iIndex, // 指定CH341设备序号 ULONG iOutLength, // 准备写出的数据字节数,单次必须小于29字节 PVOID iOutBuffer ) // 指向一个缓冲区,放置准备写出的数据 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG mLength; if ( iOutLength == 0 || iOutLength > ( mCH341_PACKET_LENGTH - 1 - 1 - 1 ) ) return( FALSE ); mBuffer[ 0 ] = mCH341A_CMD_I2C_STREAM; // 命令码 mBuffer[ 1 ] = (UCHAR)( mCH341A_CMD_I2C_STM_OUT | iOutLength ); // 输出数据,位5-位0为长度 memcpy( &mBuffer[2], iOutBuffer, iOutLength ); // 数据 mBuffer[ 1 + 1 + iOutLength ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = 1 + 1 + iOutLength + 1; return( CH341WriteData( iIndex, mBuffer, &mLength ) ); // 写出数据块 }

BOOL WINAPI IIC_OutByteCheckAck( // 输出一字节数据并检查应答是否有效 ULONG iIndex, // 指定CH341设备序号 UCHAR iOutByte ) // 准备写出的数据 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG mLength, mInLen; mBuffer[ 0 ] = mCH341A_CMD_I2C_STREAM; // 命令码 mBuffer[ 1 ] = mCH341A_CMD_I2C_STM_OUT; // 输出数据,位5-位0为长度,0长度则只发送一个字节并返回应答 mBuffer[ 2 ] = iOutByte; // 数据 mBuffer[ 3 ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = 4; mInLen = 0; if ( CH341WriteRead( iIndex, mLength, mBuffer, mCH341A_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) { // 执行数据流命令,先输出再输入 if ( mInLen && ( mBuffer[ mInLen - 1 ] & 0x80 ) == 0 ) return( TRUE ); // 返回的数据的位7代表ACK应答位,ACK=0有效 } return( FALSE ); }

BOOL WINAPI IIC_InBlockByAck( // 输入数据块,每输入一个字节都产生有效应答 ULONG iIndex, // 指定CH341设备序号 ULONG iInLength, // 准备读取的数据字节数,单次必须小于32字节 PVOID oInBuffer ) // 指向一个缓冲区,返回后是读入的数据 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG mLength, mInLen; if ( iInLength == 0 || iInLength > mCH341A_CMD_I2C_STM_MAX ) return( FALSE ); mBuffer[ 0 ] = mCH341A_CMD_I2C_STREAM; // 命令码 mBuffer[ 1 ] = (UCHAR)( mCH341A_CMD_I2C_STM_IN | iInLength ); // 输入数据,位5-位0为长度 mBuffer[ 2 ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = 3; mInLen = 0; if ( CH341WriteRead( iIndex, mLength, mBuffer, mCH341A_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) { // 执行数据流命令,先输出再输入 if ( mInLen == iInLength ) { memcpy( oInBuffer, &mBuffer[0], iInLength ); // 数据 return( TRUE ); } } return( FALSE ); }

BOOL WINAPI IIC_InByteNoAck( // 输入一字节数据,但是不产生应答 ULONG iIndex, // 指定CH341设备序号 PUCHAR oInByte ) // 指向一个字节的缓冲区,返回后是读入的数据 { UCHAR mBuffer[ mCH341_PACKET_LENGTH ]; ULONG mLength, mInLen; mBuffer[ 0 ] = mCH341A_CMD_I2C_STREAM; // 命令码 mBuffer[ 1 ] = mCH341A_CMD_I2C_STM_IN; // 输入数据,位5-位0为长度,0长度则只接收一个字节并发送无应答 mBuffer[ 2 ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = 3; mInLen = 0; if ( CH341WriteRead( iIndex, mLength, mBuffer, mCH341A_CMD_I2C_STM_MAX, 1, &mInLen, mBuffer ) ) { // 执行数据流命令,先输出再输入 if ( mInLen ) { *oInByte = mBuffer[ mInLen - 1 ]; // 数据 return( TRUE ); } } return( FALSE ); }


那使用上面方法的时候,要发送数据的时候是只要直接调用IIC_OutByteCheckAck等读写操作函数,还是必须得同时调用IIC_IssueStart/Stop函数来操作时序(实际上就是我问的第一个问题)


必须得同时调用IIC_IssueStart/Stop函数来操作时序


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