Software-Lösung

Wie schon im vorhergehenden Abschnitt beschrieben wird der PIC16F630 mit internem Oszillator auf 4MHz betrieben. Brown-Out und Watchdog sind abgeschaltet. RA3 und RA5 sind logische Ports, wobei Port RA3 nur als Eingang genutzt werden kann. Port RA2 ist als externer Interrupt-Eingang mit steigender Flanke programmiert. Alle anderen Ports sind Ausgänge.

 

Es gibt eine Grundschleife und 3 Interrupt-Tasks die der Prozessor abarbeiten muss:

  • Der interne Timer0 erzeugt aller 0,5ms einen Interrupt. In dieser Serviceroutine wird der Zeitgeber neu justiert und Port RA3 abgefragt. Bei einem Pegelwechsel von Low auf High wird ein Zähler "VMeasure" erhöht, dessen Zählwert später in der Anzeigeroutine übernommen wird. Weiterhin wird ein Zähler "DisplayCnt" heruntergezählt, der den Anzeige-Refresh steuert. Dieser Zähler dividiert das 2KHz-Signal durch 16, so dass eine Wiederholfrequenz von 125Hz erreicht wird.
  • Port RA2 'lauscht' am DCC-Signal und erzeugt bei einer Low-High Flanke ein Interrupt. Innerhalb dieses Interrupts wird Timer1 gestartet, mit dem Ziel nach etwa 75µs einen eigenen Interrupt auszulösen. Da das DCC-Signal für eine "1" 56µs und für eine "0" 112µs lang ist, erfolgt idealer Weise die Abtastung des DCC-Signals in der Mitte des 2. "1"- Pulses, also bei 87µs. Die 75µs ergeben sich aus der Verzögerung durch noch auszuführende Befehle, die jeweils selbst eine Länge von 1µs haben, um den Zeitpunkt möglichst exakt zu treffen.
  • In der Serviceroutine von Timer1 wird eine Änderung des Pegels an RA2 gegenüber der Startbedingung getestet. Wenn sich der Pegel geändert hat, wurde eine "1" übertragen, wenn nicht, eine "0". Die Einsen werden nun gezählt und bei Erreichen von 21 Einsen am Stück liegt ein Servicebefehl vor worauf das Service-Flag gesetzt wird. Eine "0" setzt den Zähler "DCCCount" wieder auf 0.
  • Wenn keine Serviceroutinen abgearbeitet werden, befindet sich das Programm in der Grundschleife. Der Anzeige-Refresh wird hier durchgeführt, wenn "DisplayCnt" 0 erreicht hat. DisplayCnt" erhält nun wieder den Startwert 16. Beim Auffrischen der Anzeige wird der Einer, Zehner oder Hunderter den Segmenten der aktuellen Anzeigespalte zugeordnet und die Spalte über RB0,1 oder 2 = High aktiviert. Ein weiterer Zähler "MeasureCnt" wird nun noch heruntergezählt der bei 0 die Berechnung des Messsignals auslöst. Der Wert von "MeasureCnt" von 212 ergibt sich aus dem Umfang des Messrades in mm

    Umfang (mm) * 3600s * 160 * 125Hz =
    1000000mm *4 *2

    23,5619mm * 3600s * 160 * 125Hz = 212
    10000000mm * 4 * 2

    wobei 3600s eine Stunde sind, 160 der Massstab und 125Hz die Basisfrequenz aus der Widerholfrequenz der Anzeige. Weiterhin ergeben 1000000mm einen KM und es werden 4 Pulse pro Umdrehung abgegeben, der Zeitraum der Messung soll über 2 Umdrehungen laufen. Alles zusammen ergibt es eine Messzeit von ~1,69s was einem Zählwert von 212 entspricht.

    Nach diesem nun ermittelten Zeitraum von 1,69s erfolgt die Auswertung des Messzählers einfach in der Art, dass der Wert mit 2 multipliziert der modellmässigen Geschwindigkeit in Km/h entspricht, so dass dieser Wert nur noch in Einer, Zehner und Hunderter zerlegt werden muss. Bei dieser Zelegung wird gleich für die Vornullenunterdrückung ein Flag gesetzt, welches ein Dunkeltasten der Spalte bewirkt.

    Wurde das Service-Flag gesetzt, erfolgt die Dunkeltastung aller Spalten mit dem gleichen Mechanismus für den Zeitraum von 2 Messzyklen. Das Serviceflag kann natürlich von der Serviceroutine retriggert werden, so dass sich die Dunkeltastzeit entsprechend verlängert.


    Beim Einschalten der Schaltung wird der Lampentest gestartet und für 2 Messzyklen in gleicher Art wie die Dunkeltastung durchgeführt.

 

Die zugehörige .hex-Datei gibt es im Download-Bereich, ebenso für registrierte Benutzer die Quelldateien für STM's MPLAB. Die Hex-Datei enthält im Übrigen auch die Einstellungen der Fuses, mit einem PIC-Brenner z.B. Sprut's USB-Programmer8 kann das Programm komfortabel auf den PIC übertragen werden.