如題,我在使用CH341進(jìn)行I2C通訊,使用PmBus協(xié)議,但是在讀取較多數(shù)據(jù)時(shí)經(jīng)??ㄋ?,4個(gè)6個(gè)字節(jié)短一點(diǎn)的都可以,多了的話如20個(gè)25個(gè)都不行了。其他情況如讀寫字節(jié)或字均正常,請問有什么解決辦法嗎?
您好,可以把完整測試代碼發(fā)下,我們協(xié)助您看下是否為代碼調(diào)用問題導(dǎo)致。此外,您反饋的卡死是API發(fā)生阻塞嗎?如是,此時(shí)設(shè)備管理器中設(shè)備狀態(tài)是否正常?
????你好,下面是我的C#代碼
public?SmbusStatus?BlockRead(byte?cmd,?ref?byte[]?data,?byte?dataLen,?bool?bPec) { byte[]?txBuffer?=?new?byte[10]; byte[]?rxBuffer?=?new?byte[512]; byte?txLength?=?0; byte?rxLength?=?bPec???(byte)(dataLen?+?2):?(byte)(dataLen?+?1); try { //?Write?SlaveAddress?and?Cmd,?ReadAddress?will?be?sent?automatically?to?fetch?data txBuffer[txLength++]?=?NodeId; txBuffer[txLength++]?=?cmd; Marshal.Copy(txBuffer,?0,?ptrTx,?txLength); if?(!CH341StreamI2C_Delay(DevIndex,?txLength,?ptrTx,?rxLength,?ptrRx,?0,?0,?60,?0))//?動態(tài)延時(shí) { return?SmbusStatus.I2cError; } else?if(rxLength?>?2)//?CNT?+?DATA?+?PEC { Marshal.Copy(ptrRx,?rxBuffer,?0,?rxLength); //?validate?CRC if?(bPec) { byte[]?crcBuffer?=?new?byte[256]; crcBuffer[0]?=?NodeId; crcBuffer[1]?=?cmd; crcBuffer[2]?=?(byte)(NodeId?+?1); crcBuffer[3]?=?rxBuffer[0];//data?cnt for?(uint?i?=?0;?i?<?rxBuffer[0];?i++) { crcBuffer[4?+?i]?=?rxBuffer[i+1]; } if?(rxBuffer[rxLength-1]?!=?(byte)CRC(CRC_8,?crcBuffer,?0,?(byte)(4?+?dataLen))) { return?SmbusStatus.PecError; } } //?return?received?byte,?except?cnt?and?rec for?(uint?i?=?0;?i?<?dataLen;?i++) { data[i]?=?rxBuffer[1?+?i]; } return?SmbusStatus.Successful; } else { return?SmbusStatus.I2cError; } } catch { return?SmbusStatus.I2cError; } }
????我在使用您之前提供的博客中的CH341StreamI2C_Delay代碼后返回FALSE,多讀取幾次之后API卡死,需要重新插拔CH341設(shè)備才能退出GUI。
????在我第一次調(diào)用讀取函數(shù)時(shí)可以用邏輯分析儀看到收發(fā)的數(shù)據(jù),仿真查看嵌入式設(shè)備的回復(fù)正常,但CH341回讀回來的數(shù)據(jù)似乎是錯(cuò)的
????以下是正?;貜?fù)數(shù)據(jù):
抱歉,上面的數(shù)據(jù)解析似乎是RIGOL的邏輯分析功能解析數(shù)據(jù)時(shí)錯(cuò)位了,請幫我看下API卡死的問題就好,謝謝。
您好,可以把完整的代碼工程發(fā)到我們技術(shù)郵箱,我們工程師同步試下。郵箱地址:tech@wch.cn。
好的,感謝,我在這兒同步貼下我的CH341StreamI2C_Delay代碼,這通訊搞得確實(shí)頭疼,只剩下這一個(gè)問題沒解決了。
#define?CH341_TX_LEN_MAX????32??//每包數(shù)據(jù)最多發(fā)送的數(shù)據(jù)長度,最大32 inline?UCHAR?CH341_DELAY_US(PUCHAR?mBuf,?UCHAR?uDelay) { ????UCHAR?i?=?0; ????while?(uDelay?>?mCH341A_CMD_I2C_STM_DLY) ????{ ????????mBuf[i++]?=?mCH341A_CMD_I2C_STM_US?|?mCH341A_CMD_I2C_STM_DLY;?//?延時(shí)15微秒 ????????uDelay?-=?mCH341A_CMD_I2C_STM_DLY; ????} ????if?(uDelay?>?0) ????????mBuf[i++]?=?mCH341A_CMD_I2C_STM_US?|?(uDelay?&?0x0f);?//?填入剩余的延遲 ????return?i; } inline?UCHAR?CH341_DELAY_MS(PUCHAR?mBuf,?UCHAR?uDelay) { ????UCHAR?i?=?0; ????while?(uDelay?>?mCH341A_CMD_I2C_STM_DLY) ????{ ????????mBuf[i++]?=?mCH341A_CMD_I2C_STM_MS?|?mCH341A_CMD_I2C_STM_DLY;?//?延時(shí)15毫秒 ????????uDelay?-=?mCH341A_CMD_I2C_STM_DLY; ????} ????if?(uDelay?>?0) ????????mBuf[i++]?=?mCH341A_CMD_I2C_STM_MS?|?(uDelay?&?0x0f);?//?填入剩余的延遲 ????return?i; } BOOL?WINAPI?CH341StreamI2C_Delay( ????ULONG?iIndex,??????????//?指定CH341設(shè)備序號 ????ULONG?iWriteLength,????//?準(zhǔn)備寫出的數(shù)據(jù)字節(jié)數(shù) ????PVOID?iWriteBuffer,????//?指向一個(gè)緩沖區(qū),放置準(zhǔn)備寫出的數(shù)據(jù),首字節(jié)通常是I2C設(shè)備地址及讀寫方向位 ????ULONG?iReadLength,?????//?準(zhǔn)備讀取的數(shù)據(jù)字節(jié)數(shù) ????PVOID?oReadBuffer,?????//?指向一個(gè)緩沖區(qū),返回后是讀入的數(shù)據(jù) ????UCHAR?iWriteDataDelay,?//?連續(xù)寫數(shù)據(jù)之間的延時(shí),單位US,數(shù)值范圍:0~15 ????UCHAR?iAddrDelay1,?????//?寫地址到讀地址之間的延時(shí),單位US,數(shù)值范圍:0~15 ????UCHAR?iAddrDelay2,?????//?讀地址和讀數(shù)據(jù)的延時(shí),單位US,數(shù)值范圍:0~15 ????UCHAR?iReadDataDelay)??//?連續(xù)讀數(shù)據(jù)之間的延時(shí),單位US,數(shù)值范圍:0~15 { ????UCHAR?mBuffer[mDEFAULT_COMMAND_LEN?+?mDEFAULT_COMMAND_LEN?/?8]; ????UCHAR?mBufferTemp[mDEFAULT_COMMAND_LEN?+?mDEFAULT_COMMAND_LEN?/?8]; ????ULONG?i,?j,?mLength; ????PUCHAR?mWrBufTemp,mWrBuf; ????//?內(nèi)存分配 ????mLength?=?max(iWriteLength,?iReadLength); ????if?(mLength?>?mMAX_BUFFER_LENGTH) ????????return?(FALSE); ????if?(mLength?<=?mDEFAULT_BUFFER_LEN)//?不超過默認(rèn)緩沖區(qū)長度 ????{ ????????mWrBuf?=?(PUCHAR)mBuffer; ????????mWrBufTemp?=?(PUCHAR)mBufferTemp; ????} ????else?//?超過則需要另外分配內(nèi)存 ????{ ????????mWrBuf?=?(PUCHAR)LocalAlloc(LMEM_FIXED,?mMAX_COMMAND_LENGTH?+?mMAX_COMMAND_LENGTH?/?8);?//?分配內(nèi)存 ????????mWrBufTemp?=?(PUCHAR)LocalAlloc(LMEM_FIXED,?mMAX_COMMAND_LENGTH?+?mMAX_COMMAND_LENGTH?/?8);?//?分配內(nèi)存 ????????if?((mWrBuf?==?NULL)?||?(mWrBufTemp?==?NULL)) ????????????return?(FALSE);?//?分配內(nèi)存失敗 ????} ????//?填充發(fā)送數(shù)據(jù) ????i?=?0; ????//mWrBufTemp[i++]?=?mCH341A_CMD_I2C_STREAM;??//?命令碼,從次字節(jié)開始為I2C命令流 ????mWrBufTemp[i++]?=?mCH341A_CMD_I2C_STM_STA;?//?產(chǎn)生起始位 ????//?填入發(fā)送數(shù)據(jù) ????j?=?0; ????while?(j?<?iWriteLength) ????{ ????????//?填入一個(gè)字節(jié)的數(shù)據(jù) ????????mWrBufTemp[i++]?=?(UCHAR)(mCH341A_CMD_I2C_STM_OUT?|?0x01);?//?輸出數(shù)據(jù),位5-位0為長度 ????????mWrBufTemp[i++]?=?*((PUCHAR)iWriteBuffer?+?j++);?//?復(fù)制地址 ????????i?+=?CH341_DELAY_US(&mWrBufTemp[i],?iWriteDataDelay); ????} ????if?(iReadLength?>?0) ????{ ????????//?填入讀地址與寫地址之間的延遲 ????????i?+=?CH341_DELAY_US(&mWrBufTemp[i],?iAddrDelay1); ????????//?填入讀地址 ????????mWrBufTemp[i++]?=?mCH341A_CMD_I2C_STM_STA;?//?產(chǎn)生起始位 ????????mWrBufTemp[i++]?=?(UCHAR)(mCH341A_CMD_I2C_STM_OUT?|?0x01);?//?輸出數(shù)據(jù),位5-位0為長度 ????????mWrBufTemp[i++]?=?*(PUCHAR)iWriteBuffer?|?0x01;?//?I2C目標(biāo)設(shè)備地址,最低位為1則進(jìn)行讀操作 ????????//?填入讀地址與讀數(shù)據(jù)之間的延遲 ????????i?+=?CH341_DELAY_US(&mWrBufTemp[i],?iAddrDelay2); ????????//?填入讀數(shù)據(jù) ????????for?(j?=?0;?j?<?(iReadLength?-?1);?j++) ????????{ ????????????mWrBufTemp[i++]?=?(UCHAR)(mCH341A_CMD_I2C_STM_IN?|?1);????????????????????????????//?輸入數(shù)據(jù),位5-位0為長度 ????????????i?+=?CH341_DELAY_US(&mWrBufTemp[i],?iReadDataDelay); ????????} ???????? ????????//?填入最后一個(gè)字節(jié)并發(fā)送無應(yīng)答 ????????mWrBufTemp[i++]?=?(UCHAR)mCH341A_CMD_I2C_STM_IN;????????????????????????????//?輸入數(shù)據(jù),位5-位0為長度 ????????i?+=?CH341_DELAY_US(&mWrBufTemp[i],?iReadDataDelay); ????} ????//?填入結(jié)束命令 ????mWrBufTemp[i++]?=?mCH341A_CMD_I2C_STM_STO;????//?產(chǎn)生停止位 ????mWrBufTemp[i++]?=?mCH341A_CMD_I2C_STM_END;????//?當(dāng)前包提前結(jié)束 ????//?復(fù)制臨時(shí)數(shù)組到發(fā)送數(shù)組,并按照指定長度分割 ????mLength?=?i;//?待分配字節(jié)數(shù) ????i?=?0;//?mWrBufTemp序列號 ????j?=?0;//?mWrBuf序列號 ????while?(mLength?>?(CH341_TX_LEN_MAX?-?1)) ????{ ????????mWrBuf[j++]?=?mCH341A_CMD_I2C_STREAM;??//?命令碼,從次字節(jié)開始為I2C命令流 ????????memcpy(&mWrBuf[j],?&mWrBufTemp[i],?(CH341_TX_LEN_MAX?-?1));???//?填充所有數(shù)據(jù) ????????j?+=?(CH341_TX_LEN_MAX?-?1); ????????i?+=?(CH341_TX_LEN_MAX?-?1); ????????mLength?-=?(CH341_TX_LEN_MAX?-?1); ????} ????//?復(fù)制最后的不足指定長度的數(shù)據(jù) ????mWrBuf[j++]?=?mCH341A_CMD_I2C_STREAM;??//?命令碼,從次字節(jié)開始為I2C命令流 ????memcpy(&mWrBuf[j],?&mWrBufTemp[i],?mLength);???//?填充所有數(shù)據(jù) ????j?+=?mLength; ????mLength?=?0; ????//?Write?&?Read ????if?(iReadLength) ????????i?=?CH341WriteRead(iIndex,?j,?mWrBuf,?CH341_TX_LEN_MAX,?(iReadLength?+?CH341_TX_LEN_MAX?-?1)?/?CH341_TX_LEN_MAX,?&mLength,?oReadBuffer);?//?執(zhí)行數(shù)據(jù)流命令,先輸出再輸入 ????else ????????i?=?CH341WriteData(iIndex,?mWrBuf,?&j);?//?寫出數(shù)據(jù)塊 ????//?檢測是否讀回所需數(shù)據(jù) ????if?(i?&&?mLength?!=?iReadLength) ????????i?=?FALSE; ????//?釋放分配的內(nèi)存 ????if?(mWrBuf?!=?mBuffer) ????{ ????????LocalFree(mWrBuf); ????????LocalFree(mWrBufTemp); ????} ????return?(i); }
? 這兩天測試下來發(fā)現(xiàn)確實(shí)是CH341WriteRead這個(gè)API有BUG,每次點(diǎn)擊讀數(shù)據(jù)時(shí),前32個(gè)數(shù)據(jù)發(fā)送和讀取均正常,從第二個(gè)數(shù)據(jù)流開始時(shí)鐘信號發(fā)送的越來越晚,到第三次重新讀數(shù)據(jù)第二個(gè)數(shù)據(jù)流干脆就沒有時(shí)鐘信號產(chǎn)生了。
? 我試過更換CH341DLL.LIB庫版本也沒有用,所以想請教下有沒有什么解決辦法?或者能提供CH341WriteRead的源碼以便我自行修改嗎?
? 真的很急,謝謝!
? 聯(lián)系方式:個(gè)人信息保護(hù),已隱藏
補(bǔ)貼
增加了讀數(shù)據(jù)復(fù)位操作以防卡死
//?檢測是否讀回所需數(shù)據(jù) if?(i?&&?mLength?!=?iReadLength) { CH341ResetRead(iIndex);//復(fù)位讀操作以防下次讀數(shù)據(jù)卡死 i?=?FALSE; }
未加CH341ResetRead復(fù)位讀操作前第一個(gè)信號流能讀到數(shù)據(jù),第二個(gè)信號流讀不到。
加上之后在復(fù)位之后CH341才正常產(chǎn)生了時(shí)鐘信號,后續(xù)第二個(gè)信號流的數(shù)據(jù)用示波器抓到了
您好,工程師已添加您微信,后續(xù)有問題可隨時(shí)溝通。