Atmega TWI EEprom

Gast #2147575
Lesenswert?

Moin,

ich versuche mich grade in die Materie von µC einzuüben und versuche 
grade den von mir geschrieben Code auszuführen.

Das Problem ist das lesen/schreiben eines EEPROM mittels Atmega.

Es handelt sich um einen Atmega16L und 24LC256m EEPROM.
Ich möchte ein Byte an eine bestimmte Adresse speichern, danach wieder 
auslesen und an einem Port ausgeben.

Dazu habe ich 2 Unterprogramme geschrieben, read und write.
Das Problem ist, dass nach schreiben und lesen im Datenregister des TWI 
immernoch das zuvor abgeschickte Controllbyte noch enthalten ist und 
nicht der erwartete zuvpor gespeicherte Wert.

Die Reihenfolge für lesen ist ja:
-Start
-Controllbyte
-Adressebyte1
-Adressebyte2
-Start
-Controllbyte
-Stop

Übersehe ich etwas?

Code im Anhang :)
-Ports als Aushänge definieren
-schreiben
-lesen
-wert an ausgang schicken
-endlosschleife

mfg,
Nils
Angehängte Dateien:
Gast #2147928
Lesenswert?

Hallo Nils,
ich hatte auch mal Probleme mit TWI bis ich auf die Routinen von 
Bernhard.S gekommen bin. Die haben mir geholfen, werden auch dir helfen 
:-)

Beitrag "TWI / I2C einf. MASTER SLAVE Beispiel(Assembler) ATmega8"
/*********************************************************/
Bitte beachte das man auf einmal nur 1Byte schreiben kann, weil die 
Daten vom 24x256 beim Schreiben nicht gepuffert werden!
Während das Byte in den EEPROM gebrannt wird ist dein Bausteil(24x256) 
vom Bus getrennt! (siehe Datenblatt)

Also Ein Byte schreiben:
1) Start, SLA+W, Address High_B, Address Low_B, 1Byte(daten), Stop
2) 5ms warten
3) danach zum ersten Schritt, wenn weitere Daten da sind sonst beenden.


Lesesequenz:
Start, Address High_B, Address Low_B, RepeatedStart, SLA+R, 1Byte, 
2Byte...Stop

Hierbei fallen keine nennenswerten delays an, deswegen können mehrere 
Bytes durchgehend gelesen werden
Gast #2147992
Lesenswert?

Ja seinen Code habe ich auch schon unter die Finger bekommen.
Ich habe mal einen ganz einfachen Code geschrieben, der an PORTA eine 1 
bei Error schickt. Ich versuche lediglich das Startsignal zu schicken.
Pullups sind da und es ist soweit alles richtig verkabelt.

Und wie es ist, kriege ich hiermit nur einen Fehler aus, also immer 1 an 
PortA. Wieso :(?
Der Code ist wohl selbsterklärend:
1
.include "m16def.inc"
2

3
start:
4

5
ldi r16,0xFF
6
out DDRA,r16
7

8
ldi r18,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ;starten
9
out TWCR,r18
10
rcall warten
11

12
in r16,TWSR
13
andi r16,0xF8
14
cpi r16,START
15
brne error
16

17
noerror:
18
ldi r16,0
19
rjmp loop
20
error:
21
ldi r16,1
22

23
loop:
24
out PORTA,r16
25
rjmp loop
26

27
write:
28

29
ret
30

31
warten:
32
push r18
33
warten1:
34
in r18,TWCR
35
sbrs r18,TWINT
36
rjmp warten1
37
pop r18
38
reti
Gast #2148035
Lesenswert?

Zuerst würde ich nach dem Reset eine Verzögerung einfügen. Damit der 
EEPROM seine Power Up- Phase überwunden hat.
Danach prüfen ob die konstante „Start“ auch wirklich 0x08 beträgt.
Bei mir sieht’s so aus:
1
.equ  MT_Start_Condition     = $08      // A START condition has been transmitted


Wenn’s das nicht ist, dann würde ich noch einmal die Hardware prüfen.
1)  Ist SDA & SCL richtig verbunden?
2)  Wird dein EEPROM mit Strom Versorgt?
Gast #2148097
Lesenswert?

Das habe ich doch auch soweit gemacht. ALso ich gehe davon aus, dass 
nach dem SLA+R automatisch in TWDR das byte gelesen wird? Wäre dann mein 
Code fürs lesen korrekt?
1
read:
2
ldi r18,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN) ;starten
3
out TWCR,r18
4
rcall warten
5

6
ldi r19,0b10100000            ;SLA+W senden
7
out TWDR,r19
8
ldi r18,(1<<TWINT)|(1<<TWEN)
9
out TWCR,r18
10
rcall warten
11

12
out TWDR,r21              ;HIGH_B senden        
13
ldi r18,(1<<TWINT)|(1<<TWEN)
14
out TWCR,r18
15
rcall warten
16

17
out TWDR,r22              ;LOW_B senden
18
ldi r18,(1<<TWINT)|(1<<TWEN)
19
out TWCR,r18
20
rcall warten
21

22

23
ldi r18,(1<<TWINT)|(1<<TWSTA)|(1<<TWEN)                       ;startrepeat
24
out TWCR,r18
25
rcall warten
26

27
ldi r19,0b10100001                                        ;SLA+r
28
out TWDR,r19
29
ldi r18,(1<<TWINT)|(1<<TWEN)
30
out TWCR,r18
31
rcall warten
32

33
in r16,TWDR        ;gelesene Daten kopieren
34

35
ldi r18,(1<<TWINT)|(1<<TWSTO)|(1<<TWEN) ;stoppen
36
out TWCR,r18
37
reti
Gast #2148665
Lesenswert?

Ich habe eine Teilösung.
Ich führe erst an eine Adresse ein Schreibvorgang aus, dann löse ich mit 
einen Intertrupt den Lesevorgang aus. Porta zeigt die erwartete Zahl an.

Wenn ich allerdings nur einen Lesevorgang machen will funktioniert das 
nicht (PORTA bleibt 00000000).

Ich muss min. 1 Schreibvorgang ausgeführt haben um eine Leseoperstion 
durchzuführen? WIeso? ist das so?

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren