1 | #include <avr/io.h>
|
2 | #ifndef F_CPU
|
3 | #warning "F_CPU war noch nicht definiert, wird nun mit 8 MHZ definiert"
|
4 | #define F_CPU 8000000UL /* Quarz mit 8 Mhz */
|
5 | #endif
|
6 | #include <util/delay.h>
|
7 | #include <avr/interrupt.h> // fuer Interrupts
|
8 |
|
9 |
|
10 | // Potis: ADC0, ADC1 = PA0, PA1
|
11 | // Poti-Wechseltaster: INT0 = PD2
|
12 | // Potis ein/aus: INT1 = PD3
|
13 | // Taster aktive high: Pin mit GND verbinden
|
14 | // PWM: OC1A = PD5
|
15 | // LEDs fuer Potis: PC0, PC1
|
16 | // LEDs fuer Poti an/aus: an, gruen, PA5
|
17 | // aus, rot, PA6
|
18 |
|
19 |
|
20 | extern volatile uint8_t triggerflag_poti = 0;
|
21 | extern volatile uint8_t triggerflag_adjustmode = 0;
|
22 | extern volatile uint8_t timefactor = 100;
|
23 |
|
24 |
|
25 | // Interrupt-Routine fuer Channelwechsel ADC
|
26 | ISR( INT0_vect )
|
27 | {
|
28 | if (triggerflag_poti == 0) triggerflag_poti = 1;
|
29 | else if (triggerflag_poti == 1) triggerflag_poti = 0;
|
30 | }
|
31 |
|
32 | // Interrupt-Routine fuer Poti-Einstellen ein/aus
|
33 | ISR( INT1_vect )
|
34 | {
|
35 | if (triggerflag_adjustmode == 0) triggerflag_adjustmode = 1;
|
36 | else if (triggerflag_adjustmode == 1) triggerflag_adjustmode = 0;
|
37 | }
|
38 |
|
39 |
|
40 | // delay-funktion
|
41 | void mydelay(int t);
|
42 |
|
43 |
|
44 | // ADC Wert holen
|
45 | uint16_t get_ADC(uint8_t channel);
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 | int main( void )
|
53 | {
|
54 |
|
55 | // INTERRUPTS
|
56 |
|
57 | // INT0 und INT1 akivieren, triggern bei fallender Flanke
|
58 | EIMSK |= ( 1<<INT0 ) | (1 << INT1 ); // triggern bei Flankenerkennung
|
59 | EICRA |= ( 1<<ISC01 ) | ( 0<<ISC00 ) | ( 1<<ISC11 ) | ( 0<<ISC10 ); // triggern bei fallender Flanke
|
60 |
|
61 | DDRD &= ~( 1<<PD2 ); // PD2 an PORTD als Eingang setzen // INT0 interrupt Vektor
|
62 | DDRD &= ~( 1<<PD3 ); // PD3 an PORTD als Eingang setzen // INT1 interrupt Vektor
|
63 | PORTD |= ( 1<<PD2 ); // Pullups setzen // interne
|
64 | PORTD |= ( 1<<PD3 ); // Pullups setzen // interne
|
65 |
|
66 |
|
67 | // OC1A auf Ausgang
|
68 | DDRD = ( 1<<PD5 ); // PD5 an PORTD als Ausgang setzen
|
69 |
|
70 | // LED-Pins auf Ausgang:
|
71 | DDRC = ( 1<<PC0 ) | ( 1<<PC1 ); // PC0 und PC1 fuer Poti LEDs
|
72 | DDRA = ( 1<<PA5 ) | ( 1<<PA4 ); // PA4 und PA5 fuer LED Potis an/aus
|
73 |
|
74 |
|
75 |
|
76 | // Timer 1 einstellen
|
77 | //
|
78 | // Modus 14:
|
79 | // Fast PWM, Top von ICR1
|
80 | //
|
81 | // WGM13 WGM12 WGM11 WGM10
|
82 | // 1 1 1 0
|
83 | //
|
84 | // Timer Vorteiler:
|
85 | // CS12 CS11 CS10
|
86 | // 0 0 1
|
87 | //
|
88 | // Steuerung des Ausgangsport: Set at BOTTOM, Clear at match
|
89 | // COM1A1 COM1A0
|
90 | // 1 0
|
91 |
|
92 | TCCR1A = ( 1<<COM1A1 ) | ( 1<<WGM11 )| ( 0<<WGM10 );
|
93 | TCCR1B = ( 1<<WGM13 ) | ( 1<<WGM12 ) | ( 1<<CS10 ) ;
|
94 |
|
95 |
|
96 |
|
97 |
|
98 | // ADC einstellen
|
99 |
|
100 | ADMUX = ( 1<<REFS0 ); // ADC Referenz Vcc an AVCC
|
101 | ADMUX = ( 0<<ADLAR ); // Ergebnis rechtsbuendig
|
102 | ADCSRA = ( 1<<ADPS2 ) | ( 1<<ADPS1 ); // Prescaler 64 --> 125 kHz ADC Takt
|
103 | ADCSRA = ( 1<<ADEN ); // ADC aktivieren
|
104 |
|
105 |
|
106 | // TOP-Wert
|
107 | ICR1 = 0xc300; // Initialisierung: 50000 => 5 ms Impuls
|
108 |
|
109 |
|
110 | // Compare-Wert
|
111 | OCR1A = 0xbb8;
|
112 |
|
113 | sei(); // interrupts aktivieren
|
114 |
|
115 |
|
116 | while (1)
|
117 | {
|
118 | // falls Poti-Einstellen erlaubt
|
119 | if (triggerflag_adjustmode == 1)
|
120 | {
|
121 |
|
122 | // gruene LED am Taster an (rote aus)
|
123 | PORTA |= ( 1<<PA5 ); // gruen an
|
124 | PORTA &= ~( 1<<PA4 ); // rot aus
|
125 |
|
126 |
|
127 | // Zeitlupe -> Poti 0
|
128 | if (triggerflag_poti == 0) // falls Poti 0 zugeschaltet
|
129 | {
|
130 | // LED fuer Poti 0 an, Poti 1 aus
|
131 | PORTC |= ( 1<<PC1 );
|
132 | PORTC &= ~( 1<<PC0 );
|
133 |
|
134 | uint16_t ADCvalue0;
|
135 | ADCvalue0 = get_ADC(triggerflag_poti); // channel ADC0
|
136 |
|
137 | ICR1 += (500 - ADCvalue0)*timefactor; // TOP-Wert aus ADC Messung berechnen
|
138 |
|
139 | }
|
140 |
|
141 | // Hoch-Tief -> Poti 1
|
142 | if (triggerflag_poti == 1) // falls Poti 1 zugeschaltet
|
143 | {
|
144 |
|
145 | // LED fuer Poti 1 an, Poti 0 aus
|
146 | PORTC |= ( 1<<PC0 );
|
147 | PORTC &= ~( 1<<PC1 );
|
148 |
|
149 | // Werte messen und voneinander abziehen
|
150 | uint16_t ADCvalue1;
|
151 | ADCvalue1 = get_ADC(triggerflag_poti); // channel ADC1, ersten Wert einlesen
|
152 |
|
153 | uint16_t ADCvalue2;
|
154 | ADCvalue2 = get_ADC(triggerflag_poti); // zweiten Wert einlesen
|
155 |
|
156 | // hoch oder tief
|
157 | if ( (ADCvalue1-ADCvalue2) > 10 ) // falls aelterer Wert groesser
|
158 | {
|
159 | mydelay ( (ADCvalue1-ADCvalue2)/10 ); // Unterschied durch 10 in ms
|
160 | }
|
161 | if ( (ADCvalue2-ADCvalue1) > 10 ) // falls neuer Wert groesser
|
162 | {
|
163 | mydelay (ADCvalue2-ADCvalue1); // Unterschied in ms
|
164 | }
|
165 |
|
166 | }
|
167 | }
|
168 | return 0;
|
169 | }
|
170 |
|
171 |
|
172 |
|
173 |
|
174 | // Funktion ADC Wert holen mit Mittelwert
|
175 | uint16_t get_ADC(uint8_t channel)
|
176 | {
|
177 | //Zwischenspeicher
|
178 | uint16_t buffer;
|
179 | uint8_t i;
|
180 |
|
181 | buffer = 0;
|
182 |
|
183 | //ADC Kanal wählen
|
184 | ADMUX=(ADMUX &~(0x1F)) | (channel & 0x1F);
|
185 |
|
186 | //4 Messungen mit Mittelwertbildung
|
187 | for (i=0; i<4; i++)
|
188 | {
|
189 | ADCSRA = ( 1<<ADSC ); // Messung starten
|
190 | // while(ADCSRA & (1 << ADSC)); // wofuer?
|
191 | buffer += ADCL; // erst low, dann high lesen und addieren
|
192 | buffer += (ADCH << 8);
|
193 | }
|
194 | //buffer durch 4 teilen und zurückgeben
|
195 | return(buffer/4);
|
196 |
|
197 | }
|
198 |
|
199 |
|
200 |
|
201 |
|
202 | // delay-funktion
|
203 | void mydelay(int t)
|
204 | {
|
205 | int i;
|
206 | for( i = 0; i <= t; i++ )
|
207 | {
|
208 | _delay_ms(1);
|
209 | }
|
210 | }
|