Forum: Mikrocontroller und Digitale Elektronik PWM - Breite von 0


von Lens (Gast)


Lesenswert?

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?

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Lens schrieb:
> wie im Bild in grün zu sehen

ich seh nix

von Bernd (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Angehängte Dateien:

Lesenswert?

Entschuldige mich. Jetzt hab ich sie angehangen.

von Lens (Gast)


Lesenswert?

Ich arbeite mit dem Infineon C515C-L

von Ben _. (burning_silicon)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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

von Spess53 (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

Timer0 ist ein 8-Bit-Timer
Timer2 ist ein 16-Bit-Timer

von Karl H. (kbuchegg)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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 :-)

von Karl H. (kbuchegg)


Lesenswert?

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.

von Lens (Gast)


Angehängte Dateien:

Lesenswert?

Hab den Code für Timer2 angehangen.

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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

von Spess53 (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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

von Bernd (Gast)


Lesenswert?

Gibt es in deiner Entwicklungsumgebung keinen Simulator, mit dem man 
Schritt für Schritt verfolgen kannst, was passiert?

von Spess53 (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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 :-)

von Lens (Gast)


Lesenswert?

--> "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..

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Angehängte Dateien:

Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

Es ist auf jeden Fall der richtige Reload-Modus eingestellt: "on T2 
overflow". Daran kanns also nicht liegen.

von Bernd S. (bernds1)


Lesenswert?

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!

von Lens (Gast)


Lesenswert?

--> "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!

von Bernd S. (bernds1)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

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?

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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!

von Bernd S. (bernds1)


Lesenswert?

So, jetzt bin ich wirklich weg.
Viel Erfolg und denk dran, ich bin neugierig!

Gruß Bernd

von Lens (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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.

von Bernds1 (Gast)


Lesenswert?

Kannst du dir nicht mit einem Oszi angucken, was an dem Pin passiert, wo 
die LED dranhängt?

von Lens (Gast)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

Hab leider kein Oszi

von Lens (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernds1 (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

Ich glaub Bernd ist grad genauso ratlos wie ich.. :)
Naja trotzdem danke an alle für die Hilfe!

von Bernd S. (bernds1)


Angehängte Dateien:

Lesenswert?

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

von Lens (Gast)


Lesenswert?

Hi Bernd,

Ok ich probiers jetzt gleich aus :)

von Lens (Gast)


Lesenswert?

An Bernd: Es heißt bei "IRCON &= ~(1<<TF2);": bad operand type

von Lens (Gast)


Lesenswert?

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 ? :)

von Bernd S. (bernds1)


Lesenswert?

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!

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

@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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Angehängte Dateien:

Lesenswert?

Es handelt sich um den C51-Compiler von Keil. Die Headerdatei hab ich 
angehangen.

von Lens (Gast)


Lesenswert?

TF2 = 0 wird vom Compiler umgewandelt in:

;   // Timer2 Interrupt-Flag zurücksetzen
;   TF2 = 0;
; SOURCE LINE # 17
  CLR    TF2
;

von Bernd S. (bernds1)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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?

von Bernd S. (bernds1)


Lesenswert?

@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

von Lens (Gast)


Lesenswert?

Dann wirds denk ich noch schlechter, denn P1.0 ist gleichzeitig der 
compare-output des Timer2. Aber ich versuchs mal.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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 :-)

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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?

von Bernd S. (bernds1)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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 :)

von Lens (Gast)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

Sry verbessere: High und Low-Puls müssen unterschiedliche Pulsbreiten 
haben.

von Dietrich L. (dietrichl)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

Jetzt funktionierts zwar, aber die LED flimmert sehr stark :). 
Wahrscheinlich, weil es langsamer geworden ist, weil der Zählbereich 
eben größer ist (65536).

von Lens (Gast)


Lesenswert?

Das ist jetzt schlecht. An der Geschwindigkeit vom Timer2 kann man auch 
nichts ändern. Das Flimmern kann man durch die "Compare"-Methode nicht 
beseitigen..

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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?

von Lens (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

@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?

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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.

von Lens (Gast)


Angehängte Dateien:

Lesenswert?

Hab das Bild angehangen, wo es steht.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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

von Lens (Gast)


Lesenswert?

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!

von Bernd S. (bernds1)


Lesenswert?

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

von Bernd S. (bernds1)


Lesenswert?

Was sagst du dazu? Geht das?

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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 ;-)

von Wilhelm F. (Gast)


Lesenswert?

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.

von Lens (Gast)


Lesenswert?

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 :)

von Bernd S. (bernds1)


Lesenswert?

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 :-)

von Bernd S. (bernds1)


Lesenswert?

@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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Wilhelm F. (Gast)


Lesenswert?

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.

von Bernd S. (bernds1)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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.

von Georg G. (df2au)


Lesenswert?

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)

von Wilhelm F. (Gast)


Lesenswert?

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.

von F. F. (foldi)


Lesenswert?

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

von Wilhelm F. (Gast)


Lesenswert?

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!

von Wilhelm F. (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.