- LiFePO4 Speicher Test         
Ergebnis 1 bis 2 von 2

Thema: Kriege TWI mit ATmega-Master & ATtiny-Slave nicht zum La

  1. #1
    Benutzer Stammmitglied
    Registriert seit
    16.10.2008
    Beiträge
    39

    Kriege TWI mit ATmega-Master & ATtiny-Slave nicht zum La

    Anzeige

    Praxistest und DIY Projekte
    Hallo allerseits,

    ich habe hier einen ATmega 644P welcher Daten per TWI an einen ATtiny2313 schicken soll, welcher diese dann auf einem LCD-Display ausgibt.

    Nun kann der ATtiny2313 ja kein echtes TWI, stattdessen läuft das Ganze über USI ab. Daher würde ich gerne zunächst wissen, ob man Hardware-TWI des 644P überhaupt mit dem USI-TWI des 2313 zum Laufen kriegen kann.

    Mein Problem ist nämlich, dass ich nun schon das Ganze Wochenende dran gesessen habe, die Kommunikation zum Laufen zu kriegen, das Ganze jedoch vollkommen erfolglos. Ich habe bereits fertig implementierte I2C-Slaves für den 2313 ausprobiert, aber auch hier kriege ich keine Daten übertragen.

    Master-seitig sieht der Code wie folgt aus:

    Code:
    #ifndef F_CPU
    #define F_CPU 8000000
    #endif
    #include <avr/io.h>
    #include <util/delay.h>
    
    uint8_t twiControl;
    
    void send_i2c() {
    	// signalisiere START
    	TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);									
    	// warte auf Bus
    	waitForTWI();
    		
    	// falls Bus nicht frei
    	if((TWSR & 0xF8) != 0x08 && (TWSR & 0xF8) != 0x10) {
    		// TODO
    	} else {
    		// grüne LED an
    		PORTA &= ~(1<<PB2);
    		
    		// Slave-Adresse und WRITE senden
    		TWDR = 0x40<<1;
    		TWCR = (1<<TWINT)|(1<<TWEN);
    
    		// warte auf Bus
    		waitForTWI();
    
    		// falls kein ACK oder NACK empfangen
    		if((TWSR & 0xF8) != 0x18 && (TWSR & 0xF8) != 0x20) {
    			// rote LED an
    			PORTA &= ~(1<<PB4);
    		} else {
    			// gelbe LED an
    			PORTA &= ~(1<<PB3);
    		}
    	}
    	_delay_ms(20);
    	// LEDs aus
    	PORTA = 0b11111111;
    	_delay_ms(20);
    }
    
    void waitForTWI() {
    	do {
    		twiControl = TWCR & 0x80;
    	} while(twiControl != 0x80);
    }
    
    int main() {
    	// setze TWI auf 100 kHz
    	TWBR = (F_CPU/200000)-18;
    	// aktiviere TWI
    	TWCR = 0b00000100;
    	// aktiviere PORT A
    	DDRA = 0b11111111;
    	PORTA = 0b11111111;
    	
    	while(1) {
    		send_i2c();
    	}
    }
    Auf dem Slave habe ich bis jetzt das hier:

    Code:
    uint8_t state = 0x00;
    
    
    int main() {
    	// initialisiere PWM für Ladungspumpe
    	initPWM();
    	// initialisiere Display
        initLCD();
    
    	// aktiviere Interrupts
    	USICR = 0b11111000;
    	// aktiviere SCL-Pin
    	PORTB |= (1<<PORTB7);
    	// aktiviere SDA-Pin
    	PORTB |= (1<<PORTB5);
    	// SCL auf Eingang
    	DDRB |= (1<<PORTB7);
    	// SDA auf Ausgang
    	DDRB &= ~(1<<PORTB5);
    
    	// Interrupts aktivieren
    	sei();
    	
       	while(1) {
    		// fortlaufend Inhalt von USICR, USISR und USIDR ausgeben
    		lcd_home();
    		hexout(USICR);
    		lcd_data(' ');
    		hexout(USISR);
    		lcd_data(' ');
    		hexout(USIDR);
       	}
    }
    
    // START-Bedingung per USI erhalten
    ISR(SIG_USI_START) {
    	// schreibe "START" auf LCD
    	lcd_setcursor(0,2);
    	lcd_string("START");
        uint8_t tmpUSISR;
        tmpUSISR = USISR;
    	// setze Start-State
        state = 0x00;
    	// SDA auf Eingang
        DDRB  &= ~(1<<PORTB5);
        while ((PINB & (1<<PORTB7)) & !(tmpUSISR & (1<<USIPF)) );
    	// aktiviere Interrupts
        USICR  =    0b11111000;
    	USISR  =    (1<<USI_START_COND_INT)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x0<<USICNT0);    
    	lcd_clear();
    }
    
    // USI-Overflow-Interrupt
    ISR(SIG_USI_OVERFLOW) {
    	switch(state) {
    		// Start-State
    		case 0x00:
    			// General oder eigene Adresse erhalten
    			if ((USIDR == 0) || (( USIDR>>1 ) == 0x40)) {
    				// akzeptiere nur Write-Requests
            		if (!(USIDR & 0x01)) {
    	          		state = 0x01;
    				}
    				
    				// schreibe "CHECK" auf LCD
    				lcd_setcursor(6,2);
    				lcd_string("CHECK");
    
    				// leere USIDR
    	          	USIDR    =  0; 
    				// SDA auf Ausgang                                          
            		DDRB |=  (1<<PORTB5);                           
            		USISR    =  (0<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x0E<<USICNT0);                              
          		}
          		else {
           			USICR    =  0b101010000;
    			  USISR = (0<<USISIF)|(1<<USIOIF)|(1<<USIPF)|(1<<USIDC)|(0x00<<USICNT0);                                                                                                    \  
          		}
          		break;
    	}
    
    	_delay_ms(20);
    	lcd_clear();
    }
    Allerdings erscheint mir der Slave-Code auch irgendwie spanisch, ich habe den aus den Appnotes AVR312 für einen USI-TWI-Slave entnommen. Doch scheint sich z.B. der Inhalt von USISR bei den entsprechenden Zuweisungen gar nicht zu ändern. Am schlimmsten ist aber, dass sich in USIDR keine Daten finden d.h. die Adresse, die ich im Master sende scheint gar nicht am Ziel anzukommen. Zudem bin ich auch skeptisch, was die Funktion des Masters angeht, da die LEDs auch fröhlich flackern, wenn der Tiny gar nicht angeschlossen ist.

    Ich bin da leider wirklich mit meinem Latein am Ende und auch etwas entnervt, dass so ein Krampf als "TWI-fähig" verkauft wird.

    Vielleicht kann mir ja hier jemand helfen oder mich auf die richtige Bahn lenken. Ich bin ja schon froh, dass ich am Master und Slave überhaupt ein wenig sehen kann, was passiert, aber selbst das ist doch eher dürftig

    Achja, SCL und SDA sind auf dem Master mit 10k Ohm gegen VCC geschaltet, beide µC werden mit 3.3V versorgt.

  2. #2
    Benutzer Stammmitglied
    Registriert seit
    16.10.2008
    Beiträge
    39
    Ok, Kommando zurück.

    Das ist mir jetzt super peinlich, aber ich habe gerade nochmal die Platine des Tiny kontrolliert und dabei festgestellt, dass ich vergessen hatte den SCL-Pin des Tiny mit dem Wannenstecker zu verbinden -.-

Berechtigungen

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

12V Akku bauen