Hallo habe Probleme mit dem EEPROM und wahrscheinlich dem Uart. Ich möchte die vom Uart geschickten Zeichen im EEPROM speichern. Dies geschieht im Uart Interrupt Receive. Die im EEPROM abgespeicherten Zeichen möchte ich dann lesen und (als Kontrolle für den korrekten Empfang) wieder auf einem Display ausgeben (Passiert ebenfalls noch im Uart Interrupt Receive). Wie sich zeigt funktioniert es nicht korrekt. Schicke ich z.B. vom PC die Zeichen : 12345678901234567890 so werden auf dem LCD nur die Zeichen 123970 angezeigt. Die Funktionen zum EEPROM schreiben und Lesen haben ich dem Tutorium entnommen. Woran kann es liegen. Hängt es vielleicht damit zusammen, dass einfach nicht alle Zeichen vom Mikrocontroller empfangen bzw. verarbeitet werden können. Oder ist mein LCD zu langsam? Ich verwende das LCD204B LED von Reichelt. Wie müsste ich mein Programm umändern? Quelltext ist angehängt ATMega32, 11MHz
Denke daran, Daß das EEPROM 4ms Zeit für das Speichern von 1 Byte benötigt. Wahrscheinlich ist Deine Baudrate zu hoch. Wartest Du in der Schreibroutine auf das Ende des eventuell gerade laufenden Schreibzyklusses?
hi ja ich warte auf auf das Ende des Schreibzyklusses EEPROM_write: sbic EECR, EEWE ; prüfe ob der letzte Schreibvorgang beendet ist rjmp EEPROM_write ; wenn nein, nochmal prüfen
Macht knapp ein Byte pro Millisekunde - das schaffst Du nicht im EEPROM wegzuspeichern!
Das heisst Du musst das Schreiben in das EEPROM aus der RX-Interrupt-Routine herausnehmen. Am besten schreibst Du die Daten erstmal in eine (Ring-)buffer. Grundsätzlich ist es sehr gut zu überlegen ob solche langen Programmteile im Interrupt stehen sollten. Eher nicht. Dann schreibst Du die Daten im Hauptprogramm. Während Du auf den Abschluss des Schreibvorganges wartest, kann der RX-Int dann weiterhin zuschlagen. Verstanden?
Hallo, vorausgesetzt, du hast ein selbstgeschriebenes Programm am PC, welches Zeichen ausgibt! Machst es in einem billig Protokoll: z.B. wenn TX vom Pc senden will schickt es ein ACK, z.B. 0xAA. Wenn der uC gerade nix zu tun hat schickt er ein, z.B. 0xBB zurück. Dann kommen die Daten, die du im, ich hoffe ich irre mich jetzt nicht, UDR-Register empfängst. Nach Ende des Empfangs sendest du z.B. ein 0xCC an den PC, damit das Proggi aufm PC wartet. Dann kommt die LCD Ausgabe, oder sonstwas und dann sendest du z.B. ein 0xDD an den PC, damit dein Proggi weiss er kann neues Zeichen senden. Falls du z.B. Hyperterminal benutzt und weisst wieviel Daten kommen werden, würde ich diese im RAM speichern, ausserdem Variable hochzählen, wenn max. errreicht, aufm LCD Zeichen ausgeben. Gruss fubu.
Hallo danke für die Antworten. Die Variante von fubu fällt jedoch aus, da die Daten später nicht vom PC gesendet werden und ich auch nicht entscheiden kann ein bestimmtes Zeichen bei Bereitschaft ect zu senden. Zu der Sache mit dem Ring-Buffer: Gibt es hierfür evt. schon eine fertige Routine? Da es sich hierbei nur um ein Teilstück in einem größerem Projekt handelt, würde es mich freuen, wenn mir jemand dabei behilflich sein kann. Wie würde das mit dem Ring-Buffer denn in etwa in Assembler aussehen? Muss ich da den rol-Befehl nutzen?
stelle Dir den Ringbuffer wie die Rotation des Akkus über Carry vor. Nur nicht mit Bits sondern mit Bytes. Und das was sonst ins Carry geht, geht dann eben in den EEPROM.
Hi habe jetzt schon studenlang im Netz nach Assembler-Routinen für Ring-Buffern gesucht. Leider ohne Erfolg. Es wäre nett wenn mir jemand evt. kleinere Code-Snipsel zukommen lassen kann. Da ich absolut nicht weiss wie man das mit den Ring-Buffern realisieren kann. Bin auch noch nicht soooo bewandert in Assembler.
Kulli wrote: > Hi > habe jetzt schon studenlang im Netz nach Assembler-Routinen für > Ring-Buffern gesucht. Leider ohne Erfolg. Dann: selber schreiben. Dabei lernst du sowieso mehr, als wenn du nur fertige Routinen abkupferst. > Es wäre nett wenn mir jemand evt. kleinere Code-Snipsel zukommen lassen > kann. Da ich absolut nicht weiss wie man das mit den Ring-Buffern > realisieren kann. Hast du schon tausende male benutzt. Wenn du grade an was arbeitest und jemand kommt zu dir ins Zimmer und will dir was mitteilen, dann schreibst du das erst mal auf und siehst es dir erst dann genau an, wenn Zeit dazu ist. Ein Ringbuffer ist nichts anderes als eine Speicherfläche in der die Daten erst mal landen. Rungbuffer heist er deswegen, weil er logisch zu einem Ring zusammengeklebt wird. Ist man am Ende der Speicherfläche angelangt, dann beginnt man ganz einfach wieder vorne zu schreiben. So wie auf einem Papierstreifen den man zu einem Ring zusammenklebt und einfach drauflosschreibt und dabei das was vorher dort stand einfach überschreibt. Du musst dir 2 Dinge in Variablen merken: Wo darf das nächste Zeichen geschrieben werden Von wo ist das letzte Zeichen gelesen worden Das sei deine Speicherfläche +---+---+---+---+---+---+---+---+ | | | | | | | | | +---+---+---+---+---+---+---+---+ und jetzt das ganze mit den Schreib/Lesezeigern +---+---+---+---+---+---+---+---+ | | | | | | | | | +---+---+---+---+---+---+---+---+ ^^ || |+----------------+ | | Lesen Schreiben Wenn jetzt ein Text zwischengespeichert werden muss, dann wandert der erst mal in den Ringbuffer. Zb. der Text "abc" +---+---+---+---+---+---+---+---+ | a | b | c | | | | | | +---+---+---+---+---+---+---+---+ ^ ^ | | | +---+ | | Lesen Schreiben Jetzt nehmen wir mal an, dein µC hat keine Zeit den Text zu bearbeitn aber in der Zwischenzeit kommt ein neuer Text herein: 1 2 Diese Zeichen wandern ebenfalls in den Ringbuffer +---+---+---+---+---+---+---+---+ | a | b | c | 1 | 2 | | | | +---+---+---+---+---+---+---+---+ ^ ^ | | | +--+ | | Lesen Schreiben Dein µC hat jetzt endlich Zeit und beginnt sich das erste Zeichen aus dem Ringbuffer zu holen: a +---+---+---+---+---+---+---+---+ | a | b | c | 1 | 2 | | | | +---+---+---+---+---+---+---+---+ ^ ^ | | +----+ +--+ | | Lesen Schreiben Er holt sich das nächste Zeichen: b +---+---+---+---+---+---+---+---+ | a | b | c | 1 | 2 | | | | +---+---+---+---+---+---+---+---+ ^ ^ | | +--------+ +--+ | | Lesen Schreiben und dann ist er erst mal beschäftigt. In der Zwischenzeit trifft weiterer Text ein: defg Auch der wird erst mal im Ringbuffer abgelegt +---+---+---+---+---+---+---+---+ | g | b | c | 1 | 2 | d | e | f | +---+---+---+---+---+---+---+---+ ^ ^ +----------------+ +--------+ | | | Lesen Schreiben Beachte: nach f ist die Speicherfläche zu Ende, also wird das noch eingetroffene g ganz am Anfang geschrieben. Ist ja auch kein Problem, das a das vorher dort stand wurde schon verarbeitet. Dein µC hat jetzt wieder Zeit und widmet sich den nächsten Zeichen aus dem Ringbuffer: c +---+---+---+---+---+---+---+---+ | g | b | c | 1 | 2 | d | e | f | +---+---+---+---+---+---+---+---+ ^ ^ +----------------+ +------------+ | | | Lesen Schreiben und noch eins: 1 +---+---+---+---+---+---+---+---+ | g | b | c | 1 | 2 | d | e | f | +---+---+---+---+---+---+---+---+ ^ ^ +----------------+ +----------------+| | | Lesen Schreiben Aber jetzt dauerts wieder in der Bearbeitung. In der Zwischenzeit kommt das nächste über die Schnittstelle: A +---+---+---+---+---+---+---+---+ | g | A | c | 1 | 2 | d | e | f | +---+---+---+---+---+---+---+---+ ^ ^ +------------+ +----------------+| | | Lesen Schreiben usw. usw. Aufpassen muss man eigentlich nur, wenn der Ringbuffer dann tatsächlich voll wird. Wenn in der jetzigen Situation 3 Zeichen eintrudeln, dann gibt es ein Problem. Viel Spass bei der Implementierung!
Stephan Henning wrote: > Karl Heinz, > du bist eine Sonne..... Wenn möglich erkläre ich ihm lieber das Prinzip und lasse ihn selbst an einer Implementierung arbeiten. Das ist zwar für mich mehr Aufwand aber wenn ers dann durchzieht hat er mehr davon als wenn ich ihm eine fertige Routine präsentiere. Erfahrungsgemäß wird die nämlich einfach so übernommen ohne zu verstehen was da eigentlich abgeht und wie's funktioniert. Bei Problemen steht er dann da und weiß erst recht nicht wo hinten und vorne ist. Viele Algorithmen in der Programmierung sind eigentlich unglaublich einfach. Wir benutzen sie jeden Tag im täglichen Leben ohne uns dessen bewusst zu sein. (Und ausserdem hasse ich nichts mehr als Leute die sich stolz im Bekanntenkreis mit ihren Programmierkünsten präsentieren und in Wirklichkeit keinen blassen Schimmer davon haben, was sie da eigentlich gemacht haben. Mit 'Malen nach Zahlen' kann man mich nicht wirklich beeindrucken)
Wau nette Erklärung zum Ringbuffer... hier mal eine feritge UART Lib... http://homepage.hispeed.ch/peterfleury/avr-software.html#libs (und LCD Lib)
hi habs jetzt mal versucht selber zu schreiben. Könnt ihr es kontrollieren? Bin mir nicht sicher wie man die Position des letzten Bytes abfragen kann. so siehts aus: .dseg .equ L_FIFO = 128 FIFO_Data: .byte L_FIFO init_FIFO: ldi XL,low(FIFO_Data) ; read ldi XH,high(FIFO_Data) ldi YL,low(FIFO_Data) ; write ldi YH,high(FIFO_Data) ret write_fifo: push temp1 ; temp auf dem Stack sichern in temp1, sreg ; SREG sichern push temp1 push temp2 in temp1, UDR ; UART Daten lesen st Y+, temp1 ld temp2, Y cpi temp2, L_FIFO ; Ende des Ringpuffers erreicht? brne no_reset_pointerY ldi YL,low(FIFO_Data) ldi YH,high(FIFO_Data) no_reset_pointerY: pop temp2 pop temp1 out sreg, temp1 ; SREG wiederherstellen pop temp1 ; temp wiederherstellen ret read_fifo: push temp2 ld r16, X+ ld temp2, X cpi temp2, L_FIFO ; Ende des Ringpuffers erreicht? brne no_reset_pointerX ldi XL,low(FIFO_Data) ldi XH,high(FIFO_Data) no_reset_pointerX: pop temp2 ret
Hi
> ld temp2, Y ?????????????
Wenn schon, dann 'mov temp2,XL'.
Wenn man eine 2er-Potenz als Puffergrösse und eine günstige Stelle im
RAM für den Puffer wählt kann man die Prüfung des Pufferendes durch eine
AND-Operation ersetzen:
.dseg
.org $0000
Puffer: .db 128
.cseg
.....
clr XL ; Pointer initialisieren
clr XH
.....
ld temp2,X+
andi XL,0b01111111 ; XL wird bei 128 wieder 0
MfG Spess
Bei mir fängt der RAM erst ab $0060 an. Wie kann ich nun auf das Ende des Pufferendes Überprüfen?
Kulli wrote: > Bei mir fängt der RAM erst ab $0060 an. Wie kann ich nun auf das Ende > des Pufferendes Überprüfen? Im Falle des Y-Pointers: .def buffersize=32 .dseg .org sram_start buffer: .byte 32 .cseg ;... st y+,tmp cpi yl,buffer+buffersize brne weg_hier ldi yl,low(buffer) ldi xh,high(buffer) weg_hier: ...
Hallo danke an alle, nun funktioniert es.
Auch nochmal von mir ein Dank an Karl-Heinz.
Hat ja lange genug gedauert. Aber im Endeffekt ist es wirklich nicht
schwer. Wie gesagt, das kommt wenn man nicht viel Ahnung in Assembler
hat. Kann man das Ganze eigentlich auch mit nur einem Pointer
realisieren?
@Karl-Heinz
Ich hatte im Netz ja nur nach Ring-Buffern geschaut, um überhaupt
irgendetwas zu dem Prinzip zu finden. Selbst wenn ich fertige Routinen
nutze, versuche ich schon diese nachzuvollziehen.
>Und ausserdem hasse ich nichts mehr als Leute die sich stolz im >Bekanntenkreis
mit ihren Programmierkünsten präsentieren und in Wirklichkeit >keinen blassen
Schimmer davon haben, was sie da eigentlich gemacht haben.
-->Das wird bei mir noch dauern. Bis ich das Projekt endlich fertig
habe, kanns noch ne Weile dauern ;-)
Also nochmal vielen Dank
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.