Advertisement
Guest User

Untitled

a guest
Nov 18th, 2018
214
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.25 KB | None | 0 0
  1. // reziproke Frequenzmessung mit STM32F4-Discovery-Board
  2.  
  3. /*
  4. Beispielprogramm für Frequenzmessung an PE5 mit Timer9.
  5. Das Ergebnis wird 8-stellig mit max. 2 Mess./s oder minimal 1 Periodendauer
  6. angezeigt. Der Frequenzbereich ist 0,05Hz - 2,5MHz im direkten Modus ohne Vorteiler.
  7. Wird "MIT_VORTEILER" definiert verschiebt sich die obere Grenzfrequenz auf 20MHz.
  8. Da ein interner Vorteiler ./.8 zugeschaltet wird, sollte die minimale Eingangsfrequenz
  9. > 20Hz sein, um die Messdauer (minimal 8 Perioden) klein zu halten.
  10.  
  11. Das Messverfahren wird unter http://www.mino-elektronik.de/fmeter/fmeter.htm#funk
  12. näher beschrieben. Dort finden sich Beispielprogramme und weitere Schaltungen
  13. für AVR-Controller.
  14.  
  15. Für die Anzeige der Werte wird ein 4,3" TFT-Display verwendet. Die TFT-Ansteuerung
  16. ist unabhängig von der Messfunktion. Bei eigenen Schaltungen muß eine passende
  17. Anzeige samt Ausgaberoutinen ergänzt werden (RS232-Ausgabe, LCD, eigenes TFT).
  18.  
  19. Das vorliegende Programm wurde mit IAR-Embedded Workbench 6.0 Kickstart entwickelt.
  20. Der Prozessor muß mit 168MHz initialisiert sein.
  21. Die abs. Genauigkeit für 8 Stellen wird nur durch einen hochstabilen HSE-Takt erreicht.
  22. Beim Testaufbau mit dem STM32F4-Discovery-Board wird ein 20MHz TCXO verwendet.
  23. Alle Angaben ohne Gewähr!
  24.  
  25. www.mino-elektronik.de
  26. 2012-10-28
  27. */
  28.  
  29. //#define MIT_VORTEILER    // für Eingangsfrequenzen bis 20MHz
  30.  
  31.  
  32. /* Includes ------------------------------------------------------------------*/
  33. #include <stdio.h>
  34. #include "stdint.h"
  35. #include "stm32f4xx.h"
  36. //#include "LCD_DISCO_F429ZI.h"
  37. #include "mbed.h"
  38.  
  39. extern void tft_str_einmitten(char *s, uint16_t y_pos, char farbe, uint8_t zoom);
  40.  
  41. enum status {MESSEN=0, AUSLESEN, AUSWERTEN};    // die Phasen der Messung
  42.  
  43. #define F_CLOCK 168E6
  44. #define MESSZEIT  1260  // ca. 2 Messungen/sek.
  45. #define STELLEN 8       // Auflösung
  46. #define RUNDUNG 5e-8    // Wert zum Runden
  47.  
  48. double frequenz;        // aktueller Messwert
  49.  
  50. char f_text[]={"F = "};      // 1.Zeile der Anzeige
  51. char p_text[]={"P = "};      // 2.Zeile der Anzeige
  52. char f_dim[][4]={"GHz","MHz","kHz","Hz ","mHz","sek","ms ","us ","ns ","ps "};  // Dimensionen zum Messwert
  53. volatile uint8_t messwert_vorhanden,  // nur gueltige Messungen anzeigen
  54.         mess_status;        // Ablaufsteuerung
  55. volatile uint16_t temp_dauer;
  56. uint16_t zeit_low,          // Timer1-Anteil
  57.         zeit_high;          // T1 Ueberlauf-Anteil
  58. volatile uint16_t mess_dauer,         // minimale Wartezeit
  59.         ueberlauf;
  60.  
  61. uint32_t start_ereignis,    // Impulse zu Beginn der Messung
  62.         start_zeit,         // rel. Zeit: Beginn der Messung
  63.         end_zeit,           // Zeitpunkt der Auswertung
  64.         mess_zeit,          // genaue Zeit der Messung
  65.         mess_ereignisse;    // Impulse der Messung
  66. volatile uint32_t end_ereignis; // Impulse am Ende der Messung
  67.  
  68.  
  69. // Farben für TFT
  70. #define SCHWARZ   0x00
  71. #define ROT   0x03
  72. #define GRUEN     0x0c
  73. #define BLAU      0x30
  74. #define HELLGRAU  0x2a
  75. #define WEISS     (ROT+BLAU+GRUEN)
  76.  
  77. // Routine zur Wandlung und Ausgabe eines Meßwertes
  78.  
  79. void zeige_x(double x, char zeige_periode, char *s)    // Anzeige von Frequenz oder Periode
  80. {
  81. int8_t i,j,dez_punkt,dimension;
  82. char *p;
  83.  
  84.   dez_punkt = 0;
  85.   dimension = 3;
  86.   if(x >= 0.001) {                          // 1mHz ist Untergrenze
  87.     if(zeige_periode) {
  88.       x = 1/x;                              // Kehrwert bilden
  89.       dimension=5;                          // und in Sekunden als Dimension
  90.       p = p_text;
  91.       while(*p) *s++ = *p++;                // "P = " für Periodendauer
  92.     } else {
  93.       p = f_text;
  94.       while(*p) *s++ = *p++;                // "F = " für Frequenz
  95.     }
  96.     while(x<1.0) {x*=1000.0;dimension++;}   // in den Hz-Bereich bringen
  97.     while(x>=1000.0) {x*=0.001;dimension--;}
  98.     while(x >= 10.0) {
  99.       x *= 0.1;
  100.       dez_punkt++;
  101.     }
  102.     x += RUNDUNG;                           // runden
  103.     if(x >= 10.0) {             // Ueberlauf bei Rundung
  104.       x *= 0.1;                             // korrigieren
  105.       dez_punkt++;
  106.       if(dez_punkt > 2) {           // Ueberlauf der Dimension
  107.         dimension--;
  108.         dez_punkt = 0;
  109.       }
  110.     }
  111.   } else {
  112.     x = 0.0; dez_punkt=0; dimension=3;      // 0.00000 Hz ausgeben
  113.   }
  114.   for(i=0;i<STELLEN;i++) {
  115.     j = (char)x;
  116.     *s++ = (j+'0');
  117.     if(i == dez_punkt) *s++ = ('.');
  118.     x -= j;
  119.     x *= 10;
  120.   }
  121.   *s++ = (' ');
  122.   p = f_dim[dimension];
  123.   while(*p) *s++ = *p++;                    // Dimension anhängen
  124.   *s++ = 0;                                 // string abschliessen
  125. }
  126.  
  127.  
  128. void TIM1_BRK_TIM9_IRQHandler(void)
  129. {
  130. static uint32_t anzahl;
  131.   if(TIM9->SR & TIM_SR_CC1IF) {
  132.      TIM9->SR = ~TIM_SR_CC1IF;
  133.      anzahl++;
  134.     if(mess_status == AUSLESEN) {   // Ergebnisse synchron zum Eingangsimpuls auslesen+ablegen
  135.       end_ereignis = anzahl;        // Anzahl der Impulse lesen
  136.       zeit_low = TIM9->CCR1;        // capture-reg lesen: untere 16bit
  137.       zeit_high = ueberlauf;        // dazu die oberen 16bit
  138.       if((TIM9->SR & TIM_SR_UIF) && (zeit_low < 0x8000))    // evtl. Ueberlauf T9 noch offen?
  139.          zeit_high++;               // nur, wenn capture-int + overflow-int gleichzeitig !
  140.        mess_status = AUSWERTEN;     // Daten fertig fuer Auswertung
  141.     }
  142.   }
  143.   if(TIM9->SR & TIM_SR_UIF) {       // nur bei überläufen von T9
  144.      TIM9->SR = ~TIM_SR_UIF;
  145.      ueberlauf++;
  146.      mess_dauer++;
  147.   }
  148. }
  149.  
  150. void init_t9(void)
  151. {
  152.   GPIO_InitTypeDef GPIO_InitStructure;
  153.  
  154.   RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);  // Timer9 aktivieren
  155.   RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE); // PortE aktivieren
  156.  
  157.   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6;
  158.   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
  159.   GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
  160.   GPIO_Init(GPIOE, &GPIO_InitStructure);
  161.  
  162.   // PE5 und PE6 als capture-input zu T9
  163.   GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_TIM9);
  164.   GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_TIM9);
  165.  
  166.   NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);       // Int-T9 aktivieren
  167.   NVIC_SetPriority(TIM1_BRK_TIM9_IRQn,14);  // sehr hohe Priorität
  168.  
  169.   TIM9->CCMR1 = TIM_CCMR1_CC1S_0 + TIM_CCMR1_IC1F_1;     // capture zuordnung IC1 -> TI1
  170.   TIM9->CCER = TIM_CCER_CC1E;         // capture freigeben
  171.  
  172. #ifdef MIT_VORTEILER
  173. //  TIM9->CCMR1 |= TIM_CCMR1_IC1F_1;    // Eingangssignal auf 20MHz begrenzen
  174.   TIM9->CCMR1 |= TIM_ICPSC_DIV8;      // Vorteiler /8 aktivieren
  175. #else
  176. //  TIM9->CCMR1 |= TIM_CCMR1_IC1F_0 ; // Eingangssignal max. 2,5MHz
  177. #endif
  178.  
  179.   TIM9->DIER |= TIM_DIER_CC1IE + TIM_DIER_UIE; // mit interrupts
  180.   TIM9->CR1 |= TIM_CR1_CEN;           // T9 starten
  181. }
  182.  
  183.  
  184.  
  185. void f_mess(void)
  186. {
  187. char s[50];
  188. uint8_t neue_werte = 1;             // Platzhalter anzeigen
  189. char format[] = " Nin:%7d  Nref:%9d ";
  190.   init_t9();                        // T9 freilaufend mit 168MHz im capture-modus starten
  191.   mess_status = MESSEN;
  192.   messwert_vorhanden = 0;           // 1. ergebnis verwerfen
  193.   while(1) {
  194.     if(neue_werte) {
  195.       sprintf(s,"eff. Messzeit:%7.3f sek.",(float)mess_zeit/F_CLOCK);
  196.       tft_str_einmitten(s,210,HELLGRAU,2);
  197.       sprintf(s,format,mess_ereignisse, mess_zeit);
  198.       tft_str_einmitten(s,240,BLAU,2);
  199.       neue_werte = 0;
  200.     }
  201.     if(mess_status==MESSEN  && mess_dauer >= MESSZEIT) {
  202.       mess_status=AUSLESEN;         // Auswertung starten
  203.     }
  204.  
  205.     if(mess_status==AUSWERTEN) {
  206.       end_zeit = zeit_high*0x10000 + zeit_low;
  207.       mess_zeit = end_zeit - start_zeit;                // Zeit-Differenz bilden
  208.       start_zeit = end_zeit;        // neue startzeit merken
  209.       mess_ereignisse = end_ereignis - start_ereignis;  // Impuls-Differenz
  210. #ifdef MIT_VORTEILER
  211.       mess_ereignisse *= 8;
  212. #endif
  213.       start_ereignis = end_ereignis;// fuers naechste Intervall
  214.       mess_status = MESSEN;         // neu starten
  215.       mess_dauer = 0;               // und Messzeit abwarten
  216.       if(messwert_vorhanden) {
  217.         frequenz = ((double)mess_ereignisse * F_CLOCK) / mess_zeit;  // Frequenz berechnen
  218.         zeige_x(frequenz, 0, s);
  219.         tft_str_einmitten(s,120,SCHWARZ,3);
  220.         zeige_x(frequenz, 1, s);
  221.         tft_str_einmitten(s,165,SCHWARZ,3);
  222.         neue_werte = 1;             // Details der Messung anzeigen
  223.       }
  224.       else messwert_vorhanden = 1;  // sperre wieder aufheben
  225.     }
  226.   }
  227. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement