mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Problem mit myTWI Echtzeituhr.


Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Community, ich habe ein kleines Problem; und zwar funktioniert meine 
myTwi Echtzeituhr ganz plötzlich nicht mehr...
Ich weiß nicht woran das liegen kann; am Programiercode liegt es 
nicht,da der nämlich gestern noch wunderbar lief. Es muss also an der 
Hardware liegen, denke ich.
Bisher habe ich den Atmega8 ersetzt und eine andere TWI Echtzeituhr 
angeschlossen, wobei ich das Problem dabei nicht gelöst habe :(
Wenn ich die Uhrzeit auf einen LCD anzeigen lasse, steht da nur 00:00 
und laut dem folgenden Test, erhält der AtMega keine Daten von der TWI 
Echtzeituhr:
Ich habe mal das MySamertUsb Terminal runtergeldaden und die Echtzeituhr 
getestet...
Das kam dabei raus:
m:main

menu:main
OK
mode mh

OK
------------- Board: Power off,
pwr 0

OK
------------- Prozessor inaktiv, Power on
rst 1

OK
pwr 1

OK
------------- Init TWI ---------------
m:twi

menu:twi
OK (status F8=No relevant state information available)
ima

OK (status F8=No relevant state information available)
------------- Register adressieren ------
sta

OK (status 08=A START condition has been transmitted)
wr 0xD0

OK (status 20=SLA+W has been transmitted; NOT ACK has been received)
wr 0x00

OK (status 30=Data byte has been transmitted; NOT ACK has been received)
------------- Werte lesen ---------------
sta

OK (status 10=A repeated START condition has been transmitted)
wr 0xD1

OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
ack 1

OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
rd

E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
rd

E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
ack 0

OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
rd

E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
sto

OK (status F8=No relevant state information available)

Ich wäre ausgesprochen dankbar, wenn mir jemand helfen könnte...
Gruß

Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch eine kleine Ergänzung und zwar habe ich soeben meinen TWI 
Temperatur Sensor angeschlossen und dieser funktioniert??? Beide myTwi 
Echzeituhren funktionieren aber nicht??
Ich verstehe die Welt nicht mehr^^

Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hat denn niemand einen Ansatz?

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert St. schrieb:
> wr 0xD0
>
> OK (status 20=SLA+W has been transmitted; NOT ACK has been received)

Da steht doch eindeutig, daß auf die Adresse 0xD0 kein Device 
geantwortet hat. Alles dahinter ist also vollkommen sinnlos.

Ich weiß ja nicht, welche RTC Du benutzt, kann also nicht sagen, ob die 
Adresse stimmt.
Außerdem gibts bei den meisten I2C-Chips noch 1..3 Adreßwahlpins, falls 
man mehrere parallel schalten will.


Du mußt Dich schonmal selber mit den absoluten Grundlagen des I2C 
beschäftigen und ihn nicht nur als schwarzen Kasten ansehen. Sonst 
kommst Du nie weiter.


Peter

Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das mag ja sein, aber warum funktionierts 4 Monate mit dem selben Code 
und heute plötlich nicht? Die selbe Adresse hat zuvor immer 
funktioniert. Ist da etwas defekt gegangen oder wie soll ich mir das 
erklären?

Autor: Sascha Weber (sascha-w)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert St. schrieb:
> Noch eine kleine Ergänzung und zwar habe ich soeben meinen TWI
> Temperatur Sensor angeschlossen und dieser funktioniert???
Hast du hier den Code dafür angepasst ??
Frequenz des TWI erhöht ?

Sascha

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert St. schrieb:
> Ist da etwas defekt gegangen oder wie soll ich mir das
> erklären?

Prüf dochmal, ob die beiden Pullups dran sind, zur Sicherheit mal auf 
1,8..2,7k reduzieren.
Wie ist denn Dein Aufbau?
Alles schön gelötet oder Drahtverhau und Bredboard.


Peter

Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Die PullUps sind drin...
Ich benutze diese Echtzeituhr von myAvr:
http://www.myavr.info/download/techb_mytwi_rtc.pdf

Das sind die Einstellungen, bei dems nicht funktiniert
#define   F_CPU   3686400
#include <avr\io.h>
#include <stdio.h>
#include <util\delay.h>
 void lcdWriteString(char* text);
 void lcdGoto(int row, int col);
//---------------------------------------------------------------------------------
// TWI-Funktionssammlung
#ifndef TWI_CLOCK
#define TWI_CLOCK 100000 // Geschwindigkeit des TWI-Busses
#endif
// TWCR - Control-Register-Bits
#define _TWINT 0b10000000
#define _TWEA 0b01000000
#define _TWSTA 0b00100000
#define _TWSTO 0b00010000
#define _TWWC 0b00001000
#define _TWEN 0b00000100
#define _TWIE 0b00000001
uint8_t   twiAdr = 0xD0;
//------------------------------------------------------------------------
// twiInitMaster
//------------------------------------------------------------------------
void twiInitMaster(uint8_t twiAdr)
{
   // Clock
   TWBR=((F_CPU/TWI_CLOCK)-16)*2;
   // TWI-Status-Register (Vorteiler)
   TWSR=0;
   // Bus-Addr
   TWAR=twiAdr;
   // Enable
   TWCR=_TWINT|_TWEN;
}
//------------------------------------------------------------------------
// Start TWI (ohne Interrupt)
//------------------------------------------------------------------------
void twiStart()
{
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
   TWCR=x|_TWINT|_TWSTA;
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
}
//------------------------------------------------------------------------
// Stopp TWI (ohne Interrupt)
//------------------------------------------------------------------------
void twiStop()
{
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
   TWCR=x|_TWINT|_TWSTO;
}
//------------------------------------------------------------------------
// Write Byte per TWI (ohne Interrupt)
// PE: data = zu sendende Daten
//     ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
//------------------------------------------------------------------------
void twiWriteByte(uint8_t data, uint8_t ackn)
{
   TWDR=data;      // Daten bereitlegen
   // Befehl zusammenstellen
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
   x|=_TWINT;
   if(ackn)   
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
   TWCR=x;         // senden
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
}
//------------------------------------------------------------------------
// Read Byte per TWI (ohne Interrupt)
// PE: ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
// PA: Data
//------------------------------------------------------------------------
int twiReadByte(uint8_t ackn)
{
   // Befehl zusammenstellen
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
   x|=_TWINT;
   if(ackn)   
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
   TWCR=x;         // senden
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
   return TWDR;
}

//-------------------------------------------------------------------------
// rtcGetRtcData
//-------------------------------------------------------------------------
uint8_t rtcGetRtcData(uint8_t Register)
{
   // Adresse senden   
   twiStart();
   twiWriteByte(twiAdr,0);
   twiWriteByte(Register,1);
   // Daten lesen
   twiStart();
   twiWriteByte(twiAdr+1,1);
   uint8_t b = (uint8_t)twiReadByte(0);
   twiStop();
   return b;
}
//-------------------------------------------------------------------------
// rtcGetSeconds
//-------------------------------------------------------------------------
uint8_t rtcGetSeconds()
{
   return rtcGetRtcData(0) & 0x7F;
}
//-------------------------------------------------------------------------
// rtcGetMinute
//-------------------------------------------------------------------------
uint8_t rtcGetMinute()
{
   return rtcGetRtcData(1);
}
//-------------------------------------------------------------------------
// rtcGetHour
//-------------------------------------------------------------------------
uint8_t rtcGetHour()
{
   return rtcGetRtcData(2) & 0x3F;
}
//-------------------------------------------------------------------------
// rtcWaitMs
//-------------------------------------------------------------------------
void rtcWaitMs(int miliSec)
{
   _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec);   // 4 Zyklen warteschleife
}

und bei dem fuktioniert es: (ist eig identisch bis auf die twiAdresse)
#define   F_CPU   3686400
#include <avr\io.h>
 void lcdWrite(char* pText);
 uint8_t twiAdr=0x90;   // Feste und Variable (per Jumper) Adresse
#define   BAUD   9600
//---------------------------------------------------------------------------------
// TWI-Funktionssammlung
//---------------------------------------------------------------------------------
#ifndef TWI_CLOCK
#define TWI_CLOCK 100000 // Geschwindigkeit des TWI-Busses
#endif
// TWCR - Control-Register-Bits
#define _TWINT 0b10000000
#define _TWEA 0b01000000
#define _TWSTA 0b00100000
#define _TWSTO 0b00010000
#define _TWWC 0b00001000
#define _TWEN 0b00000100
#define _TWIE 0b00000001
#define REG_LM75_TEMP 0b00000000
#define REG_LM75_CONFIG 0b00000001
#define REG_LM75_HYST 0b00000010
#define REG_LM75_SET 0b00000011
#ifndef TWI_READ
#define TWI_READ 0b00000001
#endif
#ifndef TWI_WRITE
#define TWI_WRITE 0b00000000
#endif
#include <util\delay.h>

//----------------------------------------------------------------------
// Titel   : C-Funktion Zeichen zu UART senden.
//----------------------------------------------------------------------
// Funktion   : ...
// IN       : char data
// OUT      : ...
//----------------------------------------------------------------------
void uartPutChar(char data)
{
    //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
    while (!(UCSRA&32));
    //sende
    UDR=data;
}
//----------------------------------------------------------------------
// Titel   : C-Funktion Zeichen von UART holen.
//----------------------------------------------------------------------
// Funktion   : ...
// IN       : ...
// OUT      : data
//----------------------------------------------------------------------
char uartGetChar()
{
   char data=0;
    //warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
    while (!(UCSRA&128));
   //empfangen
    data=UDR;
      return data;
}
//----------------------------------------------------------------------
// Titel   : C-Funktion Zeichenkette zu UART senden.
//----------------------------------------------------------------------
// Funktion   : ...
// IN       : char *buffer, Zeichenkette mit NUll abgeschlossen
// OUT      : ...
//----------------------------------------------------------------------
void uartPutString(char *buffer)
{
   for (int i=0; buffer[i] !=0;i++)
      uartPutChar (buffer[i]);
}

//------------------------------------------------------------------------
// twiInitMaster
//------------------------------------------------------------------------
void twiInitMaster(uint8_t twiAdr)
{
   // Clock
   TWBR=((F_CPU/TWI_CLOCK)-16)*2;
   // TWI-Status-Register (Vorteiler)
   TWSR=0;
   // Bus-Addr
   TWAR=twiAdr;
   // Enable
   TWCR=_TWINT|_TWEN;
}
//------------------------------------------------------------------------
// Start TWI (ohne Interrupt)
//------------------------------------------------------------------------
void twiStart()
{
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
   TWCR=x|_TWINT|_TWSTA;
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
}
//------------------------------------------------------------------------
// Stopp TWI (ohne Interrupt)
//------------------------------------------------------------------------
void twiStop()
{
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
   TWCR=x|_TWINT|_TWSTO;
}
//------------------------------------------------------------------------
// Write Byte per TWI (ohne Interrupt)
// PE: data = zu sendende Daten
//     ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
//------------------------------------------------------------------------
void twiWriteByte(uint8_t data, uint8_t ackn)
{
   TWDR=data;      // Daten bereitlegen
   // Befehl zusammenstellen
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
   x|=_TWINT;
   if(ackn)   
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
   TWCR=x;         // senden
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
}
//------------------------------------------------------------------------
// Read Byte per TWI (ohne Interrupt)
// PE: ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
// PA: Data
//------------------------------------------------------------------------
int twiReadByte(uint8_t ackn)
{
   // Befehl zusammenstellen
   uint8_t x=TWCR;
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
   x|=_TWINT;
   if(ackn)   
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
   TWCR=x;         // senden
   // warten bis fertig
   while( !(TWCR & _TWINT))
   {}
   return TWDR;
}

//------------------------------------------------------------------------
// lm75SetRegister - schreibt ein Register des LM75
// PE: twiAdr = TWI-Adresse der LM75
//     Register = REG_CONFIG,REG_HYST,REG_SET
//     lowData,highData = zu schreibende Werte
//------------------------------------------------------------------------
void lm75SetRegister(uint8_t twiAdr,uint8_t reg, uint8_t highData, uint8_t lowData)
{
   twiStart();
   //Adresse senden
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
   //Register adressieren
   twiWriteByte(reg,0);            // kein ACKN
   //Wert schreiben
   twiWriteByte(highData,0);         // kein ACKN
   //Wert schreiben
   twiWriteByte(lowData,0);         // kein ACKN
   // Stopp
   twiStop();

}
//------------------------------------------------------------------------
// Init
// PE: twiAdr = TWI-Adresse der LM75
//------------------------------------------------------------------------
void lm75Init(uint8_t twiAdr, uint8_t compTemp=0,uint8_t compTempHalf=0)
{
   // Config = NoShutdown,ComperatorMode,ActiveLow,FaultQueue=0
   lm75SetRegister(twiAdr,REG_LM75_CONFIG,0,0);
   // keine Hysterese
   lm75SetRegister(twiAdr,REG_LM75_HYST,0,0);
   // Comperator-PIN schaltet z.B. bei = 0x1C = 28   C
   lm75SetRegister(twiAdr,REG_LM75_SET,compTemp,compTempHalf);
}
//------------------------------------------------------------------------
// Liest die aktuelle Temperatur
// PE: twiAdr = TWI-Adresse der LM75
// PA: Temperatur in Grad
//------------------------------------------------------------------------
uint8_t lm75GetTempGrad(uint8_t twiAdr)
{
   // TWI starten
   twiStart();
   // Adresse senden
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
   // Temperatur adressieren
   twiWriteByte(REG_LM75_TEMP,0);         // kein ACKN

   //--- Lesezyklus
   // TWI re-starten
   twiStart();
   // Adresse senden
   twiWriteByte((twiAdr&0xfe)|TWI_READ,1);      // mit ACKN = acknowledge = TWI-Datenanforderung
   // lesen
   uint8_t   highData=twiReadByte(1);      // mit ACKN = acknowledge = TWI-Datenanforderung
   uint8_t   lowData=twiReadByte(0);         // kein ACKN
   // Stopp
   twiStop();
   return highData;
}
//------------------------------------------------------------------------
// Liest die aktuelle Temperatur
// PE: twiAdr = TWI-Adresse der LM75
// PA: Temperatur in 1/10 Grad
//------------------------------------------------------------------------
uint8_t lm75GetTempDecGrad(uint8_t twiAdr)
{
   // TWI starten
   twiStart();
   // Adresse senden
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
   // Temperatur adressieren
   twiWriteByte(REG_LM75_TEMP,0);         // kein ACKN

   //--- Lesezyklus
   // TWI re-starten
   twiStart();
   // Adresse senden
   twiWriteByte((twiAdr&0xfe)|TWI_READ,1);      // mit ACKN = acknowledge = TWI-Datenanforderung
   // lesen
   uint8_t   highData=twiReadByte(1);      // mit ACKN = acknowledge = TWI-Datenanforderung
   uint8_t   lowData=twiReadByte(0);         // kein ACKN

   // Stopp
   twiStop();
   return (highData<<1)|(lowData>>7);
}

Autor: Robert St. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich bin grad echt am Verzweifeln :(

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Robert St. schrieb:
> Ich bin grad echt am Verzweifeln :(

Weil Du nicht systematisch suchst.
Du weißt, Du kriegst auf die Adresse ein NACK. Da mußt Du die Ursache 
ergründen.
Nur stur auf den Code zu starren, hilft da nicht.

Deine I2C-Funktionen taugen nichts. Jede Operation kann scheitern, z.B. 
durch Störungen auf dem Bus. Daher immer einen Fehlercode zurückliefern 
und auswerten.
Es hat sich eingebürgert, 0 steht für kein Fehler, dann kann man mit 
1..255 verschiedene Fehler kennzeichnen.

"int" als Rückgabe eines Bytes ist Unsinn, kostet aufm 8-Bitter mehrere 
Instruktionen. Entweder "unsigned char" oder "uint8_t".

Einfache Faustregel: Solange 8Bit unsigned reicht, dann nimm es!


Peter

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.