完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
一年前咨询过,因为iic 从机为MCU硬件,在处理主机读取数据时,速度比较慢,会出现连续读取数据时,在上一byte的ACK回复完后1个clk时间内不能释放scl的问题。
现在自己重新写读取函数实现了,如下: 但是此函数因为iic数据流包大小被限制在32byte,所以当我的读取数据连续超过12个byte时,iic数据流超出了32个字节 当我使用两个数据流宝来实现时,两个包之间的时间有200-1200us间隔不等,请问有好的解决办法没有? public bool MulReadIIC(UInt32 iIndex, byte addr, byte reg, Byte[] data, uint data_Len) { byte i = 0; Byte[] mBuffer = new Byte[64]; UInt32 mLength, mInLen; mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STREAM; // 命令码 mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_STA; // 产生起始位 mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_OUT | 2; // mBuffer[i++] = addr; // mBuffer[i++] = reg; // mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_STA; // 产生起始位 mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_OUT; // mBuffer[i++] = (byte)(addr + 1); // 产生起始位 for(byte count=0;count< data_Len-1; count++) { mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_US + 4; // 延时4us mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_IN + 1; // 输入数据,位5-位0为长度,0长度则只接收一个字节并发送无应答 } mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_US + 4; // 延时4us mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_IN; // 输入数据,位5-位0为长度,0长度则只接收一个字节并发送无应答 mBuffer[i++] = USBIOXdll.mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = i; mInLen = 0; USBIOXdll.USBIO_WriteRead(iIndex, mLength, mBuffer, 0x3F, 1, ref mInLen, mBuffer); // 写出数据块 return true; } |
|
相关推荐
1个回答
|
|
您好,可尝试按照如下方式组包,实现发送I2C设备地址后延迟一段时间读数据,以及连续读取数据的时钟之间插入微秒级延迟。如下函数支持长包读写,也即将需要读写的过程拼成长包处理。也可以发邮件给我们获取完整工程用于测试。邮箱:tech@wch.cn
BOOL WINAPI CH341StreamI2C_Delay( // 处理I2C数据流,2线接口,时钟线为SCL引脚,数据线为SDA引脚(准双向I/O),速度约56K字节 ULONG iIndex, // 指定CH341设备序号 ULONG iWriteLength, // 准备写出的数据字节数 PVOID iWriteBuffer, // 指向一个缓冲区,放置准备写出的数据,首字节通常是I2C设备地址及读写方向位 ULONG iReadLength, // 准备读取的数据字节数 PVOID oReadBuffer, // 指向一个缓冲区,返回后是读入的数据 UCHAR iReadDelay1, //地址后的延时,单位US,数值范围:0~15 UCHAR iReadDelay2) //读间隔延时,单位US,数值范围:0~15 { UCHAR mBuffer[ mDEFAULT_COMMAND_LEN + mDEFAULT_COMMAND_LEN / 8 ]; ULONG i, j, mLength; PUCHAR mWrBuf; //if ( dllCH341VerIC[ iIndex ] < 0x20 ) return( FALSE ); // not CH341A mLength = max( iWriteLength, iReadLength ); if ( mLength > mMAX_BUFFER_LENGTH ) return( FALSE ); if ( mLength <= mDEFAULT_BUFFER_LEN ) mWrBuf = (PUCHAR)mBuffer; // 不超过默认缓冲区长度 else { // 超过则需要另外分配内存 mWrBuf = (PUCHAR)LocalAlloc( LMEM_FIXED, mMAX_COMMAND_LENGTH + mMAX_COMMAND_LENGTH / 8 ); // 分配内存 if ( mWrBuf == NULL ) return( FALSE ); // 分配内存失败 } i = 0; mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 命令码 //if ( ( dllCH341StreamMode[ iIndex ] & 0x03 ) == 0 ) { // mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_US | 10; // 延时10微秒 // mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_US | 10; // 延时10微秒 //} mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_STA; // 产生起始位 if ( iWriteLength ) { for ( j = 0; j < iWriteLength; ) { mLength = mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 当前包剩余长度, if ( mLength <= 2 ) { while ( mLength-- ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = mCH341_PACKET_LENGTH; } if ( mLength >= mCH341_PACKET_LENGTH ) { mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 新包的命令码 mLength = mCH341_PACKET_LENGTH - 1; } mLength--; // 去掉尾部的提前结束码 mLength--; // 去掉输出数据的命令码 if ( mLength > iWriteLength - j ) mLength = iWriteLength - j; // 本次输出有效数据长度 mWrBuf[ i++ ] = (UCHAR)( mCH341A_CMD_I2C_STM_OUT | mLength ); // 输出数据,位5-位0为长度 while ( mLength-- ) mWrBuf[ i++ ] = *( (PUCHAR)iWriteBuffer + j++ ); // 复制数据 } } if ( iReadLength ) { mLength = mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 当前包剩余长度, if ( mLength <= 3 ) { while ( mLength-- ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = mCH341_PACKET_LENGTH; } if ( mLength >= mCH341_PACKET_LENGTH ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 新包的命令码 if ( iWriteLength > 1 ) { // 先输出 mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_STA; // 产生起始位 mWrBuf[ i++ ] = (UCHAR)( mCH341A_CMD_I2C_STM_OUT | 1 ); // 输出数据,位5-位0为长度 mWrBuf[ i++ ] = *(PUCHAR)iWriteBuffer | 0x01; // I2C目标设备地址,最低位为1则进行读操作 } else if ( iWriteLength ) { // 输出一字节后直接输入 i--; mWrBuf[ i++ ] = *(PUCHAR)iWriteBuffer | 0x01; // I2C目标设备地址,最低位为1则进行读操作 } mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_US | ( iReadDelay1& 0x0f ); // 延时10微秒 for ( j = 1; j < iReadLength; ) { mLength = mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 当前包剩余长度, //mLength = 1; if ( mLength <= 1 ) { if ( mLength ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = mCH341_PACKET_LENGTH; } if ( mLength >= mCH341_PACKET_LENGTH ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 新包的命令码 //mLength = iReadLength - j >= mCH341A_CMD_I2C_STM_MAX ? mCH341A_CMD_I2C_STM_MAX : iReadLength - j; // 本次输入有效数据长度 mLength = iReadLength - j >= mCH341A_CMD_I2C_STM_MAX ? mCH341A_CMD_I2C_STM_MAX : 1; // 本次输入有效数据长度 mWrBuf[ i++ ] = (UCHAR)( mCH341A_CMD_I2C_STM_IN | mLength ); // 输入数据,位5-位0为长度 j += mLength; if ( mLength >= mCH341A_CMD_I2C_STM_MAX ) { // 当前包将满 mWrBuf[ i ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 i += mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 跳过当前包剩余部分 } mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_US | ( iReadDelay2& 0x0f ); // 延时10微秒 } mLength = mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 当前包剩余长度, if ( mLength <= 1 ) { if ( mLength ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = mCH341_PACKET_LENGTH; } if ( mLength >= mCH341_PACKET_LENGTH ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 新包的命令码 mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_IN; // 输入数据,只接收一个字节并发送无应答 } mLength = mCH341_PACKET_LENGTH - i % mCH341_PACKET_LENGTH; // 当前包剩余长度, if ( mLength <= 1 ) { if ( mLength ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = mCH341_PACKET_LENGTH; } if ( mLength >= mCH341_PACKET_LENGTH ) mWrBuf[ i++ ] = mCH341A_CMD_I2C_STREAM; // 新包的命令码 mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_STO; // 产生停止位 mWrBuf[ i++ ] = mCH341A_CMD_I2C_STM_END; // 当前包提前结束 mLength = 0; if ( iReadLength ) j = CH341WriteRead( iIndex, i, mWrBuf, mCH341A_CMD_I2C_STM_MAX, ( iReadLength + mCH341A_CMD_I2C_STM_MAX - 1 ) / mCH341A_CMD_I2C_STM_MAX, &mLength, oReadBuffer ); // 执行数据流命令,先输出再输入 else j = CH341WriteData( iIndex, mWrBuf, &i ); // 写出数据块 if ( j && mLength != iReadLength ) j = FALSE; if ( mWrBuf != mBuffer ) LocalFree( mWrBuf ); // 如果是分配的内存则释放 return( j ); } |
|
|
|
只有小组成员才能发言,加入小组>>
518 浏览 1 评论
CH579M+RT-Thread,RTC从Sleep模式唤醒失败是什么原因?
2901 浏览 2 评论
2397 浏览 1 评论
862浏览 2评论
CH32F103C8T6使用当前官网上的CDC例程会出现设备描述符请求失败
403浏览 1评论
681浏览 1评论
riscv-none-embed-objcopy: \'PWM_Output.elf\': No such file这个咋解决,
413浏览 1评论
516浏览 1评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-12-21 21:46 , Processed in 0.869349 second(s), Total 47, Slave 40 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号