Keine korrekten Werte in der I2C-Schnittstelle in Atmega

Ich bin sehr neu im Konzept von I2C und hatte einige Probleme bei der Verbindung von I2C zwischen 2 Atmega32 (s).

  • Ich habe einen Atmega32 als Master, an den ein LCD-Bildschirm angeschlossen ist, und einen anderen I2C als Slave, an den ein LM35 angeschlossen ist, und beide Atmega wurden mit den SDA- und SCL-Leitungen verbunden.

  • Obwohl ich Daten auf dem an den
    Master angeschlossenen LCD-Bildschirm erhalte, erhalte ich nicht die richtigen Werte. Als wäre die Temperatur hier 28 Grad Celsius, aber das LCD, das mit dem Master verbunden ist, wiederholt
    aus irgendeinem Grund ständig 65280. Kann mir jemand sagen, wo ich falsch liege? Der Code für die Master- und Slave-Geräte wurde
    unten veröffentlicht.


Der Mastercode:

int main(void)
{
    unsigned int xx=0x00;
    unsigned char yy;
    DDRA=0xff;
    I2C_init(); //I2C initialization
    lcd_init(); //LCD initialization
    while(1)
    {
        for (int i=0;i<4;i++) //Getting unsigned int data from slave, so
        {                     //broke data into 4 parts and receiving 
            if (i==0)         //one byte at a time. 
            {
                I2C_start(0x01);  //I2C start along with the address of the slave
                yy=I2C_read_ack(); //Read slave data along with an acknowledgment 
                xx |= (yy << 8);    
                I2C_stop(); //I2C stop function.
            }
            else if (i>0)
            {
                I2C_start(0x01+1); //don't know any particular reason
                yy=I2C_read_ack(); //behind this, but if i don't do 0x01+1
                xx |= (yy << 8);   //then the master ends up reading the
                I2C_stop();        //address as a data packet.
            }
        }
     lcd_num(xx);   //lcd function to display unsigned int data.
    }
}

Der Slave-Code:

Der Slave-Code wiederholt nur eine Funktion immer wieder, also poste ich nicht den ganzen Code, sondern nur die Schnipsel dazwischen.

int main(void)
{
    xx=adc_read(0); //reading from ADC0 of the Atmega.
    toTransfer = (5.0 * xx * 100.0) / 1024; //calibrating the temperature

    if (byte == 1) //send packet 1
    {
        toSend = toTransfer & mask; //sending the first 8 bits of data.
        toTransfer = toTransfer >> 8;//right shift so that the next function will take the 8-16 bits of data.
        TWI_match_write_slave(); //I2C function to verify address
        TWI_write_slave(toSend); //I2C function to write data on to master
        byte = 2;
    }

    /*Repeating this till byte 4*/

    else if (byte == 4) //send packet 4
    {
        toSend = toTransfer & mask;
        toTransfer = toTransfer >> 8;
        TWI_match_write_slave();
        TWI_write_slave(toSend);
        byte = 1;
        //initialization for next turn
        mask = 0xFF;
        toSend = 0;
    }
}

Update: Ich habe dies ohne Glück versucht:

unsigned int xx;   //I just wrote it here so that you don't have to refer the code again-
unsigned char yy;  //-not present in the main loop.
I2C_start(0x01);   //yy is receiving data one byte at a time from the slave
yy = I2C_read_ack();
xx = (xx|yy);
xx<<8;
I2C_stop();

Ähnlich verhält es sich mit der else-Anweisung in dem ursprünglich von mir geposteten Code.

Welchen Wert ich auch immer sende, das LCD auf der Empfängerseite zeigt 255 an.

Sie haben "xx |= (yy << 8);" zweimal in Ihrem Master-Empfangscode, sodass Sie niemals die unteren 8-Bits von xx ändern. Sie müssen auch Ihr Adressierungsproblem (0x01 vs. 0x01+1) beheben, bevor Sie glauben, dass Sie eine zuverlässige Kommunikation zwischen Ihrem Master und Ihrem Slave erhalten.
Je nachdem, wie sich Ihr Compiler verhält, erzeugt yy << 8 möglicherweise nie etwas, da Sie yy als 8-Bit-Zeichen ohne Vorzeichen deklariert haben.
Ich bin verwirrt, wie ich das beheben kann. Könnten Sie es ein wenig mehr erklären.
Wenn Sie eine 8-Bit-Variable um 8 nach links verschieben, fallen alle Bits am Ende einfach heraus und Sie haben nichts übrig. Deklarieren Sie yy entweder als 16-Bit-Typ oder typisieren Sie es, bevor Sie die Verschiebung durchführen. Und einer Ihrer 2 "xx |= (yy << 8);" Zeilen sollten nur so etwas wie "xx = yy" sein - wahrscheinlich die 1.
Verwenden Sie zwei verschiedene Bibliotheken? Eine für Master und eine für Slave? Es scheint, dass Sie I2Cmaster als Master und Wire als Slave verwendet haben.
Ja, mach das: xx |= (((unsigned int)yy) << 8);
@PedroQuadros ja, es sind 2 verschiedene Bibliotheken für den Sklaven und den Meister.
@brhans jetzt habe ich verstanden, wovon du sprichst. Ich werde die erforderlichen Änderungen vornehmen und es ausprobieren
@brhans schau dir das Code-Snippet an, das ich unten gepostet habe.
@Alex schau dir das Code-Snippet an, das ich unten gepostet habe.
Haben Sie die Adresse Ihres Slaves konfiguriert, indem Sie 0x01 in das TWAR-Register geschrieben haben?

Antworten (1)

ES KLAPPT!! Nachdem ich also bemerkt hatte, dass das LCD nur 255 und sonst nichts druckt, habe ich mich hingesetzt und darüber nachgedacht. Dann wurde mir klar, dass 255 hexadezimal 0xff ist, was bedeutete, dass die SCL-Leitung nicht lange genug gehalten wurde, damit der Slave Daten übertragen konnte. Also habe ich einfach eine kleine Verzögerung von 100 ms nach der Lesefunktion gesetzt und es hat funktioniert. :D

 I2C_start(0x01);
 yy = I2C_read_ack();    
 _delay_ms(100);
 getdata=yy; //getdata is just another unsigned char variable. I thought that maybe yy 
 yy=0;       //isn't getting refreshed or something, so i made a small reset sort of thing here.
 xx = getdata&zz;
 xx<<8;
 I2C_stop();
Die Aussage xx<<8;bringt überhaupt nichts. Wenn Sie xx <<= 8;es verwenden, wird xx um 8 Bits nach links verschoben.