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
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
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...
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!
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.
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.
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
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:
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.
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.
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.