Moin Leute,
ich probier hier schon seit ein paar Stunden vergeblich herum, um einen
InputCapture mit dem STM32 zu erhalten. Vielleicht könnt ihr mal über
meinen Init-Code schauen, ob ich irgendwas wichtiges übersehen habe.
Im Prinzip liegt an PE13 ein Signal an, welches ab und an für 1µs auf
High geht und darauf möchte ich gern einen Timerinterrupt haben.
1
RCC->APB2ENR|=(1<<6);// enable peripheral clock for GPIOE
2
3
/* INT input PE13 -> mit timer1 verwenden */
4
GPIOE->CRH&=~0x00F00000;// reset port-pin
5
GPIOE->CRH|=0x00800000;// set input mode with pullup or pulldown
Ähem, vergiß das, hab nur was von TIM1 und TIM 3 gesehen.
Aber laut Manual soll man beim Input Capture die GPIO configuration
input floating nehmen und nicht input pull-up/down. Du hast durch den
ODR-Resetwert 0 den Pulldown aktiviert ...
Also must du im CRH 0x00400000 schreiben.
Lutz schrieb:> Du solltest dich für -einen_ Timer entscheiden...
wie meinst du das genau? Ich möchte gern vom Timer1 den dritten Channel
verwenden, weil dieser bin dem PE13 Pin verheiratet ist bzw. werden
kann.
Diesen Punkt blicke ich in der Tat auch nicht so wirklich. Echt
unglücklich geschrieben. Das CHM der Driver-Lib hilft mir da auch nicht
weiter.
Ganz sicher gehst du aber, wenn du ohne die Driver-Lib im AFIO_MAPR (S.
179) die bits 6 und 7 per Hand auf 1 setzt. Weil das gemäß S. 174 Table
46 eindeutig dazu führt, daß TIM1_CH3 von PE10 auf PE13 gemapt wird.
Und noch dran denken, den pull-down abzuschalten (Table 20 auf S. 156).
Jens schrieb:> Danke für die Tipps; werd ich morgn gleich ausprobieren und entsprechend> reporten.
jetzt läuft es. Man muss allerdings noch die RCC Clock für das AFIO
enablen.
gehe ich eigentlich in der Annahme richtig, dass im TIM3->CCR3 die
Anzahl an aufgetretenen Events (rising-edges in meinem Fall) gezählt
wird bis die Timerperiode 0xFFFFF wieder von vorne anfängt?
hatte einen kleinen Schreibfehler drinnen -> jetzt erhalte ich ein paar
Werte im CCR3 Register. Wenn ich allerdings die Frequenz des ankommenden
Signals berechnen möchte, dann hab ich irgendwo noch einen Fehler
drinnen.
Na ja, in der Ecke kenne ich mich nun gar nichts aus. Meinst du frames
per second?
Aber copy&paste hast du mit dem Quellcode schon mal nicht gemacht, denn
> unsigend short prescaler = (36000000 - 1000) - 1;
enthält neben eine Schreibfehler auch einen Wert, der bei 16 bit diverse
Male overflowed (schönes Wort, finde ich).
Bei "else if" kannst du dir den "if"-Test sparen, da du ja in der
vorherigen schon auf das Gegenteil der beiden Möglichkeiten testest.
Also reicht einfach nur "else {...}".
Auch ist es mit den anderen Datentypen nicht so ersichtlich. Wenn man
uint16_t usw. benutzt, weiß man immer, was man hat. Und kann auch auf
einer anderen Architektur nicht so schnell auf die Schnauze fallen.
Zumal es auch verwirrt, wenn du bei einem 16 bit-Wert eine Zuweisung mit
einem 8 bit-Wert machst.
Ich versteh beide Beispiele nicht: Nirgends taucht die Funktion
'TIM1_CC_IRQHandler' auf. Muss diese nicht irgendwo eingetragen werden
damit sie mit jedem Interrupt aufgerufen wird? Erklärt das den folgenden
Kommentar?
/* TIMER interrupt routine: wird nie aufgerufen */
Ich bin neu in der Mikrocontroller-Ecke und hab mir ein STM32L-Discovery
Board zum 'Spielen' zugelegt. Hiermit möchte ich ein Programm erstellen,
welches ausschließlich in einer Timer-Interrupt-Routine ein wenig
arbeitet und in der main() Hauptschleife sich nur schlafen-legt um
Energie zu sparen. Hat jemand ein einfaches Beispiel?
>Muss diese nicht irgendwo eingetragen werden>damit sie mit jedem Interrupt aufgerufen wird? Erklärt das den folgenden>Kommentar?>/* TIMER interrupt routine: wird nie aufgerufen */
Ja. Sie muss "irgendwo" eintragen werden. In der Tabelle der
Interrupt-Vektoren.
Nein. Der Kommentar bezieht sich nicht auf die Frage ob eine Funktion in
die Interrupt-Vektor-Tabelle eingetragen ist oder nicht.
Deine Frage beruht auf einer Fehldeutung bzw. nicht genügend engen
Interpretation des Wortes "aufrufen".
Hier (und allgemein beim Programmieren) kann man das auf folgendes
beziehen:
Die Nennung eines Funktionsnamens mit einer (evtl. leeren
Parameterliste) in der Definition einer anderen Funktion (ich beziehe
das jetzt mal alles auf C) bewirkt deren "ausführung".
D.h. Du siehst irgendwann im Code eine Zeile à la
1
FunktionRechneWas();
Das ist ein Aufruf der Funktion "FunktionRechneWas". Der Programmierer
will an einer bestimmten Stelle im Ablauf, nach einer vorherigen
Anweisung und vor einer nachfolgenden Anweisung, das genau das passiert.
Daher "ruft er sie auf", d.h. genauer bewirkt deren Ausführung genau an
dieser Stelle.
In diesem Sinne wird eine Interrupt-Funktion wie niemals (OK. Abgesehen
von ziemlich trickreichen Fällen die uns hier nicht interessieren) in
einer Funktionsdefinition erscheinen.
Sie wird also niemals "aufgerufen".
Das heisst nicht, das sie niemals ausgeführt wird. Sie wird nur nicht
"aufgerufen".
Sie aber dann ausgeführt, wenn etwa ein Timer überläuft oder an einem
Port-Pin der Pegel verändert wird.
Um es noch einmal in Kürze zu sagen:
"Aufrufen" heisst vom Programmautor aus gesehen: Im Programmtext an
einer bestimmten Stelle einer Funktionsdefinition nennen. Von der CPU
aus gesehen: Im Programmtext die gegenwärte Adresse auf den Stack
schieben, zu der genannten Adresse der Funktion springen, die Befehle
dort ausführen, die letze Adresse wieder vom Stack holen und wieder mit
dem Befehl nach dem Aufruf der Funktion weitermachen. (Es gehört noch
ein wenig mehr dazu, aber das lasse ich hier mal weg).
Genau dieses Eintragen in die Tabelle der Interrupt-Vektoren fehlt mir.
Ich finde das Nirgends. Wo und Wie passiert das? Gibt's genau hierzu ein
Beispiel?
Noname schrieb:>>Muss diese nicht irgendwo eingetragen werden>>damit sie mit jedem Interrupt aufgerufen wird? ..> Ja. Sie muss "irgendwo" eintragen werden. In der Tabelle der> Interrupt-Vektoren.
Hmmm. Ok. Hab ein Beispiel abgwandelt und es funktioniert :-)
Ich hätte allerdings erwartet, dass irgendwo explizit der
Funktionszeiger in die Tabelle eingetragen wird. Bin erstaunt, dass der
Compiler/Linker keine Fehlermeldung schmeisst weil die ganzen
Funktionen, die in der Tabelle (in startup_stm32l1xx_md.s) eingetragen
sind, nicht existieren. Das wird offensichtlich mit
.weak SysTick_Handler
.thumb_set SysTick_Handler,Default_Handler
umgangen.
Hat jemand parat wie man das dynamisch - durch Eintragen des
Funktionszeigers - macht? Dafür hab ich kein Beispiel gefunden. In
irgendeiner ARM Doku stand recht kompliziertes Zeug drin, dass man
verschiedene Fälle (Code im Flash oder sonstwo) unterscheiden müsse ...
Das wär für einen Zustandsautomaten ganz hilfreich um ohne grosse
"switch case" bzw. "if / else if" -Wüsten im Handler auszukommen.
> Schau Dir die Beispielcodes aus der STM Standard Peripheral Library an.