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

Thema: TWI von ATmega8 zu ATmega8

  1. #1
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2010
    Ort
    Im Städtedreieck Köln-Bonn-Aachen
    Alter
    37
    Beiträge
    106

    TWI von ATmega8 zu ATmega8

    Anzeige

    Praxistest und DIY Projekte
    Moin Moin,
    bin schon seit Wochen daran, das TWI zwischen zwe Controller an laufen zu bringen.

    Dabei bin ich auf meine Suche im Internet nirgendwo darauf gestoßen, wie der Slave die Daten aus dem TWDR abholt, bzw. wie er überhaupt zu programmieren ist.
    ^^
    das ist mein Hauptproblem.

    Da ich nicht weis, wie der Slave reagieren soll, weis ich noch nicht mal, ob das Programm für den Master richtig ist.

    Hier mal meine C-Codes:

    Master:
    Code:
    /*
    Test Programm für TWI zwischen zwei ATmega8.
    +++
    Master sendet ein Byte an Slave. Byte wird an Port B über zwei Taster (B0 und B1) eingegeben und an Port D dargestellt
    Über ein dritten Taser (B2) wird die TWI-Übertragung ausgeführt
    +++
    Slave gibt das Byte an Port B aus.
    */
    #include <avr/io.h>
    #include <avr\delay.h>
    #define empfanger 0x10 // Empfänger Adresse (1) plus Schreibbit (0) in Hex
    
    void send(unsigned char adres, unsigned char data) // Sende Funktion
    {
        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);    // TWI Starten, Startbedinung
        loop_until_bit_is_set(TWCR,TWINT);        // Warten bis fertig
        PORTC=0<<PINC0;                         // Fehler-LED "aus"
        if ((TWSR & 0xF8) != 0x08)                 // Fehlerausgabe, wenn ein Fehler auftritt
            PORTC=1<<PINC0;                     // Fehler-LED "ein"
        TWDR=adres;                             // Zieladresse ins Register schreiben
        TWCR=(1<<TWINT)|(1<<TWEN);                // Zieladresse senden
        loop_until_bit_is_set(TWCR,TWINT);         // Warten bis fertig
        PORTC=0<PINC0;                            // Fehler-LED "aus"
        if ((TWSR & 0xF8) != 0x18)                 // Fehlerausgabe, wenn ein Fehler auftritt
            PORTC=1<<PINC0;                        // Fehler-LED "ein"
        TWDR=data;                                 // Daten ins Register
        TWCR=(1<<TWINT)|(1<<TWEN);                 // Daten senden
        loop_until_bit_is_set(TWCR,TWINT);         // Warten bis fertig
        PORTC=0<PINC0;                            // Fehler-LED "aus"
        if ((TWSR & 0xF8) != 0x28)                 // Fehlerausgabe, wenn ein Fehler auftritt
            PORTC=1<<PINC0;                        // Fehler-LED "ein"
        TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);    // TWI beenden, Stopbedingung
    }
    
    int main(void)
    {
        DDRD=0xFF;     // Port D als Ausgang
        PORTD=0x00; // Port D auf Null
        DDRC=0x01;     // Port C0 als Ausgang
        DDRB=0x00;     // Port B als Eingang
    
        int bit[8]={1,3,7,15,31,63,127,255}, a=0;
        unsigned char data;
        
        TWBR=44; // Bitraten Erzeugung
        TWSR=0x01; // Vorteiler 1
    
        while(1)
        {
        if(bit_is_clear(PINB,PINB0)) // ausführen, wenn PB0 0 ist
            {
                _delay_ms(170); // 170ms  Warten (Prellen abwarten)
                
                if(a<=6) 
                {
                    a=a+1; 
                    PORTD=bit[a]; // Arraywert ausgeben
                }
                else
                    a=6;
            }
    
        if(bit_is_clear(PINB,PINB1)) // ausführen, wenn PB1 0 ist
            {
                _delay_ms(170);
                
                    if(a!=0)
                    {
                        a--;
                        PORTD=bit[a]; // Arraywert ausgeben
                    }
                    else
                        a=0;
                        
            }
        if(bit_is_clear(PINB,PINB2)) // ausführen, wenn PB2 0 ist
            send(empfanger, PORTD);
        }
    }
    Slave:
    Code:
    /*
    Test Programm für TWI zwischen zwei ATmega8.
    +++
    Master sendet ein Byte an Slave. Byte wird an Port B über zwei Taster (B0 und B1) eingegeben und an Port D dargestellt
    Über ein dritten Taser (B2) wird die TWI-Übertragung ausgeführt
    +++
    Slave gibt das Byte an Port B aus.
    */
    
    #include <avr/io.h>
    #include <avr/interrupt.h>
    
    unsigned char Daten;
    
    int main(void)
    {
        DDRB=0xFF; // Port B als Ausgang
        PORTB=0x00; // Port B aus Null
        TWAR=0x10;    // Slave Adresse 0x10
        SREG=128; // Interrupts Global aktivieren
    
        while(1)
        {
            PORTB=Daten; // Byte ausgeben
        }
    }
    
    
    SIG_2WIRE_SERIAL(void) // TWI Interrupt
    { 
        TWCR=(1<<TWEA)|(1<<TWEN);    // Bestätigung senden
        loop_until_bit_is_set(TWCR,TWINT);        // Warten bis fertig
        Daten=TWDR;                             // Daten aus dem Register in den Speicher
        TWCR=(1<<TWEA)|(1<<TWEN);    // Bestätigung senden
    }
    Wie gesagt, der Code vom Slave ist jetzt einfach mal frei geraten, das ich nirgend wo infos gefunden habe.

    Kann mir irgend wer sagen, wie das ganze funktioniert?
    Und bitte keine Links zu euren RN-Wissen artikel und Mikrocontroller.net.
    Die kenne ich mittlerweile auswendig.

    Ich bin soweit gekommen, dass die Fehler LED leuchtet, wenn ich auf den Senden-taster drücke. Das Byte kann ich auch einstellen.
    Wo ist jetzt der Fehler, wo sind die Fehlern?

  2. #2
    Erfahrener Benutzer Robotik Visionär Avatar von 021aet04
    Registriert seit
    17.01.2005
    Ort
    Niklasdorf
    Alter
    36
    Beiträge
    5.070
    Beim Master sind mir schon einige Fehler aufgefallen. Vielleicht ist das auch nur hier (nicht ganz zu 100% gleiche Programm wie beim AVR Studio).
    Du schreibst immer "PORTC = 1<<PC0;" bzw "PORTC = 0<<PC0;". Das ist falsch.
    Das sollte man so schreiben:
    zum Setzen: "PORTC |= (1<<PC0);" => mit "|=" wird nur bitweise gesetzt und beim "1<<PC0" fehlt bei dir die Klammer
    zum Löschen: "PORTC &= ~(1<<PC0);" => mit "&=" und "~" wird bitweise gelöscht und beim "0<<PC0" fehlt bei dir die Klammer
    Das findet man z.B. im (sehr guten) AVR GCC Tutorial bei www.mikrocontroller.net

    Beim Slave ist mir aufgefallen das die ISR (Interruptroutine) falsch ist.
    Der Interrupt muss so aussehen: "ISR (TWSI_vect) {...}"
    Bei einem Interrupt muss immer stehen "ISR (xxx_vect){}" => statt xxx muss der jeweilige Interrupt stehen wie z.B. Int0,...
    Hier etwas zu Interrupts (von www.mikrocontroller.net) http://www.mikrocontroller.net/artic...r_.28WinAVR.29

    Die einzelnen Register,... habe ich mir nicht angesehen. Im Datenblatt auf S170 ist ein Beispiel für eine I2C Übertragung (Master). Hast du schon andere I2C Hardware angesteuert (wie z.B. Portexpander)? Ich würde zuerst einen I2C Baustein ansteuern (z.B: PCF8574,...) Wenn das klappt würde ich stattdessen einen µC mit einem I2C Slave Programm (mit gleicher Adresse) ansteuern. Somit weiß man ob der Master funktioniert.

    MfG Hannes

  3. #3
    Erfahrener Benutzer Fleißiges Mitglied
    Registriert seit
    07.04.2010
    Ort
    Im Städtedreieck Köln-Bonn-Aachen
    Alter
    37
    Beiträge
    106

    Beitrag

    Guten Abend,
    so... endlich mal wieder Zeit gehabt.
    Also: Habe mir ein IC geholt, dass ich 1. über TWI ansteuern kann und 2. für ein Projekt in zukunft benötige). Der IC hört auf den Namen MAX517 und wandelt 8Bit in eine Spannung von 0V bis UB.

    Der Code für den Master sieht in etwa so aus:
    Code:
    /*
    Test Programm für TWI zwischen ATmega8 und MAX517 D/A-Wandler.
    +++
    Master sendet ein Byte an Slave. Byte wird an Port B über zwei Taster (B0 und B1) eingegeben und an Port D dargestellt
    Über ein dritten Taster (B2) wird die TWI-Übertragung ausgeführt.
    +++
    Slave IC: MAX517 wandelt das Byte in ein analoges Signal um. 
    Adresse vom IC: 0101111 (5E)
    */
    #include <avr/io.h>
    #include <avr\delay.h>
    #define empfanger 0x5E // Empfänger Adresse (5E) plus Schreibbit (0) in Hex
    
    void send(unsigned char adres, unsigned char data) // Sende Funktion
    {
        TWCR=(1<<TWINT)|(1<<TWSTA)|(1<<TWEN);    // TWI Starten, Startbedinung
        loop_until_bit_is_set(TWCR,TWINT);        // Warten bis fertig
        
        TWDR=adres;                             // Zieladresse ins Register schreiben
        TWCR=(1<<TWINT)|(1<<TWEN);                // Zieladresse senden
        loop_until_bit_is_set(TWCR,TWINT);         // Warten bis fertig
        
        TWDR=0x0;                                 // Command-Byte ins Register. Bei MAX517: 0! Siehe Datenblatt
        TWCR=(1<<TWINT)|(1<<TWEN);                 // Command-Byte senden
        loop_until_bit_is_set(TWCR,TWINT);         // Warten bis fertig
       
        TWDR=data;                                 // Daten-Byte ins Register
        TWCR=(1<<TWINT)|(1<<TWEN);                 // Daten senden
        loop_until_bit_is_set(TWCR,TWINT);         // Warten bis fertig
      
        TWCR=(1<<TWINT)|(1<<TWSTO)|(1<<TWEN);    // TWI beenden, Stopbedingung
    }
    
    int main(void)
    {
        DDRD=0xFF;     // Port D als Ausgang
        PORTD=0x00; // Port D auf Null
        DDRB=0x00;     // Port B als Eingang
    
        unsigned char data, a=0;
        
        TWBR=60; // Bitraten Erzeugung
        TWSR=0; // Vorteiler 1
    
        while(1)
        {
        if(bit_is_clear(PINB,PINB0)) // ausführen, wenn PB0 0 ist
            {
                _delay_ms(170); // 170ms  Warten (Prellen abwarten)
                
                if(a<=255) 
                {
                    a=a+1; 
                    PORTD=a; // Wert ausgeben
                }
                else
                    a=255;
            }
    
        if(bit_is_clear(PINB,PINB1)) // ausführen, wenn PB1 0 ist
            {
                _delay_ms(170);
                
                    if(a!=0)
                    {
                        a--;
                        PORTD=a; // Wert ausgeben
                    }
                    else
                        a=0;
                        
            }
        if(bit_is_clear(PINB,PINB2)) // ausführen, wenn PB2 0 ist
            send(empfanger, PORTD);
        }
    }
    Okay...
    Jetzt zurück zu mein Problem:
    Master Code, würde so funktionieren (Statt den Command-Byte würde ein Datenpaket zum Slave-AVR gesendet).
    Aber wie bringe ich nun den Slave AVR dazu, dass er funktioniert?
    Ich weis, dass die TWI ein Interrupt auslöst, wenn der Slave sich angesprochen fühlt.
    Aber wie müsste ein C-Code aussehen, der die Daten aus dem Register holt und in ein Array Speichert?

  4. #4
    Erfahrener Benutzer Robotik Visionär Avatar von oberallgeier
    Registriert seit
    01.09.2007
    Ort
    Oberallgäu
    Beiträge
    8.678
    Zitat Zitat von Jimmybot
    ... wie das ganze funktioniert? Und bitte keine Links zu euren RN-Wissen ...
    Das verstehe ich jetzt nicht. Der Code vom SlaveBeispiel im "TWI Slave mit a v r - g c c" läuft doch einwandfrei ! Zumindest bei mir zwischen zwei m328ern. Und - soweit ich es nachgesehen hatte - heissen die Registernamen fürs TWI auf den A tmel megas immer gleich.
    Ciao sagt der JoeamBerg

Ähnliche Themen

  1. Atmega8/16 USB ...
    Von linuxer7 im Forum AVR Hardwarethemen
    Antworten: 6
    Letzter Beitrag: 23.03.2011, 14:39
  2. PWM mit ATMega8 und LM-35
    Von rogerberglen im Forum Basic-Programmierung (Bascom-Compiler)
    Antworten: 1
    Letzter Beitrag: 08.03.2009, 19:40
  3. Antworten: 23
    Letzter Beitrag: 15.12.2007, 21:36
  4. Unterschied ATmega8-16PC und ATmega8-16AC
    Von Christian 25 im Forum AVR Hardwarethemen
    Antworten: 17
    Letzter Beitrag: 01.10.2006, 21:09
  5. Atmega8 bei ELV
    Von Goblin im Forum Elektronik
    Antworten: 1
    Letzter Beitrag: 05.12.2005, 13:18

Berechtigungen

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

Labornetzteil AliExpress