簡體   English   中英

正確格式化 I2C 數據(Wire.write)

[英]Correctly formatting data for I2C (Wire.write)

我將多個 Arduino Mega 單元連接在一起以創建一組 IO,所有 IO 都由 I2C 總線上的主控器控制。

我讓它與從站一起工作,用模擬輸入等的狀態填充一個字符串,每個字符串用冒號分隔。 然后該字符串將通過Wire.write循環。

最初的reqNo會告訴 master 正在返回哪個批次。 例如,批次 0 將是模擬 0 - 5,批次 1 將是模擬 6 - 11 等。

一切正常,直到進一步閱讀使我看到一篇文章,由於內存使用和相關問題,提倡不要使用字符串。 我試圖重構我的代碼以避免使用字符串,但是,現在我得到這樣的字符串:

:⸮:⸮:⸮:⸮:⸮:⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮⸮W

返回而不是我的預期輸出。

我認為這是編碼問題或類似問題? 任何人都可以就我做錯了什么或實現這一目標的另一種方式提供建議。 非常重要的是,設備可以長時間運行而不會重新啟動或出現任何問題,這就是為什么我非常熱衷於刪除字符串,如果這可能會導致問題。

主碼:

int i=0;
char res[32]="";
while(Wire.available()){
    char c=Wire.read();
    Serial.print(c);
    res[i]=c;
    i++;
}

奴隸代碼:

void requestStatus(){
    int i;
    Wire.write(reqNo);

    if(reqNo==0){
        for(i=0;i<6;i++){
            Wire.write(':');
            Wire.write(analogRead(i));
        }
    }else if(reqNo==1){
        for(i=6;i<12;i++){
            Wire.write(':');
            Wire.write(analogRead(i));
        }
    }else if(reqNo==2){
        for(i=12;i<16;i++){
            Wire.write(':');
            Wire.write(analogRead(i));
        }
    }
    reqNo++;
    if(reqNo==3){
        reqNo=0;
    }
}

您的代碼有兩個問題,首先是:

...
// master side
char c=Wire.read();
...
// slave side            
Wire.write(analogRead(i));

您將整數值當作ASCII編碼對待,而不是。 您必須在某些時候將它們轉換為ASCII(例如,主端)。 考慮使用sscanfsnprintf進行轉換。

其次,您不是用NUL終止 C字符串。

Wire.write(reqNo); 例如,如果您希望這樣做,它將寫一個代碼為0 1或2的字符,而不是字符“ 0”或“ 1”或“ 2”

一切正常,直到進一步閱讀導致我寫過一篇文章,主張由於內存使用和相關問題而反對使用字符串。

我假設它是在談論String對象,而不是c字符串(nul終止的char數組)。
這些使用動態內存分配並導致堆碎片。 C字符串通常是靜態分配的( char res[32]; ),如果在函數內部定義的話,則會從堆棧中徹底清除掉。

write只接受一個字節,具有明確長度的字節數組(或字符)或c字符串。
將其傳遞給int只會將其轉換為字節,並且僅保留低8位。

您需要的是“打印”方法。 它將整數立即轉換為字符。 它不使用String或c字符串。

您應該將所有Wire.write替換為Wire.print

同樣在您的主代碼中,您不會null終止res char數組,這會導致問題,因為字符串沒有顯式結尾。 您還應確保不要在其中寫入超過31個字符(nul終止符也算作一個字符),並且會導致緩沖區溢出。

在Wire.write函數中傳遞它時,您必須將reqNo轉換為char類型

Wire.write((char)(reqNo));

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM