- 12V Akku mit 280 Ah bauen         
Ergebnis 1 bis 9 von 9

Thema: I²C Bus - Erklärung zu I2CTWI_transmit3Bytes

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    26.10.2008
    Ort
    Wien
    Alter
    43
    Beiträge
    38

    I²C Bus - Erklärung zu I2CTWI_transmit3Bytes

    Anzeige

    Powerstation Test
    Hi Leute,

    die Funktion I2CTWI_transmitByte verstehe ich ja grundsätzlich... einfach 1 Byte an eine Adresse senden...

    die Funktion I2CTWI_transmit3Bytes verstehe ich demnach ja auch... nur steht ja in der Anleitung, dass hier Daten im Format "Slave Adresse – Kommandoregister – Kommando – Parameter1" gesendet werden.

    Kann mir das bitte jmd genauer erklären! (Slave Adresse ist mir übrigens klar )

    Nur wie kann man sich etwas unter Kommandoregister, Kommando & Parameter1 vorstellen? Könnte man das in einer Excel-Tabelle darstellen!?

    P.S.: RP6_Manuel Seite 108

    THX

  2. #2
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Der 3-Byte-Befehl sendet natürlich auch nur drei Bytes an einen Slave. Wie diese Bytes gedeutet werden hängt vom Aufbau des Protokolls ab. Viele I2C-Bausteine besitzen intern verschiedene Register die man mit Werten füllen muss. Deshalb steht in meiner RP6-Anleitung (vom 17.7.07) auf Seite 107 folgendes:
    Diese Funktion braucht man häufig, denn viele I²C Geräte erwarten die Daten im Format:
    Slave Adresse – Registeradresse – Daten

    void I2CTWI_transmit3Bytes(uint8_t adr, uint8_t data1, uint8_t data2, uint8_t data3)
    Alles klar?

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  3. #3
    Benutzer Stammmitglied
    Registriert seit
    26.10.2008
    Ort
    Wien
    Alter
    43
    Beiträge
    38
    Danke mal für den ersten Hilfeversuch...

    Dass der Befehl auch nur 3 Bytes sendet war mir auch klar... aber was bedeutet das in meinem Beispiel? Ich verwende das RP6 Controll M32 als Master und das RP6 Robot Base als Slave.

    Habe an den Libs auch nix geändert... also alles "Auslieferungszustand".

    Geladen hab ich in den Master das Beispielprogramm "RP6Control_06_I2CMaster"...

    Und unklar ist mir die Zeile 204 -> I2CTWI_transmit3Bytes(I2C_RP6_BASE_ADR, 0, 3, counter);

    Also schreibt der Master in meinem Beispiel bei Tastendruck als erstes eine
    eine 1 in das Komandoregister 0, Kommando 3 auf Paramter 1.

    Beim nächsten Tastendruck eine 2 in das Komandoregister 0, Kommando 3 auf Paramter 1... usw...

    Und um auf meine Frage zurückzukommen,... ich verstehe noch
    immer niocht was in mienem Fall Komando Register bzw. Komando bedeutet - sorry

  4. #4
    Benutzer Stammmitglied
    Registriert seit
    26.10.2008
    Ort
    Wien
    Alter
    43
    Beiträge
    38
    oder probieren wir es mal anders: kann mir jemand den code so umschreiben, dass ich ihn auf das Erweiterungsboard spiele... am RP6 Basis möchte ich die mitgelieferte "RP6Base_I2CSlave"-Datei verwenden!

    Vielleicht würde ich mir an Hand eines Beispiels leichter tun!?

    Code:
    //  ***************************************************************************************
    //
    //  Steuerbar sind:
    
    //    - LED an ADC1 - "einfache Helligkeitssteuerung" über eine Fernbedienung
    //
    //  ---------------------------
    //
    //  Stand: 03.12.2009
    //
    //  *************************************************************************************** 
    
    
    #include "RP6RobotBaseLib.h" 
    
    uint8_t led_rechts_high = 20;				// ADC1 20ms auf high
    uint8_t led_rechts_low = 20;				// ADC1 20ms auf low
    
    void receiveRC5Data (RC5data_t rc5data)
    {
      
      switch (rc5data.key_code)
      {
      
    	// LED auf ADC1 heller oder dünkler
    	
    	case 10:
    	  if (led_rechts_high < 40)
    	  {
    	    led_rechts_high++;
    		led_rechts_low--;
    	  }
    	break;
    	
    	case 62:
    	  if (led_rechts_high > 0)
    	  {
    	    led_rechts_high--;
    		led_rechts_low++;
    	  }
    	break;
    
      }
    
    }
    
    
    void led_rechts (void)
    {
      PORTA |= ADC1;										// ADC1 auf High setzen
      sleep(led_rechts_high);
      PORTA &=~ADC1;										// ADC1 auf Low setzen
      sleep(led_rechts_low);							
    }
    
    
    // -------------------------------------------------------------------------------------
    // -------------------------------------------------------------------------------------
    // -------------------------------------------------------------------------------------
    
    
    int main(void) 
    { 
       
      initRobotBase();										// AVR Microcontroller initialisieren
      powerON();											// ACS, IRCOMM und Motorregelung einschalten
      
      IRCOMM_setRC5DataReadyHandler(receiveRC5Data);		// Event Handler für IRCOMM starten
      
      DDRA |= ADC1;											// ADC1 als Ausgang definieren
    
      
      while(true) 
      { 
        task_RP6System();
    	led_rechts();
      }  
      return 0; 
    }
    THX

  5. #5
    Moderator Robotik Visionär Avatar von radbruch
    Registriert seit
    27.12.2006
    Ort
    Stuttgart
    Alter
    61
    Beiträge
    5.799
    Blog-Einträge
    8
    Hallo

    Ich bin mir nicht ganz sicher ob ich dein Problem verstanden habe. Du willst eine LED am ADC1-Pin der Base dimmen und den PWM-Wert dafür vom M32 per I²C senden? Dann initialisierst du die Base als Slave, sendest mit dem M32 ein Byte das die Base einließt und zur LED weiterleitet:
    void I2CTWI_transmitByte(uint8_t adr, uint8_t helligkeit)

    Bei einer zusätzlichen LED an ADC0 könnte man nun ein zweites Byte übertragen das die entsprechende LED kennzeichnet:
    void I2CTWI_transmit2Bytes(uint8_t adr, uint8_t led_nummer, uint8_t helligkeit)

    Und nun wollen wird die LEDs noch zusätzlich mit 1 Hz blinken lassen:
    void I2CTWI_transmit3Bytes(uint8_t adr, uint8_t led_nummer, uint8_t helligkeit, uint8_t blinken_1hz)

    Nun haben led_nummer, helligkeit und blinken_1hz für uns einen Sinn, für I²C sind es aber weiterhin normale Bytes. Wir hätten sie natürlich auch Kommandoregister, Kommando oder Parameter nennen können.

    Oje, es wird leider nicht besser...

    Gruß

    mic
    Bild hier  
    Atmel’s products are not intended, authorized, or warranted for use
    as components in applications intended to support or sustain life!

  6. #6
    Benutzer Stammmitglied
    Registriert seit
    26.10.2008
    Ort
    Wien
    Alter
    43
    Beiträge
    38
    1. Du liegst mit deiner Annahme richtig (Led soll gedimmt werden über PWM, usw...)

    2. Danke für deinen Denkansatz - komme schön langsam dahinter wie's geht und habe deshalb mal versucht ein ganz einfaches Programm zu schreiben, welches den I2C Bus verwendet - im Grunde genommen ist ja eh nix dabei... verstehen muss man's nur einmal

    3. Also, der Master-Code sieht so aus:

    Code:
    #include "RP6ControlLib.h"
    
    #include "RP6I2CmasterTWI.h"
    
    void I2C_transmissionError(uint8_t errorState)
    {
    	writeString_P("\nI2C ERROR - TWI STATE: 0x");
    	writeInteger(errorState, HEX);
    	writeChar('\n');
    }
    
    /*****************************************************************************/
    /*****************************************************************************/
    
    int main(void)
    {
    	initRP6Control(); 
    
    	initLCD();
    
    	I2CTWI_initMaster(100);
    
    	I2CTWI_setTransmissionErrorHandler(I2C_transmissionError);
    
        uint8_t adresse = 10;
    	uint8_t data1_master = 0;
    	uint8_t data2_master = 50;
    	uint8_t data3_master = 80;
    
    	while(true) 
    	{
    		uint8_t key = checkReleasedKeyEvent(); 
    		
    		if(key)
    		{
    			switch(key)
    			{
    				case 1:
    				  I2CTWI_transmit3Bytes(adresse, data1_master, data2_master, data3_master);
    				break;
    			}
    		}
    	}
    	return 0;
    }
    Der Slave-Code so:

    Code:
    #include "RP6RobotBaseLib.h"
    #include "RP6I2CslaveTWI.h"
    
    int main(void)
    {
      initRobotBase();
      I2CTWI_initSlave(10);
      powerON();
      
      uint8_t data1_slave;
      uint8_t data2_slave;
      uint8_t data3_slave;
      
      
      while(true)
      {
        if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy)
        {
          data1_slave = I2CTWI_writeRegisters[0];
    	  data2_slave = I2CTWI_writeRegisters[1];
    	  data3_slave = I2CTWI_writeRegisters[2];
      
          writeString_P("data1_slave: ");writeInteger(data1_slave, DEC);writeChar('\n');
    	  writeString_P("data2_slave: ");writeInteger(data2_slave, DEC);writeChar('\n');
    	  writeString_P("data3_slave: ");writeInteger(data3_slave, DEC);writeChar('\n');
          writeChar('\n');
    	  
          I2CTWI_writeRegisters[0] = 0;
      
        }
      }
    
    return 0;
    }
    Frage A) Eigentlich funzt alles. Nur verstehe ich nicht, warum wenn ich für data1_master=0, für data2_master=50 und für data3_master 80 verwende, dass der Slave dann aber in der Ausgabe (Terminal)

    data1_slave: 50
    data2_slave: 80
    data3_slave: 0

    ausgibt!?

    Sollte doch eigentlich

    data1_slave: 0
    data2_slave: 50
    data3_slave: 80

    ausgeben, oder?

    Frage B) Und warum muss der Wert "data1_master" unbedingt 0 (Null) sein? Ansonsten funztt mein Beispielprogramm nämlich nicht!?

    Aber ich denke, ich komme der Sache schön langsam näher..

  7. #7
    Erfahrener Benutzer Robotik Einstein Avatar von Dirk
    Registriert seit
    30.04.2004
    Ort
    NRW
    Beiträge
    3.803
    Hallo aircode,

    wenn du Daten vom Master zum Slave übertragen willst, muss beim Empfänger (Slave) ja klar sein, wann er die "richtigen" Daten hat.

    Dazu kann man I2CTWI_writeRegisters[0] benutzen. Ist das erste gesendete Byte z.B. != 0, wird es in data1_slave übernommen und die weiteren Bytes aus I2CTWI_writeRegisters[n] (N = 1..max. Bytezahl) in die Variablen dataX_slave. Das klappt so nur, wenn I2CTWI_writeRegisters[0] sofort auf 0 gesetzt wird, wenn es als != 0 empfangen wurde.
    Und man fragt dann den Wert von data1_slave ab, um zu klären, ob die Daten verwendet werden können.
    Man kann z.B. als erstes 99 senden, beim Slave testet man dann im Zweig
    if(I2CTWI_writeRegisters[0] && !I2CTWI_writeBusy),
    ob data1_slave 99 ist.
    Wenn ja, können die weiteren Daten ausgegeben werden.

    Also: Bei dieser Form des Empfangs kann man das 1. Byte (bei dir data1_master) nicht als 1. Datenbyte nehmen, sondern es dient quasi als Startmarke und Erkennung, dass jetzt die Daten kommen.

    Sieh dir in der Anleitung zum RP6 das Beispiel auf S. 106 noch einmal an!

    Gruß Dirk

  8. #8
    Benutzer Stammmitglied
    Registriert seit
    26.10.2008
    Ort
    Wien
    Alter
    43
    Beiträge
    38
    OK, also sagen wir mal so... ich habe mich damit abgefunden

    erstes Byte also als Startmarke, alle weiteren Bytes kann ich verwenden. Hab auch schon jetzt Programme geschrieben, wo ich das so verwende!

    Danke mal für eure Hilfe...

    Aircode

  9. #9
    Erfahrener Benutzer Roboter Genie Avatar von SlyD
    Registriert seit
    27.11.2003
    Ort
    Paderborn
    Alter
    39
    Beiträge
    1.516
    Beim normale I2C Slave Programm was bei den Beispielprogrammen dabei ist, wird Register 0 als Kommandoregister verwendet - Kommando 5 steht dann z.B. für "CMD_MOVE_AT_SPEED" also Geschwindigkeit setzen und als Parameter folgen die neuen Geschwindigkeitswerte für links und rechts...

    MfG,
    SlyD

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •  

MultiPlus Wechselrichter Insel und Nulleinspeisung Conrad