www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Phänomen Unterprogramm schlägt wieder zu!


Autor: Dominik L (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Hier nochmal ein Beispiel aus meiner Reihe einfaches Unterprogramm
versaut einem das ganze Projekt. Habs bis jetzt noch nicht geschafft
ein einziges Programm fertigzustellen. Einzeln läuft alles perfekt.
Füge ich jedoch mehrere Unterprogramme zusammen, bleibt der Controller
an seltsamen Stellen hängen. Das muss doch was mit dem Stackpointer
zutun haben oder? Hab das Programm mal angehängt. Läuft perfekt, bis
man die lcd_init und lcd_clear einfügt. Dann geht garnichts mehr.
Wäre echt nett, wenn da mal einer mit Ahnung drübersehen würde, wo da
der Bock steckt.

Grüße Dominik

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ldi temp, LOW(RAMEND)           ;LOW-Byte der obersten RAM-Adresse
out SPL, temp
ldi temp, HIGH(RAMEND)          ;HIGH-Byte der obersten RAM-Adresse
out SPH, temp

Versuchs mal in dieser Reihenfolge, ist bei mir ohne Probleme im
Einsatz wenns dait nicht geht liegts zumindest nicht am Stack

Autor: Mathias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Christoph:

Zugriff auf 16- Bit Reg.:

Schreiben: High dann Low;
Lesen: Low dann High

Also dürfte deine Aussage Schwachsinn sein.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
DU kannst gerne Vorbeikommen und dich vom Gegenteil überzeugen.
Zumal es 1 zu 1 aus dem Tutorial hier auf der Seite übernommen ist:
http://www.mikrocontroller.net/tutorial/stack
"Bei Controllern die mehr als 256 Byte RAM besitzen (z.B. ATmega8)
passt die Adresse nicht mehr in ein Byte alleine. Deswegen gibt es bei
diesen Controllern noch ein Register mit dem Namen SPH, in dem das
High-Byte der Adresse gespeichert wird. Damit es funktioniert, muss das
Programm dann folgendermaßen geändert werden:

.include "m8def.inc"

.def temp = r16

         ldi temp, LOW(RAMEND)             ; LOW-Byte der obersten
RAM-Adresse
         out SPL, temp
         ldi temp, HIGH(RAMEND)            ; HIGH-Byte der obersten
RAM-Adresse
         out SPH, temp
"

Bei mir Funktionierts, bei ihm Funktionierts nicht. Ich weiss nicht was
daran Schwachsinn sein sollte, ich (fast) alle meien Projekte bisher mit
meinem ATmega16 gemacht udn es hat auch mit Unterprogrammen, Interupt,
Push und Pop ohne Probleme funktioniert.

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habe jetzt mal beide Varianten ausprobiert und keine führt zum Erfolg.
Eine Veränderung zu gestern ist aber zu sehen, obwohl der rest des
Codes nicht verändert wurde. Bekommen jetzt ein OHM-Zeichen auf dem
Display ausgegeben. Allerdings bei beiden Varianten das gleiche. Ich
verstehe es nicht. Gibts da nicht noch andere Möglichkeiten, woran das
liegen könnte?

Grüße Dominik

Autor: Werner A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
funktioniert die Displayausgabe mit einer "festen" Variablen denn? Der
Fehler hört sich eher nach Timingproblemen an.
Werner

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Also die LCD-Ausgabe für sich alleine funtioniert ja einwandfrei. Nur
in Verbindung mit anderen Unterprogrammen macht sie Probleme. Also
dürfte es ein Timingproblem doch eigentlich nicht sein oder?
Dominik

Autor: Philipp Sªsse (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann setzte Dir doch bitte zwischendurch irgendwelche Ports, damit Du
verfolgen kannst, an welcher Stelle er hängen bleibt. Oder simulier das
Ganze. Sonst stocherst Du doch total im Dunkeln mit "Dann geht
garnichts mehr".

Allgemein: solange Du sinnige Namen wie "temp1" usw. vergibst und die
sowohl im Hauptprogramm als auch in Unterprogrammen benutzt, wirst Du
die Probleme mit dem Zusammenspiel nie loswerden.

Autor: Chris (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sers Leute,
Sers Dominik,
ich habe in etwa das gleiche Problem. Ich programmiere meinen AVR über
den Code-Vision C-Compiler.
Erstmal ein kleiner Überblick über mein Projekt:
In einer Endlosschleife im Hauptprogramm wird eine Auswertung einer
Tastatur vorgenommen und entsprechende Unterprogramme aufgerufen, die
dann auf einem LC-Display angezeigt werden. Nun empfängt mein µC Daten
über die UART, welche in einem Interrupt verarbeitet werden sollen.
Nun hat sich bei meinem Projekt herausgestellt, dass die ankommenden
Daten nicht immer richtig verarbeitet werden.
Wenn ich mich im Hauptprogramm(der Menüführung) befinde, wird ganz
normal ein Int ausgelöst und die Daten verarbeitet.
Befinde ich mich jedoch in einem bestimmten Unterprogramm, so wird zwar
ein Int ausgelöst. Der µC kann dann jedoch nicht mehr auf eine bestimmte
Variable zugreifen bzw. diese verarbeiten.
Ich kann mich noch erinnern, dass mein Prof. mal gesagt hat, dass
gerade die Routinen für die LCD-Ansteuerung nicht 100% implementiert
sind und schon bei manchen Projekten Probleme gemacht haben.

Ergo, was ich damit sagen will, ist, dass es vielleicht nicht am
Stackpointer liegt, sondern irgendwo ne andere Schraube wackelt.
Bin auch noch am rumprobieren, wie ich das Problem in den Griff
bekomme. Falls du etwas neues rausfindest, dann gib bitte kurz
bescheid.

Gruß Christian

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das sicherste wäre, mit Push und pop alle in den LCD udn warteroutinen
verwendeten Varibalen zu sichern bzw rückzusichern.

Autor: M. M. (miszou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

also ich habs mal auf dem M16 mit dem JTAG durchlaufen lassen. Bei mir
bleibt er nirgends hängen. Ich hab zwar kein Display dran, aber da kein
busy flag abgefragt wird, läuft es ja so durch.

Wegen dem Stackpointer, so wie es für mich aussieht ist es völlig egal
wie rum geschriedne wird. Es endet immer in 0x045F.
Mit dem Stackpointer sollte es meiner Meinung nach keine Probleme
geben.

Wegen dem Kommentar von dir "PORTB bleibt auf0x00" nach dem Einfügen
von den zwei Unterporgrammen. So versteh ich des.
Kann ich nicht nachvollziehen. Ich setzt meinen Cursor an das "ret"
in deiner Ausgabe, jedes mal wenn ich ihn bis dahin durchratern lasse
erhöt sich PORTB um 1. Nach 0xFF, fängt er wieder von neuem an.
Egal wie lange ich es laufen lass, einen hänger bekomme ich nicht.

Mir fällt kein Fehler auf, ich sehe zwar nichts auf dem Display, was
wahrscheinlich daran liegt, dass keines dranhängt. Aber sonst kann ich
kein Problem entdecken.

Timing Porbleme könntest du aber haben. Wenn du eine Variable mit einem
Wert irgendwo überschreibst. Dann stimmen deine Timings natürlich nicht
mehr.

Gruß MISZOU

Autor: Uwe Nagel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dss du versehentlich den Watchdog aktiviert hast? Im
Programm ja nicht, aber eventuell über die WDTON-Fuse. Regelmässige
Resets würden am PortB kaum auffallen, er wird ja immer gleich wieder
geschrieben. Aber ein Reset während der LCD-Initialisierung wäre übel.

Uwe

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Mathias: Beim Stack-Pointer ist das mit der Reihenfolge, ob zuerst high
und dann low oder umgekehrt, völlig egal.
Oder hast Du im Datenblatt zufällig was von einem temporären Register
für SPH entdeckt?
Ich zumindest nicht.
Das mit der bestimmten Reihenfolge, zuerst high, dann low beim
schreiben und erst low, dann high beim lesen, ist nur bei 16Bit-Timer
nötig um zu einem Zeitpunkt 16 Bit zu schreiben oder zu lesen, sonst
hätte man unter Umständen ein verfälschtes 16Bit-Ergebnis beim lesen,
bei einem Prescaler von 1 sowieso.

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo allerseits!
In der Simulation hab ich auch keine Probleme. Das würde ja auf ein
Timing-Problem oder den Watchdog hindeuten oder?
Zum Thema Watchdog:
Wie überprüfe ich denn das WDTON-Fuse-Bit? Im Studio habe ich das unter
Fuses nicht aufgeführt. Oder kann ich das softwaretechnisch bearbeiten?

Zum Thema Timingproblem:
In den Warteschleifen werden doch die Register, die die Schleifen
zählen bei jedem Unterprogrammaufruf neu gesetzt. Also müssten sie doch
die gleichen Wartezeiten ergeben, wie wenn die LCD-Ausgabe für sich
alleine läuft oder? Und somit dürfte doch kein Timing-Problem entstehen
richtig?

MFG Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik, wie schnell läuft Dein Mega16?
Die Warteschleife für 50µs mit 205 Takte inkl. RCALL und RET ist für
4MHz ausgelegt (205 Takte / 50µs = 4,1).
Wenn Dein Mega16 schneller läuft, z. B. 8MHz, dann sind das nur noch
25µs und das LCD spielt dann nicht mehr mit da mindestens 43µs das LCD
benötigt.
Dann heißt es, Schleife verlängern, z. B. mit 0x84 statt 0x42.

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab den nur auf 1 MHz internen Takt laufen. Also sollten die Schleifen
ja absolut lang genug sein oder? Und zu lange wird doch nicht wild sein
oder?

Gruß Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also hast Du die CKSEL-Fuses auf 0001 eingestellt oder belassen?
Ja, zu langsam schadet nicht.

MfG
Andi

Autor: M. M. (miszou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

kannst du mal die einzelnen Teile so reinstellen wie sie funktionieren.
Vielleicht sieht man ja dann einen Fehler. Des zusammengebaute haben wir
ja bereits.

Wie sieht denn jetzt dein Problem aus. Bleibt dein Programm immer noch
an Stellen hängen oder kommt jetzt einfach nichts auf dem Display an?

Gruß MISZOU

Autor: Uwe Nagel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Tschuldigung, es geht ja um einen mega16, der hat kein WDTON. Das ist
der JTAGEN-Fuse gewichen. Ich dachte an den mega8...
Aber am Quelltext ist nichts Auffälliges, die Schleifen in den
LCD-Routinen sollten irgendwann ablaufen und das Busy-Flag vom Display
wird nicht abgefragt. Interrupts sind auch nicht freigegeben. Warum
sollte sich das aufhängen? Wenn es aber nicht am Programm liegt, dann
vielleicht an der Hardware? Verdrahtung, Entkopplung, Reset-Beschaltung
oder zu kleine VCC?

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das JTAGEN is bei mir gesetzt? Soll ich das mal rausnehmen oder is das
gefährlich?

So wie das Programm oben im Anhang gepostet ist, funktioniert es.
Alleine das hinzufügen von

rcall lcd_init    ; Wenn diese Zeilen hinzugefügt werden,
rcall lcd_clear          ; läuft Programm nicht mehr!!!!!!!!!!!
      ;PORTB bleibt auf0x00

lässt es dann nicht mehr laufen. Die LCD-Ausgabe ist eins zu eins aus
dem Tutorial übernommen. Das läuft bei mir auch für sich alleine. Und
das oben gepostete Programm auch für sich. In dem Zustand wie es oben
ist sind alle LCD Ausgaben noch herausgenommen.

Gruß Dominik

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ach ja sorry. Die Hardware ist einfach ein STK500. Und als Display ein
EA DIPS082 von Reichelt. Am AD-Wandler eingang hängt eine
Lichtschranke, die ohne die LCD-Ausgabe auch gut funktioniert. Dann
wird der zaehler inkrementiert, so wie es sein soll.

Autor: M. M. (miszou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin

JTAG ist bei dir egal, JTAG verwendet beim Mega16 die PortC2-C5/PORTE
RST und die Ports verwendest du ja gar nicht. Kannst es aber testweise
deaktivieren. Also bei mir läuft er durch wenn ich die Zeilen
rcall lcd_init
rcall lcd_clear
und
rcall ausgabe

wieder ins programm hole, habs aber auf dem Atmega16 ablaufen lassen
(JTAG) nicht im AVRStudio Simulator.

Ich glaub auch langsam das irgendwie das etwas hardwareseitig nicht
passt.

Was machst du mit dem AD Wandler? Wenn da eine Lichtschranke dranhängt
bekommst du eine 1 oder eine 0. Oder hast du was spezielleres. Oder ist
der AD Wandler für eine andere Komponente?


Gruß MISZOU

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Guten Morgen.
Ja genau der AD-Wandler ist für die Lichtschranke. Es soll, wenn ein
bestimmter Wert überschritten wird, der zaehler inkrementiert werden.
Soll später einfach zählen, wie oft die Lichtschranke unterbrochen
wird. Is aber noch im Anfangsstadium, weil dann ja die Probleme
aufgetaucht sind.
An Hardware habe ich sonst nur das STK500 dranhängen. Was könnte da
denn nicht stimmen?
Oder soll ich es mal mit einem anderen Controller versuchen? Habe da
noch einen mega32. Den könnte man ja fast problemlos austauschen.

Gruß Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Dominik!

Du wartest mit dem ADIF-Bit (ADC Interrupt Flag) bis eine Konvertierung
fertig ist.
Weis nicht, ob das 100%ig geht, wenn das Bit ADIE (ADC Interrupt
Enable) nicht aktiviert ist (0):

  ldi temp1, 0x00    ;ADC initialisieren
  out ADCH,  temp1
  out ADCL,  temp1
  out ADMUX, temp1
  out SFIOR, temp1

warten:  rcall delay
  ldi temp1, 0b11000101
  out ADCSRA, temp1
wart:  sbis ADCSRA, 4
  rjmp wart

Besser wäre es mit dem Bit ADSC=0 zu prüfen, ob eine Konvertierung
fertig ist. ADSC wird von der Hardware nach beenden der Konvertierung
automatisch auf 0 gesetzt.
Ersetze mal Deinen obigen Code mit folgendem:

  ldi temp1, 0x00    ;ADC initialisieren
  out ADMUX, temp1
  LDI TEMP1, 1<<ADEN | 0b101  ;0b10000101
  OUT ADCSRA, TEMP1

warten:  rcall delay
  SBI ADCSRA,1<<ADSC ;Konvertierung starten
wart:  SBIC ADCSRA,1<<ADSC ;Prüfen, ob Konvertierung fertig (ADSC=0)
  rjmp wart

Die geänderten Zeilen sind groß geschrieben.
ADCL und ADCH brauchst (kannst) Du nicht auf 0 setzen, da sowieso nur
read only, also weglassen und SFIOR kannst Du in Ruhe lassen, da ADATE
(ADC Auto Trigger Enable) sowieso nicht gesetzt/benutzt wird.

MfG
Andi

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Falle:
Wenn Interrupt-Enable-Flags gesetzt werden, dann müssen am
Programmstart unbedingt die Interruptvektoren eingetragen werden. Und
wenn da nur RETI steht. Denn sonst springt das Programm (einen
Interrupt vermutend) die irgendwo mitten ins Programm und mangels RETI
nicht wieder zurück (mit zusätzlichem Stack-Überlauf).

Übrigens funktioniert das Zählen der Lichtschrankenunterbrechungen so
einfach nicht. Eine Unterbrechung kann mehrere Abfragen lang dauern,
dann wird mehrfach gezählt, das wolltest du sicher nicht. - Oder?

Ansonsten ist das ein Programmierstil, der in eine Sackgasse führt. Mit
Zeitschleifen und Busy-Warteschleifen verbrätst du nur Rechenzeit.
Schaff dir mittels Timer-Interrupt eine solide Zeitbasis, in der du die
zu erledigenden Aufgaben verteilst. Dort kannst du auch die
Lichtschranke entprellen, indem du den Zustand (frei, unterbrochen) mit
dem vorherigen Wert vergleichst und nur bei Änderung darauf reagierst.
Da dich irgendwann nicht nur interessiert WIE OFT die Lichtschranke
unterbrochen war, sondern auch noch WANN, wirst du später sowiso eine
Uhr einbauen wollen. Da ist ein Timer-Interrupt-Takt von 10ms schon mal
recht wertvoll.

...

Autor: M. M. (miszou)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi

noch zu deiner Lichtschranke, was spricht dagegen diese über einen ganz
normalen Pin der als Input geschaltet ist abzufragen. So wie ich dich
verstanden haben geht es dir nur wie oft sie unterbrochen wurde. Dann
interessiert dich ja nicht die Spannung sodern nur ob ein
High(Lichtschranke frei) oder ob ein Low (Lichtschranke unterbrochen)
anliegt.
Meine Lichtschraken die ich bisher verwendet hab prellen nicht. Dachte
immer des wäre ein mechanisches Problem bei Tastern und Schaltern.


Gruß MISZOU

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Hannes!

Das mit dem Interrupt Enable ist schon klar.
ADIE war ja bisher nicht gesetzt und SEI fehlt sowieso immer noch.
Jetzt erst mal schauen, das man das so wie es ist zum laufen bekommt.
Das mit den Interrupts muß ja auch erst mal "verdaut" werden bis man
das handeln kann und ebenfalls der Umgang mit SRAM für Variablen was
hier wohl auch noch fehlt.

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
@ HanneS:
Hab die Inteerrupts ja generell nicht aktiviert. Dann dürfte doch auch
wenn das Flag vom AD-Wandler gesetzt wird kein Interrupt ausgelöst
werden oder? Damit in einer Unterbrechung nicht mehrmals gezählt wird,
wollte ich später dann noch eine zweite Schleife einfügen, in der
gewartet wird bis die Unterbrechung der Lichtschranke beendet ist und
dann erst wieder in die Schleife gehen, die dann wieder einen
hochzählt, wenn unterbrochen wird. Wenn ich mein Unterprogrammproblem
gelöst hab denke ich aber mal über deinen Vorschlag mit dem Timer nach.
Danke dafür.

@ Andi K.:
Ich habe jetzt meinen Code mit deinem ausgetauscht. Bekomme allerdings
zwei Fehlermeldungen com Compiler:

zur Zeile  SBI ADCSRA,1<<ADSC   ;Konvertierung starten
die Fehlermeldung: error: operand 2 out of range: 0x40

und zur Zeile  SBIC ADCSRA,1<<ADSC ;Prüfen, ob Konvertierung fertig

die gleiche Fehlermeldung wie oben.

weiß jetzt leider nicht woran es liegt, weil ich mit den "<<"
operatoren noch nicht gearbeitet habe. Hast du da noch eine Idee woran
es da haken könnte?

Nochmal dankeschön, dass ihr euch jetzt so intensiv damit beschäftigt.

MFG Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oh man, ja ja, vor lauter Bit-Verknüpferreien für OUT überträgt sich das
auch anders wo.
OK, sollte heißen:

 SBI ADCSRA,ADSC ;Konvertierung starten

und

 SBIC ADCSRA,ADSC ;Prüfen, ob Konvertierung fertig (ADSC=0)

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ok so geht es. Der zaehler zählt sogar. Auch wenn lcd_init und lcd_clear
eingefügt ist. Allerdings zeigt das keine Wirkung. Es werden immernoch
ein bis drei Ohmzeichen ausgegeben, obwohl das Display ja ganz leer
sein sollte.
Wenn ich dann aber "rcall ausgabe" auch noch wieder hinzufüge, dann
zählt der zaehler nichteinmal mehr. Und auf dem Display immernoch die
Ohms.
Irgendwie habe ich das Gefühl, dass ich so nicht wirklich weiter komme.
Wäre das nicht eine Möglichkeit, dass einer von euch mal ein Programm
postet oder mir einen Link sagt, was ein paar Unterprogrammaufrufe
beinhaltet und auf dem STK500 so zu betreiben und nachzuvollziehen ist
ob es sauber läuft? Dann könnte ich wenigstens mal überprüfen, ob es an
meinem Programmietstil oder meiner Hardware liegt.

Gruß Dominik

Autor: Rolf Magnus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Besser wäre es mit dem Bit ADSC=0 zu prüfen, ob eine Konvertierung
> fertig ist. ADSC wird von der Hardware nach beenden der
> Konvertierung automatisch auf 0 gesetzt.

Noch besser wäre, den Mikrocontroller während der Konvertierung in den
sleep-Modus zu versetzen. Aber dazu muß der Interrupt auch aktiviert
sein, denn der muß die MCU nach der Wandlung wieder aufwecken. Aber
dann ist das die einfachste Möglichkeit, abgesehen davon ist es noch
etwas genauer und braucht etwas weniger Strom, was natürlich nicht bei
jeder Anwendung wichtig ist.

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik, überprüfe mal Deine Ausgabe-Routine.
Die beginnt bei ASCII '0' an zu erhöhen.
Wenn jetzt z. B. die 100er-Stelle 0 hat, dann wird bis zum gesetzten
Carry Zahl1 um 1 erhöht, dann ist Zahl1 aber nicht mehr 0 sondern 1 und
bei 9 ist es dann ASCII ':'.
Endweder Du verringerst nach jedem BRCC ZahlN oder Du fängst nicht bei
ASCII '0' sondern bei ASCII '0'-1 an zu Zählen in der
Ausgabe-Routine.
Ansonsten kontroliere Deine LCD-Funktionen noch mal ob die nicht den
Stack irgend wo 'verbiegen'.

MfG
Andi

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dominik, abgesehen vom Stack vergiss das letzte von mir!

MfG
Andi

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Allerdings soltest Du vor der Ausgabe auf das LCD eine feste Position
(LCD-Adresse) setzen, sonst läuft das ganze einfach nur durch.
Das geht mit dem LCD-Comando 0x80 + Adresse.
Je nach LCD ist die Berechnung der Adresse für Zeile und Spalte
verschieden (1 Line Mode, 2 Line Mode).
Siehe Datenblatt Deines LCD unter Set DDRAM Adress.

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Bei den LCD Ausgaben kann ich nichts entdecken. Die habe ich auch so aus
dem Tutorial übernommen. Was mir aber gerade wieder seltsames
aufgefallen ist:
Wenn ich diese Veränderungen mache,

lcd_init: drin
lcd_clear: raus
rcall delay(in "warte"-Schleife: raus

dann funktioniert wieder alles. Der "zaehler" wird erhöht und auch
die Ausgabe läuft. Die Zahlen flitzen dann zwar über las LCD, weil ich
die clear_lcd anweisung ja noch nicht verwende, aber er gibt den
"zaehler" korrekt aus. Also macht jetzt die delay-Schleife die
Probleme. Und so geht das die ganze Zeit. Ich bekomme durch Zufall das
Programm wieder zum laufen, wenn ich irgendwo eine Zeile einfüge oder
herausnehme, aber genausoschnell läuft es dann auch wieder nicht, wenn
ich woanders was ändere. Und das finde ich absolut merkwürdig.

Gruß Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Trotzdem, mache mal am Anfang der Ausgabe erst mal

 ldi temp1,0x80
 rcall lcd_command

hinein um einen Schritt weiterzukommen und wieder klar denken zu
können.

Das Register Zähler wird ja sowieso nicht beeinflusst.
Die Ausgabe ist dann oben links im LCD.
Für andere Positionen einfach ändern in 0x80+nn (nn=0 bis 127 (7F)).

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich drehe am rad! Jetzt habe ich nur hinzugefügt:

ldi temp1,0x80
rcall lcd_command

und zwar einfach in "ausgabe" über

mov temp1, zahl1    ;Ausgabe dreistellig auf LCD
rcall lcd_data
mov temp1, zahl2
rcall lcd_data
mov temp1, zahl3
rcall lcd_data
ret

Und jetzt wird garnichts mehr auf dem LCD ausgebgeben. Und "zaehler"
läuft auch nicht mehr weiter, bzw wird nicht mehr an PORTB ausgegeben.
Da liegt jetzt die ganze Zeit 0x00 an.

MFG Dominik

Autor: Andi K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Etwa so?:

ausgabe:
    ldi temp1,0x80            ;LCD-Adresse ausgeben
    rcall lcd_command

   ldi zahl1, -1 + '0'    ;Noch garnicht verwendet
hunderter:
    inc zahl1
    subi zaehler, 100
    brcc hunderter
    subi zaehler, -100
    ldi zahl2, -1 + '0'
zehner: inc zahl2
    subi zaehler, 10
    brcc zehner
  subi zaehler, -10

  ldi Zahl3, '0'
    add zahl3, zaehler

  mov temp1, zahl1    ;Ausgabe dreistellig auf LCD
  rcall lcd_data
  mov temp1, zahl2
  rcall lcd_data
  mov temp1, zahl3
  rcall lcd_data
  ret

MfG
Andi

Autor: Dominik L (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hab deins jetzt eingefügt. Ich hatte das direkt über den mov befehlen.
Aber mit deinem kommt es auf das Gleiche hinaus. So wie es in meinee
letzten Antwort beschriebn ist.

MFG Dominik

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.