Ich habe eine einfache Timing-Prüfung für mein STM32F4-Discovery-Board codiert.
#define IT_PER_SEC 100
int main(void)
{
if (SysTick_Config(SystemCoreClock / IT_PER_SEC))
{
while (1){}; // error
}
initGPIO();
for(;;)
{
}
return 0;
}
void SysTick_Handler(void)
{
static uint32_t csec = 0;
static uint32_t ctime = 0;
++csec;
if(csec == IT_PER_SEC) // every second
{
// every second
GPIO_ToggleBits(GPIOD, GPIO_Pin_12);
csec = 0;
// clock
++ctime;
if((ctime % 10) == 0) // every 10 seconds
{
GPIO_ToggleBits(GPIOD, GPIO_Pin_13);
}
if((ctime % 60) == 0) // every minute
{
GPIO_ToggleBits(GPIOD, GPIO_Pin_14);
}
if(ctime == 3600) // every hour
{
GPIO_ToggleBits(GPIOD, GPIO_Pin_15);
ctime = 0;
}
}
}
Dies scheint gut zu funktionieren. Ich habe es mit der Stoppuhr-App auf meinem Android-Handy überprüft. Aber nach einer Stunde und etwas bemerkte ich, dass das LED-Timing etwa eine Sekunde im Voraus war und nach zweieinhalb Stunden bin ich fast bei zwei Sekunden.
Ich schätze, meine App ist hier nicht schuld, oder doch? Der SysTick sollte auch in Ordnung sein, nehme ich an. Also muss es mein Code sein...
Die Schaltpläne sind die Standardschaltpläne des STM32F4 Discovery Boards. Sie sind im Benutzerhandbuch auf Seite 32 zu finden. Dort findet man einen 8-MHz-Quarz zusammen mit den beiden üblichen 20-pF-Kondensatoren.
Kristalle sind normalerweise viel besser als eine Genauigkeit von 50 ppm ... ABER ... Kristalle haben zwei Resonanzmodi - Serienresonanz und Parallelresonanz (bei einem Impedanzdiagramm sehen Sie, wie die Impedanz bei Parallelresonanz gegen unendlich steigt und bei Serienresonanz gegen Null fällt ).
Wichtig ist nun, dass die beiden Resonanzmoden normalerweise einige hundert PPM voneinander entfernt sind und nur einer von ihnen die markierte Frequenz hat!
Wenn Sie einfach einen "8-MHz"-Quarz kaufen, ohne auf das Kleingedruckte zu achten, erhalten Sie möglicherweise einen Schnitt auf 8 MHz im falschen Modus. und Ihr Oszillator wird mehrere hundert PPM verstimmt sein.
(Die Parallelresonanz ist auch über 50 ppm oder mehr abstimmbar, daher wird sie normalerweise bei einer bestimmten Lastkapazität angegeben).
Man könnte meinen, die meisten professionellen Designer würden mehr Aufmerksamkeit schenken und den richtigen Kristall auswählen – und Sie würden normalerweise Recht haben – aber ich habe sogar einige hochpreisige digitale Audiogeräte gesehen, bei denen dieser Fehler gemacht wurde!
Oder vielleicht hat der Komponenteneinkauf ein "gutes Geschäft" gefunden oder es wurde einfach entschieden, dass für ein Budget-Evaluierungsboard der Preis wichtiger ist als die Genauigkeit des Timings ...
Aber ich vermute trotzdem, dass der Kristall im falschen Modus arbeitet, um einen Frequenzfehler von 300 ppm zu erzeugen.
Systick leitet sich vom Prozessortakt ab, der wiederum vermutlich von einem xtal (oder vom internen RC-Oszillator?) stammt.
1 Sekunde Fehler in 1 Stunde ist 1 : 3600 oder 277 ppm. Ein 08/15 xtal ist garantiert auf 50 ppm genau, daher ist es unwahrscheinlich, dass dies nur durch die xtal-Ungenauigkeit verursacht wird.
Sind Sie sicher, dass Ihr Chip auf dem xtal läuft? Die mir bekannten LPC-Chips laufen standardmäßig auf ihrem internen RC-Oszillator, der weitaus ungenauer ist als ein xtal.
Ein weiterer Schuldiger könnte eine falsche Initialisierung sein, sind Sie sicher, dass das richtig gemacht wird?
Nebenbemerkung: Für eine genaue Zeitmessung scheinen 32-kHz-Quarze beliebter zu sein, aber ich sehe keinen auf einem Foto eines STM32F4-Discovery-Boards. Es gibt einen leeren Platz, der mit X3 gekennzeichnet ist, vielleicht ist das für so ein xtal gedacht.
Im Datenblatt des STM32F4 habe ich das gefunden, vielleicht ist es Ihre Antwort:
SysTick-Kalibrierwertregister
Der SysTick-Kalibrierwert ist auf 18750 festgelegt, was eine Referenzzeitbasis von 1 ms ergibt, wenn der SysTick-Takt auf 18,75 MHz eingestellt ist (HCLK/8, wobei HCLK auf 150 MHz eingestellt ist).
Es hört sich so an, als ob Ihr uC vom HSI-Oszillator läuft - ich habe einen Discovery F4 und ich erinnere mich, dass ich anfangs ein wenig Schwierigkeiten hatte, ihn vom externen Oszillator zum Laufen zu bringen.
Eine einfache Möglichkeit zum Testen besteht darin, den Ausgangspin des externen Oszillators zu prüfen, um festzustellen, ob er läuft.
Wenn Sie einen Blick in die Dokumentation Ihrer Peripheriebibliothek werfen, werden Sie unter CMSIS die Funktionen SystemInit
und sehen. SetSysClock
IIRC, beim Zurücksetzen besteht das normale Verhalten darin, das HSI zu verwenden, sofern nicht anders definiert. Stellen Sie sicher, dass STD_PERIPH_DRIVER definiert ist, und überprüfen Sie Ihre Datei system_stm32f4xx.c, um sicherzustellen, dass der richtige Oszillator ausgewählt ist. Stellen Sie sicher, dass Ihr HSE_VALUE auch definiert (und auf den richtigen Wert gesetzt) ist.
Stöbern Sie im Grunde in den Setup-Dateien des CMSIS-Systems und in der Dokumentation in der Bibliothek - ich vergesse spontan, was Sie genau einstellen müssen (ich schlafe hier halb und werde sehr bald die andere Hälfte sein ... .), aber es ist alles irgendwo drin (die Codekommentare zeigen Ihnen, wie Sie den richtigen Oszillator einstellen), zum Beispiel haben Sie in der Datei system_stm32f4xx diesen Kommentar ganz oben:
* 5. This file configures the system clock as follows:
*=============================================================================
*=============================================================================
* Supported STM32F4xx device revision | Rev A
*-----------------------------------------------------------------------------
* System Clock source | PLL (HSE)
*-----------------------------------------------------------------------------
* SYSCLK(Hz) | 168000000
*-----------------------------------------------------------------------------
* HCLK(Hz) | 168000000
*-----------------------------------------------------------------------------
* AHB Prescaler | 1
*-----------------------------------------------------------------------------
* APB1 Prescaler | 4
*-----------------------------------------------------------------------------
* APB2 Prescaler | 2
*-----------------------------------------------------------------------------
* HSE Frequency(Hz) | 25000000
*-----------------------------------------------------------------------------
* PLL_M | 25
*-----------------------------------------------------------------------------
* PLL_N | 336
*-----------------------------------------------------------------------------
* PLL_P | 2
*-----------------------------------------------------------------------------
* PLL_Q | 7
*-----------------------------------------------------------------------------
* PLLI2S_N | NA
*-----------------------------------------------------------------------------
* PLLI2S_R | NA
*-----------------------------------------------------------------------------
* I2S input clock | NA
*-----------------------------------------------------------------------------
* VDD(V) | 3.3
*-----------------------------------------------------------------------------
* High Performance mode | Enabled
*-----------------------------------------------------------------------------
* Flash Latency(WS) | 5
*-----------------------------------------------------------------------------
* Prefetch Buffer | OFF
*-----------------------------------------------------------------------------
* Instruction cache | ON
*-----------------------------------------------------------------------------
* Data cache | ON
*-----------------------------------------------------------------------------
* Require 48MHz for USB OTG FS, | Enabled
* SDIO and RNG clock |
*-----------------------------------------------------------------------------
Es gibt ein paar Möglichkeiten, die HSI-Uhr realistischer zu kalibrieren, indem Sie 50 Hz oder RTC verwenden. Die ST-Appnote ist hier .
Zählen Sie grundsätzlich sowohl mit Systick als auch mit RTC auf eine Sekunde und teilen Sie die Hardware mit den HSITRIM-Bits auf.
Zebonaut
aLu
Chris Stratton