Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- // reziproke Frequenzmessung mit STM32F4-Discovery-Board
- /*
- Beispielprogramm für Frequenzmessung an PE5 mit Timer9.
- Das Ergebnis wird 8-stellig mit max. 2 Mess./s oder minimal 1 Periodendauer
- angezeigt. Der Frequenzbereich ist 0,05Hz - 2,5MHz im direkten Modus ohne Vorteiler.
- Wird "MIT_VORTEILER" definiert verschiebt sich die obere Grenzfrequenz auf 20MHz.
- Da ein interner Vorteiler ./.8 zugeschaltet wird, sollte die minimale Eingangsfrequenz
- > 20Hz sein, um die Messdauer (minimal 8 Perioden) klein zu halten.
- Das Messverfahren wird unter http://www.mino-elektronik.de/fmeter/fmeter.htm#funk
- näher beschrieben. Dort finden sich Beispielprogramme und weitere Schaltungen
- für AVR-Controller.
- Für die Anzeige der Werte wird ein 4,3" TFT-Display verwendet. Die TFT-Ansteuerung
- ist unabhängig von der Messfunktion. Bei eigenen Schaltungen muß eine passende
- Anzeige samt Ausgaberoutinen ergänzt werden (RS232-Ausgabe, LCD, eigenes TFT).
- Das vorliegende Programm wurde mit IAR-Embedded Workbench 6.0 Kickstart entwickelt.
- Der Prozessor muß mit 168MHz initialisiert sein.
- Die abs. Genauigkeit für 8 Stellen wird nur durch einen hochstabilen HSE-Takt erreicht.
- Beim Testaufbau mit dem STM32F4-Discovery-Board wird ein 20MHz TCXO verwendet.
- Alle Angaben ohne Gewähr!
- www.mino-elektronik.de
- 2012-10-28
- */
- //#define MIT_VORTEILER // für Eingangsfrequenzen bis 20MHz
- /* Includes ------------------------------------------------------------------*/
- #include <stdio.h>
- #include "stdint.h"
- #include "stm32f4xx.h"
- //#include "LCD_DISCO_F429ZI.h"
- #include "mbed.h"
- extern void tft_str_einmitten(char *s, uint16_t y_pos, char farbe, uint8_t zoom);
- enum status {MESSEN=0, AUSLESEN, AUSWERTEN}; // die Phasen der Messung
- #define F_CLOCK 168E6
- #define MESSZEIT 1260 // ca. 2 Messungen/sek.
- #define STELLEN 8 // Auflösung
- #define RUNDUNG 5e-8 // Wert zum Runden
- double frequenz; // aktueller Messwert
- char f_text[]={"F = "}; // 1.Zeile der Anzeige
- char p_text[]={"P = "}; // 2.Zeile der Anzeige
- char f_dim[][4]={"GHz","MHz","kHz","Hz ","mHz","sek","ms ","us ","ns ","ps "}; // Dimensionen zum Messwert
- volatile uint8_t messwert_vorhanden, // nur gueltige Messungen anzeigen
- mess_status; // Ablaufsteuerung
- volatile uint16_t temp_dauer;
- uint16_t zeit_low, // Timer1-Anteil
- zeit_high; // T1 Ueberlauf-Anteil
- volatile uint16_t mess_dauer, // minimale Wartezeit
- ueberlauf;
- uint32_t start_ereignis, // Impulse zu Beginn der Messung
- start_zeit, // rel. Zeit: Beginn der Messung
- end_zeit, // Zeitpunkt der Auswertung
- mess_zeit, // genaue Zeit der Messung
- mess_ereignisse; // Impulse der Messung
- volatile uint32_t end_ereignis; // Impulse am Ende der Messung
- // Farben für TFT
- #define SCHWARZ 0x00
- #define ROT 0x03
- #define GRUEN 0x0c
- #define BLAU 0x30
- #define HELLGRAU 0x2a
- #define WEISS (ROT+BLAU+GRUEN)
- // Routine zur Wandlung und Ausgabe eines Meßwertes
- void zeige_x(double x, char zeige_periode, char *s) // Anzeige von Frequenz oder Periode
- {
- int8_t i,j,dez_punkt,dimension;
- char *p;
- dez_punkt = 0;
- dimension = 3;
- if(x >= 0.001) { // 1mHz ist Untergrenze
- if(zeige_periode) {
- x = 1/x; // Kehrwert bilden
- dimension=5; // und in Sekunden als Dimension
- p = p_text;
- while(*p) *s++ = *p++; // "P = " für Periodendauer
- } else {
- p = f_text;
- while(*p) *s++ = *p++; // "F = " für Frequenz
- }
- while(x<1.0) {x*=1000.0;dimension++;} // in den Hz-Bereich bringen
- while(x>=1000.0) {x*=0.001;dimension--;}
- while(x >= 10.0) {
- x *= 0.1;
- dez_punkt++;
- }
- x += RUNDUNG; // runden
- if(x >= 10.0) { // Ueberlauf bei Rundung
- x *= 0.1; // korrigieren
- dez_punkt++;
- if(dez_punkt > 2) { // Ueberlauf der Dimension
- dimension--;
- dez_punkt = 0;
- }
- }
- } else {
- x = 0.0; dez_punkt=0; dimension=3; // 0.00000 Hz ausgeben
- }
- for(i=0;i<STELLEN;i++) {
- j = (char)x;
- *s++ = (j+'0');
- if(i == dez_punkt) *s++ = ('.');
- x -= j;
- x *= 10;
- }
- *s++ = (' ');
- p = f_dim[dimension];
- while(*p) *s++ = *p++; // Dimension anhängen
- *s++ = 0; // string abschliessen
- }
- void TIM1_BRK_TIM9_IRQHandler(void)
- {
- static uint32_t anzahl;
- if(TIM9->SR & TIM_SR_CC1IF) {
- TIM9->SR = ~TIM_SR_CC1IF;
- anzahl++;
- if(mess_status == AUSLESEN) { // Ergebnisse synchron zum Eingangsimpuls auslesen+ablegen
- end_ereignis = anzahl; // Anzahl der Impulse lesen
- zeit_low = TIM9->CCR1; // capture-reg lesen: untere 16bit
- zeit_high = ueberlauf; // dazu die oberen 16bit
- if((TIM9->SR & TIM_SR_UIF) && (zeit_low < 0x8000)) // evtl. Ueberlauf T9 noch offen?
- zeit_high++; // nur, wenn capture-int + overflow-int gleichzeitig !
- mess_status = AUSWERTEN; // Daten fertig fuer Auswertung
- }
- }
- if(TIM9->SR & TIM_SR_UIF) { // nur bei überläufen von T9
- TIM9->SR = ~TIM_SR_UIF;
- ueberlauf++;
- mess_dauer++;
- }
- }
- void init_t9(void)
- {
- GPIO_InitTypeDef GPIO_InitStructure;
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE); // Timer9 aktivieren
- RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); // PortE aktivieren
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
- GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
- GPIO_Init(GPIOE, &GPIO_InitStructure);
- // PE5 und PE6 als capture-input zu T9
- GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_TIM9);
- GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_TIM9);
- NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn); // Int-T9 aktivieren
- NVIC_SetPriority(TIM1_BRK_TIM9_IRQn,14); // sehr hohe Priorität
- TIM9->CCMR1 = TIM_CCMR1_CC1S_0 + TIM_CCMR1_IC1F_1; // capture zuordnung IC1 -> TI1
- TIM9->CCER = TIM_CCER_CC1E; // capture freigeben
- #ifdef MIT_VORTEILER
- // TIM9->CCMR1 |= TIM_CCMR1_IC1F_1; // Eingangssignal auf 20MHz begrenzen
- TIM9->CCMR1 |= TIM_ICPSC_DIV8; // Vorteiler /8 aktivieren
- #else
- // TIM9->CCMR1 |= TIM_CCMR1_IC1F_0 ; // Eingangssignal max. 2,5MHz
- #endif
- TIM9->DIER |= TIM_DIER_CC1IE + TIM_DIER_UIE; // mit interrupts
- TIM9->CR1 |= TIM_CR1_CEN; // T9 starten
- }
- void f_mess(void)
- {
- char s[50];
- uint8_t neue_werte = 1; // Platzhalter anzeigen
- char format[] = " Nin:%7d Nref:%9d ";
- init_t9(); // T9 freilaufend mit 168MHz im capture-modus starten
- mess_status = MESSEN;
- messwert_vorhanden = 0; // 1. ergebnis verwerfen
- while(1) {
- if(neue_werte) {
- sprintf(s,"eff. Messzeit:%7.3f sek.",(float)mess_zeit/F_CLOCK);
- tft_str_einmitten(s,210,HELLGRAU,2);
- sprintf(s,format,mess_ereignisse, mess_zeit);
- tft_str_einmitten(s,240,BLAU,2);
- neue_werte = 0;
- }
- if(mess_status==MESSEN && mess_dauer >= MESSZEIT) {
- mess_status=AUSLESEN; // Auswertung starten
- }
- if(mess_status==AUSWERTEN) {
- end_zeit = zeit_high*0x10000 + zeit_low;
- mess_zeit = end_zeit - start_zeit; // Zeit-Differenz bilden
- start_zeit = end_zeit; // neue startzeit merken
- mess_ereignisse = end_ereignis - start_ereignis; // Impuls-Differenz
- #ifdef MIT_VORTEILER
- mess_ereignisse *= 8;
- #endif
- start_ereignis = end_ereignis;// fuers naechste Intervall
- mess_status = MESSEN; // neu starten
- mess_dauer = 0; // und Messzeit abwarten
- if(messwert_vorhanden) {
- frequenz = ((double)mess_ereignisse * F_CLOCK) / mess_zeit; // Frequenz berechnen
- zeige_x(frequenz, 0, s);
- tft_str_einmitten(s,120,SCHWARZ,3);
- zeige_x(frequenz, 1, s);
- tft_str_einmitten(s,165,SCHWARZ,3);
- neue_werte = 1; // Details der Messung anzeigen
- }
- else messwert_vorhanden = 1; // sperre wieder aufheben
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement