Hallo zusammen, ich überlege gerade, wie ich ne Software PWM für meinen mega8515L mit BASCOM realisiere. Klingt das so geschickt: Wenn Timerwert = 100 dann die LED einschalten, ansonsten aus Oder sollte ich lieber den Timer bei sagen wir 155 starten lassen, und beim Interrupt die LED einschalten, und wenn der Interrupt wieder weg ist, ausschalten?
Dennis Brenzel schrieb: > Hallo zusammen, > > ich überlege gerade, wie ich ne Software PWM für meinen mega8515L mit > BASCOM realisiere. Klingt das so geschickt: > > Wenn Timerwert = 100 dann die LED einschalten, ansonsten aus Nö, denn dann kannst Du auf den Interrupt verzichten und den Port direkt von der Compare-Einheit des Timers schalten lassen, also Hardware-PWM. > > Oder sollte ich lieber den Timer bei sagen wir 155 starten lassen, und > beim Interrupt die LED einschalten, und wenn der Interrupt wieder weg > ist, ausschalten? Auch das ist es nicht... Es gibt verschiedene Varianten der Soft-PWM, eine (die leicht verständlichere) funktioniert so: Ein Timer generiert in regelmäßigen Zeitabständen Interrupts. In diesem Interrupt wird: - ein PWM-Zähler hochgezählt - bei Erreichen des PWM-Zählumfangs wird der PWM-Zähler auf 0 gesetzt und der Portpin eingeschaltet - bei Erreichen des Tastgrades (PWM-Wertes) wird der Portpin wieder ausgeschaltet - Dies kann für mehrere PWM-Kanäle mit eigenen PWM-Werten und Portpins quasi gleichzeitig erfolgen. In Bascom hast Du allerdings eine schwerwiegende Einschränkung: Bei jedem Interrupt werden alle 32 Register auf Stack gesichert, was 128 CPU-Takte zusätzlich kostet. Dies reduziert die erreichbare Interruptfrequenz drastisch und begrenzt die erreichbare PWM-Frequenz. So richtig flimmerfrei wird die PWM also kaum werden.
> - bei Erreichen des Tastgrades (PWM-Wertes) wird der Portpin wieder > ausgeschaltet Das hab ich irgendwie nicht ganz verstanden. Der PWM - Zähler zählt dabei nochmals auf den eingestellten Wert hoch und schaltet dann wieder zurück, oder was ist mit Tastgrad gemeint.
Ah, jetzt hab ich es glaube ich verstanden. Der Timer löst sagen wir bei 200 einen Interrupt aus, zählt aber weiter bis 255. Bei diesem Interrupt schaltet er eine LED ein. Hat der Timer 255 zählt er wieder zurück auf 0. Wenn er die 200 unterschreitet, löst er wieder einen Interrupt aus, der die LED dann ausschaltet. Wobei ich beim nächsten Problem wäre: Wie lass ich nen Timer rückwärts laufen, und wie sag ich dem Timer dann, welchen Interrupt er auslösen soll?
Der PWM-Zähler zählt von 0 bis zum PWM-Zählumfang, und zwar bei jedem Timer-Interrupt nur einen Schritt. Bei Erreichen des Zählumfangs wird er wieder auf 0 gesetzt. Gleichzeitig werden alle PWM-Kanäle auf H-Pegel gesetzt (eingeschaltet). In jedem Timer-Interrupt wird der PWM-Zähler mit den PWM-Werten (Sollwert Tastgrad) aller Kanäle verglichen und bei Gleichstand der entsprechende PWM-Kanal ausgeschaltet. Bei dieser Art der Software-PWM beginnen alle Kanäle zum gleichen Zeitpunkt mit dem Impuls, was eine impulsförmige Gesamtbelastung der Stromversorgung bewirkt. Es gibt aber auch eine andere Art der Software-PWM, die diesen Nachteil nicht hat. Sie braucht dafür aber für jeden Kanal einen eigenen PWM-Zähler. Diese Methode ist auch hier irgendwo im Forum beschrieben. <such...> Hier geht's weiter: Beitrag "Re: Software PWM auf 8 Kanälen" Unter Tastgrad verstehe ich das Verhältnis Impulsdauer zu Periode in Prozent oder als Bruch.
Das Problem wird für mich sein, das ganze auf BASCOM zu portieren, wie du ja schon beschrieben hast. Und wenns dann noch in C geschrieben ist, verstehe ich leider nur Bahnhof. Assembler versteh ich noch einigermaßen, wobei das auch schon wieder 8 Jahre her ist, und das war noch auf Siemens µC's. Ich danke dir auf jedenfall, ich werde versuchen mich da durch zu kauen.
Dennis Brenzel schrieb: > Ah, jetzt hab ich es glaube ich verstanden. Der Timer löst sagen wir bei > 200 einen Interrupt aus, zählt aber weiter bis 255. Bei diesem Interrupt > schaltet er eine LED ein. Hat der Timer 255 zählt er wieder zurück auf > 0. Wenn er die 200 unterschreitet, löst er wieder einen Interrupt aus, > der die LED dann ausschaltet. Nein, das Wäre Hardware-PWM im Phase-correct-Mode.... > Wobei ich beim nächsten Problem wäre: > Wie lass ich nen Timer rückwärts laufen, Gar nicht, das geht nur bei Hardware-PWM im Phase-correct-Mode. > und wie sag ich dem Timer dann, > welchen Interrupt er auslösen soll? Die Frage erübrigt sich im speziellen Fall, war sie allgemein gemeint, so verweise ich auf das Kapitel Timer im Datenblatt des verwendeten AVRs. Auch das Benutzen von Bascom befreit nicht vom Lesen des Datenblattes. ;-) Software-PWM wird durch einen Software-Timer (eine stinknormale Zählvariable) gesteuert. Der Timer mit seinem Interrupt sorgt nur dafür, dass diese Zählvariable in exakt gleichen Zeitabständen hochgezählt wird. Welchen Timer-Interrupt und Timer-Modus man nutzt, kommt darauf an, was der Timer sonst noch erledigen soll. Soll er nichts weiter als Software-PWM erledigen, nimmt man den Compare-Interrupt im CTC-Modus, denn der erübrigt Preload oder Aufaddieren des Intervalls auf das Compare-Register.
Dennis Brenzel schrieb: > Das Problem wird für mich sein, das ganze auf BASCOM zu portieren, wie > du ja schon beschrieben hast. Bascom ist für schnelle Folge von Interrupts absolut ungeeignet, weil es durch die Sicherung aller (also auch der unbenutzten) Register auf Stack zuviel wertvolle Rechenzeit vertrödelt. Es lohnt sich also nicht, Zeit dafür zu investieren. In der Zeit, bis Du merkst, dass es zu langsam wird, bist Du in ASM zehnmal fertig. > Und wenns dann noch in C geschrieben ist, > verstehe ich leider nur Bahnhof. Das geht mir nicht besser. > Assembler versteh ich noch > einigermaßen, wobei das auch schon wieder 8 Jahre her ist, und das war > noch auf Siemens µC's. Naja, jede Architektur hat ihren eigenen Assembler, abstrahiert gesehen ist zwar alles ähnlich, die details unterscheiden sich aber erheblich. Es lohnt sich aber, mit Hilfe von ASM die Architektur des Controllers kennen zu lernen. > Ich danke dir auf jedenfall, ich werde versuchen > mich da durch zu kauen. Viel Erfolg
So, ich hab bis heute versucht, was Gescheites hinzubekommen, aber wie ihr seht, komm ich nicht weiter. Hier mein Code:
1 | $regfile = "m8515.dat" |
2 | $crystal = 8390000 |
3 | Dim A As Integer |
4 | Dim B As Integer |
5 | |
6 | Config Timer0 = Timer , Prescale = 64 |
7 | |
8 | On Timer0 Timer0_isr |
9 | |
10 | Config Portc = Output |
11 | Portc = 255 |
12 | B = 120 |
13 | A = 0 |
14 | Enable Timer0 |
15 | Enable Interrupts |
16 | Portc.1 = 0 |
17 | |
18 | Do |
19 | Loop |
20 | |
21 | Timer0_isr: |
22 | Incr A 'A eins hoch zählen |
23 | If A = 200 Then |
24 | Portc.0 = 0 'Wenn A 200 ist dann portc.0 ein |
25 | A = 0 |
26 | End If 'A wieder nullen |
27 | If A = B Then 'Wenn A 120 ist dann |
28 | Portc.0 = 1 'Portc.0 aus |
29 | A = 0 'A wieder nullen |
30 | endif |
31 | Return |
Ich weiß, das A nie die 200 erreichen wird, da sie vorher von den 120 abgefangen wird, aber irgendwie steh ich momentan aufm Schlauch. Könnte mir jemand einen Wink mit der Blockhütte geben?
Hallo, > If A = B Then 'Wenn A 120 ist > Portc.0 = 1 'Portc.0 aus >> A = 0 'A wieder 0 >>endif >Return In diesem Fall darf A NICHT auf Null gesetzt werden. Dann ist es soweit korrekt. Den Befehl "endif" gibt es in BASCOM nicht ... Wenn ich richtig gerechnet habe, wird die Timer-ISR alle 1,9ms aufgerufen. > $crystal = 8390000 Was ist das für eine komische Frequenz?
AVRuser schrieb: > Den Befehl "endif" gibt es in BASCOM nicht ... Ohne bekomm ich einen Fehler. > Wenn ich richtig gerechnet habe, wird die Timer-ISR alle 1,9ms > aufgerufen. > >> $crystal = 8390000 > > Was ist das für eine komische Frequenz? Die hab ich mit nem Frequenzzähler ermittelt. Pin toggeln in ASM und die Befehle umgerechnet. ist aber auch nur ungefähr.
wenn Du aus A und B Bytes machst statt Interger, kannst Du Deine ISR extrem vereinfachen, indem Du Dir den "Überlauf" zunutze machst (255+1=0): Timer0_isr: Incr A if A > B then PortC.0=0 else PortC.0=1 'oder auch andersrum return PS: Das Speichern der Register beim ISR-Aufruf wird hier (prescaler 64) kaum eine Rolle spielen, man kann es aber mit Parameter NOSAVE verhindern.
> PS: Das Speichern der Register beim ISR-Aufruf wird hier (prescaler 64) > kaum eine Rolle spielen, man kann es aber mit Parameter NOSAVE > verhindern. Wo trag ich den ein?
Vor allem fällt mir ein, dass ich dass dann ja für jedes Register explizit machen muss, welches ich nicht speichern möchte, oder hab ich das falsch verstanden?
Also werden alle nicht gespeichert, so hab ich es verstanden:
1 | When you specify NOSAVE, no registers are saved and restored in |
2 | the interrupt routine. So when you use this option make sure to save |
3 | and restore all used registers. |
Dennis Brenzel schrieb: > Also werden alle nicht gespeichert, Etwas unglücklich ausgedrückt. no registers kein Register, kein einziges are saved wird gesichert and restored und wieder hergestellt .... daher when you use wenn sie das benutzen make sure müssen sie sicherstellen to save and restore alle benutzten Register selbst all used registers zu sichern und wieder herzustellen Wenn dir das jetzt erst mal nichts sagt, dann ist es besser du benutzt diese Möglichkeit erst mal nicht. Und nein, mit Registern sind keine Variablen gemeint, sondern die echten CPU-Register. Man muss also den Assembler Output studieren um festzustellen, welche davon vom Compiler in der ISR benutzt werden.
> Man muss also den > Assembler Output studieren um festzustellen, welche davon vom Compiler > in der ISR benutzt werden. Man benutzt aber Bascom, um genau das (sich mit Assembler befassen) zu vermeiden. Und man hat auch kein Interesse daran, mal selbst die Nase in eine Doku (Bascom-Hilfe, Controller-Datenblatt) zu stecken, es ist ja viel bequemer, sich alles zusammenzufragen und hinterher doch nicht selbstständig denken zu können. Ohne Verständnis der Architektur ist es (auch in einer Hochsprache) nicht möglich, halbwegs effiziente Programme zu schreiben. Und Software-PWM (auf mehreren Kanälen, denn sonst könnte man ja Hardware-PWM nutzen) verlangt nunmal halbwegs effiziente Programmierung, sonst wird es einfach zu langsam.
> Also werden alle nicht gespeichert Damit meinte ich kein Register, das mit den Variablen war mir klar. > Und man hat auch kein Interesse daran, mal selbst die Nase in eine Doku > (Bascom-Hilfe, Controller-Datenblatt) zu stecken, es ist ja viel > bequemer, sich alles zusammenzufragen und hinterher doch nicht > selbstständig denken zu können Das ist deine Meinung. Nur wenn ich auf Arbeit bin (Die im Übrigen nichts mit µC's zu tun hat), kann ich schlecht die Bascom Hilfe bemühen, geschweige denn ein Datenblatt lesen.
> Nur wenn ich auf Arbeit bin (Die im Übrigen > nichts mit µC's zu tun hat), kann ich schlecht die Bascom Hilfe bemühen, > geschweige denn ein Datenblatt lesen. Dann solltest Du Dich auch besser um Deine Arbeit kümmern und nicht dem Chef Deine Arbeitszeit stehlen... ;-) MfG
Kluchscheißender Consulter schrieb: > Dann solltest Du Dich auch besser um Deine Arbeit kümmern und nicht dem > Chef Deine Arbeitszeit stehlen... ;-) :P Paul Baumann (Gast) schrieb: > Vielleicht hilft Dir das: > Beitrag "Software PWM Bascom" Den hatte ich auch schon entdeckt, nur irgendwie war das für den Anfang doch etwas verwirrend und hatte leider nicht weiter geholfen. Danke trotzdem. Jetzt muss ich das nur noch auf die anderen LEDs konvertieren, damit ich mein "fadendes" Lauflicht habe.
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.