Zum Zählen bietet sich der Timer0 an. Dieser kann direkt oder über einen einstellbaren Vorteiler mit dem Eingangspin RA4 verbunden werden. Da der PIC16F84 aber nur einen Timer hat, muss die feste Messdauer durch eine Programmschleife realisiert werden. Für eine Messzeit von 1 Sekunde benütigt man eine Warteschleife mit 2.500.000 Takten auf einem 10 MHz PIC.
8-Bit-Zähler
Der Timer0 ist leider
nur 8 Bit groß - kann also nur bis 255 zählen. Mit 1 Sekunde
Messzeit, beträgt also die höchste messbare
Frequenz
255 Hz. Zu wenig.
Durch Nutzung des Vorteilers lässt sich die Eingangsfrequenz
bis zu 256:1 herunterteilen. Die 255 entspräche dann
255*256=65280Hz.
Schon besser, allerdings verringert der Vorteiler die
Messgenauigkeit:
die 65280 Hz werden nur mit 256 Hz Genauigkeit gemessen.
Verwendet man anstelle der 1 Sekunde Messzeit 1/100 Sekunde, dann zählt der Zähler nur 1/100stel der Frequenz. Die richtige Frequenz wäre also 255*256*100=6,528 MHz. Durch weitere Verkürzung der Messzeit lassen sich auch höhere Frequenzen problemlos messen. Die Grenze ist die maximale Eingangsfrequenz des Vorteilers. Bis 50 MHz habe ich problemlos erreicht.
Natürlich verringert sich durch den Vorteiler und die kurze Messzeit die Auflösung der Messung gewaltig. Bei einem Vorteiler 256:1 und 1/100Sekunde Messzeit, wird die Frequenz in Schritten von 25,6 kHz bestimmt. Durch den kleinen 8 Bit Timer bedingt ist die Messgenauigkeit auf 0,4% des Messbereichsmaximalwerts begrenzt. Für einfache Zwecke reicht das. Für höhere Ansprüche benötigen wir eine bessere eine Lösung.
24-Bit-Zähler
Wenn man jeden Überlauf des Timer0 per Software in einem 16-Bit
Software-Zähler mitzählt hat man einen 24-Bit Zähler mit
dem man von 1 bis 16777215 zählen kann. Damit ließen sich
ohne
Vorteiler theoretisch mit einer Messzeit von 1 Sekunde Frequenzen
bis zu 16 MHz mit einer Genauigkeit von 1 Hz messen, wenn der Timer0 16
MHz vertragen würde. Leider ist sein Eingangstakt auf 1/4 des
Prozessortaktes
beschränkt. Der Timer0 eines mit 10 MHz getakteter PIC kann also
maximal
2,5 MHz zählen. Für höhere Frequenzen kann man aber den
Vorteiler einsetzen.
Ein besonderes Problem ist es, den Überlauf des Timer0 zu zählen, und trotzdem den Wert des Timer0 richtig auszulesen. Es ist nämlich nicht möglich dafür das praktische T0IF-Bit zu benutzen. Zwischen der letzten Abfrage des T0IF-Bits und dem Auslesen des Zählers am Ende der Messzeit könnte der Timer0 schon wieder übergelaufen sein. Deshalb wäre das Zählergebnis in Ausnahmefällen um 256 verfälscht. Man greift besser zyklisch auf den Timer0-Wert zu, und beobachtet das Bit 7, um den Überlauf zu erkennen (springt von 1 auf 0) mit dem gelesenen Wert hat man automatisch am Ende der Messzeit die unteren 8 Bit des 24-Bit-Zählwerts verfälschungsfrei.
Berechnung der Frequenz aus dem Zählwert
Zählt man eine Sekunde lang und verwendet man nicht den Vorteiler,
so ist das Zählergebnis gleich der Frequenz. In allen anderen
Fällen
muss man die Frequenz aus dem Zählergebnis berechnen. Dazu
multipliziert
man das Zählergebnis mit dem Vorteilerwert und dividiert es durch
die Messzeit (gemessen in Sekunden). Um den mathematischen Aufwand
in Grenzen zu halten, sollten als Messzeit 1s, 1/2 s, 1/4 s, 1/8
s,
1/16 s, 1/32 s usw. verwendet werden. Dann ist die Division
nämlich
eine Multiplikation mit 1, 2, 4, 8, 16, 32 usw. All dies
lässt
sich durch wiederholte Multiplikation mit 2 erreichen, und diese
Multiplikation
ist lediglich eine Verschiebung der Bits im Zählergebnis um
jeweils
eine Stelle nach links.
Das gleiche gilt für die Multiplikation mit dem Vorteiler (1, 2, 4, 8, 16, 32...) so dass die Frequenzberechnung mit ein paar 'RLF' Befehlen zu erschlagen ist. Dabei kann die Zahl länger als 24 Bit werde, wir gehen deshalb auf 32-Bit über.
Umrechnung der Frequenz in eine Dezimalzahl
Leider ist das Rechenergebnis eine Binärzahl, mit der wir im
täglichen
Leben kaum umgehen können. Deshalb steht nun noch die Umwandlung
in
eine Dezimalzahl an. Das würde man normalerweise durch wiederholte
Division durch 10 erledigen, aber eine vollwertige
32-Bit-Divisionsroutine
wäre ein zu großer Aufwand. Ich zerlege die Zahl durch
Subtraktion
und Division in ihre Zehnerpotenzen.
Ausgabe der Zahl
Das fertige Ergebnis kann man nun mit LCD und LED anzeigen oder z.B.
über RS232 ausgeben. Die Anzeige auf einem intelligenten
LCD-Display
ist vergleichsweise einfach und deshalb zu bevorzugen.
Eine 7-Segment LED macht schon mehr Probleme. Sie müsste 8 Stellen lang sein. Am 16F84 läss sich so eine lange Anzeige nur mit Hilfe eines 'BCD zu 1 aus 8'-Decoders oder eines Schieberegisters (beides für die Selektion der Stelle) ansteuern. Solange die LED-Anzeige leuchtet, kann der PIC keine Frequenz messen. Deshalb muss man kurze Messzeiten verwenden (1/16 s) und anschließend das Ergenis für längere Zeit anzeigen (1/4 s) um das Flackern der Anzeige erträglich zu halten.
Die Ausgabe über RS232 wäre einfach zu realisieren. So könnte man den PC schnell um einen 8 stelligen Frequenzzähler erweitern.
Ich verwende aber ein LCD-Display.
Die zu messende Frequenz wird mit TTL-Pegel an RA4 angelegt.
Vor der eigentlichen Frequenzmessung macht das Programm eine Grobmessung. Mit einem Vorteiler von 256:1, einer Messzeit von 256 Mikrosekunden und einer Genauigkeit von 8 Bit. Damit wird die Eingangsfrequenz in Megaherz bestimmt. Dem Ergebnis entsprechend wird der Vorteiler eingestellt:
Das 24-Bit Zählergebnis wird zunächst mit 2 (1/2 Sekunde Messzeit) und anschließend mit dem Vorteilerwert multipliziert.
Die so erhaltene 32-Bit Frequenz wird in eine 8-stellige Dezimalzahl gewandelt
Die Dezimalzahl wird an das LCD ausgegeben.
Anschließend erfolgt ein neuer Messzyklus.
Die Genauigkeit des Frequenzzählers wird durch den Anzeigefehler (Auflösung der Anzeige) und den Quarzfrequenzfehler bestimmt.
Da der Frequenzzähler nur mit einer Aufösung von 4 Hz anzeigt, ist sein Anzeigefehler bei kleinen Frequenzen groß. Erst ab 400Hz liegt der Anzeigefehler unter 1%. Oberhalb von 100kHz liegt der Anzeigefehler aber unter 0,005% (50ppm), so dass die Messgenauigkeit durch die Genauigkeit des Quarzes begrenzt wird.
Kalibrierung
Ohne Kalibrierung erreicht der Zähler eine Genauigkeit von ca
0,005%. Das entspricht bei einer Eingangsfrequenz von z.B. 20 MHz einem
Fehler von 1 kHz. Die Frequenzabweichungen werden durch eine
Abweichung
der PIC-Takt-Quarzfrequenz (Q1) von den gewünschten 10 MHz
verursacht
(ohne spezielle Maßnahmen ca. 50ppm). Die meisten 10 MHz Quarze
schwingen
etwa 500 Hz zu schnell (meiner Erfahrung nach, Ausnahmen wird es auch
geben),
und müssen mit einem Trimmkondensator abgeglichen ('gezogen')
werden.
Ohne Abgleich wäre der angezeigte Frequenzwert etwa 0,005% zu
klein.
(Das ist kein Pfusch. Vielmehr werden die Quarze für eine
bestimmte
kapazitive Belastung hergestellt.)
Als Trimmkondensator wird ein 30pF-Keramik-Trimmkondensator zwischen
OSC1 und Masse angeschlossen, und auf ca. 20 pF eingestellt (20 pF
'bremsen'
den 10-MHz-Quarz um etwa 600 Hz). Der Frequenzzähler wird nun an
eine
Referenzfrequenzquelle (wenn man denn eine findet) angeschlossen und
durch
Verstellen des Trimm-Kondensators die angezeigte Frequenz der
Referenzfrequenz
angeglichen. Der zulässige Anzeigefehler ist je nach
Messbereich
4 Hz (bei f < 4 MHz) bis 64 Hz (bei f > 32 MHz). Danach sollte
der Messfehler
im gesamten Frequenzbereich auf 0,001% reduziert sein. Höhere
Genauigkeiten
lassen sich nur noch mit einem Termostat erreichen, der den Quarz auf
einer
konstanten Temperatur hält.
Normale Quarze, Quarzoszillatoren, PLL-Tuner u.ä. eignen sich
nicht als Lieferant für eine Referenzfrequenz, da sie zu ungenau
sind!
Wer (wie die Meisten) keine präzise Referenzfrequenz zur Verfügung hat, kann wie hier beschrieben vorgehen. Dazu wird der Frequenzzähler komplett aufgebaut, und von OSC1 nach Masse ein 30-pF-Trimmkondensator angeschlossen. Danach wird die Software aus dem Lernbeispiel LCD-UHR in den PIC gebrannt. Genau zur vollen Stunde (nach der Fernseh-Uhr) wird die Null-Taste an der Uhr gedrückt (also RB1 kurz mit Masse verbunden). Die Uhr startet mit 00:00:00. Nach 24-Stunden wird festgestellt, ob die Uhr mehr als 1 Sekunde vor oder nach geht. Ist dass der Fall, wird der Trimmkondensator verändert, und die Uhr zur vollen Stunde wieder auf 00:00:00 gesetzt. Eine vergrößerte Kapazität bremst eine zu schnell laufende Uhr, eine verkleinerte Kapazität beschleunigt eine zu langsame Uhr. Eine Veränderung des Trimmkondensators um 1 pF bewirkt eine Gangänderung von ca. 0,25 Sekunden pro Tag. Nach einigen Tagen sollte man eine Trimmerstellung gefunden haben, bei der die Uhr genau läuft. Nun wird die Frequenzmesser-Software in den PIC gebrannt: fertig.
Maximalfrequenz
Aufgrund der Datenblätter des PIC16F84 lassen sich keine
verlässlichen
Höchstwerte für die Eingangsfrequenz des Zählers
ermitteln.
Ich habe ihn mit TTL-Signalen von bis zu 50 MHz getestet. Ein Nachbauer
erreichte mit einem geeigneten Vorteiler über 100 MHz,. aber das
ist
die Grenze, da Frequenzen oberhalb 100 MHz im Display nicht mehr als
korrekte
Dezimalzahlen dargestellt werden.
Der PIC verlangt TTL-Impulse.
Ein zusätzlicher
Vorverstärker kann den Frequenzzähler universeller einsetzbar
machen. Die nebenstehende Schaltung entstammt einem konventionellen Zähler von Joachim Münch und benutzt den Videoverstärker NE592. Da dessen Funktion erst ab 6V garantiert ist, benötigt er eine eigene Stromversorgung - in diesem Fall 8V. Der Eingangskondensator begrenzt die minimale Eingangsfrequenz der Schaltung auf etwa 100 kHz. Das ist also ein HF-Frequenzmesser. |
Auch wenn der Zähler nur mit TTL-Impulsen gespeist wird, sollte sein Eingang mit einem Reihenwiderstand und zwei Schutzdioden (gegen +5V und Masse) gegen falsche Eingangspegel geschützt werden |
Ein hochfrequenztauglicher Vorteiler kann den Frequenzbereich
bis über
1GHz erweitern.
Die Software muss natürlich angepasst
werden, und
die Messgenauigkeit verringert sich um den Faktor 64 auf 1 kHz
...2
kHz. |
Hinweis zum LCD-Display
Das Programm wurde für ein 2-zeiliges Display mit 16 Zeichen pro
Zeile geschrieben. Alle Displays mit dem Hitachi-Controllerchip HD44780
funktionieren ähnlich, so dass sich das Programm an andere
Displays
anpassen lässt. Der naheliegende Gedanke, ein 1x16-Display zu
verwenden birgt eine Falle, die aber umgangen werden kann. Die
1x16-Displays
sind eigentlich 2x8-Displays, deren beide Zeilen hintereinander
angeordnet
sind. Deshalb ist ein solches Display als 2-zeilig zu initialisieren.
Nach
der Ausgabe des 8.Zeichens ist ein Befehl einzufügen, der
das
Display veranlasst auf die 2. Zeile überzugehen.
;8 Zeichen fertig
;ACHTUNG
;die folgenden 2 Zeilen nur bei einem
1-Zeiligen
Display 1x16
movlw
B'11000000' ; Sprung zur virtuellen 2.
Zeile
bei 1x16
call
OutLcdControl ; Sprung zur virtuellen 2. Zeile bei
1x16
Wird dies nicht beachtet, dann werden nur die ersten 8 Zeichen im Display dargestellt.
Ein Beispiel für die Nutzung eines 1x16-Displays findet sich im
ASM-Code der
Frequenzanzeige für UKW-Empfänger
.
Ich habe weiter unten den angepassten Assemblercode mit dem passenden
HEX-File schon bereitgestellt.
erstellt: 25.11.2001
letzte Änderung: 24.03.2009