1 | /*********************************************************************
|
2 |
|
3 | Frequenzzähler (Berich: 1Hz bis etwa theor. 8MHz). Mit Vorteiler
|
4 | einfach erweiterbar für höhere Messfrequenzen
|
5 |
|
6 | Dieses Programm stellt die am T0 Eingang (PD4) eines Atmega8 (16Mhz)
|
7 | anliegende Frequenz (TTL Pegel Rechteck) auf einem LCD Hz-genau dar.
|
8 | Weiterhin gibt es die Möglichkeit eines Abgleiches der Frequenz
|
9 | mittels Korrekturfaktor bei Bedarf wegen der unvermeidlichen
|
10 | "Quarz-Schwingfrequenzabweichung"). Die Abweichungen sind
|
11 | ohne Abgleich innerhalb 0,03% Bereich (linear) bei annähernd konstanter
|
12 | Raumtemperatur. Für normale Zwecke völlig ausreichend.
|
13 |
|
14 | Zum Abgleich wird die Variable "korrekturfaktor" anpasst. d.h. es wird
|
15 | eine bekannte, stabile Frequenz (Rechteck, TTL - sollte mindestens
|
16 | 10Khz, besser 1Mhz sein) angelegt und der angezeite Wert ermittelt.
|
17 | Anschließend wird der wahre Wert durch den angezeigten Wert geteilt
|
18 | und sinnvoll auf 5 oder 6 Stellen nach dem Komma gerundent. z.b.
|
19 |
|
20 | 100000Hz/100026Hz=0.99974
|
21 |
|
22 | Dieser Wert wird dann der Variable "korrekturfaktor" zugeteilt.
|
23 | Genauigkeit nach Abgleich 1Hz genau. Zumindestens bei meinen
|
24 | Referenzmessungen. Viel Spass damit!
|
25 |
|
26 | Swen
|
27 |
|
28 | *********************************************************************/
|
29 |
|
30 | #include <avr/io.h>
|
31 | #include <avr/interrupt.h>
|
32 | #include "avr/interrupt.h"
|
33 |
|
34 | #define F_CPU 8000000
|
35 | #define USART_BAUDRATE 9600
|
36 | //#define BAUD 9600
|
37 | //#define BAUD 76800
|
38 | //#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)
|
39 | #define BAUD_PRESCALE ((uint16_t) ((F_CPU / ((USART_BAUDRATE) * 16.0)) + .5) - 1)
|
40 |
|
41 |
|
42 |
|
43 | int count = 0, a = 0;
|
44 | float korrekturfaktor = 1; //hier anpassen für Abgleich (z.b 0.99974)
|
45 | int ztmp = 0;
|
46 | unsigned long freq = 0;
|
47 | char anz[20];
|
48 | volatile int s=0;
|
49 | volatile unsigned short z=0;
|
50 |
|
51 |
|
52 |
|
53 | /*********************************
|
54 | Timer 0 und 2 Interruptroutinen
|
55 | **********************************/
|
56 |
|
57 | ISR(TIMER2_COMPA_vect) // Löst aus alle (16Mhz/1024/125) 8ms
|
58 | {
|
59 | s++;
|
60 | }
|
61 |
|
62 | ISR(TIMER0_OVF_vect) // Eingangsignal Overflow Zähler Timer 0
|
63 | {
|
64 | z++;
|
65 | TIFR0 = (1<<TOV0); //ov flag timer 0 zurücksetzen
|
66 | }
|
67 |
|
68 | /*************************
|
69 | Hauptfunktion
|
70 | **************************/
|
71 |
|
72 |
|
73 |
|
74 | int main(){
|
75 |
|
76 | //UCSR0B = (1 << RXEN0) | (1 << TXEN0); // Turn on the transmission and reception circuitry
|
77 | UCSR0B = (1 << TXEN0); // Turn on the transmission circuitry
|
78 |
|
79 | //UCSR0C = (1 << URSEL) | (1 << UCSZ0) | (1 << UCSZ1); // Use 8-bit character sizes
|
80 | UCSR0C = (1 << UCSZ01) | (1 << UCSZ00); // Use 8-bit character sizes
|
81 |
|
82 | UBRR0H = (BAUD_PRESCALE >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
|
83 | UBRR0L = BAUD_PRESCALE; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register
|
84 |
|
85 |
|
86 |
|
87 | TCCR2A |= (1<<WGM21); // CTC Mode Aktivierung Timer2
|
88 | TCCR2A |= (1<<COM2A0) | (1<<COM2A1); // set OCR Flag bei "Compare Match"
|
89 | TCCR0B |= (1<<CS02) | (1<<CS01) | (1<<CS00); // Ext Flanke Interrupt (T0)
|
90 | TCCR2B |= (1<<CS22) | (1<<CS21) | (1<<CS20); // Prescaler Timer2 auf 1024 setzen
|
91 | OCR2A |= 124; // Output Compare register Timer2 auf 124 (für Loop 0-124 => 125)
|
92 | TIMSK2 |= (1<<OCIE2A); // Enable comp match flag interrupt Timer 2
|
93 | TIMSK2 |= (1<<TOIE0); // Enable overflow flag interrupt Timer 0
|
94 |
|
95 | sei();
|
96 |
|
97 | char ReceivedByte;
|
98 |
|
99 | while(1)
|
100 | {
|
101 |
|
102 |
|
103 | if (s==125){ // "Zähltor": Abarbeitung jede Sekunde (16MHz/1024/125/125)
|
104 | count = TCNT0;
|
105 | s=0;
|
106 | ztmp = z;
|
107 | z= 0;
|
108 | TCNT0 = 0;
|
109 | freq = 0.5+((256UL*ztmp + count)*korrekturfaktor); //siehe Bemerkung unten
|
110 |
|
111 | // notwendig wenn RX nicht aktiviert ist?
|
112 | //while ((UCSR0A & (1 << RXC0)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
|
113 | //ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
|
114 |
|
115 | // zum testen a zurück senden
|
116 | while ((UCSR0A & (1 << UDRE0)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
|
117 | UDR0 = 'a'; // Echo back the received byte back to the computer
|
118 |
|
119 | }
|
120 | /*********************************************************************************
|
121 | - freq: Ermittlung der Frequenz: Anzahl Timer 0 Overflows + aktuellen Timer 0 Count
|
122 | - die + 0,5 sind zum korrektem "Runden" ->Fließkommazahl zu Ganzzahl
|
123 | - "korrekturfaktor" ist die SW-Korrektur zur Kompensation der lin.Quarzungenauigkeit
|
124 | **********************************************************************************/
|
125 |
|
126 | }
|
127 | }
|