Hallo allerseits, Ich habe einen ATmega328p - pu und an den ADC 5 ein Potentiometer geschlossen. An einem weiteren Pin habe ich eine LED gehängt, die immer dann genau ein mal blinkt, sobald ich die ISR des AD´s betrete (ADC_vect). Was ich komisch finde, ist ,dass sobald ich den ADC5 mit einem Jumper-Kabel mit einem konstanten Potential verbinde (z.b. +5V) (oder GND), dass bei mir die LED durchblinkt....das heißt, dass ich dauernd von neuem in die ISR hineinspringe, obwohl der AD-Eingang auf einem konstanten Level ist. Hab ich mich bis jetzt immer getäuscht, oder wurde nicht behauptet, dass nur dann in die (AD)-ISR hineingesprungen wird, wenn eine Änderung am AD-Eingang vorliegt ? Bei mir scheint dauernd hineingesprungen zu werden....außer ich lasse den AD-Eingang ohne Anschluss, also das Kabel in der Luft hängen. Oder kann es nur sein, dass meine Spannungsversorgung vom µC (USB) immer etwas schwankt, und der so leichte Änderungen merkt ? Danke für die Hilfe, mfg Felix
Hallo, also dies "ich dauernd von neuem in die ISR hineinspringe" bezweifele ich. Dafür sind wir Menschen viel zu groß. :; Es liegt an deinem Programm... Wenn der ADC mit einem passenden Prescaler und der ADC Interrupt richt eingerichtet wurde, dann wird nach ein pass µs immer der ADC Interrupt Vektor angesprungen. Dort muss man des ADC-Wert ADCW auch lesen. Startest Du dort die ADC - Wandlung neu ?
Hi, Ach ja behaupten muss man nichts ! Denn es gibt Datenblätter zu deinem AVR µC und Application Notes von Atmel zu unterschiedlichen Fragestellungen. Diese sind deine Bibel - oder auch Wissensbasis - ohne Diese man so einen AVR µC eigentlich nicht nutzen kann.
Der Interrupt schimpft sich "ADC Conversion Complete" sobald die Wandlung abgeschlossen ist wird dieser angesprungen.
Hier mein Code: #define F_CPU 8000000UL #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> //Nur zu Testzwecken void ADC_init(void); volatile int farbwert=0; int main(void) { DDRD |= (1<<PD3); PORTD |= (1<<PD3); //Hier hängt die LED, ADC_init(); sei(); while (1); } ISR(ADC_vect) { farbwert = ADCH; PORTD ^= (1<<PD3); //Hier soll sich der Status der LED ändern....hier blinkt es aber dauernd, obwohl ich nicht am POTI drehe.... ??? warum ??? _delay_ms(100); //Ich weiß, Delay in ISR = Katastrophe....ist aber nur zu Testzwecken } void ADC_init(void) { ADMUX |= (1<<REFS0)|(1<<MUX2)|(1<<MUX0)|(1<<ADLAR); //Referenzspannung intern 5V, ADC5, Nur 8 bit Result ADCSRA |= (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADIE)|(1<<ADATE)|(1<<ADSC); //Enable, Prescaller von 8, Interrupt Enable, Left-Adjust für 8 bit, Start Conversion //Per Default befindet sich der ADC im FreeRunningMode, d.h. er Triggert automatisch bei Änderung }
Sorry, hatte vergessen, den Code mit Formatvorlagen zu bearbeiten ^^
1 | Hier mein Code: |
2 | |
3 | #define F_CPU 8000000UL
|
4 | #include <avr/io.h> |
5 | #include <avr/interrupt.h> |
6 | #include <util/delay.h> //Nur zu Testzwecken |
7 | |
8 | void ADC_init(void); |
9 | |
10 | volatile int farbwert=0; |
11 | |
12 | int main(void) |
13 | {
|
14 | |
15 | DDRD |= (1<<PD3); |
16 | PORTD |= (1<<PD3); //Hier hängt die LED, |
17 | |
18 | |
19 | ADC_init(); |
20 | sei(); |
21 | |
22 | while (1); |
23 | }
|
24 | |
25 | ISR(ADC_vect) |
26 | {
|
27 | farbwert = ADCH; |
28 | |
29 | PORTD ^= (1<<PD3); //Hier soll sich der Status der LED ändern....hier blinkt es aber dauernd, obwohl ich nicht am POTI drehe.... ??? warum ??? |
30 | |
31 | _delay_ms(100); //Ich weiß, Delay in ISR = Katastrophe....ist aber nur zu Testzwecken |
32 | |
33 | }
|
34 | |
35 | void ADC_init(void) |
36 | {
|
37 | ADMUX |= (1<<REFS0)|(1<<MUX2)|(1<<MUX0)|(1<<ADLAR); //Referenzspannung intern 5V, ADC5, Nur 8 bit Result |
38 | ADCSRA |= (1<<ADEN)|(1<<ADPS0)|(1<<ADPS1)|(1<<ADIE)|(1<<ADATE)|(1<<ADSC); //Enable, Prescaller von 8, Interrupt Enable, Left-Adjust für 8 bit, Start Conversion |
39 | //Per Default befindet sich der ADC im FreeRunningMode, d.h. er Triggert automatisch bei Änderung
|
40 | }
|
Delay im isr? Ist nicht sein ernst, oder? Freerunningmode heißt der adc läuft permanent.
Hi Felix , fein nun ist doch alles klar, das Programm macht genau, was Du programmiert hast ! Wenn Du nun z.B. Timer 0 auf eine 100ms Intervall einstellst und den ADC-Wandler über den Timer 0 triggerst, dann erhälst Du eine Wandlungsrate von 10Hz. Und die LED blinkt nicht so schnell.
In 99% der Fälle muss der ADC nicht im Free-Running-Mode laufen, wenn man sowieso die Werte nur alle 0,5 bis 10 ms abholt und verarbeitet. Die Beobachtung eines Potis ist genau so ein Fall! Welche zeitliche Auflösung ist denn für die Messwerte erforderlich??? Meist geht es so viel besser: Timer-Interrupt alle 0,5 bis 10 ms (oder > 10 ms) - Hole ADC-Wert ab - Starte ADC neu (Single Aquisition!) (Bei einem ADC-Takt von 50...200 kHz ist der neue Wert nach 0,26...0,065 ms abholbereit) Also gibt's beim nächsten Timer-Interrupt einen neuen Wert. - Arbeite alles andere ab, was zeitlich getaktet sein muss... - RETI (Ende der Interrupt-Service-Routine)
Super, danke, bin fälschlicherweise immer davon ausgegangen, dass im Freerunningmode nur dann in die ISR gesprungen wird, wenn der Wert am AD-Eingang sich ändert. Danke vielmals, LG
Avr schrieb: > Delay im isr? Ist nicht sein ernst, oder? Den Kommentar daneben hast du aber auch gelesen, oder?
Je nach Prozessor ist freerunning etwas anders. Der SAM3X oder nen LPC z.B. lassen den letzten Wert im Register bis man ihn einmal ausgelesen hat. Dann wird automatisch ein neuer Wert eingelesen. Hier beim Atmega ist das aber anders. Der ADC-Wert an sich ist aber auch nie so stabil, sodass er sich auch bei angelegten VCC ändern wird.
Nico W. schrieb: > Der ADC-Wert an sich ist aber auch nie so stabil, sodass er sich auch > bei angelegten VCC ändern wird. Wie bitte? Aber nur wenn man Vcc als Referenz nimmt und AVcc nicht entsprechend beschaltet hat. Hält man sich an die Empfehlungen von Atmel dann ist der ADC-Wert bei stabilen Umgebungsbedingungen bei gleicher Messspannung bombenfest, da ändert sich schlicht gar nichts.
M. K. schrieb: > Avr schrieb: > Delay im isr? Ist nicht sein ernst, oder? > > Den Kommentar daneben hast du aber auch gelesen, oder? Der Kommentar klingt in etwa: sich ins Knie zu schießen ist nicht gut, aber ich mache es mal tritzdem, mal gucken was passiert... Wie auch immer, muss jeder selber wissen wie er etwas macht, ich bevorzuge es, das Datenblatt zu lesen.
Nunja, unsere Mutter hat uns doch auch immer davor gewarnt, dass das Herd heiß ist. Haben wir ihr es geglaubt bevor wir uns die Hand verbrannt haben?
Hi Dem TO ist scheinbar bekannt, daß ein Delay in einer ISR nichts zu suchen hat. Warum hat Er Es denn nun doch gemacht?? Naja, wenn man etwas nachdenkt, KÖNNTE dieses Delay dafür gut sein, daß man die LED aufblitzen sehen KANN - sonst hat man das gleiche Problem, wie bei einem prellendem Taster, daß dort auch 2 ISR direkt hintereinander kommen können und die Diagnose-LED scheinbar Nichts anzeigt. Aber was laber ich hier- habt Ihr bestimmt bedacht und trotzdem als 'Du pöser Pursche Du' verworfen, weil: Man macht 'Es' einfach nicht und wenn so was gemacht wird, wird auch NIEMALS das Hirn eingeschaltet ... schließlich wissen wir ja, was man nicht macht, schei? drauf, was der TO sich wohl gedacht hat ... blöde Anfänger ... So, jetzt könnt Ihr weiter machen ... Stichworte waren: ISR und Delay
:
Bearbeitet durch User
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.