Forum: Mikrocontroller und Digitale Elektronik ADC will nicht


von Ingo L. (grobian)


Lesenswert?

Versuche hier den AD Wandler zum laufen zu kriegen, was aber nicht will.
Habe externe C von 100nF an Pin 21 (MEGA8)  und Poti am  ADC1.
Nun soll der Wert an der SPI ausgegeben werden wo ein 74HC595 dran 
hängt.
Geht aber nicht. AVCC ist an +5 Volt.
Was ist falsch die SPI funktioniert
1
#define F_CPU 1000000UL
2
#include <avr\io.h>
3
#include <util/delay.h>
4
#define MOSI PINB3
5
#define SCK  PINB5
6
#define SS   PINB2
7
#define DDR_SPI  DDRB
8
9
int main (void)
10
{
11
// SPI INIT
12
DDR_SPI   = (1<<MOSI) | (1<<SCK) | (1<<SS);
13
SPCR   = (1<<SPE)  | (1<<MSTR)   | (1<<SPR0) ;
14
15
// AD INIT
16
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
17
ADMUX   |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
18
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
19
ADCSRA  |= (1<<ADPS2) |(1<<ADPS1)| (0<<ADPS0) ; // PRESCALER 64
20
ADCSRA  |= (1<<ADFR);
21
22
while(1)
23
24
ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
25
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
26
27
  {
28
      PORTB &= ~(1 << SS);   //SS LOW
29
      SPDR = ADCH;
30
      while(!(SPSR & (1<<SPIF)));
31
      PORTB |= (1 << SS);    // SS HIGH
32
      _delay_ms(100);
33
  }
34
}

Gruß
Ingo

von Jean Player (Gast)


Lesenswert?

Hi, dein Programm bleibt bei der while(1) Schleife stehen und macht 
deshalb weder Messung, noch SPI Übertragung.
Zudem glaube ich nicht, daß das Programm so kompiliert, ohne Semikolon 
nach der while(1).
Gruß

von Grrrr (Gast)


Lesenswert?

Jean Player schrieb:
> Zudem glaube ich nicht, daß das Programm so kompiliert, ohne Semikolon
> nach der while(1).

Das ist keine Frage des Glaubens. ;-)
1
while(1)
2
   ADCSRA |= (1<<ADSC);

ist legaler Code.

von holger (Gast)


Lesenswert?

while(1) ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN

>Zudem glaube ich nicht, daß das Programm so kompiliert, ohne Semikolon
>nach der while(1).

Klar geht das;)

von Jean Player (Gast)


Lesenswert?

Stimmt, habe ich übersehen, weil da ne Leerzeile zwischen war :-/

von Jean Player (Gast)


Lesenswert?

Jedoch bleibt die while(1) immer true also bleibt das Programm dort 
stehen und setzt bis zum Nimmerleins Tag den ADSC.
Gruß

von Karl H. (kbuchegg)


Lesenswert?

Was uns dann wieder mal zum Thema bringt:
1
"Welchen Einfluss hat eine saubere Codeformatierung und Einrückung auf
2
 die Fähigkeit des Programmierers, Fehler selbst zu sehen?"


Aus genau dem gleichen Grund schreib ich zb so etwas
1
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG

immer so
1
  while (!(ADCSRA & (1<<ADIF)))  // WARTEN BIS FERTIG
2
    ;

dann sieht man schneller, dass das hier eine leere Schleife ist, deren 
ganzer Zweck sich in der Abbruchbedingung verbirgt.
Technisch gesehen gehört der ; sowieso zum nächsten (in dem Fall leeren) 
Statement und nicht zum while. Ein while (genauso wie ein for oder ein 
if oder ein do) wird nicht mit einem ; abgeschlossen.

Wer seinen Coding Stil daher so aufbaut
1
    while( Bedingung )
2
      Anweisung;
(also: die abhängige Anweisung kommt immer eingerückt in die nächste 
Zeile), der handelt nur konsequent, wenn er das auch mit der leeren 
Anweisung so handhabt. Denn auch eine leere Anweisung ist eine 
Anweisung:
1
    while( Bedingung )
2
      ;     // tu nichts, Jaa das ist eine leere Anweisung. So etwas gibt es!


Dieser ; ist wichtig und es ist wichtig, dass der heraussticht und sich 
nicht in den Zeichen einer Zeile versteckt, wo ihn keiner sieht.

Besonders fies ist hier natürlich die konkrete Codefortstzung ...
1
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
2
3
  {
4
      PORTB &= ~(1 << SS);   //SS LOW
5
      SPDR = ADCH;
6
      while(!(SPSR & (1<<SPIF)));
7
      PORTB |= (1 << SS);    // SS HIGH
8
      _delay_ms(100);
9
  }

... bei der es auf den ersten Blick so aussieht, als ob der 
darauffolgende Block vom while abhängig ist. Das er es nicht ist, sieht 
man erst, wenn man den ; entdeckt hat

1
  while (!(ADCSRA & (1<<ADIF)))  // WARTEN BIS FERTIG
2
    ;
3
4
  {
5
      PORTB &= ~(1 << SS);   //SS LOW
6
      SPDR = ADCH;
7
      while(!(SPSR & (1<<SPIF)))
8
        ;
9
      PORTB |= (1 << SS);    // SS HIGH
10
      _delay_ms(100);
11
  }
So ist es IMHO ein bischen besser zu sehen, dass der Block nichts mit 
dem while zu tun hat.

von Grrrr (Gast)


Lesenswert?

Komisch. Solche Fälle hatten wir in letzter Zeit öfter. Als wenn gerade 
der Trend besteht, das das Semikolon nur so syntaktischer Zucker ohne 
eigene Bedeutung ist.
(Mensch, wie habe ich BEGIN und END gehasst).

von Ingo L. (grobian)


Lesenswert?

Gut, aber wo ist jetzt der Fehler außer der Code-Formatierung ?

von kaffeetas (Gast)


Lesenswert?

dein hauptprogram besteht nur aus einer Zeile, sieht man im Simulator 
sehr schön.

Grüße
 kaffeetas

von holger (Gast)


Lesenswert?

>Gut, aber wo ist jetzt der Fehler außer der Code-Formatierung ?

Alles überflüssige wegmachen dann sieht das so aus:
1
int main (void)
2
{
3
while(1)
4
5
ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
6
7
}

Ein paar Leerzeichen wegmachen:
1
int main (void)
2
{
3
while(1) ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
4
}

Und das ist nur der erste Fehler.

von Grrrr (Gast)


Lesenswert?

Ingo Laabs schrieb:
> Gut, aber wo ist jetzt der Fehler außer der Code-Formatierung ?

Das ist ausführlich diskutiert worden. Was hast Du daran nicht 
verstanden?
Da ist ein paar geschweifte Klammern zuwenig in Deinem Code.

Korrigiere also den Fehler erstmal, probiere es aus und poste dann 
wieder.

Abgesehen davon, wäre es wirklich ausserordentlich freundlich, wenn Du 
mal beschreibst worin sich der Fehler eigentlich äussert. "Geht nicht" 
ist nicht gerade eine ausführliche Beschreibung.

von holger (Gast)


Lesenswert?

>"Geht nicht"
>ist nicht gerade eine ausführliche Beschreibung.

In diesem Fall aber durchaus richtig;)

von Ingo L. (grobian)


Lesenswert?

1
#define F_CPU 1000000UL
2
#include <avr\io.h>
3
#include <util/delay.h>
4
#define MOSI PINB3
5
#define SCK  PINB5
6
#define SS   PINB2
7
#define DDR_SPI  DDRB
8
9
int main (void)
10
{
11
// SPI INIT
12
DDR_SPI   = (1<<MOSI) | (1<<SCK) | (1<<SS);
13
SPCR   = (1<<SPE)  | (1<<MSTR)   | (1<<SPR0) ;
14
15
// AD INIT
16
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
17
ADMUX  |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
18
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
19
ADCSRA  |= (1<<ADPS2) |(1<<ADPS1)| (0<<ADPS0) ; // PRESCALER 64
20
ADCSRA  |= (1<<ADFR);
21
22
 while(1)
23
{
24
 ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
25
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
26
27
  
28
    PORTB &= ~(1 << SS);   //SS LOW
29
    SPDR = ADC/4;
30
    while(!(SPSR & (1<<SPIF)));
31
    PORTB |= (1 << SS);    // SS HIGH
32
    _delay_ms(100);
33
  
34
35
}
36
}
so geht jetzt. Das ADC/4 habe ich weil ich nur 256 Werte darstellen 
möchte. Am HC595 werden jetzt die Werte entsprechend dargestellt (an den 
LED´s)

von holger (Gast)


Lesenswert?

Wenn du jetzt noch die beiden überflüssigen geschweiften Klammern
wegmachst denkt auch keiner mehr das sie zu dem while() darüber
gehören.

von holger (Gast)


Lesenswert?

>Wenn du jetzt noch die beiden überflüssigen geschweiften Klammern
>wegmachst denkt auch keiner mehr das sie zu dem while() darüber
>gehören.

Ok, jetzt sind sie weg;)

von Karl H. (kbuchegg)


Lesenswert?

Und die Code-Formatierung ist immer noch grauenhaft.
Aus Fehlern nichts gelernt.

von Grrrr (Gast)


Lesenswert?

holger schrieb:
> Wenn du jetzt noch die beiden überflüssigen geschweiften Klammern
> wegmachst denkt auch keiner mehr das sie zu dem while() darüber
> gehören.

Huch? Habe ich gerade einen Hänger?
Welche geschweiften Klammern meinst Du?
Die nach dem while(1) sollten doch da sein, oder?
Wenn dann waren doch die inneren Klammern nach "while (!(ADCSRA & 
(1<<ADIF))); // WARTEN BIS FERTIG" überflüssig und in dem Post von 21:12 
waren sie doch schon nicht mehr da.

Seltsam. Was mache ich da für einen Denkfehler?

von Karl H. (kbuchegg)


Lesenswert?

Grrrr schrieb:

> Seltsam. Was mache ich da für einen Denkfehler?

Keinen.
Der Code wurde nachträglich editiert.

von Grrrr (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> Keinen.
> Der Code wurde nachträglich editiert.

Ach so! Danke für die Bestätigung meiner geistigen Gesundheit. ;-)
Hier haste n Bier.

von Grrrr (Gast)


Lesenswert?

Grrrr schrieb:
> Ach so! Danke für die Bestätigung meiner geistigen Gesundheit.

Über die zeitlichen und faktischen Grenzen dieser Bestätigung bin ich 
mir im klaren... ;-)

von Ingo L. (grobian)


Lesenswert?

Karl heinz Buchegger schrieb:
> Grrrr schrieb:
>
>> Seltsam. Was mache ich da für einen Denkfehler?
>
> Keinen.
> Der Code wurde nachträglich editiert.


richtigm wurde von mir nachträglich editiert....kein Denkfehler.
An der Code-Formatierung werde ich noch Arbeiten. Nur stand gestern 
Abend das Essen auf dem Tisch, und das wollen wir doch nicht kalt werden 
lassen...GELL

von Karl H. (kbuchegg)


Lesenswert?

Du musst lernen, dass man Code Formatierung nicht nachträglich in einen 
Code einbaut, sondern sofort. Während man in schreibt!

Es tut nicht weh, wenn man Codestellen gleich von vorne herein auf die 
richtige Einrücktiefe einrückt.
Ganz im Gegenteil: Dadurch das man sich überlegt, auf welche 
Einrücktiefe eine Codestelle aufgrund der Progammlogik gehört und man 
schnell überprüft ob die Klammerhierarchie das auch hergibt, fallen 
viele Flüchtigkeitsfehler weg! Der springende Punkt hier ist die leichte 
Überprüfbarkeit, nicht das es schön aussieht.
Aber dazu muss man konsequent korrekt einrücken. Sonst funktioniert das 
nicht.

von Karl H. (kbuchegg)


Lesenswert?

Beitrag "getch-Funktion"

Der nächste der sich mit dieser bescheuerten

    while( irgendwas ) ;

Schreibweise wieder selbst ein Ei gelegt hat.

von Ingo L. (grobian)


Lesenswert?

Karl heinz Buchegger schrieb:
> Aus genau dem gleichen Grund schreib ich zb so etwas
>   while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
>
> immer so  while (!(ADCSRA & (1<<ADIF)))  // WARTEN BIS FERTIG
> ;

Hallo Herr Buchegger,
möchte mich an dieser Stelle mal für die immer wertvollen Tipps 
bedanken.

Funktionell macht die Schreibweise aber keinen Unterschied oder ?

von Oh nein (Gast)


Lesenswert?

> Funktionell macht die Schreibweise aber keinen Unterschied oder ?

Allein für diese Frage gehört Dir ein kräftiger Tritt in den Hintern!
Du hast nichts von allem Geschriebenen gelernt oder verstanden!

von Ingo L. (grobian)


Lesenswert?

nun, weil es bei mit der alten Schreibweise funktioniert. Von daher kam 
die Frage.

von Karl H. (kbuchegg)


Lesenswert?

Ingo Laabs schrieb:
> nun, weil es bei mit der alten Schreibweise funktioniert. Von daher kam
> die Frage.

Trotzdem hat "Oh nein" recht. Das sollte man eigentlich bei den 
Grundlagen, irgendwo auf den ersten 20 Seiten eines Buches gelesen 
haben.

Wenn du willst kannst du das so schreiben
1
   while
2
   (
3
 !
4
5
6
7
   (
8
                             ADCSRA
9
    &
10
              ( 1 <<
11
     ADIF )
12
    )
13
  )
14
                         ;
und es wäre immer noch dieselbe Anweisungsfolge.

Es sollte aber auch ziemlich offensichtlich sein, warum das keine gute 
Idee ist. (*)

Die einzige Einschränkung ist: in einem Wort kann kein Whitespace (also 
Leerzeichen, Tabulator, Zeilenumbruch) sein. Aber ansonsten bist du 
völlig frei darin, wo du wieviele Whitespace Character einbaust. Dem 
Compiler ist das wurscht, der filtert die sowieso aus, wenn er sich den 
Text vornimmt. Für den ist nur die Abfolge der Bausteine interessant, 
nicht in welcher Weise du sie optisch anordnest.

Eine Ausnahme ist der // Kommentar. Der geht immer bis zum aktuellen 
Zeilende. Und bei Makros gibt es auch eine Ausnahme. Allerdings kann man 
darüber debattieren, ob der Präprozessor Teil des eigentlichen Compilers 
ist oder ob man den als Vorsatz vor den Compiler nicht sowieso extra 
betrachten muss.


(*)
Edit: Ausser natürlich man nimmt am IOCCC teil. Dann muss sich schon 
einmal alles andere der äusseren Form unterordnen :-)
1
                                                   extern int
2
                                                       errno
3
                                                         ;char
4
                                                            grrr
5
                             ;main(                           r,
6
  argv, argc )            int    argc                           ,
7
   r        ;           char *argv[];{int                     P( );
8
#define x  int i,       j,cc[4];printf("      choo choo\n"     ) ;
9
x  ;if    (P(  !        i              )        |  cc[  !      j ]
10
&  P(j    )>2  ?        j              :        i  ){*  argv[i++ +!-i]
11
;              for    (i=              0;;    i++                   );
12
_exit(argv[argc- 2    / cc[1*argc]|-1<<4 ]    ) ;printf("%d",P(""));}}
13
  P  (    a  )   char a   ;  {    a  ;   while(    a  >      "  B   "
14
  /* -    by E            ricM    arsh             all-      */);    }

von Ingo L. (grobian)


Lesenswert?

Ich kann mich mit meinen Beitrag ja mal anmelden.

von Ingo L. (grobian)


Lesenswert?

Auf die Gefahr hin, dass gleich wieder mit mir gemeckert wird wegen 
formatierung.
Ich wollte jetzt mit demn Wert den ich über den ADC einlese an die PWM 
ausgeben. Das geling auch, nur kann ich das Tastverhältniss nur bis etwa 
50% einstellen.
1
#define F_CPU 1000000UL
2
#include <avr\io.h>
3
#include <util/delay.h>
4
5
int main (void)
6
{
7
8
DDRB = 255; // PORT auf Ausgang
9
10
// AD INIT
11
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
12
ADMUX  |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
13
//ADMUX   |= (1<<ADLAR);
14
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
15
ADCSRA  |= (0<<ADPS2) |(1<<ADPS1)| (1<<ADPS0) ; // PRESCALER 8
16
ADCSRA  |= (1<<ADFR);
17
18
// Timer 2 INIT
19
TCCR2 |= (1<<WGM20) | (0<<WGM21);     // MODE 1
20
TCCR2 |= (1<<COM21) | (0<<COM20);    // OC2 ON PB3
21
TCCR2 |= (1<<CS21);      // Prescaler  = 8 und Start Timer
22
23
while(1)
24
  {
25
    ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
26
    while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
27
    OCR2 = ADC/4;
28
  }
29
}

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.