Hallo zusammen,
ich habe ein Problem mit den Timereinstellungen eines STM32F4Discovery
Boards und hoffe es kann mir hier jemand weiterhelfen.
Timer 3 toggled bei jedem Timerevent PortC Pin15 welcher mit einem 10k
Widerstand auf Masse liegt. Die Frequenz am Pin messe ich mit einem
Oszi.
Systemtakt = 168MHz. Habe ich mir an MCO1 ausgeben lassen. -> Passt.
HSE Frequenz: 8MHz
AHB Prescaler: 1
APB1 Prescaler: 4
APB2 Prescaler: 2
Nun mein Problem:
bei gewissen Werten von "Period" und "Prescaler" stimmt die Frequenz mit
dem
erwarteten Wert zusammen bei einigen dann nicht mehr. Woran liegt das??
z.B.:
Period = 2;
Prescaler = 83;
Frequenz am Pin = 166,7kHz -> passt wie erwartet
Period=2;
Prescaler = 20;
Frequenz: 700kHz -> gemessen wurden aber nur 350kHz -> falsche Frequenz
Period=2;
Prescaler = 30;
Frequenz: 466,6kHz -> gemessen: 466,6kHz -> passt auch
Period=4;
Prescaler = 18;
Frequenz: 442kHz -> gemessen: 442kHz -> passt auch
Period=4;
Prescaler = 14;
Frequenz: 560kHz -> gemessen: 381/535kHz -> falsch (Oszibild ist hier
verzerrt)
Bei Period=4 ist ein Prescaler=15 der letzte Wert wo die Frequenz noch
stimmt. Alle Werte darunter ergeben falsche Frquenzwerte.
Ich probier jetzt schon sehr lange damit rum und komme einfach nicht
dahinter wo das Problem liegt.
Hoffentlich kann mir einer der ARM Spezialisten weiterhelfen.
Anbei noch der Quellcode und eine Excel-Datei welche ich zum
Kontrollrechnen verwende:
Vielen Dank schon mal
Markus
void TIM3_IRQHandler(void)
{
if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET)
{
TIM_ClearITPendingBit(TIM3, TIM_IT_Update);
GPIO_ToggleBits(GPIOC, GPIO_Pin_15);
}
}
void INTTIM_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the TIM3 gloabal Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
/* TIM3 clock enable */
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
/* Time base configuration */
TIM_TimeBaseStructure.TIM_Period = 15-1; // 1 MHz down to 1 KHz (1 ms)
TIM_TimeBaseStructure.TIM_Prescaler = 5-1; // 84 MHz Clock down to 1
MHz (adjust per your clock)
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
/* TIM IT enable */
TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
/* TIM3 enable counter */
TIM_Cmd(TIM3, ENABLE);
}
int main(void)
{
SystemInit();
SystemCoreClockUpdate();
/* GPIOD Periph clock enable */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE);
RCC_ClocksTypeDef oClock;
RCC_GetClocksFreq(&oClock);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOC, &GPIO_InitStructure);
INTTIM_Config();
while(1)
{
}
}
Hallo Uwe,
nein hat leider nix geholfen.
Ich hab auch mal versucht in einer Endlosschleife (also alles ohne
Timer) einfach einen PIN zu togglen. Hier komme ich auf eine max.
Frequenz von ca. 1MHz. Das kann eigentlich auch schon nicht stimmen,
oder??
Blöde Frage: kann das mit der ST-Link Frequenz zu tun haben über welchen
ich Debug und Flashe. Diese Frequenz ist mit 1MHz eingestellt.
Als IDE verwende ich CooCox CoIDE.
lg, markus
du hast aber nicht den Debugger laufen oder ?
1MHz kommt mir sehr wenig vor
hängt noch was anderes an dem Pin PC15 ?
komisch ist, das manche Frequenzen stimmen
und andere nicht...
lass mal den Widerstand weg
und häng das Scope direkt an den Pin
Gruss Uwe
nein debugger läuft nicht. hab auch mal die brücken zwischen dem ST-Link
und dem eigentlich STM32F4 Chip entfernt und so das program im flash
gestartet bringt auch nichts.
Widerstand ist weg und hat auch nichts gebracht....
lg, m.
ich kann hier jetzt leider nichts ausprobieren
werd aber heut abend
(wenn das problem bis dahin nicht schon gelöst ist)
mal bei meinem Discovery nachmessen...was der max GPIO speed ist
kann es an deinem Oszi liegen ?
zeigt es die Frq direkt an
oder misst du die Periode selbst aus ?
Gruss Uwe
also, so wie ich das datenblatt verstanden habe sollten max. 84MHz GPIO
Speed möglich sein.
am Oszi liegt es nicht. hab die Frequenz natürlich ermitteln lassen,
aber auch durch "abzählen" am Oszibild überprüft.
uwe,
danke erst mal für deine hilfe.
bin froh das du die gleichen werte gemessen hast und es dir auch nicht
erklären kann.
ich versteh auch deine 7,5Mhz nicht. Das ist ja eigentlich auch viel zu
wenig, oder??
und beim Timer ist nach wie vor die frage wo da die obergrenze liegt.
darf ich vielleicht einen timer nicht für so hohe frquenzen nehmen??
und die If-Abfrage ausbauen ist eigentlich nur ein schlechter
"workaround" für die 700khz. oder wie denkst du??
lg, m.
Markus F. schrieb:> ich versteh auch deine 7,5Mhz nicht. Das ist ja eigentlich auch viel zu> wenig, oder??
Wenn du dir nur deine C-Befehle ansiehst ist das so gut wie sinnlos. Du
mußt dir in Assembler window ansehen was der Compiler an
Assemblerbefehlen daraus gemacht hat. Dann wirst du auch den Einfluß von
C-Optimierungseinstellungen beobachten könne!
wegen der 7,5MHz bin ich mir nicht sicher,
müsste man mal mit Optimierung auf "speed" probieren
wieviel das bringt
ich weis ja nicht was du machen willst,
einen Pin kann ein Timer auch direkt ansteuern
(siehe PWM-Mode ...ohne Interrupt und manuellem setzen)
damit müsste es deutlich schneller gehen
und wegen der Geschwindigkeit...die Timer1 und 8
werden ja sogar mit 168MHz angefahren
ich bin da jetzt auch überfragt warum die IF-Abfrage
so lange dauert
ich kämpfe zur zeit mit einem ähnlichen Problem,
ich will per DMA ein Byte an den GPIOs ausgeben
und vom einschalten bis zum erscheinen der Werte an den Pins
vergehen 20us !! k.A. warum das so lange dauert
vlt meldet sich hier noch jemand zu deinem Problem
und klärt das ganze
Gruss
Uwe B. schrieb:> ich will per DMA ein Byte an den GPIOs ausgeben> und vom einschalten bis zum erscheinen der Werte an den Pins> vergehen 20us !! k.A. warum das so lange dauert
Etwas genauer beschreiben was du tust!
Einschalten = Aufruf der Initialisierungsroutine?
Wie hast du die 20us gemessen?
Die Library Funktionen sind recht langsam.
Wichtig auch: !!!!!!!!!
Sicherstellen, dass deine CPU wirklich mit 168MHz läuft. Bin da auch
einmal in einer Sackgasse gewesen.
> das kann nicht gehen,> wenn das "TIM_IT_Update" Bit gelöscht ist,> wird die IF-Abfrage darunter immer scheitern
Hoppla - das stimmt allerdings. Da hab ich geschlafen
Meine Idee zielte darauf sicherzustellen, dass das Interruptflag auch
wirklich gelöscht ist wenn die Intzerruptroutine verlassen wird.
Es gab da schonmal Probleme, wenn das Flag erst am Ende der Routine
gelöscht wird.
Markus F. schrieb:> uwe,> danke erst mal für deine hilfe.>> bin froh das du die gleichen werte gemessen hast und es dir auch nicht> erklären kann.> ich versteh auch deine 7,5Mhz nicht. Das ist ja eigentlich auch viel zu> wenig, oder??>> und beim Timer ist nach wie vor die frage wo da die obergrenze liegt.> darf ich vielleicht einen timer nicht für so hohe frquenzen nehmen??> und die If-Abfrage ausbauen ist eigentlich nur ein schlechter> "workaround" für die 700khz. oder wie denkst du??>> lg, m.
Bei 168MHz entspricht 7,5MHz einer Periodendauer von 22 CPU-Zyklen. Wenn
man nun den entsprechenden Assembler-Code anschaut, stellt man fest,
dass eine ganze Reihe von Assemberbefehlen aus dieser Schleife erzeugt
werden.
Bedingte Sprungbefehle mit Sprung benötigen beim Cortex-M4 bis zu 5
Zyklen(2+3 zum Aufladen der Pipeline), Load/Store jeweils 2, der Rest im
Wesentlichen 1.
Bei mir wird folgender Code erzeugt:
while(1)
{
GPIOC->ODR ^= GPIO_Pin_15;
toggle:
mov.w r3, #2048 ; 0x800 (1)
movt r3, #16386 ; 0x4002 (1)
mov.w r2, #2048 ; 0x800 (1)
movt r2, #16386 ; 0x4002 (1)
ldr r2, [r2, #20] (2)
eor.w r2, r2, #32768 ; 0x8000 (1)
str r2, [r3, #20] (2)
}
b.n <toggle> (2 mit Sprungvorhersage)
Wie man sieht ein Schleifendurchlauf hat genau 11 Zyklen, was einer
Frequenz von 7,5MHz ziemlich genau entspricht, da pro Periode die
Schleife ja 2 mal also in 22 Zyklen durchlaufen wird.
Bei einer Interrupt-Routine müssen zusätzlich noch eine ganze Reihe
Register auf den Stack gesichtert und beim Verlassen zurückgeladen
werden, somit denke ich, dass 500khz (ca. 150 Zyklen pro Routinenaufruf)
durchaus realistisch sind. Müsste man mal genau nachzählen.
Auch wenn man beim STM32F4 mit 168MHZ scheinbar unglaublich viel
Rechenleistung zur Verfügung hat, muss man in ISR-Routinen sehr
aufpassen, will man keine Interrupts verpassen.
@Michael Warenberg,
>Wie man sieht ein Schleifendurchlauf hat genau 11 Zyklen, was einer>Frequenz von 7,5MHz ziemlich genau entspricht, da pro Periode die>Schleife ja 2 mal also in 22 Zyklen durchlaufen wird.
deine Rechnung klingt plausbibel...
hier würde eine RISC-CPU (ATMEga) mit ihren
1Cyclus Befehlen vlt. Ihre Vorteile ausspielen
(ich bleib aber beim STM :-)
@Fritz,
>Etwas genauer beschreiben was du tust!>Einschalten = Aufruf der Initialisierungsroutine?>Wie hast du die 20us gemessen?
das wird zu Offtopic...ich werd (wenn ich nicht weiterkomme)
einen neuen Thread aufmachen
>Die Library Funktionen sind recht langsam.
Full ACK !!
hier hat schon mal jemand die Delays der STM-Funktionen
der GPIOs nachgemessen...(auch interresant für den TE)
http://joe-c.de/pages/posts/einstieg_mikrocontroller_stm32f103_101.php
(ganz nach unten scrollen)
Uwe B. schrieb:> @Michael Warenberg,>>>Wie man sieht ein Schleifendurchlauf hat genau 11 Zyklen, was einer>>Frequenz von 7,5MHz ziemlich genau entspricht, da pro Periode die>>Schleife ja 2 mal also in 22 Zyklen durchlaufen wird.>> deine Rechnung klingt plausbibel...> hier würde eine RISC-CPU (ATMEga) mit ihren> 1Cyclus Befehlen vlt. Ihre Vorteile ausspielen> (ich bleib aber beim STM :-)
Kommt halt auf die Anwendung an. Der STM32 spielt halt beim Verarbeiten
größerer Datenmengen seine Vorteile aus, während z.B. ein AVR bei
einfachen (IO) Aufgeben bei Stromverbrauch und Einfachheit punkten kann.
Man sollte sich halt nicht von den 168MHz allzu sehr blenden lassen, da
ein Cortex-M4 dafür auch eine 3-stufige Pipeline und bis zu 5 Waitstates
beim (Flash-) Speicherzugriff hat. Auch beim STM32F4 kommt man bei
zeitkritischen ISR möglicherweise nicht um Assembler herum. Wenn man auf
einem 32-Bit System Aufgaben implementiert, wofür auch 8 bit völlig
ausreichend wären, ist der Overhead dadurch gar nicht so gering.
> hier hat schon mal jemand die Delays der STM-Funktionen> der GPIOs nachgemessen...(auch interresant für den TE)>> http://joe-c.de/pages/posts/einstieg_mikrocontroll...>> (ganz nach unten scrollen)