Forum: Mikrocontroller und Digitale Elektronik ATMEGA644 ADC


von Marco G. (grmg2010)


Lesenswert?

Hallo,

ich versuche gerade den ADC des ATMEGA644 mit Interrupts in Betrieb zu 
nehmen. Dazu habe ich mich bei der Initialisierung an dem Tutorial hier 
im Forum orientiert.

Mein Problem ist, dass der Interrupt nie auftritt. Hier mal mein Code:
1
void AD_init(void)
2
{
3
  int first_result = 0;
4
  
5
  DIDR0 = (1<<ADC1D); //Abschalten der Digitalstufe für ADC1
6
  
7
  ADMUX = (1<<REFS0); //Einschalten der Referenzspannung: Vref = AVCC
8
  ADMUX |=(MUX1);    //Waehlen des ADC1
9
  
10
  ADCSRA = (1<<ADEN) | (1<<ADIE); // ADC aktivieren und Interrupt einschalten
11
  ADCSRA |= (ADPS2) | (1<<ADPS1) | (1<<ADPS0); //Prescaler 128
12
  
13
  
14
  _delay_ms(1);
15
  
16
  ADCSRA |= (1<<ADSC);    //Starten der Messung
17
  
18
  while (ADCSRA & (1<<ADSC))
19
  {
20
    
21
  }
22
  
23
  first_result = (ADCL + (ADCH<<8));
24
  
25
}
26
27
28
ISR(ADC_vect)
29
{
30
  PORTD ^=(1<<PD6);
31
  adc_result = (ADCL + (ADCH<<8));
32
  next = 1;
33
}
34
35
36
int main(void)
37
{  
38
39
  avr_init();
40
  UART_Init();
41
  _delay_ms(500);
42
  
43
  sei();
44
45
    while(1)
46
    {
47
48
    if (next == 1)
49
    {
50
      ADC_value = calculate_adc(adc_result);
51
      
52
      dtostrf(ADC_value, 5, 3, buffer_adc);
53
      uart_puts("Read Voltage: ");
54
      Send_UART_Char(buffer_adc);
55
      
56
      start_converting();
57
      next = 0;
58
      
59
    }
60
    
61
    _delay_ms(1000);
62
    
63
64
    
65
    }
66
}

Gruß

von c-hater (Gast)


Lesenswert?

Marco G. schrieb:

> Mein Problem ist, dass der Interrupt nie auftritt.

Wie sollte er auch? Du rufst AD_init in deinem Code niemals auf. 
Dementsprechend wird auch niemals ADIE gesetzt.

von der chef (Gast)


Lesenswert?

next muss volatile sein damit der compiler das nicht wegoptimiert. (wenn 
dann der adc initialisiert ist)

von Ingo L. (corrtexx)


Lesenswert?

Es fehlt auch noch ein
1
 sei();

von Marco G. (grmg2010)


Lesenswert?

c-hater schrieb:
> Wie sollte er auch? Du rufst AD_init in deinem Code niemals auf.

Stimmt nicht offensichtlich, AD_init wird in der Funktion avr_init 
aufgerufen.

Wieso fehlt das sei? Steht doch als letzter Befehl vor der 
endlosschleife in meiner Main.

Wieso wurde der Compiler die Variable next wegoptimieren?

: Bearbeitet durch User
von Marco G. (grmg2010)


Lesenswert?

Ich habe meinen Code jetzt mal simuliert. Es wird alles in der 
ADC-Sektion so gesetzt wie erwartet, außer dem Bit ADSC. Woran könnte 
das liegen?

von Karl H. (kbuchegg)


Lesenswert?

Marco G. schrieb:
> Ich habe meinen Code jetzt mal simuliert. Es wird alles in der
> ADC-Sektion so gesetzt wie erwartet, außer dem Bit ADSC. Woran könnte
> das liegen?

3 Möglichkeiten
* An dem Code, den du nicht gezeigt hast
* Du hast im Atmel-Studio die Freigabe beim Debuggen für ISR nicht 
eingeschaltet, so dass ein Breakpoint in der ISR nicht anspricht
* Du hast mit F10 nicht weit genug durchgesteppt. ADSC kommt in deiner 
AD_init() (bei eingeschaltetem Optimizer) erst dann, wenn man das erste 
mal F10 drückt, während die Zeilenanzeige des Debuggers schon auf der 
Zeile mit dem while steht. Aber es kommt.

Wenn ich deinen geposteten Code compilierbar mache und im Simulator 
durchlaufen lassen, ist alles in Ordnung und verhält sich so wie 
erwartet.

: Bearbeitet durch User
von Marco G. (grmg2010)


Lesenswert?

Dies ist der gesammte Code. Wie schalte ich die Freigabe der Isr denn 
ein beim Debugger? Auch wenn ich f10 drücke, bei mir setzt er das 
adsc-bit nicht.
In der Praxis merke ich das auch, pb7 wird nicht getoggelt also kein 
Sprung in die isr

von Stefan E. (sternst)


Lesenswert?

Marco G. schrieb:
> Dies ist der gesammte Code.

Garantiert nicht. Wo sind z.B. calculate_adc und start_converting?
Und wenn in letzterem auch etwas in dieser Art steht:
1
ADMUX |=(MUX1);
1
ADCSRA |= (ADPS2) ...
wäre es kein Wunder, dass es keine weitere Wandlung gibt.

von Karl H. (kbuchegg)


Angehängte Dateien:

Lesenswert?

Marco G. schrieb:
> Dies ist der gesammte Code.

So so.
Und warum musste ich dann Variablen nachdefinieren und die Hälfte der 
Hauptschleife auskommentieren, wenn das der komplette Code ist?


> Wie schalte ich die Freigabe der Isr denn
> ein beim Debugger?


Siehe Bild

> Auch wenn ich f10 drücke, bei mir setzt er das
> adsc-bit nicht.

Siehe ebenfalls Bild

: Bearbeitet durch User
von Marco G. (grmg2010)


Angehängte Dateien:

Lesenswert?

Habe mir meinen geposteten Code noch mal angesehen. Ich hatte doch nicht 
alles gepostet. Sorry :(
Im Simulator setzt er das Bit, aber bei meinem realen uC funktioniert es 
weiterhin nicht.
Edit: Ok, jetzt funktioniert es. Ursächlich war anscheinend, dass ich 
meine Funktion start_converting(); mit in der Schleife stehen hatte. 
Schreibe ich die Funktion außerhalb der Schleife geht es.

Ich habe den Code noch ein wenig umgeschrieben, um einen Mittelwert zu 
bilden, bekomme jetzt jedoch folgenden Fehler, den ich nicht so ganz 
nachvollziehen kann. Ich hatte nur´eine Header-Datei neu eingefügt

: Bearbeitet durch User
von Marco G. (grmg2010)


Lesenswert?

Ok, der Fehler ist behoben. Es fehlte ein Komma in eine der 
Header-Dateien...

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
Noch kein Account? Hier anmelden.