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
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
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 |
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?
gtf schrieb: > Lesesequenz: > Start, Address High_B, Address Low_B, RepeatedStart, SLA+R, 1Byte, > 2Byte...Stop ooops da fehlt ja SLA+W Korrektur: Start, SLA+W, Address High_B, Address Low_B, RepeatedStart, SLA+R, 1Byte, 2Byte...,Stop
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 |
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?
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.