www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ADC will nicht


Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht 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
#define F_CPU 1000000UL
#include <avr\io.h>
#include <util/delay.h>
#define MOSI PINB3
#define SCK  PINB5
#define SS   PINB2
#define DDR_SPI  DDRB

int main (void)
{
// SPI INIT
DDR_SPI   = (1<<MOSI) | (1<<SCK) | (1<<SS);
SPCR   = (1<<SPE)  | (1<<MSTR)   | (1<<SPR0) ;

// AD INIT
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
ADMUX   |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
ADCSRA  |= (1<<ADPS2) |(1<<ADPS1)| (0<<ADPS0) ; // PRESCALER 64
ADCSRA  |= (1<<ADFR);

while(1)

ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG

  {
      PORTB &= ~(1 << SS);   //SS LOW
      SPDR = ADCH;
      while(!(SPSR & (1<<SPIF)));
      PORTB |= (1 << SS);    // SS HIGH
      _delay_ms(100);
  }
}

Gruß
Ingo

Autor: Jean Player (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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. ;-)
while(1)
   ADCSRA |= (1<<ADSC);

ist legaler Code.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;)

Autor: Jean Player (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt, habe ich übersehen, weil da ne Leerzeile zwischen war :-/

Autor: Jean Player (Gast)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

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


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
    ;

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
    while( Bedingung )
      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:
    while( Bedingung )
      ;     // 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 ...
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG

  {
      PORTB &= ~(1 << SS);   //SS LOW
      SPDR = ADCH;
      while(!(SPSR & (1<<SPIF)));
      PORTB |= (1 << SS);    // SS HIGH
      _delay_ms(100);
  }

... 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

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

  {
      PORTB &= ~(1 << SS);   //SS LOW
      SPDR = ADCH;
      while(!(SPSR & (1<<SPIF)))
        ;
      PORTB |= (1 << SS);    // SS HIGH
      _delay_ms(100);
  }
So ist es IMHO ein bischen besser zu sehen, dass der Block nichts mit 
dem while zu tun hat.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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).

Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Gut, aber wo ist jetzt der Fehler außer der Code-Formatierung ?

Autor: kaffeetas (Gast)
Datum:

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

Grüße
 kaffeetas

Autor: holger (Gast)
Datum:

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

Alles überflüssige wegmachen dann sieht das so aus:
int main (void)
{
while(1)

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

}

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

Und das ist nur der erste Fehler.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

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

In diesem Fall aber durchaus richtig;)

Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
#define F_CPU 1000000UL
#include <avr\io.h>
#include <util/delay.h>
#define MOSI PINB3
#define SCK  PINB5
#define SS   PINB2
#define DDR_SPI  DDRB

int main (void)
{
// SPI INIT
DDR_SPI   = (1<<MOSI) | (1<<SCK) | (1<<SS);
SPCR   = (1<<SPE)  | (1<<MSTR)   | (1<<SPR0) ;

// AD INIT
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
ADMUX  |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
ADCSRA  |= (1<<ADPS2) |(1<<ADPS1)| (0<<ADPS0) ; // PRESCALER 64
ADCSRA  |= (1<<ADFR);

 while(1)
{
 ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
  while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG

  
    PORTB &= ~(1 << SS);   //SS LOW
    SPDR = ADC/4;
    while(!(SPSR & (1<<SPIF)));
    PORTB |= (1 << SS);    // SS HIGH
    _delay_ms(100);
  

}
}
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)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Und die Code-Formatierung ist immer noch grauenhaft.
Aus Fehlern nichts gelernt.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Grrrr schrieb:

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

Keinen.
Der Code wurde nachträglich editiert.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Grrrr (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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... ;-)

Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Beitrag "getch-Funktion"

Der nächste der sich mit dieser bescheuerten

    while( irgendwas ) ;

Schreibweise wieder selbst ein Ei gelegt hat.

Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht 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 ?

Autor: Oh nein (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!

Autor: Ingo Laabs (grobian)
Datum:

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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
   while
   (
 !



   (
                             ADCSRA
    &
              ( 1 <<
     ADIF )
    )
  )
                         ;
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 :-)
                                                   extern int
                                                       errno
                                                         ;char
                                                            grrr
                             ;main(                           r,
  argv, argc )            int    argc                           ,
   r        ;           char *argv[];{int                     P( );
#define x  int i,       j,cc[4];printf("      choo choo\n"     ) ;
x  ;if    (P(  !        i              )        |  cc[  !      j ]
&  P(j    )>2  ?        j              :        i  ){*  argv[i++ +!-i]
;              for    (i=              0;;    i++                   );
_exit(argv[argc- 2    / cc[1*argc]|-1<<4 ]    ) ;printf("%d",P(""));}}
  P  (    a  )   char a   ;  {    a  ;   while(    a  >      "  B   "
  /* -    by E            ricM    arsh             all-      */);    }


Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kann mich mit meinen Beitrag ja mal anmelden.

Autor: Ingo Laabs (grobian)
Datum:

Bewertung
0 lesenswert
nicht 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.
#define F_CPU 1000000UL
#include <avr\io.h>
#include <util/delay.h>

int main (void)
{

DDRB = 255; // PORT auf Ausgang

// AD INIT
ADMUX   |= (0<<REFS1) |(1<<REFS0);  // externe Referenz
ADMUX  |= (0<<MUX3)  |(0<<MUX2) | (0<<MUX1) | (1<<MUX0) ; //ADC1
//ADMUX   |= (1<<ADLAR);
ADCSRA  |= (1<<ADEN) ; // ADC ENABLE
ADCSRA  |= (0<<ADPS2) |(1<<ADPS1)| (1<<ADPS0) ; // PRESCALER 8
ADCSRA  |= (1<<ADFR);

// Timer 2 INIT
TCCR2 |= (1<<WGM20) | (0<<WGM21);     // MODE 1
TCCR2 |= (1<<COM21) | (0<<COM20);    // OC2 ON PB3
TCCR2 |= (1<<CS21);      // Prescaler  = 8 und Start Timer

while(1)
  {
    ADCSRA |= (1<<ADSC); // WANDLUNG STARTEN
    while (!(ADCSRA & (1<<ADIF))); // WARTEN BIS FERTIG
    OCR2 = ADC/4;
  }
}

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.