1 | /*###########################################################################
|
2 | # Spannungsmessung über A/D-Wandlung #
|
3 | # #
|
4 | # Hardware: Controller ATMega16 #
|
5 | # Takt 3,6864MHz #
|
6 | # Baudrate 9600 #
|
7 | # UART an PortD (PIN D0 und D1) #
|
8 | # AGND mit GND verbunden #
|
9 | # AVCC und AREF mit VCC verbunden #
|
10 | # folgender Spannungsteiler an PC05 #
|
11 | # VCC #
|
12 | # | #
|
13 | # R1(Poti) R1=10k #
|
14 | # | --> PA5 #
|
15 | # R2 R2=1k #
|
16 | # | #
|
17 | # GND #
|
18 | # Hyperterminal auf dem PC (Baudrate 9600) #
|
19 | # (ENTER->Start der Messung|andere Taste->Messung stoppen)#
|
20 | # oder das beigefügte Windows-Programm #
|
21 | # #
|
22 | # Funktion: Misst die am Port anliegende Spannnung mit Hilfe des #
|
23 | # eingebautem Analog-Digital-Converters. #
|
24 | # Das Messergebnis wird über das UART weitergemeldet. #
|
25 | # #
|
26 | # WinAVR: gcc version 3.3 20030421 (prerelease) #
|
27 | # #
|
28 | # Autor: Swod #
|
29 | # Kontakt: Swod@thelastinstance.de http://www.thelastinstance.de #
|
30 | # #
|
31 | ###########################################################################*/
|
32 |
|
33 | #include <avr/io.h>
|
34 | #include <avr/interrupt.h>
|
35 | #include <avr/signal.h>
|
36 | #include <inttypes.h>
|
37 | #include <stdlib.h>
|
38 | // #include <delay.h>
|
39 |
|
40 | #define CLK 3686400
|
41 | #define BAUD 9600
|
42 | #define USARTSPEED (CLK/(BAUD*16L)-1) // Formel zur Berechnung der Werte für UBBRH/UBBRL
|
43 | #define LOW(x) ((x) & 0xFF) // Makro zum Lowbyte Zugriff eines Word
|
44 | #define HIGH(x) (((x) >> 8) & 0xFF) // Makro zum Highbyte Zugriff eines Word
|
45 |
|
46 | div_t dividend;
|
47 | volatile uint8_t zeichen; //definiere zeichen als unsigned integer 8bit
|
48 | volatile uint8_t lowByte; //definiere lowByte als unsigned integer 8bit
|
49 | volatile uint8_t highByte; //definiere highByte als unsigned integer 8bit
|
50 | volatile uint16_t ergebnis; //definiere ergebnis als unsigned integer 16Bit
|
51 |
|
52 | SIGNAL (SIG_UART_RECV) //Uart Receive Interrupt wurde ausgelöst
|
53 | {
|
54 | zeichen = UDR; //den empfangenen Wert nach temp holen
|
55 | }
|
56 |
|
57 | void UART_SendByte(uint8_t data) //sendet ein Byte über das Uart
|
58 | {
|
59 | while(bit_is_clear(UCSRA, UDRE)); //warten bis UART bereit ist zum senden
|
60 | UDR = data; //data ausgeben
|
61 | }
|
62 |
|
63 | //sendet einen String über das Uart
|
64 | void putstring(char *s) //setze den Pointer s an den Anfang des übergebenen chararrays
|
65 | {
|
66 | while (*s != 0) //ist der Pointer des Zeichens=0 dann chararray zu Ende
|
67 | {
|
68 | UART_SendByte(*s); //übergibt das Zeichen an UART_SendByte
|
69 | *s++; //zeigt auf das nächste Zeichen
|
70 | }
|
71 | }
|
72 |
|
73 | //initialisieren des UART
|
74 | void uartinit (void)
|
75 | {
|
76 | UBRRH = HIGH(USARTSPEED); //Baudrate einstellen
|
77 | UBRRL = LOW(USARTSPEED); //Baudrate einstellen
|
78 | UCSRB = _BV(TXEN) | _BV(RXEN) | _BV(RXCIE); //senden, empfangen, receiveint aktivieren
|
79 | UCSRC = (1<<URSEL)|(3<<UCSZ0); //Frame Format setzen:8data, 1stop bit (URSEL=1 -> UCSRC->Settings werden genutzt)
|
80 | }
|
81 |
|
82 | //initialisieren der I/O-schnittstellen
|
83 | void ioinit (void)
|
84 | {
|
85 | DDRD = 0xFF; //PortD als Ausgang konfigurieren
|
86 | PORTD = 0xFF; //Alle Ausgänge abschalten
|
87 | }
|
88 |
|
89 | //initialisieren des Analog-Digital-Converters
|
90 | void adcinit (void)
|
91 | {
|
92 | ADMUX = 0x05; //Spannungsmessung an PA5
|
93 | ADCSRA = (_BV(ADEN) | _BV(ADSC) | _BV(ADATE)) +7; //ADC Enable|ADC Start Conversion|ADC Free Run Select + Vorteiler 128
|
94 | }
|
95 |
|
96 | void ausgabe (void)
|
97 | {
|
98 | dividend = div(ergebnis, 20.46); //Messergebnis durch 20,46 teilen (max.Darstellungswert 10 Bit/Anzahl der gewünschten Einheiten=> 1023/50)
|
99 | dividend = div(dividend.quot, 10); //nochmalige Teilung durch 10 um im Ergebnis als Rest nur noch eine Ziffer zu haben
|
100 |
|
101 | switch (dividend.quot) //Überprüfen des Divisionsergebnisses
|
102 | {
|
103 | case 0 : putstring("0."); //gemessene Einerstelle ist 0
|
104 | break;
|
105 | case 1 : putstring("1."); //gemessene Einerstelle ist 1
|
106 | break;
|
107 | case 2 : putstring("2."); //gemessene Einerstelle ist 2
|
108 | break;
|
109 | case 3 : putstring("3."); //gemessene Einerstelle ist 3
|
110 | break;
|
111 | case 4 : putstring("4."); //gemessene Einerstelle ist 4
|
112 | break;
|
113 | case 5 : putstring("5."); //gemessene Einerstelle ist 5
|
114 | break;
|
115 | default: putstring("Error");
|
116 | break;
|
117 | }
|
118 |
|
119 | switch (dividend.rem) //Überprüfen des Restes der Division
|
120 | {
|
121 | case 0 : putstring("0"); //gemessene Zehntelstelle ist 0
|
122 | break;
|
123 | case 1 : putstring("1"); //gemessene Zehntelstelle ist 1
|
124 | break;
|
125 | case 2 : putstring("2"); //gemessene Zehntelstelle ist 2
|
126 | break;
|
127 | case 3 : putstring("3"); //gemessene Zehntelstelle ist 3
|
128 | break;
|
129 | case 4 : putstring("4"); //gemessene Zehntelstelle ist 4
|
130 | break;
|
131 | case 5 : putstring("5"); //gemessene Zehntelstelle ist 5
|
132 | break;
|
133 | case 6 : putstring("6"); //gemessene Zehntelstelle ist 6
|
134 | break;
|
135 | case 7 : putstring("7"); //gemessene Zehntelstelle ist 7
|
136 | break;
|
137 | case 8 : putstring("8"); //gemessene Zehntelstelle ist 8
|
138 | break;
|
139 | case 9 : putstring("9"); //gemessene Zehntelstelle ist 9
|
140 | break;
|
141 | default: putstring("Error");
|
142 | break;
|
143 | }
|
144 |
|
145 | putstring("V\n\r"); //Anhängen der Einheit und des LF CR an das gesendete Messergebnis
|
146 | }
|
147 |
|
148 | void messung (void)
|
149 | {
|
150 | while(zeichen == 0x0D)
|
151 | {
|
152 | sbi (ADCSR, ADIF); //ADIF-Bit Setzen(Messzyklus starten)
|
153 | loop_until_bit_is_clear(ADCSR, ADIF); //ersten Messwert verwerfen
|
154 | sbi (ADCSR, ADIF); //ADIF-Bit Setzen(Messzyklus starten)
|
155 | loop_until_bit_is_clear(ADCSR, ADIF); //warten bis Messung fertig
|
156 | lowByte = ADCL; //immer zuerst das LowByte auslesen
|
157 | highByte = ADCH; //dann das mittlerweile gesperrte HighByte auslesen
|
158 | ergebnis = highByte * 256 + lowByte; //Zusammenführung von HighByte und LowByte zu einem Messwert
|
159 |
|
160 | ausgabe();
|
161 | }
|
162 | }
|
163 |
|
164 | int main(void)
|
165 | {
|
166 | ioinit(); //I/O-Schnittstellen initialisieren
|
167 | uartinit(); //I/Os einrichten
|
168 | adcinit(); //ADC initialisieren mit "Free Run" und Vorteiler 128
|
169 | sei (); //enable globale interrupts
|
170 |
|
171 | putstring("Enter druecken\n"); //zum testen Hello World ausgeben
|
172 |
|
173 | for(;;) //Loop forever
|
174 | {
|
175 | if(zeichen==0x0D) //Solange das letzte empfangene Zeichen ein ENTER war
|
176 | {
|
177 | messung(); //wird die Messung durchgeführt
|
178 | }
|
179 | }
|
180 | }
|