Forum: Mikrocontroller und Digitale Elektronik I2C Verbindung ohne ACK


von Luigi Di Carmino (Gast)


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:
1
#include <avr/io.h>
2
#include <stdint.h>
3
#include <compat/twi.h>
4
#include <timer.h>
5
#include <i2cmaster.h>
6
7
#define  adresse 0x58;     //RS500-Adresse (Slave)
8
#define data1 0x03;    //RS500 Mute Befehl High-Byte
9
#define data2 0x04;    //RS500 Mute Befehl Low-Byte
10
11
12
void ERROR()
13
{
14
wait(50);
15
TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);
16
}
17
18
19
/* define CPU frequency in Mhz here if not defined in Makefile */
20
#ifndef F_CPU
21
#define F_CPU 6000000UL
22
#endif
23
24
/* I2C clock in Hz */
25
#define SCL_CLOCK  400000L
26
27
28
/*************************************************************************
29
 Initialization of the I2C bus interface. Need to be called only once
30
*************************************************************************/
31
void i2c_init(void)
32
{
33
  /* initialize TWI clock: 100 kHz clock, TWPS = 0 => prescaler = 1 */
34
  
35
  TWSR = 0;                         /* no prescaler */
36
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable operation */
37
}
38
39
int main()
40
{
41
  i2c_init();
42
  TWCR = (1<<TWINT)| (1<<TWSTA)|(1<<TWEN);       //Senden der START Prozedur
43
  while (!(TWCR & (1<<TWINT)));            //Warten bis das TWINNT-Flag gesetzt ist.Dieser bestätigt das die START Prozedur übermittelt würde
44
  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
45
  TWDR = adresse;                    //Den SLA_W Wert in das TWDR Register laden
46
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
47
  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
48
  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
49
  TWDR = data1;                    //Den DATA1 Wert in das TWDR Register laden
50
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
51
  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
52
  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
53
  TWDR = data2                    //Den DATA2 Wert in das TWDR Register laden
54
  TWCR = (1<<TWINT) | (1<<TWEN);            //TWINT (Interrupt) Bit rücksetzen um die transmission der Adresse mit TWEN auszuführen
55
  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
56
  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
57
  TWCR = (1<<TWINT) | (1<<TWEN) | (1<<TWSTO);      //Senden der STOP Prozedur
58
  while(1)
59
  {
60
     }  
61
}
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.

von Michael U. (Gast)


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

von Luigi (Gast)


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?

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.