Forum: Mikrocontroller und Digitale Elektronik I2C Kein ACK :-(


von Joe M. (taco)


Lesenswert?

Habe eine Atmega32 16Mhz  TC74 Sensor mit I2C verbunden ( Pull up sind 
dran)

1 Schritt Frequenz einstellen

TWSR = 0;
TWBR = ((F_CPU/SCL_CLOCK)-16)/2;   // 72

2 Schritt Startbedingung

       TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
       while(!(TWCR & (1<<TWINT))); // Prüfen

3 Schritt Adresse ( 7 Bit) + Low (1 Bit)  Für das Schreiben

I2C_sende(0x90); // Hier kommt immer  Kein ACK

 void I2C_sende(int daten)
 {
   TWDR = daten;
    TWCR = (1<<TWINT)  | (1<<TWEN);
    while  (!(TWCR & (1<<TWINT))); // Warte bis gesendet
    if((TWSR & 0xF8) != TW_MT_DATA_ACK)
    {
      USART_putstring("Kein ACK");
    }
    else
    {
      USART_putstring("ACK");
    }

 }

Was mache ich Falsch ?
Habe es schon mit Adresse 0x00 Probiert auch kein Ack

: Verschoben durch Moderator
von Timmo H. (masterfx)


Lesenswert?

The TC74 is internally programmed to have a default
SMBus/I2C address value of 1001 101b.
Fehlt noch RW-Bit => 0x9A bzw. 0x9B

von Joe M. (taco)


Lesenswert?

WOW das ging ja schnell :-D
Werde es Probieren DANKE

von Joe M. (taco)


Angehängte Dateien:

Lesenswert?

Mein Code leider geht es immer noch nicht.
Hast du ein anderen Tipp?

#define F_CPU 16000000UL
#define BAUD 9600                                   // define baud
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)
 #define SCL_CLOCK  100000 //100 kHz

#include <avr/io.h>
#include <util/delay.h>
#include <util/twi.h>
#include<stdbool.h>
#include "USART.h"
#include <avr/io.h>
void I2C_sende(int daten)
{
  TWDR = daten;
  TWCR = (1<<TWINT)  | (1<<TWEN);
  while  (!(TWCR & (1<<TWINT))); // Warte bis gesendet
  if((TWSR & 0xF8) != TW_MT_DATA_ACK)
  {
    USART_putstring("Kein ACK!!!");
  }
  else
  {
    USART_putstring("ACK");
  }

}
 void I2C_start(int adresse)
 {
   TWCR = (1<<TWINT)|(1<<TWSTA)|(1<<TWEN);
   while(!(TWCR & (1<<TWINT)));
   int twst = TW_STATUS & 0xF8;
   if ( (twst != TW_START) && (twst != TW_REP_START))
   {
     USART_putstring("Fehler beim Start ");
   }
   else
   {
     USART_putstring("Kein Fehler beim Start ");
   }


   I2C_sende(adresse);


 }

 void I2C_init(void)
 {
   DDRC &= !((1<<DD0)|(1<<DD1));
   PORTC = (1<<DD0)|(1<<DD1);
   TWSR = 0;                         /* no prescaler */
   TWBR = ((F_CPU/SCL_CLOCK)-16)/2;  /* must be > 10 for stable 
operation */


 }
int main(void)
{
  USART_init();
    I2C_init();

  TWSR = 0;
  TWBR = ((F_CPU/SCL_CLOCK)-16)/2;   // 72
  I2C_start(0x9B);


    while(1)
    {
        //TODO:: Please write your application code
    }
}

von Joe M. (taco)


Lesenswert?

Mit der Adresse 0x00 gibt es auch kein ACK.  Wo liegt der Fehler :-(

von (prx) A. K. (prx)


Lesenswert?

Statt einfach bloss "Bäh!" auszugeben könntest du den Status ausgeben. 
Soweit ich mit erinnere ist der bei Adresse und Daten verschieden.

von Joe M. (taco)


Lesenswert?

Status ausgeben?

Ich gebe doch was aus wenn ich ein ACK habe oder nicht.

von (prx) A. K. (prx)


Lesenswert?

Der gelieferte Inhalt von TW_STATUS. Das was dir nicht passt.

Konkret: Bei z.B. Master Write gibts 0x18 nach der Adresse und 0x28 nach 
einem Datenbyte. Du sendest eine Adresse und erwartest die Quittung für 
ein Datenbyte.

von Joe M. (taco)


Lesenswert?

TW_STATUS passt mir ja, dass klappt alles.
BZW. Start Codition wird gesendet.

Bekomme einfach kein ACK

Mein TWSR ist 64    =   0100 0000 (Binär)   falls du das meinst.

: Bearbeitet durch User
von (prx) A. K. (prx)


Lesenswert?

Joe M. schrieb:
> TW_STATUS passt mir ja, dass klappt alles.

Deine Aussage war bisher doch, du würdest auf die Adresse kein ACK 
kriegen. Dein Code dafür sieht bisher so aus:
1
  if((TWSR & 0xF8) != TW_MT_DATA_ACK)
2
  {
3
    USART_putstring("Kein ACK!!!");
4
  }
Dieser Code ist jedoch nur für Datenbytes im Master-Transmit geeignet, 
nicht aber für das Adressbyte in egal welchem Modus, da die Statemachine 
des TWI auch bei einer erfolgreichen Adressierung des Slave 
keinesfalls TW_MT_DATA_ACK liefert.

Eben darauf wollte ich dich mit dem Hinweis stossen, dass es wesentlich 
sinnvoller wäre, statt
  USART_putstring("Kein ACK!!!");
sowas wie
  USART_puthex("TWI Status=", TWST);
auszugeben. Damit du siehst, was tatsächlich passiert.

> Bekomme einfach kein ACK

Basierend auf Oszi/LA-Anzeige, oder basierend auf dem obigen Code? Dein 
Code ist für diese Aussage nicht geeignet. Der zeigt nur, dass du nicht 
jenen Status kriegst, den du erwartest hast.

: Bearbeitet durch User
von Daniel C. (cecky)


Lesenswert?

Joe M. schrieb:
> Bekomme einfach kein ACK
>
> Mein TWSR ist 64    =   0100 0000 (Binär)   falls du das meinst.

Dann schau doch mal in deine <util/twi.h> und schau nach was die 64 
(oder 0x40 als hex) bedeuten. Vielleicht wird dir dann klarer was dir 
A.K. sagen will

von Joe M. (taco)


Lesenswert?

Habe es  Danke sehr vielen dank :-D Jetzt klappt das ACK.
ok
Jetzt das 2 Problem.
Der Sensor sendet keine Daten

         i2c_init();
   i2c_start(0x9A); // Start Cond+ Sendet Adresse + SchreibBit
   i2c_write(0x00);   // Code für das lesen der Temp.
   i2c_start(0x9A+1);  //Start Cond+ Adresse + LeseBit
   int a = i2c_readNak(); // Hier kommt leider nur 0 raus :-(
   i2c_stop();

Was im I2C Angezeigt wird:
s     (Start Cod.)
9A A (Sendet 9A bekommt ACK)
00 A (Sendet 00 bekommt ACK)
Sr    (Start Cod.)
9B A   (Sendet 9B bekommt ACK)
00 N   (Beim lesen überträgt er nur 0er Bits)
p    ( Stop bed.)

: Bearbeitet durch User
von Datenblattleser (Gast)


Lesenswert?

Der TC74 schafft 8 Samples/Sec, also alle 125 ms eine. Du versuchst es 
aber glich nach dem Start. Gib ihm einfach mal etwas Zeit.

von Joe M. (taco)


Lesenswert?

JAAAAAAAAAAAAA ES KLAPPT

von Andre (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

ich versuche gerade die RTC RV-3029-C2 in Betrieb zu nehmen, leider ohne
Erfolg. Ich nutze Altmelstudio 7 mit Codevision-Plugin. Zum lesen und
schreiben über I2C/TWI nutze ich die twi_master_trans(). Andere I2C
Busteilnehmer konnte ich damit erfolgreich auslesen und schreiben. Zu
Testzwecken ist die RTC nun alleine am BUS. In Anhang findet Ihr ein
Oszi Bild. Dort ist zu sehen das die RTC kein ACK sendet. Pullups sind
jeweils 2,7k. Wo könnte der Fehler liegen? Achso, die twi_master_trans()
Funktion gibt auch zurück das ein ACK fehlt. SCL Rate ist 400k bps. 100k
bps geht aber auch nicht.

Danke schon im Vorraus :-)

Elektrischer Anschluss:
PIN1: 3,29V (gemessen)
PIN2: Offen
PIN3: Offen
PIN4: SCL (siehe Oszibild - CH Gelb)
PIN5: SDA (siehe Oszibild - CH Blau)
PIN6: 0V (gemessen)
PIN7: Offen
PIN8: 0V (gemessen, über 10k Pulldown an GND angeschlossen)
PIN9: Offen
PIN10: Offen

Quellcodeausschnitt:

#define I2C_ADRESSE  0xAC

//Nachrichten IDs
typedef enum {
  //Controll Page
  RTC_CONTROL1 = 0x00        ,      //
  RTC_CONTROL_INT            ,
  RTC_CONTROL_INT_FLAG       ,
  RTC_CONTROL_STATUS         ,
  RTC_CONTROL_RESET          ,
  // Clock Page
  RTC_SECONDS = 0x08         ,
  RTC_MINUTES                ,
  RTC_HOURS                  ,
  RTC_DAYS                   ,
  RTC_WEEKDAYS               ,
  RTC_MONTHS                 ,
  RTC_YEARS                  ,
  // ALARM PAGE
  RTC_SECOND_ALARM = 0x10    ,
  RTC_MINUTE_ALARM           ,
  RTC_HOUR_ALARM             ,
  RTC_DAY_ALARM              ,
  RTC_WEEKDAY_ALARM          ,
  RTC_MONTH_ALARM            ,
  RTC_YEAR_ALARM             ,
  // TIMER PAGE
  RTC_TIMER_LOW = 0x18       ,
  RTC_TIMER_HIGH             ,
  // TEMPERTUR PAGE
  RTC_TEMPERATURE = 0x20     ,
  // EEPROM USER PAGE
  RTC_EEPROM_USER1 = 0x28    ,
  RTC_EEPROM_USER2           ,
  // EEPROM CONTROL PAGE
  RTC_EEPROM_CONTROL = 0x30  ,
  RTC_EEPROM_XTAL_OFFSET     ,
  RTC_EEPROM_XTAL_COEF       ,
  RTC_EEPROM_XTAL_T0         ,
  // EEPROM CONTROL PAGE
  RTC_USER_RAM =     0x38    ,
  // Size
  RTC_SIZE     =     0x3F    ,
}tRTC_REG_ID;

void twie_init(void)
{
  // General TWIE initialization
  // External Driver Interface: OFff
  // SDA Hold: Off
  twi_init(&TWIE,false,TWI_SDAHOLD_OFF_gc);
  // Note: The directions of the SDA_IN (PORTE Pin 0), SCL_IN (PORTE Pin
1),
  // SDA_OUT (PORTE Pin 2) and SCL_OUT (PORTE Pin 3) signals are
configured
  // in the ports_init function

  // TWIE Master initialization
  // Master interrupt: Low Level
  // Peripheral Clock frequency: 32000000 Hz
  // SCL Rate: 400000 bps
  // Real SCL Rate: 400000 bps, Error: 0,0 %
  twi_master_init(&twie_master,&TWIE,TWI_MASTER_INTLVL_LO_gc,
  TWI_BAUD_REG(32000000,400000));

  // TWIE Slave is disabled
  TWIE.SLAVE.CTRLA=0;
}

void RTC_SetRegister(tRTC_REG_ID StartReg, uint8_t *Data, uint8_t Anz)
{
  uint8_t TX_Buffer[16];

  TX_Buffer[0] = StartReg;
  if(Anz < 16)
  {
    memcpy(&TX_Buffer[1], Data, Anz);
    twi_master_trans(&twie_master, I2C_ADRESSE, TX_Buffer, Anz + 1, 0,
0);
  }
}

void RTC_GetRegister(tRTC_REG_ID StartReg, uint8_t *Data, uint8_t Anz)
{
  uint8_t TX_Buffer[32];
  TX_Buffer[0] = StartReg;
  twi_master_trans(&twie_master, I2C_ADRESSE, TX_Buffer, 1, Data, Anz);
}

von Joachim B. (jar)


Lesenswert?

ehrlich?

ich würde die Fleury LIB installieren.
http://homepage.hispeed.ch/peterfleury/avr-software.html

Als letztes Zeichen muss ja NACK kommen und nicht ACK.
Ich würde nicht immer auf 16 Zeichen Antwort warten, ich weiss doch wie 
viel Zeichen ich erwarte und für das letzte muss es NACK sein.

Dann gibt es noch I2C Stretching auch das wäre zu prüfen, da neheme ich 
immer die Arduino LIB und versuche den Slave solange anzusprechen bis er 
wieder antwortet, kann ja auch mit einem Timeout kombiniert werden.

: Bearbeitet durch User
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.