1 | #include <avr/io.h>
|
2 | #include <stdint.h>
|
3 |
|
4 | #ifndef F_CPU
|
5 | /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann
|
6 | F_CPU im Makefile definiert werden, eine nochmalige Definition
|
7 | hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch
|
8 | #ifndef/#endif
|
9 |
|
10 | Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio
|
11 | verwendet wird und dort eine andere, nicht zur Hardware passende
|
12 | Taktrate eingestellt ist: Dann wird die folgende Definition
|
13 | nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?)
|
14 | von AVRStudio - daher Ausgabe einer Warnung falls F_CPU
|
15 | noch nicht definiert: */
|
16 | #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 4000000"
|
17 | #define F_CPU 4000000L // Systemtakt in Hz, das L am Ende ist wichtig, NICHT UL verwenden!
|
18 | #endif
|
19 |
|
20 | #define BAUD 9600L // Baudrate, das L am Ende ist wichtig, NICHT UL verwenden!
|
21 |
|
22 | // Berechnungen
|
23 | #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden
|
24 | #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate
|
25 | #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD-1000) // Fehler in Promille
|
26 |
|
27 | #if ((BAUD_ERROR>10) || (BAUD_ERROR<-10))
|
28 | #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch!
|
29 | #endif
|
30 |
|
31 | uint16_t ReadChannel(uint8_t mux)
|
32 | {
|
33 | uint8_t i;
|
34 | uint16_t result;
|
35 |
|
36 | ADMUX = mux; // Kanal waehlen
|
37 | ADMUX |= (1<<REFS1) | (1<<REFS0); // interne Referenzspannung nutzen
|
38 |
|
39 | ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
|
40 | // setzen auf 8 (1) und ADC aktivieren (1)
|
41 |
|
42 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
43 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
44 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
45 | while ( ADCSRA & (1<<ADSC) ) {
|
46 | ; // auf Abschluss der Konvertierung warten
|
47 | }
|
48 | result = ADCW; // ADCW muss einmal gelesen werden,
|
49 | // sonst wird Ergebnis der nächsten Wandlung
|
50 | // nicht übernommen.
|
51 |
|
52 | /* Eigentliche Messung - Mittelwert aus 4 aufeinanderfolgenden Wandlungen */
|
53 | result = 0;
|
54 | for( i=0; i<4; i++ )
|
55 | {
|
56 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
57 | while ( ADCSRA & (1<<ADSC) ) {
|
58 | ; // auf Abschluss der Konvertierung warten
|
59 | }
|
60 | result += ADCW; // Wandlungsergebnisse aufaddieren
|
61 | }
|
62 | ADCSRA &= ~(1<<ADEN); // ADC deaktivieren (2)
|
63 |
|
64 | result /= 4; // Summe durch vier teilen = arithm. Mittelwert
|
65 |
|
66 | return result;
|
67 | }
|
68 |
|
69 |
|
70 |
|
71 | /* Beispielaufrufe: */
|
72 |
|
73 | void foo(void)
|
74 | {
|
75 | uint16_t adcval;
|
76 | char string[7];
|
77 | adcval = ReadChannel(0); /* MUX-Bits auf 0b0000 -> Channel 0 */
|
78 | itoa(adcval,string,10);
|
79 | // adcval = ReadChannel(1); /* MUX-Bits auf 0b0010 -> Channel 2 */
|
80 | // itoa(adcval,string,10);
|
81 |
|
82 | }
|
83 |
|
84 | void putc(char c)
|
85 | {
|
86 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich
|
87 | */
|
88 | {
|
89 | }
|
90 |
|
91 | UDR = c; /* schreibt das Zeichen x auf die Schnittstelle
|
92 | Schnittstelle */
|
93 | }
|
94 |
|
95 | void puts (char *s)
|
96 | {
|
97 | while (*s)
|
98 | { /* so lange *s != '\0' also ungleich dem "String-Endezeichen" */
|
99 | putc(*s);
|
100 | s++;
|
101 | }
|
102 | }
|
103 |
|
104 | int main(void)
|
105 | {
|
106 |
|
107 |
|
108 | UCSRB |= (1<<TXEN)|(1<<RXEN); // UART TX einschalten
|
109 | UCSRC |= (1<<URSEL)|(3<<UCSZ0); // Asynchron 8N1
|
110 |
|
111 | UBRRH = UBRR_VAL >> 8;
|
112 | UBRRL = UBRR_VAL & 0xFF;
|
113 |
|
114 |
|
115 | puts ( string );
|
116 |
|
117 |
|
118 | return 0;
|
119 |
|
120 | }
|