Forum: Compiler & IDEs Software_TWI


von Patrice A. (patrice_a)


Lesenswert?

Hi

ich hab mir eine Software TWI zusammengebastelt da ich zurzeit mit dem 
ATmega162 arbeite. Es sollen mehrere Geräte angesteuert werden, darunter 
eine LM75 und ein externer EEPROM.

Eigentlich hab ich gedacht das alles funktioniert aber nun habe ich das 
Board gewechselt und schon geht garnichts mehr. Das das Board 
funktioniert ist schon geprüft, also da gibt es keine Probleme. Es liegt 
also an der Software.

Ich hab hier mal ein kleines Beispiel zusammengestellt von einem 
einfachen LM75 Lesevorgang.
1
Master Start:
2
3
DDRE &=~(1<<PE1);  // SCL High
4
_delay_loop_1(1);
5
DDRE|=(1<<PE0);    // SDA Low
6
_delay_us(3);
7
DDRE |=(1<<PE1);   // SCL Low
8
_delay_loop_1(1);
9
10
Master write(byte=Adresse des LM75 + BIT 0 =1):
11
12
char i=0;
13
for(i=0;i<8;i++)
14
{
15
   if(byte & 0x80)
16
   {
17
      DDRE&=~(1<<PE0);   // SDA High
18
   }
19
   else
20
   {
21
      DDRE|=(1<<PE0);    // SDA Low
22
   }
23
   byte=byte<<1;
24
   _delay_us(1);
25
26
   //SCL h->low .. Bit senden
27
   DDRE&=~(1<<PE1);
28
   _delay_loop_1(2);
29
   DDRE|=(1<<PE1);
30
   _delay_loop_1(1);
31
}
32
// ACK Prüfung
33
DDRE&=~(1<<PE0);     // SDA High
34
DDRE&=~(1<<PE1);     // SCL High
35
_delay_loop_1(1);
36
37
if(PINE & (1<<PE0))   // SDA auf high oder low prüfen
38
{
39
    _delay_loop_1(1);
40
    DDRE|=(1<<PE1);   // SCL low
41
    return 0;
42
}
43
else
44
{
45
    _delay_loop_1(1);
46
    DDRE|=(1<<PE1);   // SCL low
47
    return 1;
48
}
49
50
Master read(ack = 0, nack = 1)(das ganze zweimal wegen low und high byte):
51
52
char i;
53
char byte;
54
55
DDRE&=~(1<<PE0);
56
57
for(i=0;i<8;i++)
58
{
59
    byte=byte<<1;
60
    if(PORTE & (1<<PINE)) byte|=1;
61
    //SCL h->low .. Bit empfangen
62
   DDRE&=~(1<<PE1);
63
   _delay_loop_1(2);
64
   DDRE|=(1<<PE1);
65
   _delay_loop_1(1);
66
}
67
if (ack=0)
68
{
69
    DDRE|=(1<<PE0);    //SDA low
70
}
71
else
72
{
73
    DDRE&=~(1<<PE0);   //SDA high
74
}
75
//SCL h->low .. Bit senden
76
   DDRE&=~(1<<PE1);
77
   _delay_loop_1(2);
78
   DDRE|=(1<<PE1);
79
   _delay_loop_1(1);
80
81
return byte;
82
83
84
Master Stop:
85
86
DDRE|=(1<<PE0);     // SDA vorsichtshalber auf low
87
_delay_loop_1(1);
88
DDRE&=~(1<<PE1);    // SCL high
89
_delay_loop_1(1);
90
DDRE&=~(1<<PE0);    // SDA high;
91
_delay_loop_1(1);


So sieht jemand irgendwo einen Fehler im Aufbau/Ablauf?
Klar sind das keine vollständigen Funktionen, das ist ja auch nur ein 
Beispiel.
Ein Problem hat die ACK Prüfung dargestellt, sieht da jemand vielleicht 
etwas?
Hat jemand vielleicht einen eigenen C Code geschrieben wo ich mal 
vergleichen kann?
Also wenn ich das am LM75 prüfe dann erhalte ich laut Software ein ACK 
aber das auslesen ist dann immer 0.
Wo liegt das Problem?


Gruss

von Krapao (Gast)


Lesenswert?

Ich sehe in den Codefetzen keine Aktivierung von internen Pullups und 
z.B. diese Zeile setzt Pullups voraus:

DDRE &=~(1<<PE1);  // SCL High

Daher die Frage: Sind externe Pullups auf dem Board und sind die per 
Jumper dazuschaltbar? Wenn ja, wurde auch die Stellung der Jumper 
geprüft?

von Krapao (Gast)


Lesenswert?

Nachtrag:

> DDRE &=~(1<<PE1);  // SCL High
> delay...
> DDRE |=(1<<PE1);   // SCL Low
> delay...

Ich wegen DDRE an, es handelt sich um einen AVR µC. Das oben 
funktioniert allein durch Umschalten der Datenrichtung Input <> Output 
ohne zusätzlich den Pegel am PORTE zu setzen? Wie sieht die Schaltung 
aus?

von Krapao (Gast)


Lesenswert?

> ATmega162

achso da steht's ja

von Krapao (Gast)


Lesenswert?

Angenommen du hast PORTE.1 nie gesetzt sondern noch vom Reset her 
PORTE.1 = 0 und du hast keine externen Pullups/Pulldowns.

Dann liefert dir diese Zeile korrekt einen LOW Pegel
> DDRE |=(1<<PE1);   // SCL Low

ABER diese Zeile liefert keinen garantierten HIGH Pegel:
> DDRE &=~(1<<PE1);  // SCL High

Es wird lediglich der Pin PE1 auf Eingang geschaltet und du hast dort 
einen Z-Pegel. Der Eingang ist jetzt hochohmig. Der Pegel auf dem 
angeschlossenen Bus ist nicht sicher entweder HIGH oder LOW! Es können 
Kommandos an den Slave verloren gehen und es können Daten an den Master 
verloren gehen...

von Patrice A. (patrice_a)


Lesenswert?

Danke für die schnelle antwort

Also ok hmm es sind externe Pull Ups vorhanden

Ich habe selber schonein Paar Fehler gefunden .. also ich hab da 
eindeutig was mit den Registern verhauen
Beim lesen muss ich das beim PORT Reg prüfen und nicht beim DDR.
DDRE als Eingang und dann am PORT prüfen, das klingt eigentlich 
sinnvoll. Ich habe mir nochmal einen Artikel über Pullup und Pulldown 
Widerstände angesehen und sehe da nun ein wenig klarer.


Ich denke ich überarbeite die ganze Angelegenheit nocheinmal und achte 
auf die richtigen Register.
Die Frage ist warum das vorher überhaupt funktioniert hat -.-.

Ich danke dir für deine Hilfe das hat mir aufjedenfall einen Denkanstoß 
gegeben.

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.