mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik I2C Ansteuerung ATMega128


Autor: Bernhard G. (bgwh)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich soll eine I2C Interface zwischen einem PIC (dsPIC30f6014A) als 
Master und einem ATMEL als Slave (ATMega128) herstellen. Ich habe auch 
soweit die Software fertig und auch das Signal des PIC ist soweit in 
Ordnung, nur leider reagiert der TWI Interrupt am Atmel nicht!!

Hier das Ausgangssignal des PIC: Gesendet wird zuerst 0xC4 (0x62 
Slave-Adresse und als LSB 0, da es win Writezyklus ist:
(habe es als Anhang hinzugefügt)


Nun zum Atmel, der irgendwie nichts mit dem Signal anfangen kann bzw. 
nicht reagiert.
Das ist mein Assembler Code für den Atmel-Slave:

#include <stdio.h>
#include <avr/io.h>
#include <avr/wdt.h>
#include <util/delay.h>
#include <math.h>
#include <avr/pgmspace.h>

#include <util/twi.h> //enthält z.B. die Bezeichnungen für die Statuscodes in TWSR
#include <avr/interrupt.h> //dient zur behandlung der Interrupts
#include <stdint.h> //definiert den Datentyp uint8_t

#define SLAVE_ADRESSE 0x62

#define SIG_2WIRE_SERIAL _VECTOR(34)  // Interrupt Vektor für TWI

void init_twi_slave (uint8_t adr);
void delay_ms(unsigned int period);

extern const prog_uint8_t Font1[], Font2[];
uint8_t data=0;
uint8_t contr=0;

int main(void)
{
   LCD_Init();
   delay_ms(1000);
   init_twi_slave(SLAVE_ADRESSE);
   
   Orientation = Landscape;      
   LCD_Cls(yellow);
   delay_ms(1000);
  
   while(1)
   {
      if(data != 0)
      {
    switch(data)
    {
       case '1':
                    ...
        break;
           
       case '2':
                    ...
        break;
         
       case '3':
                    ...
        break;
           
       default:
                    ...
    }
    data = 0;
      }
   } 
   return 0;
  
}

void init_twi_slave (uint8_t adr)
{
    TWAR = 0xC4;   //Slave-Addr.: 0x62 (Bit1-Bit7)
       //General Call deaktivieren (Bit0)
  
    TWCR &= ~((1<<TWSTA)|(1<<TWSTO));  // TWSTA und TWSTO auf 0 setzen
      //TWEA...TWI Enable Acknowledge Bit
      //TWEN...TWI Enable
      //TWIE...TWI Interrupt Anforderung erlauben
    TWCR |= (0<<TWEA)|(1<<TWEN)|(1<<TWIE);

    sei();    //enable global interrupts
}


//TWI ISR
SIGNAL(SIG_2WIRE_SERIAL)
{
    LCD_Cls(green);
    delay_ms(1000);
  
  ...
}


Hoffe es hat jemand einen Tipp warum die Übertragung nicht funktioniert. 
Bin schon leicht verzweifelt, wäre also über jede Art von Hilfe 
dankbar!! :)
Vielleicht hat auch schon jemand einen ATMega als Slave verwendet und 
könnte mir da ein paar Tipps geben.

Schoene Grueße
 Bernhard

Autor: Dennis (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
-  es ist ein C-Programm, kein ASM :-)

- "SIGNAL" gibt es schon eine Weile nicht mehr, statt dessen ISR

- INT: TWI_vector

Autor: BGWH (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Dennis: Erstmals Danke für deine rasche Antwort

[quote]
-  es ist ein C-Programm, kein ASM :-)
[/quote]

:) okay danke. Ist zum ersten Mal, dass ich ein uC-Programm in C und 
nicht in Assembler schreibe, deshalb noch kleine Verwirrungen. :)

[quote]
- "SIGNAL" gibt es schon eine Weile nicht mehr, statt dessen ISR
- INT: TWI_vector
[/quote]

Okay habe ich geändert. Aber bedeutet beides dasselbe und hat auch an 
der Funktion nichts geändert.

Im File iom128.h (wo die Makros sind) steht:
 #define TWI_vect    _VECTOR(33)
obwohl der TWI Interrrupt eigentlich laut Datenblatt Nummer34 ist, zählt 
da der Reset Interrupt nicht??

Vielleicht hat noch jemand andere Vorschläge, wieso die Verbindung nicht 
geht, wäre sehr dankbar!!

Sg Bernhard

Autor: Jörg X. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und das TWEA Bit musst du natürlich setzen, wenn der Atmega reagieren 
soll (also ein ACK senden soll...)
Außerdem würde ich die Init() vereinfachen:
void init_twi_slave (uint8_t adr)
{
    TWAR = SLAVE_ADRESSE << 1 | (0<<TWGCE);
    //General Call deaktivieren (Bit0)
  
    TWCR = (0<<TWSTA)
          |(0<<TWSTO)  
          |(1<<TWEA)  // auf adresse reagieren
          |(1<<TWEN)  // TWI aktiv
          |(1<<TWIE); // Interrupt an
}
und nur ein "sei()", vor der main-loop

hth. Jörg

ps. vergleiche mal die Nummerierung im Datenblatt und im io*.h-File 
(stichwort: "offset")

Autor: Bernhard G. (bgwh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke schön für eure Hilfe!! Die Übertragung funktioniert jetzt 
wunderbar!!

Da dieses Forum echt toll ist und sehr schnell beantwortet wird hätte 
ich bitte noch ein paar ganz kurze Fragen zur Bitadressierung in C:

1. Was heißt z.B. was Jörg X. geschrieben hat:
 SLAVE_ADRESSE << 1   bedeutet das, dass ab Bit 1 die Slave Adresse 
hinzugefügt wird??

2. Was ist der Unterschied zwischen:

 TWCR |= 1<<TWINT;    und   TWCR = 1<<TWINT;   ??

Ich meine er setzt doch bei beiden nur das TWINT-Bit? Oder werden beim 
rechten, wenn es nicht noch verodert wird, die anderen Bits auch 
geändert bzw, gelöscht??

3. Warum müssen, wenn man mehrere Bits löschen bzw. setzen will die 
einzelnen Elemente verodert werden??:
 z.B. TWCR = (0<<TWSTA)
            |(0<<TWSTO)
            |(1<<TWEA)  // auf adresse reagieren
            |(1<<TWEN)  // TWI aktiv
            |(1<<TWIE); // Interrupt an


Schoene Grueße
 Bernhard

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>1. Was heißt z.B. was Jörg X. geschrieben hat:
> SLAVE_ADRESSE << 1   bedeutet das, dass ab Bit 1 die Slave Adresse
>hinzugefügt wird??

Es Bedeutet, dass der Wert SLAVE_ADRESSE um 1 Bit nach links geschoben 
wird.
Oder mathematisch: Eine Multiplikation mit 2 stattfindet. Bei der I2C 
Adresse ist ja das unterste Bit das R/W Flag.

>Was ist der Unterschied zwischen:

> TWCR |= 1<<TWINT;    und   TWCR = 1<<TWINT;   ??

>Ich meine er setzt doch bei beiden nur das TWINT-Bit? Oder werden beim
>rechten, wenn es nicht noch verodert wird, die anderen Bits auch
>geändert bzw, gelöscht??

Richtig. Beim rechten werden die restlichen Bits gelöscht.

Die 1 wird ja als "0000 0001" interpretiert. Und TWINT hat z.B. (ich 
such jetzt nicht im datenblatt) den Wert 2. Also wird "0000 0001" um 2 
Bits nach links geschoben => "0000 0100" und dann ins TWCR Register 
geschrieben. Wie man sieht, sind die anderen Bits alle 0. Deshalb werden 
für Bitmaipulationen
auch sog. Read-Modify-Write Routinen benötigt. (siehe AVR-C Tutorial).

>3. Warum müssen, wenn man mehrere Bits löschen bzw. setzen will die
>einzelnen Elemente verodert werden??:
> z.B. TWCR = (0<<TWSTA)
>            |(0<<TWSTO)
>            |(1<<TWEA)  // auf adresse reagieren
>            |(1<<TWEN)  // TWI aktiv
>            |(1<<TWIE); // Interrupt an

Das mit dem (0<<TWSTA) ist für einen Neuling vielleicht nicht ganz 
nachvollziehbar. Es dient hier nur der Information des Programmieres.
Explizit löschen tut das das Bit an der Stelle nicht. Der 
Programmierstil dient vor allem dazu, dass man weiss, welche Bits man 
nicht setzen will (man könnte ja was vergessen haben) und für "faule" 
Programmierer, dass man nur die 0 zuur 1 oder umgekehrt ändern muss, 
wenn man mehrere Tests mit verschiedenen Bitkombinationen macht.

Autor: Bernhard G. (bgwh)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Matthias:

 Vielen Dank für deine ausführlichen Antworten!! Hat mir sehr geholfen!!


Schoene Grueße
 Bernhard

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.