Forum: Mikrocontroller und Digitale Elektronik Problem mit myTWI Echtzeituhr.


von Robert St. (Gast)


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:
1
m:main
2
3
menu:main
4
OK
5
mode mh
6
7
OK
8
------------- Board: Power off,
9
pwr 0
10
11
OK
12
------------- Prozessor inaktiv, Power on
13
rst 1
14
15
OK
16
pwr 1
17
18
OK
19
------------- Init TWI ---------------
20
m:twi
21
22
menu:twi
23
OK (status F8=No relevant state information available)
24
ima
25
26
OK (status F8=No relevant state information available)
27
------------- Register adressieren ------
28
sta
29
30
OK (status 08=A START condition has been transmitted)
31
wr 0xD0
32
33
OK (status 20=SLA+W has been transmitted; NOT ACK has been received)
34
wr 0x00
35
36
OK (status 30=Data byte has been transmitted; NOT ACK has been received)
37
------------- Werte lesen ---------------
38
sta
39
40
OK (status 10=A repeated START condition has been transmitted)
41
wr 0xD1
42
43
OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
44
ack 1
45
46
OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
47
rd
48
49
E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
50
rd
51
52
E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
53
ack 0
54
55
OK (status 48=SLA+R has been transmitted; NOT ACK has been received)
56
rd
57
58
E1:timeout ERROR (status 48=SLA+R has been transmitted; NOT ACK has been received)
59
sto
60
61
OK (status F8=No relevant state information available)

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

von Robert St. (Gast)


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^^

von Robert St. (Gast)


Lesenswert?

Hat denn niemand einen Ansatz?

von Peter D. (peda)


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

von Robert St. (Gast)


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?

von Sascha W. (sascha-w)


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

von Peter D. (peda)


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

von Robert St. (Gast)


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
1
#define   F_CPU   3686400
2
#include <avr\io.h>
3
#include <stdio.h>
4
#include <util\delay.h>
5
 void lcdWriteString(char* text);
6
 void lcdGoto(int row, int col);
7
//---------------------------------------------------------------------------------
8
// TWI-Funktionssammlung
9
#ifndef TWI_CLOCK
10
#define TWI_CLOCK 100000 // Geschwindigkeit des TWI-Busses
11
#endif
12
// TWCR - Control-Register-Bits
13
#define _TWINT 0b10000000
14
#define _TWEA 0b01000000
15
#define _TWSTA 0b00100000
16
#define _TWSTO 0b00010000
17
#define _TWWC 0b00001000
18
#define _TWEN 0b00000100
19
#define _TWIE 0b00000001
20
uint8_t   twiAdr = 0xD0;
21
//------------------------------------------------------------------------
22
// twiInitMaster
23
//------------------------------------------------------------------------
24
void twiInitMaster(uint8_t twiAdr)
25
{
26
   // Clock
27
   TWBR=((F_CPU/TWI_CLOCK)-16)*2;
28
   // TWI-Status-Register (Vorteiler)
29
   TWSR=0;
30
   // Bus-Addr
31
   TWAR=twiAdr;
32
   // Enable
33
   TWCR=_TWINT|_TWEN;
34
}
35
//------------------------------------------------------------------------
36
// Start TWI (ohne Interrupt)
37
//------------------------------------------------------------------------
38
void twiStart()
39
{
40
   uint8_t x=TWCR;
41
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
42
   TWCR=x|_TWINT|_TWSTA;
43
   // warten bis fertig
44
   while( !(TWCR & _TWINT))
45
   {}
46
}
47
//------------------------------------------------------------------------
48
// Stopp TWI (ohne Interrupt)
49
//------------------------------------------------------------------------
50
void twiStop()
51
{
52
   uint8_t x=TWCR;
53
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
54
   TWCR=x|_TWINT|_TWSTO;
55
}
56
//------------------------------------------------------------------------
57
// Write Byte per TWI (ohne Interrupt)
58
// PE: data = zu sendende Daten
59
//     ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
60
//------------------------------------------------------------------------
61
void twiWriteByte(uint8_t data, uint8_t ackn)
62
{
63
   TWDR=data;      // Daten bereitlegen
64
   // Befehl zusammenstellen
65
   uint8_t x=TWCR;
66
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
67
   x|=_TWINT;
68
   if(ackn)   
69
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
70
   TWCR=x;         // senden
71
   // warten bis fertig
72
   while( !(TWCR & _TWINT))
73
   {}
74
}
75
//------------------------------------------------------------------------
76
// Read Byte per TWI (ohne Interrupt)
77
// PE: ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
78
// PA: Data
79
//------------------------------------------------------------------------
80
int twiReadByte(uint8_t ackn)
81
{
82
   // Befehl zusammenstellen
83
   uint8_t x=TWCR;
84
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
85
   x|=_TWINT;
86
   if(ackn)   
87
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
88
   TWCR=x;         // senden
89
   // warten bis fertig
90
   while( !(TWCR & _TWINT))
91
   {}
92
   return TWDR;
93
}
94
95
//-------------------------------------------------------------------------
96
// rtcGetRtcData
97
//-------------------------------------------------------------------------
98
uint8_t rtcGetRtcData(uint8_t Register)
99
{
100
   // Adresse senden   
101
   twiStart();
102
   twiWriteByte(twiAdr,0);
103
   twiWriteByte(Register,1);
104
   // Daten lesen
105
   twiStart();
106
   twiWriteByte(twiAdr+1,1);
107
   uint8_t b = (uint8_t)twiReadByte(0);
108
   twiStop();
109
   return b;
110
}
111
//-------------------------------------------------------------------------
112
// rtcGetSeconds
113
//-------------------------------------------------------------------------
114
uint8_t rtcGetSeconds()
115
{
116
   return rtcGetRtcData(0) & 0x7F;
117
}
118
//-------------------------------------------------------------------------
119
// rtcGetMinute
120
//-------------------------------------------------------------------------
121
uint8_t rtcGetMinute()
122
{
123
   return rtcGetRtcData(1);
124
}
125
//-------------------------------------------------------------------------
126
// rtcGetHour
127
//-------------------------------------------------------------------------
128
uint8_t rtcGetHour()
129
{
130
   return rtcGetRtcData(2) & 0x3F;
131
}
132
//-------------------------------------------------------------------------
133
// rtcWaitMs
134
//-------------------------------------------------------------------------
135
void rtcWaitMs(int miliSec)
136
{
137
   _delay_loop_2( 1*(F_CPU/(1000/4)) * miliSec);   // 4 Zyklen warteschleife
138
}

und bei dem fuktioniert es: (ist eig identisch bis auf die twiAdresse)
1
#define   F_CPU   3686400
2
#include <avr\io.h>
3
 void lcdWrite(char* pText);
4
 uint8_t twiAdr=0x90;   // Feste und Variable (per Jumper) Adresse
5
#define   BAUD   9600
6
//---------------------------------------------------------------------------------
7
// TWI-Funktionssammlung
8
//---------------------------------------------------------------------------------
9
#ifndef TWI_CLOCK
10
#define TWI_CLOCK 100000 // Geschwindigkeit des TWI-Busses
11
#endif
12
// TWCR - Control-Register-Bits
13
#define _TWINT 0b10000000
14
#define _TWEA 0b01000000
15
#define _TWSTA 0b00100000
16
#define _TWSTO 0b00010000
17
#define _TWWC 0b00001000
18
#define _TWEN 0b00000100
19
#define _TWIE 0b00000001
20
#define REG_LM75_TEMP 0b00000000
21
#define REG_LM75_CONFIG 0b00000001
22
#define REG_LM75_HYST 0b00000010
23
#define REG_LM75_SET 0b00000011
24
#ifndef TWI_READ
25
#define TWI_READ 0b00000001
26
#endif
27
#ifndef TWI_WRITE
28
#define TWI_WRITE 0b00000000
29
#endif
30
#include <util\delay.h>
31
32
//----------------------------------------------------------------------
33
// Titel   : C-Funktion Zeichen zu UART senden.
34
//----------------------------------------------------------------------
35
// Funktion   : ...
36
// IN       : char data
37
// OUT      : ...
38
//----------------------------------------------------------------------
39
void uartPutChar(char data)
40
{
41
    //warte bis UDR leer ist UCSRA / USR bei z.B.: 2313
42
    while (!(UCSRA&32));
43
    //sende
44
    UDR=data;
45
}
46
//----------------------------------------------------------------------
47
// Titel   : C-Funktion Zeichen von UART holen.
48
//----------------------------------------------------------------------
49
// Funktion   : ...
50
// IN       : ...
51
// OUT      : data
52
//----------------------------------------------------------------------
53
char uartGetChar()
54
{
55
   char data=0;
56
    //warte bis RX-complete RXC UCSRA / USR bei z.B.: AT090S2313
57
    while (!(UCSRA&128));
58
   //empfangen
59
    data=UDR;
60
      return data;
61
}
62
//----------------------------------------------------------------------
63
// Titel   : C-Funktion Zeichenkette zu UART senden.
64
//----------------------------------------------------------------------
65
// Funktion   : ...
66
// IN       : char *buffer, Zeichenkette mit NUll abgeschlossen
67
// OUT      : ...
68
//----------------------------------------------------------------------
69
void uartPutString(char *buffer)
70
{
71
   for (int i=0; buffer[i] !=0;i++)
72
      uartPutChar (buffer[i]);
73
}
74
75
//------------------------------------------------------------------------
76
// twiInitMaster
77
//------------------------------------------------------------------------
78
void twiInitMaster(uint8_t twiAdr)
79
{
80
   // Clock
81
   TWBR=((F_CPU/TWI_CLOCK)-16)*2;
82
   // TWI-Status-Register (Vorteiler)
83
   TWSR=0;
84
   // Bus-Addr
85
   TWAR=twiAdr;
86
   // Enable
87
   TWCR=_TWINT|_TWEN;
88
}
89
//------------------------------------------------------------------------
90
// Start TWI (ohne Interrupt)
91
//------------------------------------------------------------------------
92
void twiStart()
93
{
94
   uint8_t x=TWCR;
95
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
96
   TWCR=x|_TWINT|_TWSTA;
97
   // warten bis fertig
98
   while( !(TWCR & _TWINT))
99
   {}
100
}
101
//------------------------------------------------------------------------
102
// Stopp TWI (ohne Interrupt)
103
//------------------------------------------------------------------------
104
void twiStop()
105
{
106
   uint8_t x=TWCR;
107
   x&=_TWEN|_TWIE;    // nur Beibehalten von Enable und InterruptJ/N 
108
   TWCR=x|_TWINT|_TWSTO;
109
}
110
//------------------------------------------------------------------------
111
// Write Byte per TWI (ohne Interrupt)
112
// PE: data = zu sendende Daten
113
//     ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
114
//------------------------------------------------------------------------
115
void twiWriteByte(uint8_t data, uint8_t ackn)
116
{
117
   TWDR=data;      // Daten bereitlegen
118
   // Befehl zusammenstellen
119
   uint8_t x=TWCR;
120
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
121
   x|=_TWINT;
122
   if(ackn)   
123
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
124
   TWCR=x;         // senden
125
   // warten bis fertig
126
   while( !(TWCR & _TWINT))
127
   {}
128
}
129
//------------------------------------------------------------------------
130
// Read Byte per TWI (ohne Interrupt)
131
// PE: ackn = wenn !=0 wird Acknowledge (=TWEA) gesetzt
132
// PA: Data
133
//------------------------------------------------------------------------
134
int twiReadByte(uint8_t ackn)
135
{
136
   // Befehl zusammenstellen
137
   uint8_t x=TWCR;
138
   x&=_TWEN|_TWIE;      //nur Beibehalten von Enable und InterruptJ/N 
139
   x|=_TWINT;
140
   if(ackn)   
141
      x|=_TWEA;   // evt. TWEA setzen, für Datenanforderung
142
   TWCR=x;         // senden
143
   // warten bis fertig
144
   while( !(TWCR & _TWINT))
145
   {}
146
   return TWDR;
147
}
148
149
//------------------------------------------------------------------------
150
// lm75SetRegister - schreibt ein Register des LM75
151
// PE: twiAdr = TWI-Adresse der LM75
152
//     Register = REG_CONFIG,REG_HYST,REG_SET
153
//     lowData,highData = zu schreibende Werte
154
//------------------------------------------------------------------------
155
void lm75SetRegister(uint8_t twiAdr,uint8_t reg, uint8_t highData, uint8_t lowData)
156
{
157
   twiStart();
158
   //Adresse senden
159
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
160
   //Register adressieren
161
   twiWriteByte(reg,0);            // kein ACKN
162
   //Wert schreiben
163
   twiWriteByte(highData,0);         // kein ACKN
164
   //Wert schreiben
165
   twiWriteByte(lowData,0);         // kein ACKN
166
   // Stopp
167
   twiStop();
168
169
}
170
//------------------------------------------------------------------------
171
// Init
172
// PE: twiAdr = TWI-Adresse der LM75
173
//------------------------------------------------------------------------
174
void lm75Init(uint8_t twiAdr, uint8_t compTemp=0,uint8_t compTempHalf=0)
175
{
176
   // Config = NoShutdown,ComperatorMode,ActiveLow,FaultQueue=0
177
   lm75SetRegister(twiAdr,REG_LM75_CONFIG,0,0);
178
   // keine Hysterese
179
   lm75SetRegister(twiAdr,REG_LM75_HYST,0,0);
180
   // Comperator-PIN schaltet z.B. bei = 0x1C = 28   C
181
   lm75SetRegister(twiAdr,REG_LM75_SET,compTemp,compTempHalf);
182
}
183
//------------------------------------------------------------------------
184
// Liest die aktuelle Temperatur
185
// PE: twiAdr = TWI-Adresse der LM75
186
// PA: Temperatur in Grad
187
//------------------------------------------------------------------------
188
uint8_t lm75GetTempGrad(uint8_t twiAdr)
189
{
190
   // TWI starten
191
   twiStart();
192
   // Adresse senden
193
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
194
   // Temperatur adressieren
195
   twiWriteByte(REG_LM75_TEMP,0);         // kein ACKN
196
197
   //--- Lesezyklus
198
   // TWI re-starten
199
   twiStart();
200
   // Adresse senden
201
   twiWriteByte((twiAdr&0xfe)|TWI_READ,1);      // mit ACKN = acknowledge = TWI-Datenanforderung
202
   // lesen
203
   uint8_t   highData=twiReadByte(1);      // mit ACKN = acknowledge = TWI-Datenanforderung
204
   uint8_t   lowData=twiReadByte(0);         // kein ACKN
205
   // Stopp
206
   twiStop();
207
   return highData;
208
}
209
//------------------------------------------------------------------------
210
// Liest die aktuelle Temperatur
211
// PE: twiAdr = TWI-Adresse der LM75
212
// PA: Temperatur in 1/10 Grad
213
//------------------------------------------------------------------------
214
uint8_t lm75GetTempDecGrad(uint8_t twiAdr)
215
{
216
   // TWI starten
217
   twiStart();
218
   // Adresse senden
219
   twiWriteByte((twiAdr&0xfe)|TWI_WRITE,0);   // kein ACKN
220
   // Temperatur adressieren
221
   twiWriteByte(REG_LM75_TEMP,0);         // kein ACKN
222
223
   //--- Lesezyklus
224
   // TWI re-starten
225
   twiStart();
226
   // Adresse senden
227
   twiWriteByte((twiAdr&0xfe)|TWI_READ,1);      // mit ACKN = acknowledge = TWI-Datenanforderung
228
   // lesen
229
   uint8_t   highData=twiReadByte(1);      // mit ACKN = acknowledge = TWI-Datenanforderung
230
   uint8_t   lowData=twiReadByte(0);         // kein ACKN
231
232
   // Stopp
233
   twiStop();
234
   return (highData<<1)|(lowData>>7);
235
}

von Robert St. (Gast)


Lesenswert?

Ich bin grad echt am Verzweifeln :(

von Peter D. (peda)


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

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.