www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik I2C Verbindung ohne ACK


Autor: Luigi Di Carmino (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo.
Ich sitze hier und versuche eine Kommunikation zwischen einem DRM-Modul
( SLAVE) und einem AVR ATMEL8L (MASTER) über die I2C-Schnittstell zu 
realisieren. Habe mich anhand des Forums und etlichen Beispielen bis zu 
einem Fehler/Problem vorgearbeitet bei dem mir jetzt nichts mehr 
einfällt.

Problem:
Es tritt kein ACK-Befehl vom Modul auf.

Dabei habe ich folgendes ausprobiert.

1. Beim ersten Versuch habe ich meinen ATMEL mit ca. 3,7MHz angesteuert.
2. Mit einem Logic-Analyzer habe ich mir die Datenleitung und die 
Taktleitung betrachtet und habe festgestellt das die ACK-Sequenzen immer 
zeitversetzt ankommen und somit nicht übernommen wurden.

Laut ATMEGA8L Handbuch muss das TWBR-Register > 10 sein, da es sonst zur 
Problemen bei der Übertragung mit dem SLA_W kommt.
Laut Formel komme ich mit dem Quarz genau auf 10,4 was wohl dann auf 
ganze 10 abgerundet wird. Deswegen entschloss ich mich den Quarz auf 
6MHz aufzustocken.

Das hat zur Folge das nun überhaupt keine ACK-Sequenzen mehr angezeigt 
werden.

Mein Code sieht wie folgt aus:
#include <avr/io.h>
#include <stdint.h>
#include <compat/twi.h>
#include <timer.h>
#include <i2cmaster.h>

#define  adresse 0x58;     //RS500-Adresse (Slave)
#define data1 0x03;    //RS500 Mute Befehl High-Byte
#define data2 0x04;    //RS500 Mute Befehl Low-Byte


void ERROR()
{
wait(50);
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
}


/* define CPU frequency in Mhz here if not defined in Makefile */
#ifndef F_CPU
#define F_CPU 6000000UL
#endif

/* I2C clock in Hz */
#define SCL_CLOCK  400000L


/*************************************************************************
 Initialization of the I2C bus interface. Need to be called only once
*************************************************************************/
void i2c_init(void)
{
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
  
  TWSR = 0;                         /* no prescaler */
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
}

int main()
{
  i2c_init();
  TWCR = (1<<TWINT)| (1<<TWSTA)|(1<<TWEN);       //Senden der START Prozedur
  while (!(TWCR & (1<<TWINT)));            //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die START Prozedur übermittelt würde
  if ((TWSR & TW_NO_INFO) != TW_START) ERROR();    //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der START Prozedur führe ERROR aus
  TWDR = adresse;                    //Den SLA_W Wert in das TWDR Register laden
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
  while (!(TWCR & (1<<TWINT)));            //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
  if ((TWSR & TW_NO_INFO) != TW_MT_SLA_ACK) ERROR();  //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_SLA_ACK [0x18] Prozedur führe ERROR aus
  TWDR = data1;                    //Den DATA1 Wert in das TWDR Register laden
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
  while (!(TWCR & (1<<TWINT)));            //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
  if ((TWSR & TW_NO_INFO) != TW_MT_DATA_ACK) ERROR(); //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_DATA_ACK [0x28] Prozedur führe ERROR aus
  TWDR = data2                    //Den DATA2 Wert in das TWDR Register laden
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
  while (!(TWCR & (1<<TWINT)));            //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die Adresse übermittelt würde und eine ACK/NACK empfangen wurde
  if((TWSR & TW_NO_INFO) != TW_MT_DATA_ACK) ERROR();  //TWI Status Register überprüfen und Prescaler Bits maskieren. Sind die Informationen verschieden zu der TW_MT_DATA_ACK [0x28] Prozedur führe ERROR aus
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);      //Senden der STOP Prozedur
  while(1)
  {
     }  
} 
In der Methode i2c_init() steht die Formel wie laut Datenblatt der 
Faktor berechnet wird der hier 22 beträgt und für den ersten Fall mit 
dem Quarz ~10.

Ich hoffe einer hat von euch einen Rat oder sieht sogar meinen Fehler.

Autor: Michael U. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

wenn ich richtig gesehen habe, machst Du 400kHz I2C?
Das ist üblicherweise das Maximum gängoger ICs. Gibt es einen Grund, das 
Du an die Grenze mußt? Den I2C-Takt bestimmt nur der Master, der kann 
also beliebig niedrig sein. Was sinnvoll ist, hängt nur von der 
Datenmenge oder einer nötigen Reaktionszeit des Slave ab.

Ich bin mal ziemlich auf die Nase gefallen, weil z.B. die alte 
Software-I2C-AppNote von Atmel ein Wait vom Slave nicht berücksichtigt 
hat, der MAS3507 aber fleißg Wait benutzt hat (Wait -> Slave hält SCK 
auf Low bis es weiter gehen kann).

Gruß aus Berlin
Michael

Autor: Luigi (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe die Versuche sowohl mit 100 kHz als auch mit 400kHz durchgeführt.
Die while-Schleife sollte doch eigentlich dafür sorgen das er abwartete 
bis durch das ACK das TWINT gesetzt wird oder nicht?

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.