Hi Leute, Ich dimme mithilfe der PWM eine LED. Ich versteh das nicht : 1. Wenn ich PWM mit Timer0 und einer Timer-Taktrate von fosc/32 mache, dann hab ich eine Frequenz wie im Bild in grün zu sehen und die LED geht schneller ein und aus. 2. Wenh ich hingegen PWM mit Timer2 und einer Timer-Taktrate von fosc/12 mache, dann hab ich eine Frequenz wie im Bild in rot zu sehen und die LED geht sehr langsam ein und aus. Außerdem geht die LED nicht richtig aus sondern hat noch richtig Leuchtkraft, im Gegensatz zur Nr. 1. Könnt ihr mir bitte weiterhelfen?
Lens schrieb: > Ich dimme mithilfe der PWM eine LED. Ich versteh das nicht : Also noch mal der Reihe nach: - welcher µC - wieviel Bits haben die Timer0 und 2 - mit welchem Takt betreibst du den µC - wie ist jeweils der Vorteiler eingestellt - mit welchen Frequenzen blinken deine LEDs
Lens schrieb: > Hi Leute, > > Ich dimme mithilfe der PWM eine LED. Ich versteh das nicht : > 1. Wenn ich PWM mit Timer0 und einer Timer-Taktrate von fosc/32 mache, > dann hab ich eine Frequenz wie im Bild in grün zu sehen und die LED geht > schneller ein und aus. > 2. Wenh ich hingegen PWM mit Timer2 und einer Timer-Taktrate von fosc/12 > mache, dann hab ich eine Frequenz wie im Bild in rot zu sehen und die > LED geht sehr langsam ein und aus. Außerdem geht die LED nicht richtig > aus sondern hat noch richtig Leuchtkraft, im Gegensatz zur Nr. 1. > > Könnt ihr mir bitte weiterhelfen? Ich seh' auch keine Bilder. Aber mal davon abgesehen, mit welchem Prozessor arbeitest du? Dann können wir erstmal sehen, wie Timer0 und Timer2 arbeiten, ob die 8 oder 16 Bit haben und vieles mehr. Wie sind die LED's angeschlossen? In welchem Mode sind die beiden Timer programmiert? Sag mal was zu den ganzen Fragen, dann können wir weiter überlegen. Ach ja, nochwas. Eine PWM an sich ergibt ja nur abhängig vom Tastverhältnis eine bestimmte Helligkeit (die gleich bleibt!). Nur, wenn du die PWM änderst, ändert sich auch die Helligkeit der LED. Wenn die schneller oder langsamer an- und ausgeht, liegt das an der Änderung der PWM. Und die Änderung machst du ja selber per Software.
Yep, Du mußt Dich für eines entscheiden - der Timer kann nicht beide Extremwerte (100% ein oder 100% aus) erreichen. An einem Ende der Skala bleibt immer so ein Nadelimpuls übrig.
Was aber komisch ist: 1. Wieso geht die LED schneller ein und aus beim Timer0, obwohl Timer0 eine niedrigere Taktrate von fosc/32 hat und Timer2 hingegen fosc/12? 2. Wieso kann beim Timer0 die LED viel dunkler und heller werden als beim Timer2? Wäre sehr dankbar auf Ratschläge
Lens schrieb: > Ich arbeite mit dem Infineon C515C-L Okay, mit dem kenne ich mich überhaupt nicht aus. Aber meine Fragen oben gelten prinzipiell für alle Timer. Auf den Bildern sieht man die Ausgänge der Timer. Und auch, daß sie mit unterschiedlichen Frequenzen arbeiten (fosc/32 und fosc/12). Es sind nur schmale Impulse vorhanden, also liegt der Vergleichswert sehr niedrig oder bei "0". Wie BEN schon schrieb, bleibt an einem Ende der PWM immer eine Nadel übrig, sonst wäre es ja keine PWM. Wenn der Ausgang dauerhaft auf Low oder High liegt, hast du keine PWM, sondern nur, wenn man auch ein Puls-/Pausen-Verhältnis hat. Die Bilder sind also völlig in Ordnung. Die Änderung der PWM, damit die LED heller wird, machst du ja selber. Wenn du die schneller änderst, geht auch die LED schneller an und erreicht ihren Maximalwert. Jetzt schreib nochmal genau, was dein Problem ist und vor allem, beantworte bitte die obigen Fragen, ok?
Hey super Erstmal danke für deine Antworten. Jetzt gebe ich Antworten: 1. Mein Problem: Wieso geht die LED schneller ein und aus beim Timer2 obwohl Timer2 eine höhere Taktrate hat als Timer0? 2. Modus-Timer-0: Modus-0 (8-Bit-Timer) 3. Modus-Timer-2: Timer-Modus mit Reload-Modus-0 (Auto-Reload) --> Timer2 wird bei jedem Overflow mit 0xFF00 neu initialisiert. danke
Sry, die erste frage lautet: 1. Wieso geht die LED beim Timer2 langsamer ein und aus, obwohl Timer2 eine höhere Taktrate hat als Timer0
Hi >1. Wieso geht die LED beim Timer2 langsamer ein und aus, obwohl Timer2 >eine höhere Taktrate hat als Timer0 Sind das vielleicht ein 8-Bit und ein 16-Bit Timer. MfG spess
Lens schrieb: > Timer0 ist ein 8-Bit-Timer > Timer2 ist ein 16-Bit-Timer Was wundert dich dann? Wie lange braucht ein 8-Bit Timer, der bis 255 zählt, bei einer Taktrate von fOsc/32 zählt um einmal von 0 bis 255 zu zählen. Und wie lange braucht ein 16-Bit Timer, der bis 65535 zählt, bei einer Taktrate von fOsc/12 zählt, um einmal von 0 bis 65535 zu zählen? Die Takrate ist eine Sache. Die andere Sache ist, wieviele derartige Takte zusammenkommen mssen, ehe etwas passiert.
Lens schrieb: > Sry, die erste frage lautet: > 1. Wieso geht die LED beim Timer2 langsamer ein und aus, obwohl Timer2 > eine höhere Taktrate hat als Timer0 Nochmal: Die PWM, also das Tastverhältnis high/low hängt nicht von der Taktrate des Timers ab. Wenn du eine PWM von 50% hast, also 50% high und 50% low, dann leuchtet die PWM mit halber Helligkeit (lassen wir mal die Empfindlichkeit des menschlichen Auges weg). Wenn du jetzt die Taktrate des Timers veränderst, bleibt die PWM immer noch auf 50%. Damit ändert sich überhaupt nichts an den Verhältnissen. Man merkt es nicht mal an der Helligkeit der LED! Nur, wenn du den Timer sehr langsam machst, siehst du, wie die LED mit der PWM ein- und ausgeschaltet wird. Dann flimmert die LED. Also mußt du dein Problem woanders suchen. Es hängt nicht von der Taktrate des Timers ab. Zeig doch mal, auf welche Art und Weise du die PWM änderst. Einmal für Timer0 und einmal für Timer2. Vielleicht gibt's dort Unterschiede? Wenn du z.B. auf den PWM-Wert immer 1 addierst, dauert das bei einem 16bit-Timer natürlich länger (65535 Takte) als bei einem 8bit-Timer (255 Takte). Vielleicht liegt's ja daran?
Mich wunderts weil: 1. Timer2 eine höhere Taktfrequenz hat als Timer0 2. Timer2 und Timer0 zählen gleich viel, also 256, weil Timer2 immer mit 0xFF00 reloaded wird.
Lens schrieb: > Mich wunderts weil: > 1. Timer2 eine höhere Taktfrequenz hat als Timer0 > 2. Timer2 und Timer0 zählen gleich viel, also 256, weil Timer2 immer mit > 0xFF00 reloaded wird. 0xFF00 ist nicht 256, sondern 65280. Wenn du 256 (eigentlich 255) willst, dann schreib 0x00FF. Dann klappt's vielleicht :-)
Bernd S. schrieb: > Lens schrieb: >> Mich wunderts weil: >> 1. Timer2 eine höhere Taktfrequenz hat als Timer0 >> 2. Timer2 und Timer0 zählen gleich viel, also 256, weil Timer2 immer mit >> 0xFF00 reloaded wird. > > 0xFF00 ist nicht 256, sondern 65280. Wenn du 256 (eigentlich 255) > willst, dann schreib 0x00FF. Dann klappt's vielleicht :-) Da hier immer von Reload gesprochen wird: Ich denke der Timer wird mit 0xFF00 vorgeladen und zählt dann hoch bis 0xFFFF. So gesehen dürfte das korrekt sein. Wenn ... das Vorladen funktioniert. Aber wie weiter oben schon geschrieben: damit ist nicht geklärt, warum eine LED überhaupt faden soll.
Karl Heinz Buchegger schrieb: > Bernd S. schrieb: >> Lens schrieb: >>> Mich wunderts weil: >>> 1. Timer2 eine höhere Taktfrequenz hat als Timer0 >>> 2. Timer2 und Timer0 zählen gleich viel, also 256, weil Timer2 immer mit >>> 0xFF00 reloaded wird. >> >> 0xFF00 ist nicht 256, sondern 65280. Wenn du 256 (eigentlich 255) >> willst, dann schreib 0x00FF. Dann klappt's vielleicht :-) > > Da hier immer von Reload gesprochen wird: > Ich denke der Timer wird mit 0xFF00 vorgeladen und zählt dann hoch bis > 0xFFFF. So gesehen dürfte das korrekt sein. > Wenn ... das Vorladen funktioniert. > > Aber wie weiter oben schon geschrieben: damit ist nicht geklärt, warum > eine LED überhaupt faden soll. Ich hab's auch gerade gesehen. Sorry! Wenn der Timer vorwärts zählt, stimmt der Wert zum Vorladen schon. Denkfehler von mir (0xFF00 ist doch nicht 256!) :-) Also brauchen wir wirklich mal eine Aussage, wie die PWM von Lens geändert wird. Das wissen wir immer noch nicht. Dort wird wohl die Ursache liegen... Gruß Bernd
In der Quellcodedatei ist zu sehen, wie die PWM geändert wird. Auf dieselbe Art und Weise wird auch die PWM mit Timer0 geändert. Beim Timer2 ist wirklich das Problem, dass sich die LED damit nur sehr wenig verdunkeln lässt. Beim Timer0 hingegen kann es sehr dunkel werden. Bin ratlos
Lens schrieb: > In der Quellcodedatei ist zu sehen, wie die PWM geändert wird. Auf Auf den ersten Blick fällt mir auf, daß du die PWM softwaremäßig machst. Kann der Timer das nicht selbst? Ich schaue nochmal drüber, ob ich was finde. Was machst du mit TH2 und TL2?
Aufgrund des Auto-Reload wird TH2 nach jedem Overflow mit 0xFF initialisiert und TL2 hingegen wird wie man im Code sieht von mir abhängig von der gewählten Pulsbreite "width_high" initialisiert.
Der Vorladewert des Timers ist doch CRCH und CRCL, oder? Was ist die Aufgabe von TH2 und TL2? Sind das Timer-Register? Wenn nicht, wo fragst du dann TL2 ab? Sorry für die Frage. Wie gesagt, ich kenne den Prozessor nicht, gebe mir aber Mühe die Funktion zu verstehen...
Hi
>In der Quellcodedatei ist zu sehen, wie die PWM geändert wird.
Du hast Autoreload eingeschaltet: Damit werden die Timerregister mit
CRCH und CRCL geladen. die sind aber nirgens initialisiert.
Abgesehen davon lädst du nur TL2 im Interrupt nach. Zu dem Zeitpunkt
dürfte TH2 schon Null sein.
MfG spess
Ich habe mir mal das Datenblatt geholt. Du veränderst in deiner Schleife TL2, also den eigentlichen Timer-Wert. Damit machst du den Timer schneller oder langsamer, weil er nicht mehr die Werte vom Vorladewert bis 0xFFFF (16bit) zählen darf. Der Timer wird beim Überlauf mit 0xFF00 vorgeladen, du veränderst ihn dann aber nochmal, indem du TL2 änderst. Eine PWM hat aber die Eigenschaft, daß die Summe aus low- und high-Zeit immer gleich ist und nur das Verhältnis geändert wird. Mach doch eins: Laß TL2 in Ruhe und vergleiche ihn nur mit width_high. Wenn der TL2 größer ist als width_high, schalte den Port aus. Wenn TL2 Null ist, schalte ihn ein. Damit müßte es gehen. Versuchs mal...
Erstmal danke für die Antwort Bernd, Die Summe aus high und low-Zeit bleibt auch gleich: Beim Overflow wird TH2 mit 0xFF geladen und zählt egal ob jetzt ein High oder Low-Signal anliegt immer bis 0xFFFF --> Die Summe bleibt gleich, weil gilt: TL2-bei-High = 255-width_high TL2-bei-Low = width_high --> Die Summe, die gezählt wird ist immer 255
Gibt es in deiner Entwicklungsumgebung keinen Simulator, mit dem man Schritt für Schritt verfolgen kannst, was passiert?
Hi >Beim Overflow wird TH2 mit 0xFF geladen und zählt egal ob jetzt ein High >oder Low-Signal anliegt immer bis 0xFFFF Bei einem Overflow zählt der Timer wieder ab 0x0000. Also ist TH2=0. MfG Spess
1. Der Timer2 fängt bei jedem Overflow bei 0xFF00 an zu zählen, siehe oben in der Beschreibung 2. Im Simulator kann man es nachverfolgen: Sobald ich in der ISR bin, werden gleich mehrere High und und Low-Pulse. Obwohl das Interrupt-Flag zurückgesetzt wird. Aber das ist auch beim Timer0 der Fall.
Lens schrieb: > Erstmal danke für die Antwort Bernd, > > Die Summe aus high und low-Zeit bleibt auch gleich: > Beim Overflow wird TH2 mit 0xFF geladen und zählt egal ob jetzt ein High > oder Low-Signal anliegt immer bis 0xFFFF --> Die Summe bleibt gleich, > weil gilt: > TL2-bei-High = 255-width_high > TL2-bei-Low = width_high > --> Die Summe, die gezählt wird ist immer 255 Nehmen wir mal an, width_high ist 10. High: 255-10=245, damit wird TL2 geladen und der Timer läuft los. Dann wird er nach 10 Takten die 255 (Höchstwert) erreichen und wird durch den Auto-Reload auf 0xFF00 geladen, damit ist TL2 wieder NULL. Damit ist der Timer gerade mal 10 Takte gelaufen, sollte aber 255 laufen! Wenn der Timer immer 255 Takte läuft, ohne daß er angefaßt wird, kannst du das width_high mit dem Timer (TL2) vergleichen und wenn TL2 größer als width_high ist, machst du den Port an, bei TL2=0 aus. Und das ganze, ohne den Timer anzufassen. Einfach nur bei Null einschalten und bei zutreffendem Vergleich wieder aus. Damit bleibt die PWM-Frequenz immer gleich. Oder übersehe ich hier was? Versuchs einfach mal :-)
--> "Nehmen wir mal an, width_high ist 10." Ok --> "High: 255-10=245, damit wird TL2 geladen und der Timer läuft los." Richtig --> "Dann wird er nach 10 Takten die 255 (Höchstwert) erreichen und wird durch den Auto-Reload auf 0xFF00 geladen, damit ist TL2 wieder NULL." Richtig --> "Damit ist der Timer gerade mal 10 Takte gelaufen, sollte aber 255 laufen!" Nein: Im Programm wählt der Benutzer die Pulsbreite des High-Pulses. Das ist "width_high". Wenn width_high=255 ist, dann gilt für High-Puls: TL2=255-255=0 --> Also läuft es 255. Wenn aber width_high=245 ist, dann gilt: TL=255-245=10, damit läuft es nur 10 "Oder übersehe ich hier was?" --> Der Sinn vom Programm ist es, dass die Pulsbreite des High-Pegels von "width_high" abhängig ist, was wiederum vom Benutzer immer neu eingegeben wird..
Sorry, ich habe etwas ganz anderes übersehen. Ich ging NICHT davon aus, daß der Interrupt ja nur dann auftritt (und die ISR aufruft), wenn der Timer abgelaufen und neu geladen wird. Und nur dann wird auch TL2 verändert. Wenn man jetzt 2 Timer-Overflows zusammennimmt (einmal low und einmal high), dann ist die Summe dieser beiden wieder gleich. Stimmt also. Das war ein Denkfehler meinerseits. Wo kommen jetzt die mehreren Impulse bei Eintritt in die ISR her, die du beschreibst? Wie sehen die aus? Wie lang sind sie, wie lang sind die Pausen zwischen den Impulsen und wie viele kommen dort? Vielleicht kommen wir der Sache so auf die Spur... Wie sieht es mit T2CON aus? Du setzt T2PS und T2R1 auf "1". Was ist mit den anderen Bits? Können die einen Einfluß haben auf den Timer? Vielleicht steht da eins nicht so, wie es soll...
Erstmal Danke an Bernd, das du mit mir am Ball bleibst: Wenn einmal die Interrupt Service Routine des Timer2 betreten wird, wird diese mehrmals ausgeführt, das nimmt ca 0.18 Sekunden in Anspruch. Ich habe ein Bild angehangen, dass die Signale zeigt, die während dieser 0.18 Sekunden erzeugt werden.
Nochmal kurz zu meinem vorigen Post: Kann es sein, daß durch falsche Bits der Reload Mode 1 vom Timer2 eingestellt ist? Dann wird der Reload abhängig von einer negativen Flanke an P1.5/T2EX ausgeführt. Kann es dadurch zu Unregelmäßigkeiten kommen? Ich schau jetzt mal, ob ich wegen der Impulse was finde...
Es ist auf jeden Fall der richtige Reload-Modus eingestellt: "on T2 overflow". Daran kanns also nicht liegen.
das "interrupt 5" bei der ISR ist auch richtig? Was heißt die 5? T2IO finde ich auch nicht im Datenblatt. Ich weiß nicht, ob es noch ein ausführlicheres gibt. Was ich habe, hat 96 Seiten.... Kannst du, wenn es die Hardware zuläßt, den Timer mal im Compare-Mode betreiben? Dann macht der ALLES ganz alleine, und du mußt nur noch das Compare-Register laden. Der macht immer eine PWM, und wenn du das Compare-Register änderst, ändert er die PWM. Sowas ist mir immer sympathischer als eine Software-PWM... Im Augenblick habe ich keine Idee mehr. Ich werde in ein paar Minuten erstmal ausschalten. Morgen abend bin ich wahrscheinlich wieder online. Vielleicht fällt dir ja inzwischen was ein. Wenn ja, will ich's unbedingt wissen :-) Also viel Erfolg noch!
--> "Das "interrupt 5" bei der ISR ist auch richtig? Was heißt die 5? Es ist richtig. 5 steht für "Timer2 Overflow" --> "T2IO finde ich auch nicht im Datenblatt. Ich weiß nicht, ob es noch ein ausführlicheres gibt. Was ich habe, hat 96 Seiten...." Es heißt "T2I0", nicht "T2IO" --> Kannst du, wenn es die Hardware zuläßt, den Timer mal im Compare-Mode ..." Beim Timer0 hats doch wunderbar geklappt, wieso klappts hier nicht. Das würd ich gern wissen. --> "Im Augenblick habe ich keine Idee mehr. Ich werde in ein paar Minuten erstmal ausschalten. Morgen abend bin ich wahrscheinlich wieder online. Vielleicht fällt dir ja inzwischen was ein. Wenn ja, will ich's unbedingt wissen :-)" OK :). Dann muss ich wohl weiterexperimentieren Trotzdem danke!
Lens schrieb: > Beim Timer0 hats doch wunderbar geklappt, wieso klappts hier nicht. Das > würd ich gern wissen. > Das würde mich auch interessieren, deshalb die Bitte um Nachricht, wenn du es weißt. Oder eben morgen abend wieder... Wie gesagt, ich sehen den Prozessor das erste Mal im Leben und hatte noch nie mit ähnlichen zu tun. (Früher Z80 mit aller Peripherie, da kannte ich jedes Bit, später mal kurz PIC, dann Atmel) Deshalb bin ich immer neugierig, wenn ich was (für mich) neues kennen lerne. Also bis dann, und viel Erfolg! Ich sehe gerade, im T2CON gibt es auch T2R0, das Bit ist bestimmt auch für den Reload-Mode da. Du hast bei der Initialisierung nur das T2R1 gesetzt. Reload Mode 0 ist der, den du haben willst, Mode 1 ist mit der Flanke an T2EX. Kann es sein, daß du T2R0 UND T2R1 richtig einstellen mußt?
Für den Reload-Mode-0 muss nur T2R1 gesetzt werden. Das "T2CON"-Register ist stdweise mit 0x00 initialisiert und damit auch T2R0. Deswegen gilt: T2R0=0 und T2R1=1 --> Reload-Mode-0 Man. Woran liegt das Problem .. :). Also im Simulator entstehen ja richtige Spannungen. Auch eine Spannung von 0V, nur wenns auf der Hardware läuft, wird die LED nicht sehr dunkel.. Könnte es vielleicht an der Frequenz des Timer2 liegen, dass es eventuell zu schnell für die LED ist?
Wie schnell ist denn der Timer 2? Die PWM-Frequenz müßte ja dann fTimer/512 betragen (Zeit für high + Zeit für low). Und der Timer läuft ja mit freq/12. Wie hoch ist die Taktfrequenz vom Prozessor? Die LED müßte eigenlich sehr viel mitmachen. Ich kanns nicht genau sagen, aber die sollten schon so um die 1MHz mitmachen, abhängig von der LED. Das wäre dann ein Takt des Prozessors von 6,1GHz! Das hat der bestimmt nicht :-) Ich habe was von max. 10MHz gelesen... Kannst du die LED-Zeiten mit dem Oszi kontrollieren? Stimmen die mit der berechneten Frequenz überein? Bei 10MHz ist die PWM-Frequenz bei 1627Hz. Macht die LED auf jeden Fall.
Hmm.. Sowas ist echt blöd. Es gibt keinen vernünftigen Grund, weswegen es nicht gehen sollte. Beim Timer0 gehts doch auch.. Hilft nichts. Dann muss ich grübeln. Trotzdem Danke Bernd. Danke für die Zeit, die du dafür investiert hast!
So, jetzt bin ich wirklich weg. Viel Erfolg und denk dran, ich bin neugierig! Gruß Bernd
Das gibts doch nicht: Im Debugger erreiche ich effektive 0V, aber wenn ich die Software auf dem Mikrokontroller normal laufen lasse, so leuchtet es noch ziemlich stark. Eine Nebenbemerkung: Die LED leuchtet, wenn man in den Pin eine 0 schreibt und es geht aus, wenn man in den Pin eine 1 schreibt. Ich hab grad kein Plan worans liegt
Lens schrieb: > > Eine Nebenbemerkung: Die LED leuchtet, wenn man in den Pin eine 0 > schreibt und es geht aus, wenn man in den Pin eine 1 schreibt. Hallo, nur ganz kurz, bin auf Arbeit. Wenn die LED bei 0 leuchtet und bei 1 ausgeht, hängt sie an (+) mit der Anode. Die Katode am Pin. Bis heute abend...
Dieser Pin 1.0 ist gleichzeitig /INT3 bzw. compare 0 output .. Aber das dürfte nicht das Problem sein, da diese Sekundärfunktion von mir nirgends aktiviert wird..
Hi, Es scheint wirklich an der Frequenz zu liegen. Ich glaub Timer2 ist zu schnell für die LED. Wieso sollte sonst die LED nicht sehr dunkel werden können obwohl ich TH2 und TL2 mit 0xFF initialisiere beim High-Puls.
Denn die Dauer des High-Pulses beim Timer2 (mit dem High-Puls wird die LED ausgeschalten) beträgt gerade mal 0.3ms --> Beim Timer0 hingegen beträgt die Dauer des High-Pulses ganze 5ms. Könnte es vielleicht daran liegen?
Das kann ja nicht sein. Timer0 hat doch den ein und selben Code. Der einzige Unterschied ist dass es zwei unterschiedliche Timer sind. Beide zählen aber gleich viel. Der einzige Unterschied ist, dass Timer2 schneller ist als Timer0. Es kann einfach nicht sein, dass ich einen Fehler hab. Es passt ja alles. Aber wieso wird dann die LED nicht sehr dunkel? Was ist der Grund? Wenn ich einen Fehler hätte, hätte das doch irgendjemand schon längst herausgefunden.
Lens, ich hätte dir beinahe schon einen falschen Tipp gegeben. Gelegentlich schreibe ich ja schon mal was zu den alten 80C515, und hielt den C515C auch annähernd kompatibel dazu. Ich fragte mich schon eine Weile: Wie macht denn der da mit dem 515 überhaupt PWM? Nachdem ich das Datenblatt eine Weile durchforstete, sah ich, der hat die gute alte vollautomatische PWM-Unit ja gar nicht mehr!!! Jedoch beschäftigte ich mich nicht weiter mit dem C515C, vielleicht gibt es ja da eine Produktpalette mit verschiedenen Typen. Aber das nur am Rande.
Ich hab mir mal ein größeres Datenblatt runtergeladen, da steht mehr drin. Sind um die 300 Seiten. Du machst inzwischen mal folgendes: - Timer NICHT laufen lassen - den PIN auf "0" setzen - Spannung am Pin messen (muß 0 sein), LED ist ein - PIN auf "1" setzen - Spannung am Pin messen (muß 5V sein), LED ist aus Wenn 0 am Pin liegt, muß die LED voll leuchten, wenn 1 anliegt, ist die LED ganz aus. Dabei gehe ich davon aus, daß die LED mit der Kathode am Pin hängt, dann der Vorwiderstand kommt und der hängt an VCC (+5V). Damit stellst du erstmal fest, ob der Pin richtig schaltet. Den Anschluß der LED vergleichst du mit dem Timer0. Mach das bitte bis heute abend, dann sehen wir weiter. Bernd
Hi Leute, Danke das ihr mir helft: Wenn ich den Timer2 nicht starte, dann leuchtet die LED zu 100% wenn P1.0=0 und ist zu 100% aus wenn P1.0=1. Das einzige was ich sagsen kann ist, dass Timer0 den Pin 1.0 nicht verwendet. Timer2 hingegen verwendet P1.0 nur dann, wenn ich den Compare-Mode oder capture-mode aktiviere, dann gilt: "P1.0 = INT3 = CC0 Compare output / capture input for CRC register" --> Aber ich hab sowas ja nicht aktiviert. Wenn wir das Problem lösen, dann bin ich echt erleichter.
Ich glaub Bernd ist grad genauso ratlos wie ich.. :) Naja trotzdem danke an alle für die Hilfe!
Hallo Lens, korrigiere mal bitte alle Zeilen, die ich ganz hinten mit einem Kommentar versehen habe. Zum Beispiel in der ISR ganz oben: TF2 = 0; --> IRCON &= ~(1<<TF2); und alle anderen, wo ganz hinten ein Kommentar steht. Der Hintergrund: "TF2" ist kein Byte, dem du einen Wert zuweisen kannst. Es ist ein Bit im Register "IRCON", das du in diesem Falle rücksetzen mußt. Und das passiert mit IRCON &= ~(1<<TF2); Wenn du ein Bit in einem Register setzen willst, machst du das zum Beispiel mit T2CON |= (1<<T2I0); Damit setzt du das Bit "T2I0" im Register T2CON. Die CRCH, CRCL, TH2, TL2 sind ganze Register, denen du direkt einen Wert zuweisen kannst. Dort mußt du im Programm nichts ändern. Gruß Bernd
TF2 ist so definiert: "sbit TF2 = IRCON^6;" --> Man kann TF2 einen ganz normalen Wert, 0 oder 1 zuweisen. Wenn es so gewesen wäre wie du sagst, dann müsste das auch mit Timer0 nicht hinhaun. Ganz schön knackige Aufgabe ha ? :)
Dann ist das wohl als Makro in einem *.h-File definiert? Das habe ich auch noch nicht gesehen... Na gut, einen Versuch war's wert. Ich kenne die Schreibweise, wie ich es vorgeschlagen habe, als normale C-Syntax. Kennt eigentlich jeder Compiler, weil es Standard ist. Mittlerweile bin ich auch ratlos. Ich kann dir nur empfehlen, mal jemanden zu fragen, der einen Oszi hat. Vielleicht kommt er mal vorbei oder leiht ihn dir aus für die Fehlersuche. Damit kannst du auf jeden Fall sehen, was wirklich am Port des Prozessors passiert, kannst Frequenzen und Zeitabstände messen und sehen, was Programm-Änderungen für Auswirkungen haben. Der Simulator zeigt nicht unbedingt die Wirklichkeit. Wenn du z.B. ein freies Bit des Prozessors an einer Programmstelle setzt und an einer anderen Stelle wieder rücksetzt, kannst du die wirkliche Laufzeit messen. Oder wie oft und in welchem Abstand die ISR aufgerufen wird. Oder eben alles mögliche, was du wissen willst. Versuch mal, daß du einen Oszi bekommst... Wenn mir noch was einfällt, melde ich mich. Und wenn du die Ursache findest, meldest du dich. Ok? Viel Erfolg!
TF2 ist ein einzelnes bit, dem man direkt 0 oder 1 zuweisen kann. Das war bisher schon richtig. Der Compiler wandelt diesen Code TF2 = 0 in den Bitbefehl CLR TF2 um, das sollte man ja im Listing nach schauen können.
@wilhelm: Naja, nur TF2 löschen ist nicht - Der Compiler muß auch wissen, in welchem Byte bzw. Register dieses eine Bit ist. Nur so kann er sagen: "lösche das Bit TF2 im Register IRCON". Und das passiert hier wahrscheinlich durch ein Makro, nehme ich an. Leider kenne ich die hier verwendete Syntax bzw. den Preprozessor dieses Compilers nicht. @Lens: Was ist das für ein C-Compiler, den du verwendest? Vielleicht kannst du auch mal ein *.h-File posten, in dem die Register und deren Bits definiert werden? Dann kann ich mir mal die Syntax anschauen. Gruß Bernd
Bernd S. schrieb: > @wilhelm: > Naja, nur TF2 löschen ist nicht - Der Compiler muß auch wissen, in > welchem Byte bzw. Register dieses eine Bit ist. > Nur so kann er sagen: "lösche das Bit TF2 im Register IRCON". > Und das passiert hier wahrscheinlich durch ein Makro, nehme ich an. Glaub mir, daß es so ist, wie ich schrieb. Der Lens kann ja das Assembler-Listing mal hoch laden, um nachzusehen.
Es handelt sich um den C51-Compiler von Keil. Die Headerdatei hab ich angehangen.
TF2 = 0 wird vom Compiler umgewandelt in: ; // Timer2 Interrupt-Flag zurücksetzen ; TF2 = 0; ; SOURCE LINE # 17 CLR TF2 ;
Stimmt schon, im Header-File wird das einzelne Bit definiert, in welchem Register es liegt und welche Bit-Nr. es ist. Keil geht hier einen Sonderweg und hat neue Elemente in die Sprache C aufgenommen, die nicht dem C-Standard entsprechen. Das sind z.B. "sfr" und "sbit", die hier im Headerfile verwendet werden. Das erklärt auch, warum man z.B. dem TF2 direkt eine Zuweisung macht. Ich habe bis jetzt den Keil noch nicht in den Fingern gehabt. Und ich wußte auch nicht, daß jemand auf die Idee kommt, eine Sprache so zu verändern. Nun gut, Keil hat's gemacht. Ich kenne mich einigermaßen mit C aus, aber die Sprache von Keil ist schon was anderes :-) Also wie ich das sehe, hast du das von der Syntax her richtig gemacht. Und über Keil zu meckern, hilft uns nicht weiter ;-) Wieder eine Fehlerquelle ausgeschlossen. Wie sieht's aus mit einem Oszi? Du kennst doch bestimmt jemanden, der dich mal besuchen kann oder dir einen leiht? Versuch mal einen zu bekommen. Siehe obiger Post. Gutes Gelingen weiterhin. Vielleicht packen wir's ja noch.
Lens schrieb: > TF2 = 0 wird vom Compiler umgewandelt in: > > ; // Timer2 Interrupt-Flag zurücksetzen > ; TF2 = 0; > ; SOURCE LINE # 17 > CLR TF2 > ; Na, genau so, wie ich vermutete. Durch die unterschiedlichen Bezeichner sfr und sbit bekommt der Compiler mit, ob es ein Byte oder ein bit ist. Die Headerdatei sieht soweit auch ganz OK aus. Bernd S. schrieb: > Keil geht hier einen > Sonderweg und hat neue Elemente in die Sprache C aufgenommen, die > nicht dem C-Standard entsprechen. Das sind z.B. "sfr" und "sbit", die > hier im Headerfile verwendet werden. Nicht nur Keil, das ist bei allen 8051-Compilern so, auch bei meinem SDCC. Es muß beim 8051 zwischen bits und Bytes unterschieden werden. Lens schrieb: > Timer2 hingegen verwendet P1.0 nur dann, wenn ich den Compare-Mode oder > capture-mode aktiviere, dann gilt: > "P1.0 = INT3 = CC0 Compare output / capture input for CRC register" > --> Aber ich hab sowas ja nicht aktiviert. Wenn du dich da mal nicht schwer täuschst! In alten Handbuch des 80C515, der fast oder sogar die selbe Timer2-Einheit hat, fand ich gerade einen interessanten Hinweis. Und zwar alternative Portfunktionen, Port1. Wenn eine Peripheriekomponente eingeschaltet ist, übernimmt diese die alternative Pinfunktion, und überspielt die manuelle Umschaltung des Pins per Software. Wie wäre es, wenn du dir für die LED mal einen ganz anderen Pin am anderen Port suchst, als ausgerechnet den P1.0, den haargenau auch die Alternativfunktion verwendet??? Ganz sicher ist es noch nicht. Die Kapitel sind sehr umfangreich, da muß ich mal noch ein wenig lesen. Ich könnte mal wieder den 80C517 auspacken, und deinen Code drauf spielen. Mal sehen.
Hmm.. Wenn das stimmt was du sagst, dass die Alternativfunktion des Pins 1.0 automatisch eingeschalten wird, sobald ich Timer2 einschalte, dann könnte das das Problem sein. Aber wie soll ich das verstehen? Obwohl ich selbst nicht den Comparemodus einschalte, der ja diese Alternativfunktion von Pin 1.0 verwendet, wie soll dann die Alternativfunktion von P1.0 aktiviert werden?
@Wilhelm: Danke für die Aufklärung, mit dem 8051 hatte ich noch nichts zu tun. Wieder was gelernt :-) @Lens: Wenn du die LED jetzt sowieso schon am P1.0 dranhängen hast, was auch der Ausgang vom Timer2 für die Comparefunktion ist, dann nimm doch auch mal die Comparefunktion. Hatte ich schon weiter oben vorgeschlagen. Damit hast du keine Arbeit mehr, der Timer macht alles automatisch für dich. Einfach probieren, du mußt nicht mal was umverdrahten. Schönen Tag! Gruß Bernd
Dann wirds denk ich noch schlechter, denn P1.0 ist gleichzeitig der compare-output des Timer2. Aber ich versuchs mal.
Bernd S. schrieb: > @Wilhelm: > Danke für die Aufklärung, mit dem 8051 hatte ich noch nichts zu tun. > Wieder was gelernt :-) Es bleibt hier weiterhin spannend! > @Lens: > Wenn du die LED jetzt sowieso schon am P1.0 dranhängen hast, was auch > der Ausgang vom Timer2 für die Comparefunktion ist, dann nimm doch auch > mal die Comparefunktion. Jeder andere Mensch würde das auch so machen, anstatt sich mit Software einen abzubrechen. Inzwischen rücke ich wieder davon ab, daß im reinen Reload-Mode der P1.0 irgendwie mit der Timer2-Hardware zusammen hängt. Aktuell bin ich dabei, etwas im Handbuch zu stöbern. Mir fiel aber was anderes auf: Die Interruptfunktion arbeitet bei weitem nicht schnell genug. Was ist, wenn ich dort den Timer mit FFFF lade? Er läuft schon gleich beim Restartbefehl über, noch bevor die Interruptfunktion überhaupt zu Ende ist. Da kommt doch sicher eine Menge Jitter, Verzögerungen u.ä. hinein. Der Timer läuft mit jedem einzelnen Assemblerbefehl (nicht C-Befehl!!!!!!!) auch ungefähr grob geschätzt einen Takt weiter. Und wenn er über läuft, dann dauert es eine ganze Weile, bis die Interruptschleife überhaupt erst mal verlassen ist, und wieder neu angesprungen wird. Möglicherweise ist der Assemblercode des Interrupts auch noch ellenlang, je nachdem, was der Compiler da z.B. zur Registersicherung noch an Kontext hinein mischt. Diese Dinge schaue ich mir mal noch näher an.
Lens schrieb: > Dann wirds denk ich noch schlechter, denn P1.0 ist gleichzeitig der > compare-output des Timer2. Aber ich versuchs mal. Das ist es doch gerade! Der Compare-Output des Timers SOLL doch die LED schalten, deswegen gehts doch dann automatisch.
Wilhelm Ferkes schrieb:
Stimmt, da hatte ich mir auch schon kurz überlegt. Der Timer wird ja mit
0xff00 neu geladen. In der ISR wird dann TL2 mit (maximal) 0xff
zugewiesen. Wenn das passiert ist, läuft schon im nächsten Takt der
Timer über und ein neuer Interrupt wird ausgelöst, ehe die ISR überhaupt
zu Ende ist. Und selbst wenn, nach dem Ende der ISR muß der Compiler ja
alles wieder herstellen (die gesicherten Register und...).
Das könnte schon problematisch werden. Der Compiler muß ja auch erstmal
die ISR vor dem Eintritt "vorbereiten", d.h. die Register sichern und
einiges mehr, eh die eigentliche ISR aufgerufen wird. Das braucht ja
auch Zeit...
Na mal sehen, ob es mit dem Compare klappt. Du hast recht: Es bleibt
spannend :-)
Bernd S. schrieb: > Lens schrieb: >> Dann wirds denk ich noch schlechter, denn P1.0 ist gleichzeitig der >> compare-output des Timer2. Aber ich versuchs mal. > > Das ist es doch gerade! Der Compare-Output des Timers SOLL doch die > LED schalten, deswegen gehts doch dann automatisch. So macht man es sinnvollerweise normalerweise! Dafür ist die Compare-Funktion da, um die CPU ganz von Rechnerei und Software-Laufzeiten zu entlasten.
Erstmal danke für eure Antworten. Ich werds jetzt auf jeden Fall mit dem Compare ausprobieren doch diese Fragen bleiben: 1. Wieso gehts dann beim Timer0 tadellos, obwohl Timer0 eine viel niedrigere Taktrate hat? 2. Wenn ich die Interrupt Service Routine sein lassen soll, dann hab ich ein "busy wait", wo ich dann per "polling" ständig abfrage, ob denn jetzt Timer und Compare-Wert zusammengetroffen sind. Währenddessen kann mein Programm nichts anderes erledigen. Ist auch nicht schön. Aber wie gesagt ich probiers jetzt mal aus.
Lens schrieb: > Erstmal danke für eure Antworten. Ich werds jetzt auf jeden Fall mit dem > Compare ausprobieren doch diese Fragen bleiben: > 1. Wieso gehts dann beim Timer0 tadellos, obwohl Timer0 eine viel > niedrigere Taktrate hat? > 2. Wenn ich die Interrupt Service Routine sein lassen soll, dann hab ich > ein "busy wait", wo ich dann per "polling" ständig abfrage, ob denn > jetzt Timer und Compare-Wert zusammengetroffen sind. Währenddessen kann > mein Programm nichts anderes erledigen. Ist auch nicht schön. > > Aber wie gesagt ich probiers jetzt mal aus. Nein! Du mußt nicht pollen und auch nicht vergleichen. Das macht der Timer2 völlig selbständig für dich. Der macht alles alleine, und schaltet auch noch deine LED ein und aus. Das einzige, was du machen mußt, wenn du deine Helligkeit verändern willst, ist den Vergleichswert zu ändern. Alles andere macht der Timer2. Schau dir mal im Datenblatt die Compare-Funktion an (oder such mal im Internet nach "timer compare"). Da wirst du viel finden. Ist aber auch nciht schwer. Man muß nur wissen, daß es sowas überhaupt gibt. :-)
Hi Bernd, Um den Wert zu ändern, muss ich eben entweder polling machen oder das in der ISR erledigen. Woher soll ich sonst wissen, wann der High oder Low Puls vorbei ist?
Lens schrieb: > Hi Bernd, > > Um den Wert zu ändern, muss ich eben entweder polling machen oder das in > der ISR erledigen. Woher soll ich sonst wissen, wann der High oder Low > Puls vorbei ist? Du mußt das nicht wissen. Der Timer weiß das! Er vergleicht selbst seinen Zählerwert mit dem Compare-Wert. Und wenn der Zähler größer ist als der Compare-Wert, schaltet er die LED ein. Solange er kleiner ist, bleibt die LED aus. Du mußt dafür keinen Handschlag machen. Der Timer macht das! Und dem Compare-Register einen anderen Wert zuweisen mußt du ja nicht innerhalb einer ISR. Das machst du außerhalb, zum Beispiel im Hauptprogramm.
Lens schrieb: > 1. Wieso gehts dann beim Timer0 tadellos, obwohl Timer0 eine viel > niedrigere Taktrate hat? Was hattest du da für einen Mode? Modus0? Dann wäre er in der Tat um Faktor 32 langsamer. Ein Grund kann der vorhin von mir genannte sein, daß eben die Software dem viel schnelleren Timer2 nicht mehr folgen kann, während das bei Timer0 noch gut funktioniert. > 2. Wenn ich die Interrupt Service Routine sein lassen soll, dann hab ich > ein "busy wait", wo ich dann per "polling" ständig abfrage, ob denn > jetzt Timer und Compare-Wert zusammengetroffen sind. Währenddessen kann > mein Programm nichts anderes erledigen. Ist auch nicht schön. Im Compare-Mode, wo die PWM automatisch läuft, braucht man noch nicht mal den Timer2-Interrupt. So lange die PWM in Frequenz und Tastverhältnis nicht geändert wird, hat man absolut Null CPU-Belastung.
Die duty-cycle (Dauer der High und Low-Pulse) wird ja ständig (je nach Benutzerwunsch) geändert. Diese Änderung des Compareregister-Wertes kann mir Timer2 nicht abnehmen das muss ich selber machen. Entweder per polling oder eben in einer ISR. Wenn ich den Comparregister-Wert nicht änder, dann hab ich auch kein PWM. Der Timer2 kann ja nicht autonom einfach den Wert des Comparregisters ändern :)
An Wilhelm: Deswegen, damit die Software mit dem Timer2 mitkommt wird ja in der ISR extra während der gesamten Ausführung des ISR's der Timer2 ausgeschalten..
Lens schrieb: > Die duty-cycle (Dauer der High und Low-Pulse) wird ja ständig (je nach > Benutzerwunsch) geändert. Diese Änderung des Compareregister-Wertes kann > mir Timer2 nicht abnehmen das muss ich selber machen. Entweder per > polling oder eben in einer ISR. Wenn ich den Comparregister-Wert nicht > änder, dann hab ich auch kein PWM. > > Der Timer2 kann ja nicht autonom einfach den Wert des Comparregisters > ändern :) Nein, soll er ja auch nicht. Er vergleicht nur und schaltet selbst die LED. Das Ändern machst du selbst, und zwar AUSSERHALB der ISR. Du brauchst überhaupt keine ISR für den Compare-Modus. Und was willst überhaupt pollen? Du kannst doch im Hauptprogramm dem Compare-Register einen anderen Wert zuweisen, was hindert dich daran? Währenddessen läuft der Timer einfach weiter, du brauchst ihn nicht stoppen und wieder starten.
Du verstehst mich nicht: Wenn ich nur den den Comparregisterwert ändere, dann hab ich kein PWM. Grund: Der Timer zählt ab dieser Änderung immer gleich viel --> Das ist keine PWM. Damit eine PWM zustande kommt muss der High-Puls und der Low-Puls eine unterschiedliche Spannung haben, sie müssen sich voneinander unterscheiden. Wie breit der High-Puls ist, legt der user fest. Der Low-Puls ist dann nur noch 255-HighPuls breit.
Lens schrieb: > An Wilhelm: Deswegen, damit die Software mit dem Timer2 mitkommt wird ja > in der ISR extra während der gesamten Ausführung des ISR's der Timer2 > ausgeschalten.. Ich denke noch mal drüber nach, meine aber, das ich nicht ganz falsch liege. Beim schnarchlangsamen Timer0 fallen die Softwarelaufzeiten viel weniger ins Gewicht. An einem SAB80C517A nahm ich ja selbst mal die PWM in Betrieb, um eine LED zu dimmen. Die bekommt man auch maximal hell und auch völlig dunkel. Allerdings war das die andere PWM-Einheit, die nicht den Timer2 verwendet, und einen separaten eigenen Timer hat. Ist aber im Prinzip das selbe. Die Software ist überhaupt nicht an der PWM beteiligt, und schreibt nur dann in ein Compare-Register, wenn man das Tastverhältnis der PWM ändern will. Im Grunde machte ich das aber genau so, wie es bei dir in der Hauptschleife ist, und frage über die serielle Schnittstelle zwei Tasten an der PC-Tastatur ab, U (up) und D (down). Dort verändere ich in einem switch case dann die Compare-Register, und dimme damit die LED auf und ab. Ansonsten läuft die PWM im Compare-Mode vollautomatisch. Warum soll das keine richtige PWM sein? Sie ist dann nur fest eingestellt, so lange die Software kein Register ändert.
Bernd S. schrieb: > Das Ändern machst du selbst, und zwar AUSSERHALB der ISR. Das einzige, das berücksichtigt werden muss, ist die Konsistenz von High-Byte und Low-Byte. Gibt es eine Vorschrift für die Reihenfolge, die das sicherstellt? Ich kenne den C515C nicht, aber bei ATmegas gibt es dazu eine HW-Unterstützung: schreiben High vor Low, Lesen Low vor High. Gruß Dietrich
Lens schrieb: > Du verstehst mich nicht: Wenn ich nur den den Comparregisterwert ändere, > dann hab ich kein PWM. Grund: Der Timer zählt ab dieser Änderung immer > gleich viel --> Das ist keine PWM. Damit eine PWM zustande kommt muss > der High-Puls und der Low-Puls eine unterschiedliche Spannung haben, sie > müssen sich voneinander unterscheiden. Wie breit der High-Puls ist, legt > der user fest. Der Low-Puls ist dann nur noch 255-HighPuls breit. Der Timer zählt immer gleich viel, das ist richtig. Und zwar ununterbrochen. Wenn er bei 255 ist, fängt er bei 0 wieder an. Und das OHNE Pause, er wird also nicht angehalten und läuft wieder los. Und während er läuft, vergleicht er seinen Zählerwert mit dem Compare-Register. Und in Abhängigkeit von diesem Vergleich shaltet er selbst die LED ein und aus. Ein Beispiel: Das Compare-Register ist mit 20 geladen. Der Timer läuft bei 0 los, vergleicht und stellt fest, daß 0 kleiner als 20 ist. Also läßt er die LED aus. Jetzt erreicht er den Zählerstand 21 und stellt fest, daß die 21 größer als die 20 im Compare-Register ist. Deshalb schaltet er die LED jetzt ein. Bei 22 das gleiche und so weiter bis 255. Dann kommt er wieder zur 0 und stellt jetzt fest, daß 0 kleiner als 20 ist, er schaltet die LED aus. Und das alles, ohne daß du auch nur einen Finger rührst oder der Timer eine ISR braucht. Er macht das alles hardwaremäßig. In diesem Beispiel ist die LED also 20 Takte an und 235 Takte aus. Das ganze macht er bis in alle Ewigkeit. Jetzt ändere einfach das Compare-Register, indem du eine andere Zahl reinschreibst, z.B. 100. Dann vergleicht er seinen Zählerwert mit 100. Jetzt ist also die LED 100 Takte an und 155 Takte aus. Du mußt NUR(!) das Compare-Register ändern! Alles andere geht von alleine.
Dietrich L. schrieb: > Bernd S. schrieb: >> Das Ändern machst du selbst, und zwar AUSSERHALB der ISR. > > Das einzige, das berücksichtigt werden muss, ist die Konsistenz von > High-Byte und Low-Byte. Gibt es eine Vorschrift für die Reihenfolge, die > das sicherstellt? > Ich kenne den C515C nicht, aber bei ATmegas gibt es dazu eine > HW-Unterstützung: schreiben High vor Low, Lesen Low vor High. > > Gruß Dietrich Hallo Dietrich. Das ist richtig. Steht bestimmt im Datenblatt, das habe ich jetzt nicht hier. Ich bin auch kein Fachmann beim C515, ich habe mich vorgestern das erste Mal mit dem Teil beschäftigt (als dieser Thread eröffnet wurde) :-) Sonst habe ich auch meist mit Atmel zu tun.
Dietrich L. schrieb: > Das einzige, das berücksichtigt werden muss, ist die Konsistenz von > High-Byte und Low-Byte. Gibt es eine Vorschrift für die Reihenfolge, die > das sicherstellt? Der größere Bruder hat es zumindest so in seiner separaten PWM-Einheit. In der Timer2-Einheit fand ich noch nichts. Ich schaue aber noch mal nach. Was ich aber fand: Dumm, daß man die PWM ausgerechnet an P1.0 (Kanal 0) braucht, und nicht an P1.1 bis P1.3 (Kanal 1 bis 3). Denn: Das Compare-Register ist beim Kanal 0 auch das Autoreload-Register für den Timer2. Aber mal sehen, es wird sich sicher was finden. Irgendwo habe ich noch olle Beispiele von früher, z.B. wo die PWM direkt über ein Poti am ADC gesteuert wird, die muß ich mal durchsuchen. Dort werden aber auch nur P1.1 bis P1.3 angesprochen, P1.0 aus besagtem Grund nicht. Lens, du könntest mal noch folgendes versuchen: Und zwar den Reloadwert für Timer2 nicht nur auf den Bereich FF00 bis Überlauf begrenzen, und nur das Low-Byte ändern, sondern auf einen 16-bit-Wert erweitern. Z.B. auf den Bereich F800 bis Überlauf. Das dürfte dann zeitlich etwa dem Timer0 in Modus 0 entsprechen. D.h., die Grundfrequenzen müßten gleich sein.
Wilhelm Ferkes schrieb: > Was ich aber fand: Dumm, daß man die PWM ausgerechnet an P1.0 (Kanal 0) > braucht, und nicht an P1.1 bis P1.3 (Kanal 1 bis 3). Denn: Das > Compare-Register ist beim Kanal 0 auch das Autoreload-Register für den > Timer2. Stimmt. Man kann vielleicht den Timer2 ohne Reload laufen lassen, muß dann aber den Vergleichswert mit 16bit (von 0..65535) nehmen. Dann braucht man das Reload-Register nicht und kann es nur als Compare verwenden. Inwieweit der Timer2 und damit die PWM dann zu langsam ist, muß man sehen. Aber das wäre vielleicht eine Möglichkeit.
An Wilhelm Ferkes: Was kollidiert denn genau mit P1.0, solange ich weder /INT3 noch CC0 aktiviert habe?? Das sollte ja nicht die Ursache sein für das Problem
Jetzt funktionierts zwar, aber die LED flimmert sehr stark :). Wahrscheinlich, weil es langsamer geworden ist, weil der Zählbereich eben größer ist (65536).
Das ist jetzt schlecht. An der Geschwindigkeit vom Timer2 kann man auch nichts ändern. Das Flimmern kann man durch die "Compare"-Methode nicht beseitigen..
Bernd S. schrieb: > Inwieweit der Timer2 und damit die PWM dann zu langsam ist, muß man > sehen. Aber das wäre vielleicht eine Möglichkeit. Bei vollem Durchlauf des Timers käme man ungefähr nur auf eine Überlauffrequenz im Bereich von etwa 20Hz. Das geht nicht, würde bei der LED sichtbares Flackern verursachen. Lens schrieb: > An Wilhelm Ferkes: > Was kollidiert denn genau mit P1.0, solange ich weder /INT3 noch CC0 > aktiviert habe?? Das sollte ja nicht die Ursache sein für das Problem Wie gerade beschrieben, ist der Kanal 0 mit P1.0 ein Sonderfall. Die Register CRC kann man nicht gleichzeitig als Autoreloadwert für den Timer und Compare-Wert verwenden. In Beispielen fand ich gerade, daß die Register CRCH und CRCL für den Autoreload des Timer2 benutzt, und die Register CC1 bis CC3 für den Compare-Wert. Das funktioniert nur an den Pins P1.1 bis P1.3. Für eine variable PWM mit einstellbarer Grundfrequenz hat man also nur 3 PWM-Kanäle. Es geht schon aus den Bezeichnungen der Register hervor. CC0 gibt es nicht, was eigentlich der Kanal 0 sein müßte, nur CC1 bis CC3. Warum man dem Timer2 kein völlig separates Reloadregister spendierte? Keine Ahnung.
Lens schrieb: > Jetzt funktionierts zwar, aber die LED flimmert sehr stark :). > Wahrscheinlich, weil es langsamer geworden ist, weil der Zählbereich > eben größer ist (65536). Ja, das kann gut sein. Versuch mal T2PS auf 0 zu setzen, dann müßte er statt mit f/12 dann mit f/6 laufen. Das ist immerhin doppelt so schnell. Reicht das?
Ne leider nicht :). Flacker immer noch. Im Manual steht auch, dass man für jedes der Register CRC und CC1 bis CC3 "compare enable" machen kann, also als Compareregister hernehmen kann.
@Lens: Geht es denn nicht, die LED an P1.1 bis P1.3 zu legen? Ist die LED an P1.0 fest auf einem Board installiert, eingelötet? Sind die Pins P1.1 bis P1.3 schon anderweitig benutzt?
Lens schrieb: > Im Manual steht auch, dass man > für jedes der Register CRC und CC1 bis CC3 "compare enable" machen kann, > also als Compareregister hernehmen kann. Warum heißen die vier Register nicht CC0 bis CC3? Weil CC0 das CRC ist, Reloadregister für den Timer2. CC0 gibt es nämlich gar nicht.
Lens schrieb: > Ne leider nicht :). Flacker immer noch. Im Manual steht auch, dass man > für jedes der Register CRC und CC1 bis CC3 "compare enable" machen kann, > also als Compareregister hernehmen kann. Ja, es gibt eben nur keines für den Compare-Kanal0, für die 1..3 schon. Die Compare-Register sind den Kanälen zugeordnet. Wenn du z.B. an die Ports P1.1 bis P1.3 jeweils eine LED hängst (so wie an P1.0), dann kannst du mit dem gleichen Timer 3 LED's unabhängig voneinander steuern. Nur, indem du die Compare-Register änderst. Die Compare-Ausgänge des Timers sind eben fest den Ports zugeordnet. Wenn du also die Ports P1.1 bis P1.3 frei hast, häng die LED z.B. an P1.1 und du kannst auch den Timer wieder mit Preload betreiben (also kleineren Zählumfang und höhere Frequenz). Dann CC1 als Compare nehmen und CRC als Preload. Aber eben nur, wenn die Ports frei siond auf deiner Platine.
Ja das ist schon klar:). Aber das Register heißt "CRC" und das bedeutet: "Compare-Reload-Capture", d. h. es kann in zu all diesen 3 Zwecken eingesetzt werden, wie es auch im Manual steht.
Lens schrieb: > Ja das ist schon klar:). Aber das Register heißt "CRC" und das bedeutet: > "Compare-Reload-Capture", d. h. es kann in zu all diesen 3 Zwecken > eingesetzt werden, wie es auch im Manual steht. Für den Kanal 0, also für den Pin P1.0, und nur für Kanal 0 und P1.0, kann es aber nur entweder als Reloadregister oder als Compareregister verwendet werden. Das ist der feine Unterschied.
Lens schrieb: > Ja das ist schon klar:). Aber das Register heißt "CRC" und das bedeutet: > "Compare-Reload-Capture", d. h. es kann in zu all diesen 3 Zwecken > eingesetzt werden, wie es auch im Manual steht. Aber nicht gleichzeitig, sondern nur für eine Aufgabe! Wenn es als Reload eingesetzt wird, kann man es nicht für Compare verwenden und umgekehrt. Und wenn du einen kleineren Zählumfang und PWM brauchst, mußt du für den Timer ein Preload-Register haben zum Vorladen UND ein Compare zum Vergleichen. Bei den Kanälen 1-3 geht das, aber beim Kanal 0 nicht. Und wie ich oben schrieb, die Kanäle sind den Ports zugeordnet, deshalb auch die Frage, ob du P1.1 bis P1.3 frei hast und dort eine LED anschließen kannst.
Oh man.. Ich frag mich echt was sich die Board-Entwickler dabei gedacht haben, diese LED ausgerechnet an der Stelle anzulöten, mit der u. a. das Reloadregister verbunden ist..
Naja. Ich danke allen, die mir bei dieser Aufgabe zur seite gestanden sind. Wir haben den Post-Rekord allein mit diesem Thema schon geknackt. Das ist der Guiness-Mikrokontroller.net-Rekord :). Trotzdem danke an alle!
Lens schrieb: > Oh man.. Ich frag mich echt was sich die Board-Entwickler dabei gedacht > haben, diese LED ausgerechnet an der Stelle anzulöten, mit der u. a. das > Reloadregister verbunden ist.. Mit ein wenig Augenzwinkern könnte man jetzt den Entwicklern dankbar sein, denn dadurch hast du was gelernt ;-) Aber wie gesagt, mit Augenzwinkern. Ärgerlich ist es trotzdem. Was ist das für ein Board, ein Experimentierboard? Leiterzug durchkratzen am P1.0 und die LED an P1.1 ranhängen kommt wohl nicht in Frage? Ist zwar nicht schön, aber wenn's möglich ist...
Lens schrieb: > Naja. Ich danke allen, die mir bei dieser Aufgabe zur seite gestanden > sind. Wir haben den Post-Rekord allein mit diesem Thema schon geknackt. > Das ist der Guiness-Mikrokontroller.net-Rekord :). Nöö, noch nicht unbedingt. Wer sagt denn, daß hier das Ende ist? > Trotzdem danke an alle! Also: Ich werde am späteren Nachmittag mal wieder mein Board mit dem SAB80C517A hervor kramen. Dort ist ja die gleiche Timer2-Einheit drinne, wie im SAB80C515A und C515C. Mal sehen, ob sich da was machen läßt, und man aus dem P1.0 doch noch irgendwie PWM heraus bekommen kann. Den Modus 1 habe ich mir nämlich noch nicht weiter angeschaut, und ich habe noch die olle Literatur mit besseren Erklärungen als im User Manual, nämlich mit Beispielen und Anwendungen.
Wilhelm Ferkes schrieb: > ... Mal sehen, ob sich da was machen läßt, und > man aus dem P1.0 doch noch irgendwie PWM heraus bekommen kann. Das wäre natürlich die beste Lösung, wenn es so klappt, wie es jetzt aufgebaut ist. Mal sehen, ob du was findest. Ich lese auf jeden Fall weiter mit. Wenn es nicht gehen sollte, bleibt immer och die Möglichkeit mit dem Umlöten. Natürlich nur, wenn die anderen Ports (1..3) noch nicht belegt sind. Aber das wissen wir auch noch nicht. Lens hat sich noch nicht geäußert dazu. Mal sehen, ob er nochmal im Thread auftaucht. Das Thema ist noch nicht erledigt, wie du schon sagst ;-)
Bernd S. schrieb: > Wilhelm Ferkes schrieb: > >> ... Mal sehen, ob sich da was machen läßt, und >> man aus dem P1.0 doch noch irgendwie PWM heraus bekommen kann. > > Das wäre natürlich die beste Lösung, wenn es so klappt, wie es jetzt > aufgebaut ist. Mal sehen, ob du was findest. Ich lese auf jeden Fall > weiter mit. Jedenfalls habe ich noch etwas alte Literatur zu diesen µC-Typen, sogar in deutscher Sprache, Englisch liest sich einfach nicht ganz so flüssig, auch wenn man es kann. Ja, und diese Literatur war mir bisher auch immer sehr hilfreich, dort befinden sich nähere Beschreibungen zu den einzelnen Peripherieteilen drin. Eine schöne Erweiterung zu Datenblatt und User Manual. Außerdem, ganz interessant, auch Beispiele und mit Beispielcode, allerdings Assembler. Hochsprachen hatte man zu der Zeit noch nicht so, und für den Hobbyisten sowieso unbezahlbar. Zum 80C517A ist beispielsweise eine Dreiphasen-Sinus-Generation mit der PWM sehr ausführlich beschrieben. Lesen und verstehen muß man aber nach wie vor. Also das sind nicht nur einfache primitive Standard-8051-er, wie es hier oft verunglimpft wird. > Wenn es nicht gehen sollte, bleibt immer och die Möglichkeit mit dem > Umlöten. Natürlich nur, wenn die anderen Ports (1..3) noch nicht belegt > sind. Aber das wissen wir auch noch nicht. Lens hat sich noch nicht > geäußert dazu. Mal sehen, ob er nochmal im Thread auftaucht. Das Thema > ist noch nicht erledigt, wie du schon sagst ;-) Ja, es wäre nett, wenn Lens sich mal zu seinem Board äußern würde. Einfach auch interessehalber. Auch, ob es ein Demo-Board ist, oder eine industrielle Entwicklung. Ich selbst besitze noch diverse Boards mit diesen Controllern, eines aus einem FH-Projekt aus dem Studienfach Mikroprozessortechnik, das muß ich zwingend in Assembler programmieren, wenn ich viel Funktionalität hinein bekommen möchte, denn es hat nur 2k Programmspeicher. Ein anderes von Elektor, aber hauptsächlich beschäftige ich mich noch mit dem Opto-Net-Mini mit dem SAB80C517A aus dem Hause Otmar Feger & Co.. Dort ist wenigstens der Speicherausbau maximal. OK, sowas wie CAN oder I2C haben die ollen µC noch nicht, auch kein integriertes Flash, aber letzt genanntes hat beispielsweise eine serielle Schnittstelle mit LWL, die man mit weiteren gleichen Boards zum Ringnetz konfigurieren kann. Das ist auch mal ganz interessant, wobei der Hardwareaufwand nicht besonders gigantisch ist. Testprogramme flashen tue ich ins RAM, das hat auch eine quasi unendliche Zyklenzahl, darauf muß ich überhaupt gar nicht achten. Sowas wie moderne Debugger mit Breakpoints gibt es auch nicht, das geht bei mir immer noch wie früher, mit dem Terminal oder mit LEDs, und es geht sogar ganz gut. Ich löte und kratze auch nicht gerne auf Demo-Boards herum. Meine haben meistens auch alle Pins über doppelreihige Stiftleisten heraus geführt, und dann hänge ich da mal ein Gebrutzele auf einer Lochrasterplatte an.
Also ich bin ehrlich gesagt begeistert. Obwohl das mein Problem ist und ich es längst in die Schublade geschoben hab, macht ihr einfach weiter :D. Was soll ich sagen. Wenn ich solche Enthusiasten wie euch sehe, dann ist mir das irgendwie peinlich und ich komm mir irgendwie faul vor :)
Lens schrieb: > ist mir das irgendwie peinlich und ich komm mir irgendwie faul vor :) Na dann schreib mal was zu den obigen Fragen. Wilhelm schaut inzwischen mal Handbücher und Code durch, ob es softwaremäßig lösbar ist. Wenn nicht, wie sieht es mit der Platine aus? Ich bin noch auf Arbeit. Wenn ich zu Hause bin, melde ich mich wieder. Und dann will ich aber auch Antworten sehen. Kann doch nicht sein, daß du so schnell aufgibst und alles in die Ecke feuerst. War kein Anschiß, nur ein kleiner :-)) Also bis dann :-)
@Lens: So, ich bin da, und ich sehe --NICHTS-- :-( Was ist los ? Gibst du jetzt doch auf, wo du schon fast am Ziel bist? @Wilhelm: Ja, da stimmt, was du sagst. Man kann keinen Controller runtermachen, im Gegenteil. Jeder hat seine Existenzberechtigung, und man kann ja versuchen, gerade die Stärken der Eigenheiten auszunutzen. Das geht aber eben nur, wenn man den Controller bis ins letzte Bit kennt. Ich habe auch klein angefangen, damit noch mit dem Z80. Das war ja noch nicht mal ein Controller, sondern nur eine reine CPU. Ohne RAM, ohne Programmspeicher, ohne Timer, keine Ein- und Ausgänge, eben nichts. Alles mußte man extern anschließen. Aber einen tollen Befehlssatz hatte er. Den Maschinencode und die dazugehörigen Assemblerbefehle kannte ich auswendig. In Ermanglung eines richtigen Assemblers aben wir damals unsere Programme auf dem Papier in Maschinencode übersetzt und dann hexadezimal in das EPROM-Progammiergerät eingegeben, dann 3mal kontrolliert und schließlich den EPROM gebrannt. Einstecken und testen. Und wenn was nicht richtig war, EPROM mit UV löschen und das ganze Spiel von vorne... Da hat man wirklich jedes Bit mit Vornamen gekannt :-)) Man kann ja heute viele Sachen schon mit dem nackten Controller machen, fast ohne Außenbeschaltung. Damals undenkbar. Taktgenerator selbst bauen war angesagt und mindestens ca. 20 ICs verdrahten... Aber das kann wirklich nur jemand nachvollziehen, der ähnliches gemacht hat. Heute mit kompletten Controllern, C-Compiler usw. ist das komfortabel ohne Ende... So, ich bin gespannt, ob sich Lens noch meldet. Und auch, ob du was passendes für ihn gefunden hast. Bis später Bernd
Bernd S. schrieb: > In Ermanglung eines richtigen Assemblers aben wir damals > unsere Programme auf dem Papier in Maschinencode übersetzt und dann > hexadezimal in das EPROM-Progammiergerät eingegeben, dann 3mal > kontrolliert und schließlich den EPROM gebrannt. So fing ich Anfang der 1990-er mit dem 8051 an. Ich hatte von µC auch überhaupt keine Ahnung, und verstand in diesem Stadium die Literatur auch nur schwer, weil Prozessoren mal was ganz anderes war, als TTL-Gräber und Analogelektronik. Dann kaufte ich beim Schuricht zwei 8031-er, auch Original Intel, die alten NMOS-Typen. Und dann mußte ich mich ja mal damit beschäftigen. Einen PC besaß ich noch nicht, und baute mir selbst Eingabegeräte zur Programmierung eines EPROM. Ich kaufte zuvor auf der Hobby-Tronic in Dortmund bei einem Händler gebrauchte EPROM 27C128. Meine Aufbauten: TTL-Gräber. Dann ging es los, byteweise Eingabe von Hand, 8 Tasten für die 8 bits. Also, es wurde jedes Bit einzeln eingegeben, zur Sichtkontrolle je eine LED an jeder Taste, und dann die neunte Taste Brennen gedrückt. Alles vom Papier abgelesen, worauf das Assemblerprogramm von Hand in Maschinencode übersetzt war. Man mußte schon äußerst sorgfältig die Sprungadressen berechnen. Für mehr als ein A4-Blatt war die Sache aber wirklich nicht geeignet, zu fehleranfällig. Aber mal ein paar kleine Progrämmchen wie ein Lauflicht mit LEDs an einem Port. Eine Firma, wo ich mal angestellt war, hatte auf dem Dachboden noch einen ganz alten Apparat von 1980 stehen. Eine Intel-Programmierstation. Dafür mußte man auch einen guten fünfstelligen Betrag auf den Tisch legen, und das Ding war zwar ein Rechner, aber kein PC, konnte nur 8048-er programmieren, sonst nichts. Man arbeitete dort in den 1980-er Jahren mit dem 8048, dem Vorgänger des 8051. > So, ich bin gespannt, ob sich Lens noch meldet. Und auch, ob du was > passendes für ihn gefunden hast. Ich baute gestern mein Board nicht mehr auf, aber heute. Ein altes Programm läuft schon mal testweise. Jetzt muß ich dann nur noch ein Projekt aufsetzen. Das wird aber auch später, ich muß jetzt am Nachmittag noch mal weg. Weiter oben hatte ich dem Lens aber auch schon mal empfohlen, für seine Software-Variante mal die Variablen von einem Byte auf zwei Bytes zu vergrößern, und den Reloadwert für Timer2 auf F800 zu setzen. Damit sein Timer2 um den Faktor 32 langsamer wird, wie in der Version mit Timer0, die ja angeblich einwandfrei funktionierte.
Hallo Wilhelm, du hast ja auch eine ganze Menge mitgemacht und dabei viel gelernt. Dann weißt du ja auch, von was ich rede :-) Der 8048 ist schon legendär. Und schon damit konnte man viel machen. Der war doch sogar bei Korg in verschiedenen Synthesizern eingesetzt, oder? Aber mit der ganzen 8051er Reihe habe ich gar nichts gemacht. Und auch die Nachfolger gingen "an mir vorbei". Ich habe gleich den Schritt gemacht vom Z80 auf den PIC. Der hat mir aber überhaupt nicht zugesagt in der Anfangszeit (lag hauptsächlich am Assembler-Programmieren). Die Befehle sind ja katastrophal. Jetzt, mit C mag das anders aussehen. Aber damals habe ich mich dann für Atmel entschieden, den konnte man auch gut in Assembler programmieren. Heute mache ich auch (fast) nur noch C. Ich sollte auch mal den Schritt zu 32bit machen (irgendwann). Da habe ich aber bis jetzt noch keine Hardware... So, die Spannung steigt, ob sich Lens wieder meldet. Du hast inzwischen vielleicht auch was rausgefunden in Bezug auf sein Problem. Schauen wir mal...
Bernd S. schrieb: > Der 8048 ist schon legendär. Und schon damit konnte man viel machen. Der > war doch sogar bei Korg in verschiedenen Synthesizern eingesetzt, oder? Ja, Bernd, du kennst die Zeiten anscheinend selbst bestens. Das Ding war spartanisch wie bspw. ein 8085, hatte keinen UART, aber immerhin einen 8-bit-Timer und einen externen Interrupt, vor allen Dingen aber 12 freie eigene I/O-Pins. Sowas hatten Z80 und 8085 ja gar nicht. Außer, ich mißbrauchte den SOD-Pin (Serial Output Data am 8085) mal als I/O-Pin für eine Blink-LED. Die Software konnte ihn immerhin direkt setzen oder löschen. Das ist aber nur ein einziger Pin am ganzen Prozessor. Der 8048 war der erste 8-bit Single-Chip-µC der Welt. Ich baute vor ein paar Jahren auch mal einen auf Lochraster auf, einfach aus Nostalgiegründen. Mit dem TASM-Assembler konnte ich dann ein paar Testprogrämmchen erstellen. Den µC hatte ich aus einer industriellen Phasenanschnittsteuerung fürs 230V-Netz vom Schrott. Ein I/O-Pin ist von 230V zerschossen, deswegen landete das Gerät auf dem Schrott, aber der µC läuft. Die Verwendung bei Korg sagt mir jetzt nichts, aber man erlebte ja in den 1980-er Jahren die ersten programmgesteuerten intelligenteren Geräte. 1979 wurde bei der Post die Familientelefonanlage für Privatkunden eingeführt, eine kleine Hausanlage mit 4 Telefonen und einer Amtsleitung. Dort war er drin. Oder ich sprach von einer Firma, die 1980 damit industrielle Steuerungen baute. Im Hobby konnte man 1980 kaum was machen, eben weil man z.B. die teueren Intel-Programmierstationen brauchte. Die konnten damals übrigens nur Assembler. Das geht auch nur in einem Industriebetrieb, der Stückzahlen produziert. Ein alter Projektleiter sagte mir, er hätte die 8048-er nur in Assembler programmiert. Einen PC hatte noch niemand, manche aber die PC-Vorläufer wie Apple-2, oder ZX81, C64, was es da so alles gab. Bevor ichs vergesse: In einer relativ neueren PC-Tastatur um das Jahr 2005 ist der 8048 auch drin. Dann habe ich hier schon 10 Jahre lang eine Stange 80C382 liegen, die schon vorher 10-20 Jahre in einem entrümpelten Lager lagen. Ich wußte lange nichts damit anzufangen. Erst letztes Jahr fand ich jemanden hier im Forum, der mit einen Tipp gab, was das überhaupt ist, und ein Datenblatt. Es ist ein Telekommunikationscontroller, Low Power und mit voll statischem Design, und 8048-Core. Aber interessant. Vielleicht baue ich damit auch noch mal eine Retro-Schaltung, oder überlasse sie der NASA. Mit der NASA, das ist kein Witz. Die suchten bei Firmen und Bastlern schon mal nach gebrauchten 8085, weil niemand von den Herstellern mehr die alten Designs hatte, aus Herstellungsprozessen vor 30-35 Jahren. Er ist anscheinend robust im Space und gegen EMV, Riesen-Halbleiterstrukturen, auch wenn die Leistungsfähigkeit aus heutiger Sicht eher mickrig ist. Passend dazu hätte ich auch noch EPROM 2716 von 1979, das bekommt man in drei Durchgängen mit dem EPROM-Löscher noch nicht mal gelöscht. ;-) Der Standard-8051 ist da schon wieder sehr komfortabel, hat immerhin ein paar Interrupts, einen UART, auch immerhin zwei 16-bit-Timer. Einen größeren PIC programmierte ich für meine Diplomarbeit in Assembler. Es kamen von manchen Seiten mal spitze Bemerkungen, ich mache eine Strafarbeit für Häftlinge, aber nein, ich hatte Spaß daran. Mit meinen detaillierten Hobbykenntnissen über den 8051 verhalf ich mal gut 10 Studenten, das Studium zu bestehen. Ich übte mit denen Assembler und Architektur und externe Hardware für die Nachklausuren, wobei ich selbst die Erstklausur mit 1,0 bestand. Die wären sonst unter gegangen. Mit µC taten sich 90% der Studenten furchtbar schwer, auch wenn es nur um den popeligen 8051 ging. Die meisten gehen auch später in Bereiche, wo man gar nichts mit µC zu tun hat. E-Technik ist ja schließlich nicht Informatik. > Ich sollte auch mal den Schritt zu 32bit machen (irgendwann). > Da habe ich aber bis jetzt noch keine Hardware... Das kann man mal machen, wenn man es wirklich benötigt. Ich besitze als Hobbyist nur die 8051-Derivate, die ich hier im Verlauf des Threads mal nannte. Das reicht für meine Zwecke auch völlig. Wohl hatte ich beruflich mal mit ARM7-ern zu tun, das war aber ganz nett. Für mehrkanälige PWM und auch Rechnereien ist der 80C517A immer noch ein schönes Teil. > So, die Spannung steigt, ob sich Lens wieder meldet. > Du hast inzwischen vielleicht auch was rausgefunden in Bezug auf sein > Problem. Schauen wir mal... Zumindest habe ich mein Board mal hier neben dem PC aufgebaut und in Betrieb genommen, jetzt müßte ich nur noch mal ein neues Softwareprojekt am PC anlegen. Aktuell habe ich mehr in meiner Literatur gelesen, was man noch machen könnte. In den Beispielen wird dort auch aus schon besagten Gründen der Kanal 0 mit Pin P1.0 nicht verwendet, sondern nur die weiteren 3 Kanäle. Aktuell habe ich ja eine Idee, wie man den P1.0 für PWM doch noch verwenden könnte. Und zwar verzichtet man auf den Autoreload des Timers 2, und lädt den Timer im Interrupt mit einem festen Wert neu, womit man dann auch wieder eine höhere PWM-Frequenz erreichen kann. Dann hat man die Register CRC wieder frei für den Compare-Wert. Die Software müßte für eine PWM-Änderung nur das Register CRC beschreiben, und sonst nichts. Sehr wahrscheinlich wird man aber hier auch Aussteuerungsgrenzen haben, daß man die PWM nicht völlig an oder aus bekommt, sondern Impulse im Bereich der Länge eines Taktzyklusses verbleiben. So einen Spezialfall könnte man aber immer noch per Software behandeln, und die PWM abschalten, den Pin auf 0 setzen, wenn die LED aus sein soll. Wenn das Tastverhältnis im Promillebereich liegt, sollte man an der LED aber auch nichts mehr sehen können. Man wird da unter Umständen nicht drum herum kommen, den Timer präzise per Assembler bzw. Inline-Assembler in einer 16-bit-Addition nachzuladen, um Jitter durch z.B. Interruptlatenzzeiten zu vermeiden. Denn Autoreload fällt ja weg. Aber das ist auch kein Thema. Dem Timer sollte man evtl. auch die höchste Interruptpriorität geben. Die PWM-Auflösung könnte man noch mit 13 bit hin bekommen, damit die Frequenz hoch genug liegt, und die LED nicht sichtbar flimmert. Ich selbst muß noch mal sehen, wie ich vernünftig eine LED am P1.0 befestigt bekomme. Denn ich hab nur 4 Stück an P4.0 bis P4.3, dort spielt die bessere PWM-Einheit im 80C517A, mit völlig separatem Timer. Dort bekomme ich die LEDs auf jeden Fall auch maximal ausgesteuert, von völlig dunkel bis ganz eingeschaltet. Am 517 habe ich also 7 PWM-Kanäle mit 16-bit-Auflösung, das reicht für so einiges. Ob ich heute was fertig getestet bekomme, steht noch in den Sternen. Ich hatte die Projekte und die Software über ein Jahr lang nicht mehr in den Fingern. Das Command-File zum Compilieren muß ich auch überarbeiten. Bei SDCC hat man klugerweise die Namen von Assembler und Compiler umbenannt, und auch an den Optionen Parametern was geändert. Das gibt ja erst mal Fehlermeldungen, File not found, u.ä.. Aber es ging noch immer gut. Ich mußte zu den 8051-ern und den Tools noch nie jemand nach relevanten Dingen fragen. Außer ehemals Tipps zu Toolquellen, SDCC, Geany, Oberflächen und Editoren, die bekam ich hier im Forum, und das ist natürlich ausgezeichnet gut.
So, ich hab mal was probiert, das wäre doch schon was für den Lens. Und zwar habe ich erst mal Dosbox installiert, und die 20 Jahre alten Assembler und Simulator in Betrieb genommen. Also nur simuliert, anstatt auf dem realen µC getestet. Aber es sieht gut damit aus:
1 | $PROCESSOR(80C517) |
2 | $NOPAGING |
3 | $NOXREF |
4 | $NOSYMBOLS |
5 | $ERRORPRINT(ERROR.TXT) |
6 | $DATE(MAR 2013) |
7 | $TITLE(Programmtest) |
8 | $WF(C:) |
9 | $INCLUDE(80C517A.INC) |
10 | ;----------------------------------------------------------- |
11 | |
12 | ; Codesegment |
13 | |
14 | CSEG AT RESET ; Programmstartadresse |
15 | |
16 | Start: |
17 | AJMP INIT |
18 | |
19 | CSEG AT 002BH ; Interrupt Timer2 |
20 | |
21 | AJMP INT_T2 |
22 | |
23 | CSEG AT 0100H ; Programmstartadresse |
24 | |
25 | INIT: |
26 | ; Timer 2: |
27 | MOV CRCH, #0FFH |
28 | MOV CRCL, #0F0H |
29 | MOV TH2, #0FFH |
30 | MOV TL2, #0E0H |
31 | ; Compare-Capture Funktionsauswahl: |
32 | MOV CCEN, #002H ; Compare CRC eingeschaltet |
33 | ; Compare-Timer-Steuerregister CTCON: |
34 | ANL CTCON, #07FH ; T2PS1 Vorteiler fosc/12 |
35 | ; Timer 2 Steuerregister T2CON: |
36 | CLR T2PS ; Vorteiler fosc/12 |
37 | CLR T2R1 ; T2 Nachladen abgeschaltet |
38 | CLR T2R0 ; T2 Nachladen abgeschaltet |
39 | CLR T2CM ; Compare-Mode 0 |
40 | CLR T2I1 ; T2 vom Oszillator gespeist |
41 | SETB T2I0 ; T2 vom Oszillator gespeist, Start |
42 | ; Interruptfreigabe: |
43 | SETB ET2 ; Interruptfreigabe Timer 2 |
44 | SETB EAL ; Interruptfreigabe global |
45 | |
46 | AJMP MAIN |
47 | |
48 | ;----------------------------------------------------------- |
49 | |
50 | MAIN: |
51 | NOP |
52 | AJMP MAIN |
53 | |
54 | ;----------------------------------------------------------- |
55 | |
56 | INT_T2: |
57 | MOV TL2, #0E0H |
58 | MOV TH2, #0FFH |
59 | CLR TF2 |
60 | RETI |
61 | |
62 | ;----------------------------------------------------------- |
63 | END |
Man sieht beim Compare-Ereignis und beim Timerüberlauf auch schön den Pin P1.0 toggeln. Der Timer2 läuft jetzt ohne Autoreload, aber mit manueller Nachladung im Timer-Interrupt. Die Nachladung für den Timer2 im Interrupt muß noch präzisiert werden, aber das war ja jetzt erst mal nur ein Test. Sorry, leider in Assembler. Der olle Simulator versteht auch nur Assembler vom originalen Intel-ASM51. Das kann man immer noch sehr leicht nach C umbauen.
Und weiter gehts noch mal:
1 | $PROCESSOR(80C517) |
2 | $NOPAGING |
3 | $NOXREF |
4 | $NOSYMBOLS |
5 | $ERRORPRINT(ERROR.TXT) |
6 | $DATE(MAR 2013) |
7 | $TITLE(Programmtest) |
8 | $WF(C:) |
9 | $INCLUDE(80C517A.INC) |
10 | ;----------------------------------------------------------- |
11 | |
12 | ; Codesegment |
13 | |
14 | CSEG AT RESET ; Programmstartadresse |
15 | |
16 | Start: |
17 | AJMP INIT |
18 | |
19 | ;----------------------------------------------------------- |
20 | |
21 | ; Interruptvektoren: |
22 | |
23 | CSEG AT 002BH ; Interrupt Timer 2 |
24 | |
25 | AJMP INT_T2 |
26 | |
27 | ;----------------------------------------------------------- |
28 | |
29 | ; Initialisierung: |
30 | |
31 | CSEG AT 0100H ; Programmstartadresse |
32 | |
33 | INIT: |
34 | ; Timer 2: |
35 | MOV CRCH, #0FFH ; Compare-Register |
36 | MOV CRCL, #0F0H |
37 | MOV TH2, #0FFH ; Timerwert |
38 | MOV TL2, #0E0H |
39 | ; Compare-Capture Funktionsauswahl: |
40 | MOV CCEN, #002H ; Compare CRC eingeschaltet |
41 | ; Compare-Timer-Steuerregister CTCON: |
42 | ANL CTCON, #07FH ; T2PS1 Vorteiler fosc/12 |
43 | ; Timer 2 Steuerregister T2CON: |
44 | CLR T2PS ; Vorteiler fosc/12 |
45 | CLR T2R1 ; T2 Nachladen abgeschaltet |
46 | CLR T2R0 ; T2 Nachladen abgeschaltet |
47 | CLR T2CM ; Compare-Mode 0 |
48 | CLR T2I1 ; T2 vom Oszillator gespeist |
49 | SETB T2I0 ; T2 vom Oszillator gespeist, Start |
50 | ; Interruptfreigabe: |
51 | SETB ET2 ; Interruptfreigabe Timer 2 |
52 | SETB EAL ; Interruptfreigabe global |
53 | |
54 | AJMP MAIN |
55 | |
56 | ;----------------------------------------------------------- |
57 | |
58 | ; Hauptprogrammschleife: |
59 | |
60 | MAIN: |
61 | NOP |
62 | AJMP MAIN |
63 | |
64 | ;----------------------------------------------------------- |
65 | |
66 | ; Interrupt Timer 2: |
67 | |
68 | T2_RELOAD EQU 0FFE0H + 7 ; 7 Taktzyklen vergehen bei Nachladung |
69 | |
70 | INT_T2: |
71 | PUSH ACC ; Akku sichern |
72 | CLR EAL ; Interrupts global sperren |
73 | CLR T2I0 ; Timer Stop |
74 | MOV A, #(LOW T2_RELOAD) ; 1 Taktzyklus |
75 | ADD A, TL2 ; 1 Taktzyklus |
76 | MOV TL2, A ; 1 Taktzyklus |
77 | MOV A, #(HIGH T2_RELOAD) ; 1 Taktzyklus |
78 | ADDC A, TH2 ; 1 Taktzyklus |
79 | MOV TH2, A ; 1 Taktzyklus |
80 | SETB T2I0 ; 1 Taktzyklus |
81 | SETB EAL |
82 | POP ACC |
83 | CLR TF2 |
84 | RETI |
85 | |
86 | ;----------------------------------------------------------- |
87 | END |
Im Datenblatt fand ich, daß der C515C voll aufwärtskompatibel zum alten SAB50C515A ist. Da sollte also nichts schief laufen. Im Code habe ich jetzt die präzise Timernachladung in den Interrupt eingefügt. Voraussetzung für die richtige Funktion ist, daß man den Zähltakt für den Timer genau so wählt, wie die CPU-Taktzyklen. Diesen Assemblercode muß man auch bei C in Assembler belassen, vielleicht als Inline-Code.
Hallo Wilhelm, das mit der NASA hätte ich wirklich für einen Witz gehalten, wenn du nicht das Gegenteil gesagt hättest. Kaum zu glauben... Dein Programm sieht jetzt so aus, wie du es schon im Thread vorgeschlagen hattest. Auf den automatischen Preload verzichten und statt dessen in der ISR "von Hand" neu laden. Das gleiche mache ich z.B. auch beim Atmel in der ISR, um eine bestimmt Interrupt-Frequenz bzw. Zeitspanne einzustellen. Das ganze im Zusammenhang mit dem Vorteiler kriegt man da fast alles hin. Nachdem du dir jetzt so viel Arbeit gemacht hast und alles erstmal wieder aufbauen mußtest, könnte sich Lens wirklich mal melden, um die Lösung auszuprobieren. Auch wenn das ganze (bzw. ein Teil) noch in C umgesetzt werden muß. Dabei kriegt er doch auch noch Hilfe. Jetzt, wo es schon fast fertig ist. Also, Lens. Du liest das doch bestimmt. Also melde dich einfach hier, damit wir deine LED noch zum Blinken kriegen. Das ist dann der Grundstein für die nächsten Projekte. Jedes Erfolgserlebnis ist dafür da, daß man auf ihm aufbaut. Mit einem Mißerfolg aufhören ist genau so, als wenn man vom Pferd fällt. Wenn man nicht gleich wieder aufsteigt, hat man ein Leben lang Angst vor den schönen Tieren, und das grundlos...
Bernd S. schrieb: > Dein Programm sieht jetzt so aus, wie du es schon im Thread > vorgeschlagen hattest. Auf den automatischen Preload verzichten und > statt dessen in der ISR "von Hand" neu laden. Das gleiche mache ich z.B. > auch beim Atmel in der ISR, um eine bestimmt Interrupt-Frequenz bzw. > Zeitspanne einzustellen. Das ganze im Zusammenhang mit dem Vorteiler > kriegt man da fast alles hin. Zugegeben, ich war etwas faul, und wählte den einfachen Weg, wo ich am schnellsten zu einer Lösung komme. Mit 8051-Assembler verstehe ich mich auch prima, das steckt schon im Blut. Ein C-Projekt aufsetzen, hätte mich etwas mehr Zeit gekostet. Aber das werde ich bestimmt auch noch tun. Ich wollte ja unbedingt an den alten Simulator, neuere Debugger etc. habe ich ja gar nicht. In den C-Projekten habe ich auch alle Libraries drin, die man mal so braucht, z.B. den System-Timer, oder die serielle Schnittstelle mit FIFOs. Im Beispiel habe ich die Timerwerte etwas kurz gewählt. Das ist aber nur rein wegen dem Simulator. In der Praxis werden die noch mal verlängert. > Nachdem du dir jetzt so viel Arbeit gemacht hast und alles erstmal > wieder aufbauen mußtest, könnte sich Lens wirklich mal melden, um die > Lösung auszuprobieren. Auch wenn das ganze (bzw. ein Teil) noch in C > umgesetzt werden muß. Dabei kriegt er doch auch noch Hilfe. Jetzt, wo es > schon fast fertig ist. Als unsinnige Mühe sehe ich es jedenfalls nicht, denn ich arbeite ja selbst noch ein Weilchen mit diesen µC-Typen. Die haben noch nicht ausgedient. Dann hab ich was neues für meine Codesammlung, falls ich sowas auch mal brauche. Die Umsetzung nach C mache ich gerne auch selbst, wenn sich niemand findet. Das ist nicht so schwierig, eigentlich nur eine Umwandlung 1:1 der Assemblerzeilen nach C-Zeilen. Der Assemblerteil zur Nachladung des Timers im Interrupt muß aber so bleiben, wie er ist. Für solche Sachen gibts ja genau Inline-Assembler im C-Code. Man weiß nie, was der Compiler sonst für einen Code produziert, besonders zwischen Compiler-Updates und Optimierungsstufen. Das will man ja nicht bei jeder Änderung immer wieder nach schauen. Das Programm macht jetzt die PWM vollautomatisch, und der Timer-Interrupt lädt nur manuell den Timer mit der gewünschten PWM-Grundfrequenz, die man haben möchte. Möglicherweise muß man dem Timer 2 auch die höchste Interruptpriorität geben, das habe ich im Beispiel gar nicht weiter berücksichtigt. Wir sind ja nicht am Ende angekommen, falls der Lens überhaupt noch mit machen will.
Wilhelm Ferkes schrieb: > Englisch liest sich einfach nicht ganz so flüssig, > auch wenn man es kann. Naja... Geschmacksache... speziell alte Siemens Unterlagen sind da sehr gewöhnungsbedürftig. Da gibt es Namensfelder (Abkürzung ist "oplab") und den Kellerspeicherzeiger und anderes mehr. Oder das Handbuch zum ersten IBM-PC: "Die Hauptleiterplatte ist in Einzelkreis pro Kanal Technik ausgeführt." (Da ist aber auch die englische Version nur unwesentlich besser "single land per channel". Das japanische Original konnte leider niemand lesen)
Georg G. schrieb: > Wilhelm Ferkes schrieb: >> Englisch liest sich einfach nicht ganz so flüssig, >> auch wenn man es kann. > > Naja... Geschmacksache... speziell alte Siemens Unterlagen sind da sehr > gewöhnungsbedürftig. Da gibt es Namensfelder (Abkürzung ist "oplab") und > den Kellerspeicherzeiger und anderes mehr. Nun ja, ich kenne nicht alle Siemens-Schriften. Die Handbücher, die ich habe, beziehen sich auf deren eigene 8051-Derivate 80C515 und 80C517. Dann habe ich zusätzlich noch ein Buch von denen über den Makroassembler ASM51 von Ashling Microsystems, worin der Assembler genau beschrieben ist, auch ein Disassembler, Simulator, und auch Kapitel über Planung und Projektmanagement mit µC, das ist wirklich gut. Die entsprechenden Programme und Beispiele waren auf Buchdiskette. Internet hatten wir ja Anfang der 1990-er Jahre noch nicht, und dann gab es eben alles in Büchern. Als ich Internet bekam, zog ich mir bei Infineon natürlich auch alle englischsprachigen Unterlagen. Die Bücher sind vom Einband auch bestens, sie zerfallen durch häufige Benutzung nicht, das ist auch schon was wert. Nachfolgeliteratur habe ich von Otmar Feger & Co., der führte die Handbuchserien mal fort, mit Boards und Beispielen, und die Bestimmung war "für Ausbildung und Beruf". Auch Elektor hatte in den 1990-ern Boards und Bücher zu den 80C515. Die sind etwas anders als die aus der Siemens-Ecke, aber beides ergänzt sich gut. Heute lebt man in der Regel vom User Manual als PDF aus dem Internet. Manchmal ist das einfach grauenhaft. Aber dem Inschinör ist ja nichts zu schwör. Bezüglich Begriffen steht eine Bemerkung in den Handbüchern: Man wollte bewußt eingedenglischte Begriffe nicht mehr ins Deutsche übersetzen, und man findet dort in Texten den Begriff "Stack". Das ist ihnen doch gut gelungen. In einem ältern Buch von 1987 von einem Autor, der bei Valvo mit 8051 zu tun hatte, ja, da findet man tatsächlich noch den Kellerspeicher oder Stapel.
Karl Heinz Buchegger schrieb: > Wie lange braucht ein 8-Bit Timer, der bis 255 zählt, bei einer Taktrate > von fOsc/32 zählt um einmal von 0 bis 255 zu zählen. > Und wie lange braucht ein 16-Bit Timer, der bis 65535 zählt, bei einer > Taktrate von fOsc/12 zählt, um einmal von 0 bis 65535 zu zählen? @Karl Heinz So mein lieber Karl Heinz! Ab jetzt schreib ich dir mindestens einmal die Woche diesen Satz: Schreib ein Buch über Mikrocontroller und wie man sie programmiert!!!!!! Hab dir das schon ein- bis zweimal vorgeschlagen. Du kannst alles so einfach und toll erklären, gar nicht so kryptisch wie das in den meisten Büchern steht. Ich glaub ich muss mal mit deiner Frau reden ;-), dass die dich anschiebt. Lieben Gruß Frank
So, ich hole den Thread mal wieder hoch, auch wenn sich der TO nicht wieder meldete. Ostermontag ist ein gut geeigneter Basteltag. Inzwischen habe ich den Code von hier Beitrag "Re: PWM - Breite von 0" mal einwandfrei nach C umgeschrieben, und auf den 80C517A geschmissen. Das .rst-File (SDCC Gesamt-Listing) sieht auch exakt wie der gezeigte und simulierte Assemblercode aus. Meine Quarzfrequenz beträgt 7,372800 MHz. Das hatte den Grund, Baudraten bis 115200 zu bekommen, und exakte Timerraster mit 5ms für den Systemtimer ergibt das auch noch. Der Takt wird für den Timer2 durch 12 geteilt, also läuft dieser mit 614,4 kHz. Im Interrupt lade ich den Timer2 per Software mit 32768 nach, und die LED blinkt noch eben gerade sichtbar mit ca. 20 Hz. Für eine höhere PWM-Frequenz setzt man jetzt einfach den Timerwert höher, von 0x8000 in Richtung 0XFFFF, aber wegen der Interruptlaufzeit etwas von 0xFFFF weg, z.B. 0xFFC0. Jetzt kann man schön den Timernachladewert fest belassen, um eine feste PWM-Frequenz zu erhalten. Das Tastverhältnis der PWM variiert man bequem mit den CRC-Registern CRCH und CRCL. So hat man denn am Pin P1.0 doch noch PWM. Hier noch mal der C-Code mit etwas Inline-Assembler bei der Timernachladung, den kann jemand, der ihn brauchen kann, auf einen C515C, 80C515 oder 80C517 werfen. Compiler ist bei mir der SDCC 3.2.0.
1 | /*******************************************************************************
|
2 | Main.c
|
3 | Testprogramm Timer2 und PWM an Pin P1.0 mit Controller SAB80C517A
|
4 | *******************************************************************************/
|
5 | |
6 | /*******************************************************************************
|
7 | Includes und Defines
|
8 | *******************************************************************************/
|
9 | |
10 | #include "sab80c517.h" // Header-File lokal |
11 | |
12 | #define T2_RELOAD 0x8000+7 // Timer 2 Reloadwert
|
13 | // Die 7 sind die Stopzyklen im Interrupt, wo der Timer zur Nachladung
|
14 | // angehalten ist.
|
15 | |
16 | #define CRC_RELOAD 0xF000 // PWM Einschaltpunkt
|
17 | |
18 | /*******************************************************************************
|
19 | Variablen
|
20 | *******************************************************************************/
|
21 | |
22 | unsigned long __xdata i, j; |
23 | |
24 | /*******************************************************************************
|
25 | Funktionen
|
26 | *******************************************************************************/
|
27 | |
28 | /*******************************************************************************
|
29 | Interrupt Timer 2
|
30 | *******************************************************************************/
|
31 | void TF2_ISR (void) __interrupt (5) __using (0) __naked |
32 | {
|
33 | __asm
|
34 | PUSH ACC ; Akku sichern |
35 | CLR _EAL ; Interrupts global sperren |
36 | CLR _T2I0 ; Timer Stop |
37 | MOV A, #((T2_RELOAD >> 0) & 0xFF) ; 1 Taktzyklus |
38 | ADD A, _TL2 ; 1 Taktzyklus |
39 | MOV _TL2, A ; 1 Taktzyklus |
40 | MOV A, #((T2_RELOAD >> 8) & 0xFF) ; 1 Taktzyklus |
41 | ADDC A, _TH2 ; 1 Taktzyklus |
42 | MOV _TH2, A ; 1 Taktzyklus |
43 | SETB _T2I0 ; 1 Taktzyklus |
44 | SETB _EAL |
45 | POP ACC |
46 | CLR _TF2 |
47 | RETI
|
48 | __endasm; |
49 | }
|
50 | /*******************************************************************************
|
51 | Hauptprogramm mit while(1)-Endlosschleife
|
52 | *******************************************************************************/
|
53 | int main ( |
54 | void
|
55 | )
|
56 | {
|
57 | i = 1; |
58 | j = 2; |
59 | |
60 | CRCH = ((CRC_RELOAD >> 8) & 0xFF); // Compare-Register |
61 | CRCL = ((CRC_RELOAD >> 0) & 0xFF); |
62 | TH2 = ((T2_RELOAD >> 8) & 0xFF); // Timerwert |
63 | TL2 = ((T2_RELOAD >> 0) & 0xFF); |
64 | // Compare-Capture Funktionsauswahl:
|
65 | CCEN = 0x02; // Compare CRC eingeschaltet |
66 | // Compare-Timer-Steuerregister CTCON:
|
67 | // CTCON &= 0x7F; // T2PS1 Vorteiler fosc/12
|
68 | // Timer 2 Steuerregister T2CON:
|
69 | T2PS = 0; // Vorteiler fosc/12 |
70 | T2R1 = 0; // T2 Nachladen abgeschaltet |
71 | T2R0 = 0; // T2 Nachladen abgeschaltet |
72 | T2CM = 0; // Compare-Mode 0 |
73 | T2I1 = 0; // T2 vom Oszillator gespeist |
74 | T2I0 = 1; // T2 vom Oszillator gespeist, Start |
75 | // Interruptfreigabe:
|
76 | ET2 = 1; // Interruptfreigabe Timer 2 |
77 | EAL = 1; // Interruptfreigabe global |
78 | |
79 | // PCON |= SD; // Slow-Down-Mode
|
80 | |
81 | while(1) // Endlosschleife |
82 | {
|
83 | i++; // Dummy |
84 | j++; // Dummy |
85 | } // while(1) |
86 | } // main() |
87 | /******************************************************************************/
|
88 | // End of File
|
Bei hoher PWM-Frequenz kann man mal über die Interruptprioritäten nach denken, ob man dem Timer2 die höchste Priorität gibt, damit er die Nachladung rechtzeitig schafft. Bei Pipelined-8051-Core könnte die Sache mit der präzisen Timernachladung im Interrupt nicht mehr unbedingt funktionieren, weil dort der Core nicht mehr ganz fest synchron mit dem Timer läuft. Modernste 8051-Derivate könnten so einen haben. Bei anderen PWM-Pins außer dem P1.0 ist, wie schon gesagt, PWM erheblich einfacher, und ohne Softwareinvolvierung wie die Timernachladung. Falls ein Moderator das hier zufällig sieht: Der Thread sollte mal in den Filter "8051", sonst findet den niemand mehr so leicht, der mit gewissen 8051-Derivaten zu tun hat. Frohe Ostern allerseits!
Hier noch mal ein kleines Testprogrämmchen. Die LED direkt mit Vorwiderstand vom P1.0 gegen VCC fährt jetzt wie bei einem negativen Sägezahn langsam runter, und beginnt wieder von vorne. Ich installierte mal den Compare-Interrupt EX3. Hoch zählen darf man die Compare-Register im Interrupt nicht. Das führt zu einem Interrupt-Chaos. Zumindest auf die einfache Weise des Testprogrammes. Ich zählte sie runter.
1 | /*******************************************************************************
|
2 | Main.c
|
3 | Testprogramm Timer2 und PWM an Pin P1.0 mit Controller SAB80C517A
|
4 | *******************************************************************************/
|
5 | |
6 | /*******************************************************************************
|
7 | Includes und Defines
|
8 | *******************************************************************************/
|
9 | |
10 | #include "sab80c517.h" // Header-File lokal |
11 | |
12 | #define T2_RELOAD 0xC000+7 // Timer 2 Reloadwert + 7 Stopzyklen
|
13 | |
14 | #define CRC_RELOAD 0xC100 // PWM Einschaltpunkt
|
15 | |
16 | /*******************************************************************************
|
17 | Variablen
|
18 | *******************************************************************************/
|
19 | |
20 | unsigned long __xdata i, j; |
21 | |
22 | volatile unsigned int __xdata crcval; |
23 | |
24 | /*******************************************************************************
|
25 | Funktionen
|
26 | *******************************************************************************/
|
27 | |
28 | /*******************************************************************************
|
29 | Interrupt Timer 2
|
30 | *******************************************************************************/
|
31 | void TF2_ISR (void) __interrupt (5) __using (0) __naked |
32 | {
|
33 | __asm
|
34 | PUSH ACC ; Akku sichern |
35 | CLR _EAL ; Interrupts global sperren |
36 | CLR _T2I0 ; Timer Stop |
37 | MOV A, #((T2_RELOAD >> 0) & 0xFF) ; 1 Taktzyklus |
38 | ADD A, _TL2 ; 1 Taktzyklus |
39 | MOV _TL2, A ; 1 Taktzyklus |
40 | MOV A, #((T2_RELOAD >> 8) & 0xFF) ; 1 Taktzyklus |
41 | ADDC A, _TH2 ; 1 Taktzyklus |
42 | MOV _TH2, A ; 1 Taktzyklus |
43 | SETB _T2I0 ; 1 Taktzyklus |
44 | SETB _EAL |
45 | POP ACC |
46 | CLR _TF2 |
47 | RETI
|
48 | __endasm; |
49 | }
|
50 | /*******************************************************************************
|
51 | Interrupt Extern 3 an P1.0 bzw. Compare-Interrupt CRC
|
52 | *******************************************************************************/
|
53 | void CRC_ISR (void) __interrupt (10) __using (0) |
54 | {
|
55 | if (crcval < CRC_RELOAD) |
56 | {
|
57 | crcval = 0xFF00; |
58 | }
|
59 | else
|
60 | {
|
61 | crcval -= 0x80; |
62 | }
|
63 | CRCH = (crcval >> 8) & 0xFF; |
64 | CRCL = (crcval >> 0) & 0xFF; |
65 | }
|
66 | /*******************************************************************************
|
67 | Hauptprogramm mit while(1)-Endlosschleife
|
68 | *******************************************************************************/
|
69 | int main ( |
70 | void
|
71 | )
|
72 | {
|
73 | i = 1; |
74 | j = 2; |
75 | crcval = CRC_RELOAD; |
76 | |
77 | CRCH = ((CRC_RELOAD >> 8) & 0xFF); // Compare-Register |
78 | CRCL = ((CRC_RELOAD >> 0) & 0xFF); |
79 | TH2 = ((T2_RELOAD >> 8) & 0xFF); // Timerwert |
80 | TL2 = ((T2_RELOAD >> 0) & 0xFF); |
81 | // Compare-Capture Funktionsauswahl:
|
82 | CCEN = 0x02; // Compare CRC eingeschaltet |
83 | // Compare-Timer-Steuerregister CTCON:
|
84 | // CTCON &= 0x7F; // T2PS1 Vorteiler fosc/12
|
85 | // Timer 2 Steuerregister T2CON:
|
86 | T2PS = 0; // Vorteiler fosc/12 |
87 | T2R1 = 0; // T2 Nachladen abgeschaltet |
88 | T2R0 = 0; // T2 Nachladen abgeschaltet |
89 | T2CM = 0; // Compare-Mode 0 |
90 | T2I1 = 0; // T2 vom Oszillator gespeist |
91 | T2I0 = 1; // T2 vom Oszillator gespeist, Start |
92 | I3FR = 1; // Int. Steigende Compare-Flanke an P1.0 |
93 | // Interruptfreigabe:
|
94 | EX3 = 1; // Interruptfreigabe Compare an P1.0 |
95 | ET2 = 1; // Interruptfreigabe Timer 2 |
96 | EAL = 1; // Interruptfreigabe global |
97 | |
98 | // PCON |= SD; // Slow-Down-Mode
|
99 | |
100 | while(1) // Endlosschleife |
101 | {
|
102 | i++; // Dummy |
103 | j++; // Dummy |
104 | } // while(1) |
105 | } // main() |
106 | /******************************************************************************/
|
107 | // End of File
|
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.