Hallo
ich will grade mit einem STM32 Timer 2 Impulse zählen.
Und zwar habe ich ein Impulspaket, wo während ca. 2 Sekunden ein Takt
von 4.5MHz anliegt, danach kommt eine Pause von einigen Sekunden, danach
kommen wieder für 2 Sekunden die 4.5MHz und so weiter. Ich will die
Anzahl der Zyklen während des 2 Sekunden-Fensters zählen.
Glucklicherweise habe ich ein externes Signal, welches ankündigt, wann
das Zeitfenster beginnt, und wann es endet.
Daher dachte ich ich kann folgendes machen:
- den Timer 2 (hat 32 Bit) konfigurieren als Counter, welcher vom
externen Taktsignal getaktet wird.
- das Hilfssignal wird mit einem GPIO abgefragt.
- Der Counter zählt die Impulse. Wenn das Hilfssignal logisch 0 wird,
ist das Zeitfenster vorüber und es kommen keine Impulse mehr und ich
kann den Zählerstand auswerten.
- Danach wird der Zähler zurückgesetzt und man wartet, bis das
Hilfssignal wieder 0 wird.
Grundsätzlich funktioniert es, wie es soll, ABER mein Timer 2 zählt
immer doppelt so viele Impulse wie er soll! :-)
Ich habe es mit einem HP 5315B Universalzähler verifiziert. Der HP zählt
gut 9000000 Takte. Das wäre O.K. Der STM32 zählt aber 18000000 Takte!
und ich kann mir nicht erklären wieso. Edge Detector habe ich geprüft,
der ist auf 'rising' konfiguriert, müsste also passen.
Anmerken muss man, dass mein externes Signal ca. 5 V Amplitude hat,
weshalb ich einen 1kOhm Seriewiderstand verbaut habe, um den STM32 nicht
zu grillieren.
Momentan benutze ich das Discovery Board. Als Takt für den STM wird der
8MHz Quarz verwendet, die PLL ist auf 160 MHz konfiguriert.
Hier mein Code:
1
RCC->AHB1ENR|=(1u<<0);// enable gpio a
2
GPIOA->MODER|=(2u<<0);// pa0 = alternate function
3
GPIOA->AFR[0]|=(1u<<0);// pa0 = tim2_ch1 input
4
5
RCC->APB1ENR|=(1u<<0);// enable timer2
6
7
// reset timer
8
TIM2->CR1=0;
9
TIM2->CR2=0;
10
11
TIM2->SMCR=(4u<<4)|(7u<<0);// select edge detector as trigger, count on TI1F_ED
12
TIM2->CCER=0;// disable all channels (otherwise ccmr is not writable)
13
TIM2->CCMR1=(2u<<0);// select TI1 input for channel 1
14
TIM2->CR1=1;// counter enable
15
16
while(1)
17
{
18
uint32_ta;
19
20
// led off, wait until trigger signal goes low
21
GPIOD->BSRRH=1<<12;
22
do
23
{
24
a=GPIOD->IDR;
25
}while(a&(1u<<11));
26
27
// led on
28
GPIOD->BSRRL=1<<12;
29
30
// read & reset counter
31
staticuint32_tcnt=0;
32
cnt=TIM2->CNT;
33
TIM2->CR1&=~1;
34
TIM2->CNT=0;
35
TIM2->CR1|=1;
36
37
// wait until trigger signal goes high
38
do
39
{
40
a=GPIOD->IDR;
41
}while(!(a&(1u<<11)));
42
}
Das Triggersignal liegt am PD11 und das Signal, dessen Zyklen zu zählen
sind liegt an PA0. Ich sehe grade den Fehler nicht. Ist Jahre her seit
ich zum letzten mal mit einem STM was gemacht habe :-(
Wer sieht das Problem?
Tobias P. schrieb:> Wer sieht das Problem?
Wie sieht das Signal am Pin mit dem Oszi aus? Klingelt da was? Schwingt
da was über? Was ist die Triggerschwelle des HP?
übrigens hätte ich gern den Timer direkt mit dem Triggersignal gestartet
und gestoppt. Allerdings gefällt mir nicht, dass es diesen Delay gibt
aufgrund der Synchronisationslogik. Ich denke, aufgrund dieses Delays
kann man sich gut um einzelne Pulse verzählen :-(
Wenn du verkraften kannst, dass die erste Messung falsch ist, kannst du
auch immer zählen und erst wenn das Triggersignal abschaltet mit einem
Interrupt den Zähler auswerten und zurücksetzten.
Vorsicht, beliebte Falle beim STM32: Der hat intern zwei Busse, von
denen der eine nur halb so schnell getaktet ist. Manche Timer hängen auf
dem einen Bus, manche auf dem Anderen. Studier mal das Datenblatt deines
POD bzgl. clock tree (ich habe gerade keinen Zugang dazu, sorry).
Mampf F. schrieb:> Verwende doch bitte die StdPeriphLibrary ... Dann ist es wenigstens> leserlich ... ;-)
Nein. Diese Lib finde ich unermesslich hässlich. Will ich nicht und
werde ich nie einsetzen :-)
Wende doch du bitte die normalen Registerzugriffe an.
Tobias P. schrieb:> Nein. Diese Lib finde ich unermesslich hässlich. Will ich nicht und> werde ich nie einsetzen :-)
Wie du willst - reduziert halt die Hilfe, die du erwarten kannst xD
> Wende doch du bitte die normalen Registerzugriffe an.
Die StdPeriphLib ist doch nur ein Wrapper um die normalen
Registerzugriffe herum und auf das Minimum reduziert - aber immerhin
leserlich, bewährt und vielfach verwendet :)
Lass mich raten - du hast vorher AVRs programmiert? ;-)
So, ich hör schon auf mit meiner Lästerei ... :)
Ah noch ganz kurz ... Ich hab die Erfahrung gemacht, dass man öfters mal
die STM32s wechseln muss, weil die nicht alle das gleiche können. Die
Portierung mit StdPeriphLib war da immer nur minimal und ziemlich
schmerzfrei ... Aber gut, musst du wissen.
*edit*: Wie sieht denn die Initialisierung deines Clock-Trees aus?
Auch zu Fuß erledigt oder fertigen Startup-Code verwendet?
Mampf F. schrieb:> Die StdPeriphLib ist doch nur ein Wrapper um die normalen> Registerzugriffe herum und auf das Minimum reduziert - aber immerhin> leserlich, bewährt und vielfach verwendet :)
Direkte Registerzugriffe sind genauso leserlich, wenn man vernünftige
defines für die Bitmasken verwendet - was der OP leider nicht getan hat.
Ich würde erstmal den externen Taktgenerator wegnehmen und stattdessen
manuell den Takt schalten, mit einem entprellten Schalte natürlich. Also
vorzugsweise elektronisch. Dann eine steigende Flanke, gucken was im
Counter ist (1 oder 2), eine fallende und wieder nachsehen (1 oder 2).
so sehen meine Signale aus, also nicht allzu schlimm. Wenn ich an PA0
einen 1 Hz Clock vom Funktionsgenerator ran gebe, zählt der Timer meiner
Meinung nach richtig.....
Hallo, du nutzt den TI1_ED, das ist wahrscheinlich Edge detector, daher
zählt er jede Flanke.
Nutze doch den filtered input 1 oder 2, da kannst du einstellen, ob er
rising oder falling triggert.
also 5<<4 oder 6<<4 im SMCR Register
Hi Martin,
ja genau den Edge Detector benutze ich.
Bist du sicher, dass er jede Flanke zählt? das würde die Sache
allerdings erklären! :-) obwohl ich meine, dass man da
rising/falling/both edges konfigurieren kann.
Aber ich probiers morgen aus. Danke für den Hinweis!
Ich weiß nicht welchen STM32 du benutzt... Aaaaber:
Tobias P. schrieb:> Anmerken muss man, dass mein externes Signal ca. 5 V Amplitude hat,> weshalb ich einen 1kOhm Seriewiderstand verbaut habe, um den STM32 nicht> zu grillieren.
Bei den meisten STM32 sind fast alle IOs (außer die ADC Pins) 5V
tolerant bei 3V3.
Rene K. schrieb:> Bei den meisten STM32 sind fast alle IOs (außer die ADC Pins) 5V> tolerant bei 3V3.
Es geht hier nicht um die 5V-Toleranz, sondern darum, daß an diesen
extrem schnellen Zählereingängen auch ganz steilflankige Signale
erwartet werden.
Per Software kann man die Eingangsfilter der betreffenden Eingänge
aktivieren und bekommt bei langsamen Signalen saubere Impulse.
Den Code oben tue ich mir nicht an. Es ist jedoch unnötig, irgendwelche
Pakete zu schnüren. Es reicht, einfach den Zähler durchlaufen zu lassen
und Zwischenergebnisse per Capture einzufangen.
Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.
Wichtige Regeln - erst lesen, dann posten!
Groß- und Kleinschreibung verwenden
Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang