Znaczenie cmd param w write_i2c_block_data

12

Testuję komunikację i2c między Pi a Arduino.

Doktor mówi:

write_i2c_block_data(addr,cmd,vals)  Block Write transaction.    int addr,char cmd,long[]    None

Mam ten test:

Na Pi:

import smbus
bus = smbus.SMBus(0)
bus.write_i2c_block_data(address, 48, [49, 50, 51] )

W Arduino:

void receiveData(int byteCount){
    Serial.print("byte count=");
    Serial.println(byteCount);

    while(Wire.available()) {
        number = Wire.read();
        Serial.print((char)number);
     }
}

Na Arduino widzę ten wynik:

byte count=4
0123

Moje pytanie brzmi: do czego służy ten cmdparametr? Nie widzę rozróżnienia na Arduino, którego bajt reprezentuje co.
Chyba mogę sobie z tym poradzić, jak się wydaje. Może chcę użyć pierwszych 2 bajtów jako polecenia.

Na tej stronie nie ma zbyt wiele informacji na temat metody: http://wiki.erazor-zone.de/wiki:linux:python:smbus:doc

Gus Smith
źródło
Możesz określić, jaki cmdjest parametr ... Musiałem sporo się zastanowić, żeby zrozumieć, co masz na myśli. Nie znalazłem jednak odpowiedzi ... Może być używana tylko przez określone układy, takie jak ekspander GPIO lub coś w tym stylu
Butters,
Ok, dodałem link do dokumentacji (co nie jest wiele)
Gus Smith,
6
Nie mam teraz czasu na udzielenie pełnej odpowiedzi (mam nadzieję, że ktoś to zrobi), ale w skrócie - tak działa I²C. Master może po prostu wysłać mu kilka bajtów danych (po wysłaniu właściwego adresu) i nie ma specyfikacji, jakie są te bajty (ich znaczenie jest zdefiniowane dla każdego urządzenia). Zdarza się, że pierwszy bajt jest często numerem polecenia (lub rejestru). Również zawsze masz wysłać przynajmniej jeden bajt tak niepodobne vals, cmdjest obowiązkowe.
Krzysztof Adamski
1
@KrzysztofAdamski To brzmi dla mnie jak kompletna odpowiedź.
Butters,

Odpowiedzi:

9

I²Cprotokół jest bardzo prosty. Tak naprawdę nie definiuje struktur danych przesyłanych przewodowo. Ramka składa się z adresu podrzędnego (z bitem kierunku wskazującym, czy master chce czytać lub zapisywać) oraz (w przypadku zapisu) niektórych bajtów danych. Ponieważ nie ma sensu inicjowanie zapisu z 0 bajtami danych, pierwszy bajt jest obowiązkowy.

Ten pierwszy bajt jest często używany jako adres rejestru podrzędnego lub numer polecenia, ale nie musi. Po pierwszym mogą istnieć dodatkowe bajty. Protokół wyższego poziomu definiujący znaczenie każdego bajtu jest specyficzny dla urządzenia.

To może wyjaśniać, dlaczego istnieją dwa oddzielne argumenty - pierwszy ( cmd) jest obowiązkowy, a drugi ( vals) jest opcjonalny. Chociaż twój przykład jest w Pythonjęzyku, użyty tutaj interfejs API jest w rzeczywistości bardzo ścisłym odwzorowaniem oryginalnego Cinterfejsu API, w którym nie można łatwo utworzyć opcjonalnych argumentów.

Krzysztof Adamski
źródło
To jest trochę dłuższe wyjaśnienie tego, co napisałem w komentarzu pod pytaniem.
Krzysztof Adamski,
Cieszę się że zrobiłeś! Tego rodzaju proste, a jednak „aha!” wyjaśnienia są czasami bardzo pomocne, jak dzisiaj :-)
uhoh
3

Kiedy wydajesz blokowy zapis / odczyt z Pi za pomocą:

bus.write_i2c_block_data(address, 48, [49, 50, 51] )

lub

bus.read_i2c_block_data(address, 48, [49, 50, 51] )

Dwie rzeczy dzieją się (mogą) na Arduino w zależności od odczytu lub zapisu.

Bajt cmd jest pierwszym bajtem zapisanym na magistrali I2C z Pi, zawsze jest wysyłany jako żądanie „zapisu”. Oznacza to, że jeśli Pi wydaje a

bus.read_i2c_block_data

lub

bus.write_i2c_block_data

najpierw pisze

cmd

do magistrali I2C zanim to czyta .

Jest to przydatna funkcja, ponieważ niektóre urządzenia I2C wymagają inicjalizacji przed odczytem.

W Arduino oznacza to, że:

Po pierwsze,

Wire.onReceive(yourCallback)

funkcja jest wywoływana, ponieważ cmdzostała napisana do magistrali przez Pi. cmdbędzie pierwszym bajtem dostępnym w autobusie. Jeśli Pi wysłał żądanie zapisu, Arduino pozostanie w wywołaniu zwrotnym Wire.onReceive, dopóki funkcja nie zostanie zakończona. Jeśli Pi wysłał żądanie odczytu, Arduino dokończy Wire.onReceive, a następnie wywoła callback Wire.onRequest.

Musisz upewnić się, że wartość umieszczona w cmd nie powoduje niezamierzonego zachowania w systemie, odpowiednio obsługując jej wartość. Jeśli na przykład Twoje wywołanie zwrotne Wire.onReceive wyłącza diodę LED, gdy Wire.read = 0x30. Wtedy nawet jeśli wysłałeś żądanie odczytu , najpierw wyłączyłoby diodę LED pisząc 0x30, a następnie odczytałoby żądane bajty z magistrali.

deltatango
źródło
1

Piszę do I2C LCD, Newhaven NHD ‐ 0216K3Z ‐ FL ‐ GBW ‐ V3. Jego arkusz specyfikacji można przeglądać w Google. W takim przypadku, gdy bajt polecenia ma wartość 0xfe, oznacza to, że następujący bajt jest poleceniem - jest ich około 20. Wyczyść, podświetlenie, migający kursor i tak dalej. Jeśli cmd nie jest 0xfe, to tylko jakiś znak do wyświetlenia.

psich zaprzęgów
źródło