Moin, sitze gerade vor einem PIC16F84A welcher mit Assembler programmiert werden soll. Nun ist die Aufgabe mit dem RISC Befehlssatz eine Funktion zu schreiben in welcher eine Verzögerung von etwa 1s vorkommen soll. Bin allerdings etwas aufgeschmissen und weiß nicht genau wie ich die Verzögerung von etwa 1s hinbekomme. Vielleicht kann mir ja jemand einen Denkanstoß oder ähnliches geben! Danke im vor raus!
Gast
#7153534
Marcel H. schrieb: > Bin allerdings etwas aufgeschmissen und weiß nicht genau > wie ich die Verzögerung von etwa 1s hinbekomme. Du weißt die Taktfrequenz deines PIC? Dann bastelst du dir Zählschleifen, die den Controller für eine Sekunde blockieren. Um auf die "genaue" Zeit zu kommen, musst du natürlich wissen, wie lang jeder Befehl deiner Schleifen braucht. Oder du nimmst eine Kamera, die auf eine Uhr (mit Sekundenzeiger) guckt, die dann meldet, dass der Sekundenzeiger sich bewegt hat.
Entweder stupide ne For-Schleife mit NOP(s) oder den Timer benutzen um damit ne Var hoch|runter zählen.
Für so extrem lange Zeiten nimmt man einen Timerinterrupt, z.B. alle 1ms. Darin zählt man dann eine Variable runter und wenn sie 0 erreicht, führt man einen Callback aus oder setzt ein Flag, was dann in der Mainloop die Aktion ausführt. Demm in real will man nicht, daß so lange die CPU überhaupt nichts macht, sondern weiterhin andere Aufgaben bearbeitet. Eine elegante Lösung ist auch ein Scheduler, in den man z.B. bis zu 10 verzögerte Aufgaben reinstellen kann und der sie dann einmalig oder zyklisch aufruft. Den Scheduler schreibt man natürlich in C, in Assembler wird das zu unübersichtlich.
Peter D. schrieb: > Den Scheduler schreibt man natürlich in C, in > Assembler wird das zu unübersichtlich. Wie so sollte das? Ist doch nur ne Liste von Calls.
Teo D. schrieb: > Wie so sollte das? > Ist doch nur ne Liste von Calls. Assembler kennt keine Variablentypen und erst recht keine Structs und Arrays. Die ganzen Indirectionen, Pointer und Displacements zu Fuß zu berechnen, ist nur was für extreme Masochisten.
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
Gast
#7153583
Peter D. schrieb: > Denn in real will man nicht, dass so lange die CPU überhaupt nichts > macht, sondern weiterhin andere Aufgaben bearbeitet. Die Aufgabe klingt nach einer Grundlagenveranstaltung der Mikrocontroller-Programmierung (zumindest kenne ich das sowohl aus der Ausbildung, als auch aus dem FH-Studium). Dabei geht es darum, die Zählparameter einer Warteschleife zu bestimmen, wenn man die Taktanzahl der benötigten Befehle kennt. Natürlich kann man es anders machen, aber jemand, der nicht mal solchen Pippifax hinbekommt, soll einen Scheduler programmieren / verwenden?
Peter D. schrieb: > Assembler kennt keine Variablentypen und erst recht keine Structs und > Arrays. Du denkst zu komplex. Mann muss nicht gleich einen ganzen Walt planen, wenn man nur ne Verkehrsinsel begrünen will.
Teo D. schrieb: > Du denkst zu komplex. War jetzt auch nur mal als Ausblick gedacht, wenn man erfahrener ist. Ab der 2. Zeitaufgabe geht es mit dem Scheduler einfacher. Ein Timerinterrupt hat den Vorteil, daß man die Dauer direkt einstellen kann und nicht umständlich Befehlszyklen abzählen muß. Man kann also das Programm leicht erweitern, ohne daß sich die Zeiten durch die zusätzlichen Befehle verlängern.
Als ich 1990 mit dem 8051 angefangen habe, habe ich sehr schnell schon die Timer benutzt. Ich war einfach zu faul, Befehle abzählen zu müssen, denn dabei kann man sich auch schnell verzählen und die Zeiten stimmen nicht.
Gast
#7153610
Peter D. schrieb: > Als ich 1990 mit dem 8051 angefangen habe, habe ich sehr schnell schon > die Timer benutzt. > Ich war einfach zu faul, Befehle abzählen zu müssen, denn dabei kann man > sich auch schnell verzählen und die Zeiten stimmen nicht. Timer erfordern i.d.R. auch Interrupts. Die werden vielleicht noch später im Unterricht behandelt.
Peter D. schrieb: > Teo D. schrieb: >> Du denkst zu komplex. > > War jetzt auch nur mal als Ausblick gedacht, wenn man erfahrener ist. Ab > der 2. Zeitaufgabe geht es mit dem Scheduler einfacher. Tja, rein aus Forentradition, sollten wir uns jetzt drei Tage und Nächte, die Köppe darüber einhauen, was denn nu genau als "Scheduler" gelten darf und ob das ab dem 2. oder 5. Slot sinnvoller ist... ;D
Gast
#7153625
Peter D. schrieb: > War jetzt auch nur mal als Ausblick gedacht, wenn man erfahrener ist. Nein, mein Lieber. Deine Ratschläge setzen nicht nur einen C-Compiler voraus, sondern auch noch genügend Platz im Zielcontroller. Bedenke mal, daß recht viele PIC16 mit 2K an Befehlsworten auskommen müssen und obendrein auch nur rund 200 Byte an RAM zur Verfügung haben (wenn man mal durchscheinende RAM-Bereiche und Register abzieht). Und da fängst du großspurig an von Zeugs zu schreiben, was definitiv zu fett ist für die Zielhardware. Ein Scheduler in C, und als nächstes kommt ein voll ausgebautes printf und eine Weile später ein komplettes Linux mit grafischer Oberfläche? Man sollte ein bissel auf dem Teppich bleiben. Ich erinnere mich da an einen Jung-Ex-Kollegen, der bei einem kleinen PIC10 im SOT23 Gehäuse und nur maximal 512 Befehlsworten meinte, er wüßte keinen Grund, solche Winzlinge NICHT in C zu programmieren. Nun ja, manche Leute brauchen unbedingt einen V6, um beim Bäcker um die Ecke ihre Frühstücks-Semmel zu holen. Und hier ein kleines Beispiel, wie man sowas in etwa machen kann:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
W.S.
W.S. schrieb: > Man sollte ein bissel auf dem Teppich bleiben. Man kann auch mit 2kB Flash ne ganze Menge machen, z.B. float habe ich auch auf dem AT89C2051 benutzt, braucht 1kB Flash. Atmel hat aber auch die kleinen 8Pinner gut ausgerüstet, z.B. ATtiny85: 8kB Flash, 512B RAM. Mit PIC kenne ich mich nicht aus. Ich hab hier noch ein Delaymacro für den 8051 gefunden:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
0..4 Zyklen werden mit NOP gemacht, 5..514 Zyklen mit einem DJNZ und 515..65535 Zyklen mit 2 DJNZ. Der alte A51 Assembler kann leider nur 16Bit rechnen.
Gast
#7153753
W.S. schrieb: > Bedenke mal, > daß recht viele PIC16 mit 2K an Befehlsworten auskommen müssen und > obendrein auch nur rund 200 Byte an RAM zur Verfügung haben (wenn man > mal durchscheinende RAM-Bereiche und Register abzieht). Der 16F84A hat nur 1K Befehlsworte und 68 Bytes RAM.
Gast
#7153776
W.S. schrieb: > Ich erinnere mich da an einen Jung-Ex-Kollegen, der bei einem kleinen > PIC10 im SOT23 Gehäuse und nur maximal 512 Befehlsworten meinte, er > wüßte keinen Grund, solche Winzlinge NICHT in C zu programmieren. Recht hatte er.
Gast
#7153794
H. H. schrieb: > Der 16F84A hat nur 1K Befehlsworte und 68 Bytes RAM. Ist eben noch enger als ich so allgemein geschrieben habe. Jan schrieb: > Recht hatte er. Damit daß er es nicht weiß. Tja, das isses wohl. Peter D. schrieb: > Man kann auch mit 2kB Flash ne ganze Menge machen, z.B. float habe ich > auch auf dem AT89C2051 benutzt, Benutzt. Hmm. Für die PIC16 hatte ich die GK-Arithmetik selber geschrieben. Sowohl für 4 Byte GK als auch eine Variante mit 5 Byte. Damit die Mantisse groß genug ist, um das auch im Frequenzzähler benutzen zu können. Ansonsten weiß ich, was man alles in Assembler hinkriegt, auch wenn man keine Riesenvorräte an RAM+Flash hat. Alles andere sind die leider vielgehörten Ausreden von C-Programmierern, die nur vertuschen wollen, daß sie es eben nicht können. W.S.
H. H. schrieb: > Der 16F84A hat nur 1K Befehlsworte und 68 Bytes RAM. Ich hab ne kleine Dosierpumpe gebaut, wo ein 16F84 (ohne A!:) mit C vergewaltigt wurde und da sollte man solche "Klimmzüge" nur in homöopathischen Dosen anwenden. Man muss da auch nicht wirklich geizig mit den Ressourcen sein, aber wenn der "Jagdinstinkt" einmal geweckt ist... :D Hab kürzlich erst ein neues Update gemacht. Eigentlich wollte ich ja nur "Globale Dosis-Ende Tasten-Sperre" einfügen.... /* 48 byte RAM; 864 Words Globale Dosis-Ende Tasten-Sperre hinzugefügt (+10 Words) Buzzer Init Macro, auf Funtion Aufruf geändert (-5 Words) Buzzer(void) ohne Parameter, buzzer Struct auf Global geändert (-16 Words) Buzzer_Init() an_1bit Parameter raus geworfen (-16 Words) * Geplant * 20 Byte RAM noch frei -> Strucht Bitfeld (wieder) auf Char umstellen -> weniger Code? * ERLEDIGT 49 Bayte RAM; 858 Words (-6 Words) */ Nicht geplant Auf Assembler umschreiben (-650 Words erwartet) :D
Gast
#7153860
Peter D. schrieb: > Als ich 1990 mit dem 8051 angefangen habe, habe ich sehr schnell > schon die Timer benutzt. > Ich war einfach zu faul, Befehle abzählen zu müssen, denn dabei kann man > sich auch schnell verzählen und die Zeiten stimmen nicht. Na ja, man kann auch erst mal eine Schleife bis 100000 zählen lassen, abstoppen und dann korrigiert man diesen Wert damit 1 Sekunde bei rauskommt. Man kann auch lernen wie die Inder https://youtu.be/k_S2gRkUVn8
MaWin schrieb: > Na ja, man kann auch erst mal eine Schleife bis 100000 zählen lassen, > abstoppen und dann korrigiert man diesen Wert damit 1 Sekunde bei > rauskommt. Wenns wirklich auf ne "genaue" Sekunde ankommt, ist ne Delay-Schleife eh zu ~100% der falsche Weg.
MaWin schrieb: > Na ja, man kann auch erst mal eine Schleife bis 100000 zählen lassen, > abstoppen und dann korrigiert man diesen Wert damit 1 Sekunde bei > rauskommt. Das ist mit Abstand das umständlichste, was ich je gehört habe. Gerade mit ineinander verschachtelten Schleifen wird man damit kaum einen minimalen Restfehler erzielen.
Gast
#7154115
Peter D. schrieb: > Der alte A51 Assembler kann leider nur 16Bit rechnen. Das ist doch kein reales Hindernis - man kann auch mit einem 4bit-Prozessor 10stellige Dezimalzahlen verarbeiten, das konnten schon die ersten Taschenrechner. Zählen ist noch einfacher, gibt es einen Überlauf zählt man die nächsthöhere Stelle um 1 hoch, usw. Am Assembler liegt es nicht wenn man das nicht hinbekommt. Georg
Ich hab das immer so gemacht: Einfache Schleife
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
Dauert (n-1)*3 + 2 Zyklen, plus 2 (init) plus 4 (call/return) Zyklen. Benötigt eine RAM-Adresse d1. Doppelte Schleife
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
Dauert ((n1-1)*5) + ((n2-1)*1280) + 4, plus 4 (init) plus 4 (call/return) Zyklen. Damit kommt man schonmal etwas weiter, braucht dafür 2 Bytes RAM. Dreifache Schleife
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
Dauert ((n1-1)*7) + ((n2-1)*1792) + ((n3-1)*458752) + 6, plus 6 (init) plus 4 (call/return) Zyklen. Braucht 3 Bytes RAM. Natürlich kann man alle 3 Versionen auch "inline" benutzen, dann entfällt halt das return und die jeweils 4 Zyklen fehlen. Und: es geht auch, nur eine Schleife "Delay_0" zu nutzen, aber mehrere Initialisierungsteile mit verschiedenen Werten, da muss man dann aber noch jeweils ein goto einrechnen (2 Zyklen). Sehr kurze Verzögerungen kann man mit nop (1 Zyklus) oder goto $+1 (2 Zyklen) machen. Bei 4MHz Quarz-Takt ist ein Zyklus = 1 µs, auch ein gern genommenes Verständnisproblem beim PIC.
Georg schrieb: > Das ist doch kein reales Hindernis Dann erzähle mir mal, wie ich dem Delay-Macro den Wert 65537 übergebe, wenn der Assembler nur 16-bittig rechnet.
Peter D. schrieb: > Georg schrieb: >> Das ist doch kein reales Hindernis > > Dann erzähle mir mal, wie ich dem Delay-Macro den Wert 65537 übergebe, > wenn der Assembler nur 16-bittig rechnet. Na so wie alle das machen. Man kann halt nur einen gewissen Bereich abdecken und für jeden gibts halt dann ein eigens Macro.
Teo D. schrieb: > Na so wie alle das machen. Man kann halt nur einen gewissen Bereich > abdecken und für jeden gibts halt dann ein eigens Macro. Man kann sich aber auch die Hose mit der Kneifzange anziehen. Der AVR-Assembler rechnet intern 64-bittig, d.h. selbst ein Delay von 24h läßt man ihn bequem selber ausrechnen:
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
Beitrag "Re: 24h Schalter mit Attiny 12"
Peter D. schrieb: > Dann erzähle mir mal, wie ich dem Delay-Macro den Wert 65537 übergebe, > wenn der Assembler nur 16-bittig rechnet. Peter D. schrieb: > Der AVR-Assembler rechnet intern 64-bittig, d.h. selbst ein Delay von > 24h läßt man ihn bequem selber ausrechnen: ..... Wenn dir langweilig ist, such die einen interessanteren Job!
Gast
#7157530
Bei Sprut findest Du Beispiele für Warteschleifen in Assembler, einfach etwas weiter runterblättern: https://www.sprut.de/electronic/pic/programm/lauflicht/lauflich.htm So ähnlich habe ich das bereits für Projekte genutzt. Der PIC wartet dann natürlich einfach dumm und ist blockiert für weitere Aufgaben. Anders ginge es via Interrupt ähnlich dem millis() Befehl bei Arduino.
Gast
#7157964
Alter Falter, wer programmiert noch Assembler? Nimm MPLAB IDE und dir gehts deutlich besser, glaub mir !
Gast
#7158370
Daniel schrieb: > Alter Falter, wer programmiert noch Assembler? Nimm MPLAB IDE und dir > gehts deutlich besser, glaub mir ! Alter Falter, wer kaut noch selber sein täglich Brot? Nimm lieber fertig gekauten Instant-Brei und dir gehts deutlich besser, glaub mir ! W.S.
Gast
#7158437
Was soll das mit dem Taktzahlgefummel? Für sowas nimmt man nen Timer.
Antwort schreiben
Bitte melde dich an, um einen Beitrag zu schreiben.