Hallo Leute, 1. Beschreibung der anwendung Das Progi soll später ein Zählwerk für eine Maschine werden. Man könnte es als Impulszähler beschreiben. Ich würd auch einen fertigen kaufen um mir erst gar nicht die mühe machen wenn er den rest könnte was er später auch noch tun soll! 2. Beschreibung des Programms Das Grund Programm ist eine LCD Ansteuerung mit 8Bit wo noch ein verstellbarer counter am eingang dranhängt. Nun da meine Ausgabe einen wert von 000000-999999 haben muss ist es auf diesem wege nicht möglich es zu verwirklichen (Beispiel im Anhang). Ich frage mich wie man das anders machen kann oder ob man mit einem Befehl die Tabellen automatisch hochzählen lassen kann so das aus ldi ZL,LOW(Tabelle0*2) ldi ZH,HIGH(Tabelle0*2) wenn sbic PINA,0x00 ist ldi ZL,LOW(Tabelle1*2) ldi ZH,HIGH(Tabelle1*2) usw. habt ihr eine idee ich würd mich sehr darüber freuen!
Hallo, zuerst mal eine kurze Anmerkung : Welchen Controller vewendest Du ? Das Programm ist anscheinen für einen AVR (AT90S2313) geschrieben. Da steht aber was von ''.include "8515def.inc"''. Ist das die richtige Definitionsdatei ? Du solltest noch kurz sagen, welche Hardware verwendet wird.. MfG, Khani
Hallo, und vielen dank für deine antwort ich habe das Programm auf einen 8515 umgeschrieben, und die Portbelegung geändert. da ich später noch den counter des Mikros brauche und der ja auf Port B liegt. Die Text Ausgabe funktioniert einwandfrei. Ich nutze ein Standart LCD mit einem HD44780, laufen lasse ich das über mein stk500! Problem wie gesasgt, ist das ich die unter Text Zeile im LCD von 000000-999999 hochzählen lassen will, immer um einen schritt sobald PINA 0x00 gedrückt wird. Mfg Franzi
Hallo nochmal, also Du scheinst in Assmbler programmieren zu wollen. Ich weiß die Befehle nicht auswendig, aber die Idee sollte reichen, dass man sich informieren kann. Zähler von 000000-999999 : Der Wertebereich wird von einer 20bit abgedeckt, das folgt aus dem maximalen Wert. beginnend bei 0 bei jedem erkannten Tastendruck eine Variable hochzählen (Inkrement) Falls bei dieser Inkrementoperation ein Überlauf stattfindet (zu erkennen aus dem Carry-Flag), wird eine zweite Variable um 1 erhöht. Falls auch diese Variable überläuft, einfach eine dritte Variable erhöhen. Die Zahl ist nun folgendermaßen gespeichert "Var3 Var2 Var1". Diesen Komplex kann man nun mit einer binär->ascii Umwandlung auf das Display schmeißen (diese Routinen sind im Forum recht gut ausdiskutiert. ich persönlich würde mal die von peter dannegger empfehlen, die sind dokumentiert und elegant). Jetzt muss man nur noch die drei Variablen mit einem festen Muster vergleichen, um festzustellen, ob 999999 erreicht ist. Ist das der Fall, werden alle drei Variablen auf Null gesetzt. Viel Spaß beim informieren über die Befehle und die Routinen. MfG, Khani P.S.: man kann das sicher auch mit Hilfe einer Timer-Counter-Unit lösen. Aber so ist es erst mal straight-forward.
Ich würde es mit einer BCD-Zahl lösen, die braucht zwar mehr Speicherplatz, das ist aber in dieser Anwendung nicht tragisch. So ersparst Du Dir die Umrechnung einer 20-Bit Binärzahl zur dezimalen Anzeige.
Hallo Leute, ich hab ein ähnliches Problem, hat das schonmal jemand gemacht? ich mein ein Impulszähler in dieser form realiesiert? wäre echt nett wenn jemand mal nen beispiel posten könne, ich stehe nämlich auch vor dem Problem das ich es nicht gebacken bekomme den LCD zu sagen das bei eingangs impuls er hochzählen soll! Vielen Dank
@FK wenn eine Zahl zwar binär dargestellt wird aber nur einen Wertebereich von 0 bis 9 aufweist und die Darstellungen von 1010b (Ah) bis 1111b (Fh) verboten sind. siehe hier: http://www.danbbs.dk/~erikoest/bcd.htm Mach es wie thkais sagt und am einfachsten nur je ein Byte pro Digit, dann brauchst Du Dich nicht einmal mit den pseudotetraden beim packed BCD abmühen. Der AVR hat keinen BCD-Korrekturbefehl und Du müsstest es bei packed BCD mit Abfragen des Halfcarrys nachbilden. Das kannst Du ja mal machen wenn Du es Dir unbedingt beweisen mußt oder der RAM-Speicher knapp wird. Beginne mit der niederwertigsten Steller, den "Einern" und addiere beim Event eine Eins dazu (mit inc z.B.). Vergleiche auf 10. Ist 10 erreicht, setze zurück auf 0 und erhöhe in gleicher Weise die nächst höhere Stelle. Gibt es keinen Übertrag mehr mußt Du das Inkrementieren abbrechen.. Das kannst Du locker in einer Loop machen die fast bel. viele Stellen bearbeitet. qad, nicht getestet, also keine Gewähr! ANZAHLSTELLEN: .equ 6 countreg: .BYTE ANZAHLSTELLEN IncCounter: ldi XL, low( countreg ) ; universal, wenn als Parameter übergeben ldi XH,high( countreg ) ldi r17,ANZAHLSTELLEN ; universal, wenn als Parameter übergeben loop: lds r16,X ; Digit holen inc r16 ; erhöhe um 1 cpi r16,10 ; vergleiche mit 10 brsh uebertrag ; Ergebnis >=10, (breq reicht hier auch) sts X,r16 ; Ergebnis zurückschreiben rjmp end ; und beenden uebertrag: clr r16 ; Addition hat Übertrag ergeben -> Digit löschen sts X+,r16 ; zurückschreiben und X auf nächste Digit stellen dec r17 ; Schleifenzähler -1 brne loop ; noch was da? end: ret ; Beim Ausgeben der Zahl brauchst Du dann nur noch jede Stelle mit '0' zu addieren. Am besten Du schreibst Dir eine Spezielle Ausgabe für den Zählstand, die vor dem Übertragen zum LCD zu jedem BCD-Digit den Offset ASCII 0 dazuaddiert. z.B. (nicht in BCDCOUNT!) : lds r16,X+ ; hole ein Digit ldi r17,'0' ; ASCII 0 (besser einmal ausserhalb der loop) add r16,r17 ; addiere ASCII 0 zum Digit rcall Lcd_Putc ; LCD erwartet Zeichen in r16 : Natürlich wäre eine binär/dezimal Umwandlung geschickter, da Du dann auch andere Werte, die Nicht vom Zähler kommen, dezimal darstellen könntest...aber das ist nun Dein Ding. MooseC
Hallo MooseC, als erstes möchte ich mich erstmal für deine mühe und deinen code bedanken! Ich habe ihn mir mal durchgelesen und denke auch das ich verstanden habe was er tut und auch wie er es tut! Was ich jetzt aber noch nicht ganz verstehe ist wie ich die ausgabe meinem LCD beibringen soll, mit dem derzeitigen code zur ausgabe wird das ja sicher nichts mehr, kann ich mir vorstellen, weil ich kann die ausgabe sicher schwierig in Tabelle0: .DB " " innerhalb der "" einfügen.?. Sehe ich soweit richtig das die Ausgangszahl später in r16 liegt? ldi counter,16 ;Zeichenzaehler ldi ZL,LOW(Tabelle0*2) ;Low-Zeiger auf Tabellenanfang ldi ZH,HIGH(Tabelle0*2) ;High-Zeiger auf Tabellenanfang loop_msgstart: lpm ;hole Zeichen aus Tabelle mov buffer,zeichen ;Zeichen uebergeben rcall write_data ;schreibe Zeichen in LCD inc ZL brcc no_carrystart inc ZH no_carrystart: dec counter ;alle Zeichen gesendet? brne loop_msgstart ;Nein! Sende naechstes Zeichen
Hmm irgendwie glaube ich wir reden nicht über das Gleiche oder ich habe Dein Problem völlig falsch verstanden. Wolltest Du nicht einen Zählwert auf das LCD ausgeben? Dein Beispiel mit dem lpm-Befehl holt sich die (unveränderlichen) Zeichen aus Flash und gibt sie aus. Dein 6-Stelliger Zähler muß sich im RAM befinden (oder in Register, aber das laß mal lieber) Für Textausgabe wie ein Begrüßung von Deinem Gerät oder Warnungen etc. ist die Lösung mit lpm zu empfehlen, aber nicht für Variablen. Variablen werden so definiert: countreg: .BYTE 6 Dem Label countreg weist der Assembler die nächste freie RAM-Addresse zu und beachtet das die nächste freie dann 6 Bytes weiter ist. Du brauchst zwei Ausgaben: eine für Variablen, die Zähler und eine für konstate Zeichen, wie eben die Meldungen üblich ist es Zeichenketten (Strings) mit einer 0 (nicht ASCII) enden zu lassen und beim Ausgeben eben auf diese Null zu testen und diese nicht mehr auszugeben. hello_txt: .db "hello world!",0 ; Null am Ende Deine Zeichenausgabe ist doch über r16, genannt buffer. Also sollte es ohne Änderung gehen. Mein Lcd_Putc wäre dann bei Dir write_data Also: Gebe die Zahl mit dem Ausgabemodul für den Zähler aus und hänge den konstanten Text "Bunde",0 mit einer Textausgabe aus dem Flash hinten dran. (oder gebe die paar Zeichen händisch aus) Sag mal hattest Du etwa vor für alle Zählstände Tabelle1: .db "000001 Bunde" bis Tabelle999999 .db "999999 Bunde" einzugeben? Ich täusch mich hoffentlich... MooseC
Ja ne genau das hatte ich eben nicht vor weil ähm wie man schon sieht wären das dann ein paar viele befehle die ich ihm schreiben müsste! ach so das mit der zeichen ausgabe hatte ich eben nicht so ganz gerafft aber jetzt scheint es mir einzulechten ich werd das mal ausprobieren, nochmals danke schön!
Hi MooseC, ich schon wieder, ich hab das ganze mal Coded, und hab folgende Probleme a. ANZAHLSTELLEN: .equ 6 ich denke das sollte .equ Anzahlstellen = 6 heissen oder? b. countreg: .BYTE ANZAHLSTELLEN das will er nicht in .cseg habe es nach .dseg geschrieben c. X und X+ da bin ich noch ahnungslos was damit überhaupt ist. ich hoff ich raube dir nich allzuviel zeit! mfg franzi
Dazu must Du Dir eine Routine schreiben, mit Loop und so.. Nicht einfach blind in Deinen Code pasten. Das X+ ist dabei entscheidend... ld r16,X+ ; hole ein Digit ldi r17,'0' ; ASCII 0 (besser einmal ausserhalb der loop) add r16,r17 ; addiere ASCII 0 zum Digit ?? inc r16 ; ???????? Was soll das denn? rcall write_data ; LCD erwartet Zeichen in r16 richtig erkannt .equ Anzahlstellen = 6 auch richtig .dseg X ist einer der 3 16Bit-Indexregister mit dem Du im Datenspeicher herrumpointern kannst. (Z kann auch im Programmspeicher zugreifen) X+ ist ein Autoinkrement nach dem Zugriff lds r16,X holt ein Byte aus dem Datensegment auf das X zeigt mit X+ passiert das Gleiche, nur das X automatisch NACH (daher postincrement) dem lesen/schreiben auf das nächste Byte gestellt wird. ließ bitte dazu den Instructionset des AVR Seite 5 und 6 Figure 6,7 und 8 Und dann noch bitte Seite 83..87 MooseC
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.