Hallo, ich Programmiere mit dem STK500 und einem AT90S8515, ich will einen Port benutzen (vorerst mal Port B mit LED's) um folgendes zu tun: Es soll bei den ersten 4 Bits ein BCD Code hochgezählt werden, die anderen 4 Bits werden je nach einem Überlauf des BCD Codes um eins verschoben. Der Port soll 4 74LS2154 (4-to16-Line Decoder) ansteuern, mit den ersten 4 Bits übermittel ich den BCD Code an alle IC's und mit den anderen 4 möchte ich die Freigabe geben bzw. sperren für die einzelnen IC's. Wäre nett wenn ich dazu ein paar Tips bekommen könnte. MFG kinglazee
Hi King, Hallo HanneS, habe ich letztes Jahr für meine Xmas-Beleuchtung gemacht. Nach Weihnachten fangen wieder alle an zu bauen, weil se sich über die bunten Lichter vom Nachbarn geärgert haben (Weil die bunter leuchteten und der Nachbar nu gar keine Ahnung von Elektronischem Zeuchs hat, sondern alles bei Pflanzen Kölle gekauft hat) - zähle einfach drauf los. - nach jedem Step eine AND Verknüpfung mit 0x0F.Ergebins als Dateninformation für die 154er im Ausgaberegister weglegen, original 8Bit Zählerstand aufheben, zur nächsten berechnung heranziehen. ..... [ich lass es mal stehen] AND 0xF0 . Ergebins ist 0x10, 0x20, 0x30 oder 0x40 (bis, logisch 0xF0 - soweit kommen wir nicht) Dieses Ergebins in einem Extra Register 'SELECT_DECODER' aufheben. Die Dateiinformation und das ergebbnis der letzen AND "Rechnung" einfach verodern. Da Du oben mit 0x0F die oberen 4Bit's gekillt hast, sind da auch keine, die jetzt stören, also einfach 'Dateninfo' OR 'SELECT_DECODER'. Checken musste noch, ob im 'SELECT_DECODER' das Ergebins größer 0x40 ist,, dann setze es auf 0x00. Das geht am einfachsten, in dem Du oben nicht AND 0xF0, sondern gleich AND 0x40 rechnest, dann tauchen die ......... original 8Bit Zählerstand NICHT überschreiben, siehe oben. auf Bit4 Testen mit 'Zählerstand' AND 0x10. wenn wahr, dann 'SELECT_DECODER' mit 0x10 laden, sofern 'SELECT_DECODER' auf 0x80 stand. Sonst 'SELECT_DECODER' 1 nach links schieben (mal 2 nehmen).original 8Bit Zählerstand AND 0x0F. 'SELECT_DECODER' OR 'AUSGABEREGISTER' beinhaltet jetzt den Zählerstand 0 bis 15 in den unteren Bits 0 bis 3 und gesetze Bits 4,5,6 oder 7 im oberen Nibble. Codeschnipsel wieder nur auf Anfrage. Ihr seht, auch ich komme manchmal durcheinander, ich hab's mal stehen gelassen Gruß AxelR.
Hallo, AxelR ich konnte deinen Vorschlag bis jetzt noch nicht wirklich nachvollziehen. Ich habe jetzt folgendes getan, ein register mit inc hochzählen lassen, dieses Register direkt an port B gesendet, jetzt bräuchte ich eine abfrage mit der ich einen Sprung mache wenn ich den Wert 0b00001111 habe, ich habe leider noch nichts mit dem Status register gemacht, kann mir da jemand ne kurze erläuterung dazu geben? besten dank im voraus MFG kinglazee
Hi, naja, sagte ich doch schon: auf Bit4 Testen mit 'Zählerstand' AND 0x10. oder eben 0b00010000. Kann man mit einer AND verknüpfung machen. Geht sicher auch anders... Du musst im Prinzip die oberen 4Bits von deinem Register, welches hochzählt, isoliert weiter verarbeiten und die neuen Informationen, also die oberen 4Bit wieder zum 'Zählerstand' zurückschreiben. Die oberen 'neuen' 4Bit musst du also separat berechnen und mit OR dem 'Zählerstand' wieder hinzufügen. Gruß Axel
Also mit dem Befehl OR bin ich nicht weit gekommen, hatte irgendwie keinen erfolg damit, hab ich das register r20 den wert 0b00010000 geladen, dann mit dem register "zahler" (für zähler) folgendermaßen oder verknüpft: OR zahler, r20 Aber bit 4 wurde einfach nicht gesetzt, habs jetzt leider mit cbi direkt über den port machen müssen. hier mein Programm: (wenn euch dinge einfallen alles en bisl einfacher zu machen, dann schreibt sie ruhig, ich bin sehr dankbar für jede Hilfe! .nolist .include "C:\Programme\Atmel\AVR Tools\AvrAssembler\Appnotes\8515def.inc" .list .def tmp=r16 ;Universalregister deklarieren .def leds=r17 .def zahler=r19 rjmp reset ;Reset Handler rjmp interrupt0 ;IRQ0 Handler reti ;IRQ1 Handler reti ;Timer1 Capture Handler reti ;Timer1 compare Handler reti ;Timer1 Overflow Handler reti ;Timer0 Overflow Handler reti ;SPI Transfer Complete Handler reti ;UART RX Complete Handler : RXCIE reti ;UDR Empty Handler reti ;UART TX Complete Handler reti ;ADC Conversion Complete Interrupt Handler reti ;EEPROM Ready Handler reti ;Analog Comparator Handler ;======================================================================= ===== ; Initialisierung ;======================================================================= ===== reset: ;STACK-Initialisieren ldi tmp, LOW(RAMEND) ;LOW-Byte der obersten-Adresse out SPL, tmp ldi tmp, HIGH(RAMEND) ;HIGH-Byte der obersten-Adresse out SPH, tmp ldi tmp, 0xFF ;8 Einsen in Register "tmp" out DDRB, tmp ;an Datenrichtungsregister von Port B ldi leds, 0b11111111 out PORTB, leds ldi tmp, 1<<INT0 ; 0100 0000 out GIMSK, tmp ldi tmp, 0b00000010 out MCUCR, tmp ldi zahler, 0b00000000 sei ;======================================================================= ===== ; Hauptprogramm ;======================================================================= ===== main: rjmp main interrupt0: ;wird aufgerufen wenn SW2 gedrückt ldi zahler, 0b00000000 ;Zähler auf null setzen _sektor_x1: inc zahler ;Zähler +1 mov leds, zahler ;Zähler in Leds kopieren com leds ;Register Leds umdrehen out portb, leds ;An Port B ausgeben cbi portb, 4 ;Bit 4 für freigabe IC 1 com leds ;Register Leds wieder umdrehen rcall wait ;warteschleife cpi zahler, 15 ;prüfen ob zähler schon auf 15 (0b0000.11111) brne _sektor_x1 ;wenn nicht auf 15, dann springe auf _sektor_x1 ldi zahler, 0b00000000 _sektor_x2: inc zahler mov leds, zahler com leds out portb, leds cbi portb, 5 com leds rcall wait cpi zahler, 15 brne _sektor_x2 ldi zahler, 0b00000000 _sektor_x3: inc zahler mov leds, zahler com leds out portb, leds cbi portb, 6 com leds rcall wait cpi zahler, 15 brne _sektor_x3 ldi zahler, 0b00000000 _sektor_x4: inc zahler mov leds, zahler com leds out portb, leds cbi portb, 7 com leds rcall wait cpi zahler, 15 brne _sektor_x4 ldi leds, 0b11111111 out portb, leds reti
Hi... ---->8---- ich Programmiere mit dem STK500 und einem AT90S8515, ich will einen Port benutzen (vorerst mal Port B mit LED's) um folgendes zu tun: Es soll bei den ersten 4 Bits ein BCD Code hochgezählt werden, die anderen 4 Bits werden je nach einem Überlauf des BCD Codes um eins verschoben. ----8<---- BCD oder Binär?? BCD zählt (wie der Name schon sagt) nämlich nur von 0 bis 9. ---->8---- Der Port soll 4 74LS2154 (4-to16-Line Decoder) ansteuern, mit den ersten 4 Bits übermittel ich den BCD Code an alle IC's und mit den anderen 4 möchte ich die Freigabe geben bzw. sperren für die einzelnen IC's ----8<---- Da du einen (eigentlich 4) "1 aus 16-Decoder" dranhängen willst (um ein Lauflicht zu realisieren), solltest du lieber bis 15 zählen, also nicht BCD sondern binär. Du nimmst als Taktquelle zum Zählen den Int0. Und da hängt sicherlich ein Taster dran. Taster haben die unangenehme Eigenschaft, mechanisch zu prellen, was dafür sorgt, dass dein Int etliche male hintereinander ausgelöst wird, bis der Taster zur Ruhe kommt. Diese Methode geht also nicht. Mechanische Schalter und Taster fragt man grundsätzlich nicht per INT ab sondern mit einer Entprellroutine (Codesammlung -> suchen). Ein Lösungsansatz: - Nimm getrennte Register für Zählen und Schieben der Select- Leitungen und ein drittes zum Zusammenfassen und Ausgeben. - Zähle das Zählregister hoch (oder runter) (inc zahl) - blende die oberen 4 Bits aus (andi zahl,15) - vergleiche zahl mit 0 oder 15 (je nach Zählrichtung) (cpi zahl,0) - überspringe die nächsten Programmzeilen (mit Label), wenn Vergleich nicht stimmt (brne label1) - schiebe den Inhalt des Registers zum Schieben der Select-Leitungen nach links oder rechts (asl schieb / asr schieb), je nachdem, wie die Aktivierungsreihenfolge sein soll - falls du nach rechts schiebst, blende die 4 unteren Bits aus (andi schieb,$f0), denn wir nutzen ja nur die oberen 4 Bit - überspringe (zum Label), wenn schieb dabei nicht leer wird (brne label1) - setze Schieb auf Startwert (ldi schieb,16 / ldi schieb,128) kopiere schieb zum Ausgaberegister (mov ausgeb,schieb), eines der 4 oberen Bits ist nun gesetzt - solltest du zum Aktivieren (CipSelect) eine Null brauchen und keine Eins, dann invertiere es und blende die unteren Bits wieder aus (com ausgeb , andi ausgeb,$f0) nun ist eines der oberen Bits gelöscht und alle unteren Bits auch - kopiere die unteren Bits von zahl zum Ausgaberegister, ohne dabei die oberen 4 Bits zu verändern (or ausgeb,zahl) - gib das Register an den Port aus (out portx,ausgeb) - warte auf das nächste Zählereignis und beginne von vorn... (rjmp warteauftastendruck) Falls du das in eine Interrupt-Routine einbauen willst, dann beherzige die 3 goldenen Regeln der Interruptprogrammierung: http://www.mikrocontroller.net/forum/read-1-130140.html#130537 ...
Hallo "König der faulen" (Kinglazee), na, ich werd' mal nich so sein... ich habe dein Code mal ins AVR Studio übernommen. Die Wait Routine habe ich mal aussen vor gelassen, klar. Wenn Du den Wert für die LED's ausgibts, ist dein Bit4,5,6 oder7 natürlich wieder "weg", weil jedesmal bei Ausgabe der LED's die oberen 4 Bit's mit überschrieben werden. Danz ganze direkt in der Int0-routine zu machen, ist jetz ein anderes Thema... Ich geh' noch mal drüber. Axel toller nick ;-))
bei jedem Tastendruck (Int0 evtl. noch auf fallende oder steigende Flanke einstellen) wird jetzt der zählerstand erhöht und abhängich(?) von den oberen 4 Bits die 154 angesteuert. Ich habe das grob im Simulator überflogen. Die Zeitschleife zum hochzählen im Interrupt, das lass mal sein. Kannst Du später im Timerinterrupt machen. Setz mal INT0 auf fallende Flanke und drück den Taster, dann müssten die LED's ancheinander angehen (Vom Tastenprellen mal abgesehen). LED's habe ich nicht "umgedreht", war mir im Simlulator zuunübersichtlich. .nolist .include "C:\Programme\Atmel\AVR Tools\AvrAssembler\Appnotes\8515def.inc" .list .def tmp=r16 ;Universalregister deklarieren .def leds=r17 .def zahler=r19 .def shift_cnt=r20 rjmp reset ;Reset Handler rjmp interrupt0 ;IRQ0 Handler reti ;IRQ1 Handler reti ;Timer1 Capture Handler reti ;Timer1 compare Handler reti ;Timer1 Overflow Handler reti ;Timer0 Overflow Handler reti ;SPI Transfer Complete Handler reti ;UART RX Complete Handler : RXCIE reti ;UDR Empty Handler reti ;UART TX Complete Handler reti ;ADC Conversion Complete Interrupt Handler reti ;EEPROM Ready Handler reti ;Analog Comparator Handler ;======================================================================= ===== ; Initialisierung ;======================================================================= ===== reset: ;STACK-Initialisieren ldi tmp, LOW(RAMEND) ;LOW-Byte der obersten-Adresse out SPL, tmp ldi tmp, HIGH(RAMEND) ;HIGH-Byte der obersten-Adresse out SPH, tmp ldi tmp, 0xFF ;8 Einsen in Register "tmp" out DDRB, tmp ;an Datenrichtungsregister von Port B ldi leds, 0;0b11111111 out PORTB, leds ldi tmp, 1<<INT0 ; 0100 0000 out GIMSK, tmp ldi tmp, 0b00000010 out MCUCR, tmp ldi zahler, 16 sei ;======================================================================= ===== ; Hauptprogramm ;======================================================================= ===== main: rjmp main interrupt0: ;wird aufgerufen wenn SW2 gedrückt ; ldi zahler, 0b00000000 ;Zähler auf null setzen ;Zähler +1 mov leds, zahler ;Zähler in Leds kopieren mov shift_cnt,zahler andi leds,15 ;nur die untersten 4Bits andi shift_cnt,240 ;bit 7,6,5 und 4 isolieren cpi shift_cnt,16 ;1? breq firstchip cpi shift_cnt,32 ;2? breq second_chip cpi shift_cnt,48 ;3? breq third_chip cpi shift_cnt,64 ;4? breq fourth_chip firstchip: clr shift_cnt ldi shift_cnt,16 or leds, shift_cnt ;com leds out portb,leds inc zahler reti second_chip: clr shift_cnt ldi shift_cnt,32 or leds,shift_cnt ;com leds out portb,leds inc zahler reti third_chip: clr shift_cnt ldi shift_cnt,64 or leds,shift_cnt ;com leds out portb, leds inc zahler reti fourth_chip: clr shift_cnt ldi shift_cnt,128 or leds,shift_cnt ;com leds out portb, leds inc zahler reti
@...HanneS...: Mein Code zählt Binär und soll als BCD am Port am unteren halben Byte anstehen. "cpi zahler, 15" - Wie man sehen kann zählt er bis 15, dann erst gehts zum nächsten IC. Zum Thema Entprellen, beim Tastendruck wird einmal komplett durchgezählt, mit dem Porgramm sollen nachher 64 LED's angesteuert werden die bei jedem Takt am Eingang einmal durchlaufen sollen. Also fällt die Entprellroutine schonmal komplett weg! @AxelR.: ---------- Die Zeitschleife zum hochzählen im Interrupt, das lass mal sein. Kannst Du später im Timerinterrupt machen. ---------- Wie meinst du das genau? Kannst du mir das mal beschreiben oder Erläutern? P.S. König der faulen steht im Bezug aufs Coden, denn ich bin manchmal einfach zu faul um soviel Code hinzuschreiben und desshalb überlege ich mir lieber wie ich mir das ganze ersparen kann mit Routinen oder Makros. @: Das Programm läuft mit dem geposteten Code genau wie ich es haben will von den Ausgangssignalen her, ich wollte nur wissen ob ihr kleinigkeiten evtl. anders machen würdet um so noch ein paar Wörter zu sparen.
Aha, du zählst also binär und willst BCD ausgeben??? BCD heißt doch aber Binär Codierter Dezimalcode und reicht nur von 0 bis 9. Fallst du das nicht willst, dann nenn' es nicht BCD. Wenn du meinst, Taster ohne Entprellen mittels Ext-Int. abfragen zu können, dann mach... Timer-Interrupt... Axel meint sicherlich, du solltest einen Timer einrichten, der in regelmäßigen Abständen einen Interrupt auslöst. In dieser ISR wird dann der Zähler hochgezählt. So würde ich das auch machen, wobei ich gleich die gesamte Zähl- Schieberei und Ausgabe mit in die ISR packen würde. Du wolltest wissen was wir anders machen würden, um etwas Code einzusparen? Das habe ich dir weiter oben schon geschrieben. Schau dir die Erklärungen und die zugehörigen Codezeilen an und versuche sie nachzuvollziehen. Das kann so wie es ist in die ISR eines Timers und läuft. Macht genau das, was du vorgegeben hast, allerdings mit rund 10% deiner Codemenge. Ich habe den Eindruck, du hast das entweder nicht verstanden oder garnicht erst gelesen. Daher denke ich auch, dass sich "Faulpelzkönig" eher auf das Lesen (auch von Datenblättern) bezieht als auf das Einsparen von Code. ...
Hi, da hassu! Bei fallender Flanke am Taster wird der Timer0 gestartet und die 64 LED werden der Reihe nach eingeschaltet. Danach wird Timer0 wieder angehalten und die Ausgabe gelöscht. Man muss neu drücken. Das SREG habe ich nicht gesichert! Die Interruptvectortabelle scheint nicht vom 8515 zu sein. nochmal kontrollieren. Kann sein, dass das Lauflicht mal so von alleine losläuft, da der Taster nicht entprellt ist... Gruß Axel
@AxelR.: Mit Interruptvectortabelle meinst du doch bestimmt die Liste am Anfang des Programms, in der die vielen RETI stehen? Tut mir echt Leid, ich hab mit dem ganzen noch nicht so recht den Umgang gefunden, aber Danke dass du mir dabei hilfst! Werde mir mal eine Vectortabelle zu meinem 8515 suchen. ------------- Kann sein, dass das Lauflicht mal so von alleine losläuft, da der Taster nicht entprellt ist... ------------- Also bis jetzt hatte ich mein STK500 schon stundenlang eingeschaltet, aber es ist noch nichts einfach so losgelaufen, es scheint wirklich so als wäre der Taster gut entprellt, oder es Funktioniert über den Interrupt so gut, ich weiß es noch nicht genau! Das Programm werde ich nachher noch Testen und schauen ob alles so ist wie ich es wollte, und dann werd ich mir ansehen was genau getan wurde! Recht Herzlichen Dank! MFG kinglazee
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.