Hallo zusammen,
kann ich an einem STM32F100VBT6B über den PWM-Input-Mode ein
DCF77-Signal einlesen?
Der Prozessor läuft mit 24MHz.
Das DCF-Signal kommt an Pin D13 an, also TIM4-(Channel-2).
Die beiden Counter für den PWM-Input-Mode sind 16-Bit-Register.
Das heißt sie laufen bis maximal 65535. Das heißt nach ca 2,7ms
(65535/24M) ist der Counter übergelaufen. Ich brauche für das DCF-Signal
allerdings 1000ms zum zählen.
Kann ich einen Prescaler hierfür einsetzen?
Der Prescaler aus der Struktur "TIM_ICInitStructure"
funktioniert leider nicht wie benötigt. Da wird auf Wunsch lediglich
jede, jede 2, jede 4 oder jede 8 Flanke ausgewertet.
Meine Initialisierung sieht folgendermaßen aus und funktioniert auch
grundsätzlich, nur sind die Werte in den Countern halt leider quatsch.
Es stehen nahezu wahllos Werte drin. Wobei ich das Verhalten auch nicht
logisch finde, da eigentlich doch jedesmal 65535 in den beiden Countern
stehen müsste?! Oder laufen die über und fangen dann von vorne an zu
zählen?
Hallo,
probiere mal den anhängenden Code.
DCF- Signal wird über PWM-Input eingelesen (per DMA in die Variablen
geschrieben), gleichzeitig wird ein externer Int. ausgelöst, der die
vorhergehenden Informationen auswertet.
Musst halt die Timer entsprechend Deiner Taktfrequenz anpassen. Bei mir
läuft die CPU mit 96 MHz.
Gruß
Tom
Hallo nochmal,
ich war etwas voreilig - bzw. habe mich verlesen. Mein Code ist für
einen STR912. Aber vielleicht gehts bei Dir ja auch - musst halt etwas
umschreiben.
Ich nehme an, diese Zeilen sind interessant für mich. Ich kann dem Timer
also zusätzlich zu dem PWM_Input einen Prescaler geben, um so die
aufnehmbare Zeitspanne zu verlängern. Ich muss mal schauen wie es bei
dem STM32F10X gemacht wird.
Warum in DMA schreiben? Bei der Frequenz ist eine schnelle Bearbeitung
nicht wirklich notwendig, oder? Oder gibt es noch andere Gründe zur
Nutzung von DMA.
Gruß,
Florian
Hi Florian,
ich benutze den DMA aus einem einfachen Grund, ich muss mich nicht in
irgendeiner Interruptroutine rumplagen. So werden meine Variablen Puls
und Periode automatisch aktualisiert. Das hat nur bei der Abarbeitung zu
etwas Verwirrung geführt.
Der Systemclock ist der Timereingang bei mir. So kann man die Vorteiler
in einem relativ großen Bereich nutzen.
Gruß und viel Spaß
Tom
TIM4->PSC=0x5DC0;//24000 -> 1Tick pro ms (1000Ticks pro Sekunde)
Kann ich nun mein DCF-Signal sauber per PWM-Input auslesen!
Es funktioniert nun also, danke! :)
OK, aber ganz verstehe ich nicht was dir das per DMA für einen Vorteil
bringt. Der Interrupt-Handler läßt sich auch gut nutzen und ich benötige
keinen zusätzlichen External-Interrupt.
1
voidTIM4_IRQHandler(void){
2
3
/* Clear TIM3 Capture compare interrupt pending bit */
4
TIM_ClearITPendingBit(TIM4,TIM_IT_CC2);
5
IC2Value=TIM_GetCapture2(TIM4);
6
IC2Value_1=TIM_GetCapture1(TIM4);
7
8
if(IC2Value!=0)
9
{
10
/* Period of Low Signal in ms */
11
DutyCycle=IC2Value_1;//Should be about 80-120 or 180-220
Florian K. schrieb:> kann ich an einem STM32F100VBT6B über den PWM-Input-Mode ein> DCF77-Signal einlesen?
Man muß nicht immer alles so kompliziert wie möglich machen.
Man kann ganz einfach in einem Timerinterrupt mitzählen, wie oft der Pin
high oder low war.
Einen Timerinterrupt (z.B. 1ms oder 10ms) hat man ja eh in jeder
Anwendung, da einfach den Code mit rein hängen.
Dann hat man auch kein Problem, die interne Zeit mit dem DCF zu
synchronisieren. Da es der gleiche Interrupt ist, kann es zu keiner
Race-Condition kommen.
Hat man verschiedene Interrupts, kann mal der eine und mal der andere
zuerst kommen und plötzlich geht Deine Uhr eine Sekunde falsch.
Hallo Florian,
freut mich, dass Deine Funktion nun funktioniert.
Tja, warum DMA ?
Nun, ich werte im EXTINT2 die Zeitinformation gleich aus. Sprich, mit
jeder negativen Flanke des DCF- Signals (habe keinen Inverter davor)
wird die vorherige Information ausgewertet - und falls die Minute herum
ist - auch die gesamte Zeitinformation verarbeitet. Ich brauche so also
keine zusätzliche Funktion in den anderen Programmteilen.
Man muss es nicht so machen, hat bei mir aber zu einer Steigerung der
Performance des Gesamtsystems geführt. Es geht ja nicht ausschliesslich
nur um eine Uhr. :)
Peter Dannegger schrieb:> Florian K. schrieb:>> kann ich an einem STM32F100VBT6B über den PWM-Input-Mode ein>> DCF77-Signal einlesen?>> Man muß nicht immer alles so kompliziert wie möglich machen.>> Man kann ganz einfach in einem Timerinterrupt mitzählen, wie oft der Pin> high oder low war.> Einen Timerinterrupt (z.B. 1ms oder 10ms) hat man ja eh in jeder> Anwendung, da einfach den Code mit rein hängen.>> Dann hat man auch kein Problem, die interne Zeit mit dem DCF zu> synchronisieren. Da es der gleiche Interrupt ist, kann es zu keiner> Race-Condition kommen.> Hat man verschiedene Interrupts, kann mal der eine und mal der andere> zuerst kommen und plötzlich geht Deine Uhr eine Sekunde falsch.
Hallo Peter,
warum kompliziert ?
PWM-Input geht ohne Interrupt und wenn Du einen extra Interrupt auf die
Pulsflanke auslöst, kannst Du dort gleich die Zeitinformation
verarbeiten. Die interne RTC wird erst synchronisiert, wenn das
DCF-Signal in Ordnung war und keine Fehler auftraten, und die RTC läuft
absolut synchron.
Tom Strippe schrieb:> Hallo Peter,> warum kompliziert ?> PWM-Input geht ohne Interrupt und wenn Du einen extra Interrupt auf die> Pulsflanke auslöst, kannst Du dort gleich die Zeitinformation> verarbeiten. Die interne RTC wird erst synchronisiert, wenn das> DCF-Signal in Ordnung war und keine Fehler auftraten, und die RTC läuft> absolut synchron.
Und wenn mal aus dem Empfänger nur ein Rauschen kommt, kannst du den vom
Interrupt getriggerten Sekundenzeiger als Ventilator benutzen...
Ich würde es auch immer wie Peter machen. Das ist bei solchen
Eingangssignalen die einzige Variante die sich garantiert durch nichts
aus der Ruhe bringen lässt und auch noch ziemlich tolerant ist mit dem
Dreck auf dem Einganssignal.
Tom Strippe schrieb:> Bei mir> läuft die CPU mit 96 MHz.
Bei einer so langsamen CPU kann man natürlich die riesige Datenrate von
1Baud nur per DMA wuppen;-)
DMA mag ein lustiges Experiment sein, einen praktischen Nutzen hat es
hier nicht.
Tom Strippe schrieb:> ich benutze den DMA aus einem einfachen Grund, ich muss mich nicht in> irgendeiner Interruptroutine rumplagen.
Das "Rumplagen" (Dekodieren) mußt Du trotzdem, Du hast es nur an eine
andere Stelle verschoben. Statt im bestehenden schon anderweitig
genutzten Timerinterrupt, in den zusätzlichen externen Interrupt.
Tom Strippe schrieb:> Das hat nur bei der Abarbeitung zu> etwas Verwirrung geführt.
Das kann ich mir gut vorstellen.
old man schrieb:> Und wenn mal aus dem Empfänger nur ein Rauschen kommt, kannst du den vom> Interrupt getriggerten Sekundenzeiger als Ventilator benutzen...
Das sollte man nicht auf die leichte Schulter nehmen.
Ich hab schon Gerätsoftware abstürzen sehen, nur weil jemand ein Kabel
zu stecken vergessen hat und dann der Eingang floatete und die CPU mit
Interrupts flutete.
Das ist bei den ARM besonders tragisch, da die damit das Main komplett
totlegen können.
Bei den AVRs läuft das Main noch, wenn auch langsam (1 Zyklus zwischen
den Interrupts). Der AVR könnte z.B. eine Fehlermeldung anzeigen.
Beim ARM müßte man einen höher priorisierten Timer aufsetzen. Der
externe Interrupt zählt eine Variable hoch und der Timer prüft, ob sie
einen kritischen Wert überschreitet und disabled ihn dann.
Danke für die weiteren Beiträge, ich habe das DCF-Signal schon
erfolgreich per Software eingelesen, alle 4ms das Signal abtasten und
per external interrupt jede Sekunde die Auswertung...
Ich wollte mich nur mit dem PWM_Input auch noch beschäftigen, da ich
dachte es wäre die elegantere Methode, auch wenn es bei dieser Anwendung
völlig unerheblich ist, wie ich das DCF-Signal erhalte.
old man schrieb:> Ich würde es auch immer wie Peter machen. Das ist bei solchen> Eingangssignalen die einzige Variante die sich garantiert durch nichts> aus der Ruhe bringen lässt und auch noch ziemlich tolerant ist mit dem> Dreck auf dem Einganssignal.
Was genau meinst du damit? Wo ist das Problem wenn das Signal mal
verrauscht ist? Mich interessieren die Argumente dagegen wirklich. :)
Ich bin davon ausgegangen, dass das einlesen per PWM_Input grundsätzlich
effizienter ist als die Abtastung... und daher eher angewendet würde.
Ich arbeite noch nicht so lange mir µC und bin daher noch sehr
lernbegierig :P
edit:
Peter Dannegger schrieb:> die CPU mit> Interrupts flutete.
Bei der PWM_Input Variante wird also eher unkontrolliert das
TIM4-Interrupt ausgelöst und könnte theoretisch wenn das Signal am
DCF-Eingang eine verrauschte Frequenz von 24MHz hätte mein Programm lahm
legen. Ist das die Entscheidung dagegen?
Florian K. schrieb:> Was genau meinst du damit? Wo ist das Problem wenn das Signal mal> verrauscht ist? Mich interessieren die Argumente dagegen wirklich. :)
das bezog sich darauf:
Tom Strippe schrieb:> PWM-Input geht ohne Interrupt und wenn Du einen extra Interrupt auf die> Pulsflanke auslöst,
Wenn man mit dem Eingangssignal externe Interrupts an der Fanke auslöst,
dann ist nicht mehr vorhersehbar was passiert wenn das Eingangssignal
nur ein ordentliches Rauschen ist.
Florian K. schrieb:> Ich bin davon ausgegangen, dass das einlesen per PWM_Input grundsätzlich> effizienter ist als die Abtastung
Ich würde mal sagen, alles was man mit 1ms oder länger abtasten kann,
stellt für den ARM keine merkbare Last dar.
D.h. für solche langsamen Signale Signale würde ich als effizienter den
kleineren Code ansehen, gegenüber <0,001% CPU-Lastunterschied.
Florian K. schrieb:> Bei der PWM_Input Variante wird also eher unkontrolliert das> TIM4-Interrupt ausgelöst und könnte theoretisch wenn das Signal am> DCF-Eingang eine verrauschte Frequenz von 24MHz hätte mein Programm lahm> legen. Ist das die Entscheidung dagegen?
Jetzt hast du die Antwort in der Zwischenzeit schon selbst gegeben.
Genau das ist der Punkt. Es ist nicht mehr absehbar wie viele Interrupts
am Ende wirklich kommen. Das kann natürlich soweit gehen, dass der
Controller für was anderes als diesen Interrupt keine Zeit mehr hat.
Natürlich ist das hypothetisch, aber wir reden hier nicht von
Hallsensoren oder so was, sondern von Funkempfängern. Und bei denen
sollte man im allgemeinen mit allem Rechnen.
Peter Dannegger schrieb:> Ich würde mal sagen, alles was man mit 1ms oder länger abtasten kann,> stellt für den ARM keine merkbare Last dar.> D.h. für solche langsamen Signale Signale würde ich als effizienter den> kleineren Code ansehen, gegenüber <0,001% CPU-Lastunterschied.
Das kann ich nur unterstützen. Und in dem selben Kontext können dann
auch noch alle Tasten, Drehencoder oder sonstige mechanischen Sachen
abgetastet werden. Das ergibt immer reproduzierbare Durchlaufzeiten und
hat den Vorteil nur die Gpio-Eingänge selbst zu benötigen und keine
andere Hardware als den Timer für den zykl. Interrupt. Wenn man das in
der Art und Weise macht ist auch die Portierung von solchen
Codebestandteilen zwischen den verschiedenen Controllern und
Architekturen ein Kinderspiel. Auch im Layout braucht man sich weniger
Gedanken machen, da es so ziemlich egal ist an welchen Pin das hängt.
Peter Dannegger schrieb:> Tom Strippe schrieb:>> Bei mir>> läuft die CPU mit 96 MHz.>> Bei einer so langsamen CPU kann man natürlich die riesige Datenrate von> 1Baud nur per DMA wuppen;-)> DMA mag ein lustiges Experiment sein, einen praktischen Nutzen hat es> hier nicht.>>> Tom Strippe schrieb:>> ich benutze den DMA aus einem einfachen Grund, ich muss mich nicht in>> irgendeiner Interruptroutine rumplagen.>> Das "Rumplagen" (Dekodieren) mußt Du trotzdem, Du hast es nur an eine> andere Stelle verschoben. Statt im bestehenden schon anderweitig> genutzten Timerinterrupt, in den zusätzlichen externen Interrupt.>>> Tom Strippe schrieb:>> Das hat nur bei der Abarbeitung zu>> etwas Verwirrung geführt.>> Das kann ich mir gut vorstellen.
Sehr geehrter Herr Dannegger,
wie es scheint hast Du das Programm nicht verstanden - ich helfe gerne
nach.
Bei mir gibt es keinen, ich wiederhole, KEINEN, Timerinterrupt. Der
externe Interrupt wird lediglich dazu verwendet den letzten empfangenen
Sekundenimpuls auf Plausibilität zu testen und, sofern es der
Minutentakt war, die Zeit dann auszuwerten.
Bitte vor dem Meckern und kritisieren und meinemethodeistehdiebeste
Geschwätz nachlesen.