-         

Ergebnis 1 bis 4 von 4

Thema: Probleme TWI (I2C) Atmega 16

  1. #1

    Probleme TWI (I2C) Atmega 16

    Anzeige

    Hallo miteinander!
    Wollte im Rahmen meiner Technikerarbeit über mehrere Atmega 16 Daten austauschen. Dafür ist einer als Master definiert und die anderen als Slave. Wollte erstmal ein Datenpaket an den Slave senden, der diese dann an PORTA anzeigt. Nur passiert leider nichts.^^ Ich hab mal die einzelnen Schritte durchnummeriert indem dann an diversen Ports dann durchnummeriert wird, wo der Controller gerade ist. Beim Master läuft alles schön nacheinander durch. Aber der Slave will leider nicht auf die Adressierung antworten. Wenn ich dem Slave die Adresse 0x02 gebe, muss ich ihn doch vom master mit 0x04 aufrufen, wegen dem read-write zum am Ende, oder? Ich hoffe ihr könnt mir dabei helfen! Hab schon hier und in anderen Foren viel durchgeschaut und bei mir im Programm eingefügt, aber leider klappt es immernoch nicht.

    Hier mal der Master C-Code:

    Code:
    #define F_CPU 8000000UL
    
    #include <avr/delay.h>
    #include <avr/io.h>
    
    
    
    
    void i2c_init(void)
    {
      
      
      TWSR = 0;                         		// kein Vorteiler
      TWBR = 32; 								// Da Quartz bei 8 MHz
    }
    
    void start_i2c()
    {
    TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);		// Starte I2C
    while (!(TWCR & (1<<TWINT)));				// Warte, bis fertig
    
    }
    
    void stop_i2c()
    {
    TWCR = (1<<TWINT)|(1<<TWEN)|(1<<TWSTO);		// Stoppe I2C
    // Hier darf keine Warteabfrage hin, da I2C gestoppt ist.
    }
    
    void senden_i2c(char daten)
    {
    TWDR = daten;								// Sende Daten			
    TWCR = (1<<TWINT) | (1<<TWEN);
    while( !(TWCR & (1<<TWINT)) );
    				
    }
    
    
    unsigned char i2c_empfangen(void)
    {
    	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
    	while(!(TWCR & (1<<TWINT)));    
    
        return TWDR;
    
    }
    
    
    
    void main (void)
    {
    DDRB=0xFF;
    
    PORTB=0xFF;
    
    i2c_init();				
    		
    
    int daten2 = 0xAA;
    
    while(1)
    {
    		PORTB = 0x01;
    
    		// Sende 0xAA an Slave 1
    		
    		start_i2c();				// Start I2C
    		_delay_ms(1000); 
    		PORTB = 0x02;
    		senden_i2c(0x04); 			// Adressierung Slave 1
    		_delay_ms(1000); 
    		PORTB = 0x03;
    		senden_i2c(daten2);		    // Daten  übertragen
    		_delay_ms(1000); 
    		stop_i2c();
    		
    		PORTB = 0x04;
    }
    }
    und hier der Slave C-Code:

    Code:
    #define F_CPU 8000000UL
    
    #include <avr/delay.h>
    #include <avr/io.h>
    
    
    
    void i2c_init (uint8_t Address)
    {
    
      TWSR = 0;                         		// kein Vorteiler
      TWBR = 32; 								// Da Quartz bei 8 MHz
    
    /*
    ** Set the TWI slave address
    */
    	TWAR = (Address << 1);
    /*
    ** Activate TWI interface
    */
    	TWCR = (1<<TWEN)|(1<<TWEA);
    }
    
    
    
    
    unsigned char i2c_empfangen(void)
    {
    	TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWEA);
    	while(!(TWCR & (1<<TWINT)));    
    
        return TWDR;
    
    }
    
    		
    
    int daten = 0x00;
    int main(void)
    {
    DDRA=0xFF;
    PORTA=0xFF;
    uint8_t status;
    
    i2c_init(0x02);
    while(1) 
     	{
    	PORTA = 0x01;
    	while(!(TWCR & 0b10000000));
      	
    	PORTA = 0x02;
       	TWCR &=~ (1<<TWINT);   //TWINT auf 0 setzten damit TWI wieder arbeitet
    	PORTA = 0x03;
       	TWCR |=  (1<<TWEA);      //TWEA auf 1 setzten um Ack zu senden   
    	PORTA = 0x04;
      	daten = i2c_empfangen();
    
       	PORTA = daten;
     	
    }
    }
    Wie gesagt, ich hoffe ihr könnt mir helfen, weil ich sonst ganz schön alt ausschaue demnächst. xD

    Gruß Bastian

  2. #2
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    19.03.2010
    Beiträge
    161
    Mir ist in Deinem einleitenden Text schon ein Fehler aufgefallen:

    "Wenn ich dem Slave die Adresse 0x02 gebe, muss ich ihn doch vom master mit 0x04 aufrufen, wegen dem read-write zum am Ende, oder?"

    Das ist nicht richtig. Um ein Datenbyte zu senden nimmst Du die Adresse wie sie ist. Um ein Byte zu lesen, musst Du zur Adresse 1 addieren.

    Den Empfang eines Bytes musst Du mit ACK bestätigen, sofern Du mehrere Bytes nacheinander (in einem Rutsch) empfangen willst.

    Ich bin nicht ganz Sicher, ob die delays stören. Möglicherweise wird eine zu lange Verzögerung als Timeout erkannt.

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    22.05.2007
    Ort
    Stolberg
    Beiträge
    111
    Hast Du an die Pull-Up Widerstände für SDA und SCL gedacht? Ansonsten kannst Du auch die Internen verwenden: PORTC |= 0x03;

  4. #4
    Danke für eure Antworten, aber is leider schon zu spät.^^ Konnte mittlerweile schon Bytes senden. War ein rießen Aufwand und würde es keinem empfehlen.^^ Hatte das Glück, dass mir jemand in einem anderem Forum sehr gut geholfen hat. Diese Arbeit ist jetzt auch rum und ich bin glücklich darüber. Werde den ganzen Sch.... auch jetzt in den nächstgelegenen Fluss werfen, weil es mir einfach zu viel Zeit und Nerven gekostet hat.^^ Kann aber Leuten gerne helfen, die ähnliche Probleme haben. Aber wie gesagt, trotzdem danke für eure Antworten!

    Gruß Bastian

Berechtigungen

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