mikrocontroller.net

Forum: Compiler & IDEs Bedingungen werden nicht korrekt ausgeführt


Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen

Ich hab hier ein kleines, wahrscheinliches einfaches Problem... aber ich 
hab sicherlich grad den Tunnelblick und seh die Lösung nicht.

Zum Problem...

Ich habe ein Programm geschrieben, das alle paar Sekunden ein 
Unterprogramm aufruft... und die Anweisungen in den Funktionen KORREKT 
befolgt.

Der korrekte Durchlauf ist aber iwie nur das erste Mal gewährt, 
anschließend nicht mehr.

In Schritt 3 sollen mittels AD Wandler zwei Werte ermittelt werden. 
Einmal von ADC1 und ADC3! Diese subtrahiere ich anschließend und möchte 
das ab einer bestimmten Differenz die eine LED leuchtet oder die andere.

Nunja das erste Mal klappts, das zweite Mal nicht. Nachm Reset 
funktioniert wieder das erste Mal :(

Hier mal der Code: (GO wird in einem Timer alle paar Sekunden 
hochgezählt!


volatile int GO=0;

unsigned int LDR1;
unsigned int LDR3;

signed int LDR13;

// Funktionsprototypen

void initLDR1(void);    // Initialisierung des LDR1
void initLDR3(void);    // Initialisierung des LDR3

void Leuchtstaerke(void);  // Unterprogramm zur Bestimmung der Helligkeit

// Hauptprogramm===================================================================================

int main(void)

{
  SET_BIT(DDRD, DDD1);
  SET_BIT(DDRD, DDD3);

  SET_BIT(DDRB, DDB2);
  
  ADCSRA |= 0x7;    // (1<<ADPS2) | (1<<ADPS1) | (1<<ADPS0)

            // ADC aktivieren + Vorteiler 128 (Prescaler Selection Bits)
  
  sei();          // Interrupts aktivieren
    
  while(1)
  
  {  
    SET_BIT(PORTD, PD1);    // LED ausschalten, falls an
    SET_BIT(PORTD, PD3);    // LED ausschalten, falls an

    SET_BIT(PORTB, PB2);    // LED ausschalten, falls an
    

    ADCSRA &= ~(1<<ADEN);    // A/D ausschalten
    
    if (GO==1)
    {                        
      CLR_BIT(PORTB, PB2);  // LED einschalten
      _delay_ms(1500);
    }

    if (GO==2)
    {            
      initLDR1();
      Leuchtstaerke();
      LDR1=wert;
      initLDR3();
      Leuchtstaerke();
      LDR3=wert;

            LDR13=LDR1-LDR3;
    }
    
    if (GO==3)
    {
      if (LDR13>=20)
      {
      CLR_BIT(PORTD, PD1);    // LED einschalten
      GO=0;
      }
      
      if (LDR13<=-20)
      {
      CLR_BIT(PORTD, PD3);    // LED einschalten
      GO=0;
      }
      
      _delay_ms(250);
    }

    if (GO==4)
    {
      CLR_BIT(PORTB, PB2);    // LED einschalten
      _delay_ms(100);
      GO=0;
    }
  }      
}

// Initialisierung LDR1=============================================================================

void initLDR1()

{
  ADMUX |= 0xC1;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (0<<MUX1) | (1<<MUX0)

            // 1.1V mit Externen Kondensator (REFS) + ADC1 Eingang LDR (MUX)
}  

// Initialisierung LDR3=============================================================================

void initLDR3()

{
  ADMUX |= 0xC3;    // (1<<REFS1) | (1<<REFS0) | (0<<MUX3) | (0<<MUX2) | (1<<MUX1) | (1<<MUX0)

            // 1.1V mit Externen Kondensator (REFS) + ADC3 Eingang LDR (MUX)
}  

// Leuchtstärkebestimmung==========================================================================


void Leuchtstaerke()        // ADC= (Vin*1024)/(Vref)

{
  int lux;  
  int i;

  ADCSRA |= (1<<ADEN);      // AD aktivieren
  ADCSRA |= (1<<ADSC);      // Konvertierung starten

  while (ADCSRA & (1<<ADSC))    // Wenn Konvertierung gestartet ist
    
  {
    ;  
  }

  lux = ADCL;            // Erst ADCL aus Register lesen
  lux += (ADCH<<8);        // dann ADCH, weil sonst ADC Data Register nicht geupdated wird
  lux=0;
  
  for (i=0; i<4; i++)
  
  {
    ADCSRA |= (1<<ADSC);

    while (ADCSRA & (1<<ADSC))  // Wenn Konvertierung gestartet ist
  
    {
      ;  
    }

    lux += ADCL;
    lux += (ADCH<<8);      // ADCH aufsummieren
  }
    
  ADCSRA &= ~(1<<ADEN);      // Konvertierung beenden
  
  //lux = (lux>>2);        // durch 4 teilen
  lux /= 4;
  wert = lux;
  i=0;            
}


Ich bin echt ratlos... wäre dankbar für eure Hilfe!

Grüßle Alex

Autor: Stefan Ernst (sternst)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Nunja das erste Mal klappts, das zweite Mal nicht. Nachm Reset
> funktioniert wieder das erste Mal :(

Kein Wunder, wenn du in ADMUX immer nur Bits setzt, aber einmal gesetzte 
Bits nie wieder zurück setzt.

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

Bewertung
0 lesenswert
nicht lesenswert
Benutz doch die Routinen aus dem AVR-GCC-Tutorial

http://www.mikrocontroller.net/articles/AVR-GCC-Tu...

dann machst du nicht diese dummen Fehler.
Kein Grund das Rad immer wieder neu zu erfinden.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie meinst du das mit dem Zurücksetzen? sollte ich nach der Wandlung des 
ADC1 z.b. alle Bits auf 0 sezten, damit wenn der ACD3 initialisiert 
wird, keine Fehler auftreten oder verstehe ich da iwas nicht :)

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ADMUX |= 0xC1;
  ADMUX |= 0xC3;

>oder verstehe ich da iwas nicht :)

Genau, du verstehst das Oder nicht.

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

Bewertung
0 lesenswert
nicht lesenswert
Alex schrieb:
> Wie meinst du das mit dem Zurücksetzen?

Zurücksetzen, so wie in 'ein Bit welches auf 1 gestellt wurde auch 
wieder mal auf 0 zurücksetzen'. Denn wenn man es nicht tut, dann bleibt 
es auf immer und ewig auf 1
Wiwe zb bei dir die Bits, die die Kanalauswahl des ADC steuern.

Wobei die Frage immer noch nicht beantwortet ist, was an den Tutorial 
Routinen so schrecklich ist. Die machen das nämlich richtig

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Doch doch ... es gibt einmal |= (1<<x) um ein Bit zu setzen und &= 
~(1<<x) um eines zu löschen :) aber wieso klappt das dann beim ersten 
mal richtig? Es müsste eigentlich auch dort schon Fehler geben oder?

Autor: holger (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Doch doch ... es gibt einmal |= (1<<x) um ein Bit zu setzen und &=
>~(1<<x) um eines zu löschen :)

Und warum benutzt du das dann nicht?

> aber wieso klappt das dann beim ersten
>mal richtig? Es müsste eigentlich auch dort schon Fehler geben oder?

Weil die Bits nach einem Reset alle auf 0 sind.

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

Bewertung
0 lesenswert
nicht lesenswert
Vielleicht haben wirs ja auch übersehen.
Also: Wo soll das den in obigen Programm sein?

Ganz konkret am Register ADMUX. Denn dort steht ja drinn welcher Kanal 
gesampelt werden soll.

Autor: Alex (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also hatte das ganze auch schon mit 4 wandlern gemacht und nacheinander 
von adc0-3 gewandelt. Adc0 klappt ja, adc1 natürlich auch aber bei adc2 
müsste erst doch eigentlich adc3 wandeln da ja das erste und zweite Bit 
dann schon gesetzt sind... aber er hat mir da trotzdem adc2 gewandelt. 
Das hat mich vllt auch so konfus gemacht hehe

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.