1 | #define F_CPU 20000000
|
2 |
|
3 | #include <avr/io.h>
|
4 | #include <util/delay.h>
|
5 | #include <stdio.h>
|
6 | #include <avr/interrupt.h>
|
7 | #include "lcd-routines-SPI_20MHz.h"
|
8 |
|
9 | // Diese Beispiel zeigt die Anwendung des ADC eines ATmega169
|
10 | // unter Verwendung der internen Referenzspannung von nominell 1,1V.
|
11 | // Zur Anpassung an andere AVR und/oder andere Referenzspannungen
|
12 | // siehe Erläuterungen in diesem Tutorial und im Datenblatt
|
13 |
|
14 | /* ADC initialisieren */
|
15 | void ADC_Init(void);
|
16 |
|
17 | /* ADC Einzelmessung */
|
18 | uint16_t ADC_Read( uint8_t channel );
|
19 |
|
20 | /* ADC Mehrfachmessung mit Mittelwertbbildung */
|
21 | /* beachte: Wertebereich der Summenvariablen */
|
22 | uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples );
|
23 |
|
24 | /* Beispielaufrufe: */
|
25 |
|
26 | int main( void )
|
27 | {
|
28 | DDRB = 0xFC;
|
29 | PORTB |= (1<<PORTB2);
|
30 |
|
31 | uint16_t adcval;
|
32 | char Buffer[20];
|
33 | ADC_Init();
|
34 |
|
35 |
|
36 |
|
37 | spi_LCD_init();
|
38 | lcd_init();
|
39 |
|
40 | while( 1 ) {
|
41 | adcval = ADC_Read(0); // Kanal 0
|
42 | // mach was mit adcval
|
43 |
|
44 | //adcval = ADC_Read_Avg(0, 8); // Kanal 2, Mittelwert aus 4 Messungen
|
45 | // mach was mit adcval
|
46 |
|
47 | lcd_setcursor(0,1);
|
48 | sprintf(Buffer, "%d ", adcval);
|
49 | lcd_string(Buffer);
|
50 | }
|
51 | }
|
52 |
|
53 | /* ADC initialisieren */
|
54 | void ADC_Init(void) {
|
55 |
|
56 | // die Versorgungsspannung AVcc als Refernz wählen:
|
57 | ADMUX = (1<<REFS0);
|
58 | // oder interne Referenzspannung als Referenz für den ADC wählen:
|
59 | // ADMUX = (1<<REFS1) | (1<<REFS0);
|
60 |
|
61 | // Bit ADFR ("free running") in ADCSRA steht beim Einschalten
|
62 | // schon auf 0, also single conversion
|
63 | ADCSRA = (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0); // Frequenzvorteiler
|
64 | ADCSRA |= (1<<ADEN); // ADC aktivieren
|
65 |
|
66 | /* nach Aktivieren des ADC wird ein "Dummy-Readout" empfohlen, man liest
|
67 | also einen Wert und verwirft diesen, um den ADC "warmlaufen zu lassen" */
|
68 |
|
69 | ADCSRA |= (1<<ADSC); // eine ADC-Wandlung
|
70 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten
|
71 | }
|
72 | /* ADCW muss einmal gelesen werden, sonst wird Ergebnis der nächsten
|
73 | Wandlung nicht übernommen. */
|
74 | (void) ADCW;
|
75 | }
|
76 |
|
77 | /* ADC Einzelmessung */
|
78 | uint16_t ADC_Read( uint8_t channel )
|
79 | {
|
80 | // Kanal waehlen, ohne andere Bits zu beeinflußen
|
81 | ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
|
82 | _delay_ms(1);
|
83 | ADCSRA |= (1<<ADSC); // eine Wandlung "single conversion"
|
84 | while (ADCSRA & (1<<ADSC) ) { // auf Abschluss der Konvertierung warten
|
85 | }
|
86 | return ADCW; // ADC auslesen und zurückgeben
|
87 | }
|
88 |
|
89 | /* ADC Mehrfachmessung mit Mittelwertbbildung */
|
90 | /* beachte: Wertebereich der Summenvariablen */
|
91 | uint16_t ADC_Read_Avg( uint8_t channel, uint8_t nsamples )
|
92 | {
|
93 | uint32_t sum = 0;
|
94 |
|
95 | for (uint8_t i = 0; i < nsamples; ++i ) {
|
96 | sum += ADC_Read( channel );
|
97 | }
|
98 |
|
99 | return (uint16_t)( sum / nsamples );
|
100 | }
|