Forum: Mikrocontroller und Digitale Elektronik if Verschachtelung


von Beginner (Gast)


Lesenswert?

Hallo,

mein Programm bleibt in der ersten if Abfrage hängen die LED blinkt aber 
wenn die Spannung <= 7400 geht es nicht mehr in die andere if Abfrage.

Wo is der Logikfehler? (und ja vor dem PC schon klar ;-))
1
int VoltageMonitoring (void)
2
{
3
 __disable_interrupt();
4
5
  uint16_t WandleWertIn16Bit (uint8_t Address)
6
  {
7
    uint16_t Wert;
8
    uint8_t  lowByte, highByte;
9
    smb_start_wait(AdresseSlave_1+SMB_WRITE);
10
    smb_write (Address);
11
    smb_rep_start(AdresseSlave_1+SMB_READ);
12
13
    lowByte = smb_readAck();
14
    highByte = smb_readNak();
15
    smb_stop();
16
17
    Wert = ( highByte << 8 ) | lowByte;
18
19
    return Wert;
20
  }
21
22
uint16_t Akkuspannung;
23
Akkuspannung = WandleWertIn16Bit(0x09);
24
25
    if (Akkuspannung <=  7800)
26
    {
27
      PORTC |=  (1 << PC0 | 1 << PC4 | 1 << PC1 | 1 << PC5 | 1 << PC3 | 1 << PC2);
28
      while (1)
29
      {
30
        Akkuspannung = WandleWertIn16Bit(0x09);
31
        PORTB |= (1 << PB2);  // LED_ROT blinken
32
        _delay_ms(1000);
33
        PORTB &= ~ (1 << PB2);
34
        _delay_ms(50);
35
        PORTB |= (1 << PB1);  
36
        _delay_ms(1000);
37
        PORTB &= ~ (1 << PB1);
38
        _delay_ms(50);
39
      }
40
    }
41
    
42
    else
43
    { 
44
      if (Akkuspannung <= 7400)
45
      {  
46
        while (1)
47
        {  PORTC &=~  (1 << PC0 | 1 << PC4 | 1 << PC1 | 1 << PC5 | 1 << PC3 | 1 << PC2);  
48
          PORTB |= (1 << PB1);  // LED_ROT blinken
49
          _delay_ms(500);
50
          PORTB &= ~ (1 << PB1);
51
          _delay_ms(500);
52
        }
53
      }
54
    }
55
__enable_interrupt(); 
56
}

: Bearbeitet durch User
von Justus S. (jussa)


Lesenswert?

wie willst du aus den while-Schleifen kommen?

von (prx) A. K. (prx)


Lesenswert?

if (Akkuspannung <=  7800)
{
  ...
}
else
{
  if (Akkuspannung <= 7400)
  {
    ...
    }
  }
}

Wie soll dabei die zweite Abfrage eine Chance haben?

: Bearbeitet durch User
von Chris (Gast)


Lesenswert?

weil 7399 < 7800
ist und daher die erste If-Abfrage schon wahr ist.
Die zweite wird nie erreicht.

von Bastler (Gast)


Lesenswert?

>mein Programm bleibt in der ersten if Abfrage hängen die LED blinkt aber
>wenn die Spannung <= 7400 geht es nicht mehr in die andere if Abfrage.


Ja, klar! Wie auch?

Du hast eine while(1) Schleife programmiert!

von Beginner (Gast)


Lesenswert?

wie müsste ich denn die Abfrage gestalten?

es sollte wie folgt logisch ablaufen:

ist die Spannung <= 7800

dann soll die LED erst grün dann rot blinken und noch alle anderen LEDs 
sollen an sein

wenn die Spannung aber <= 7400

ist dann sollen alle LEDs aus sein nur die Statusled soll rot schnell 
blinken.

Wie schreiben ich das in C

switch / case geht ja auch nicht da dort kein Bereichsüberprüfung 
gemacht werden kann.

von Beginner (Gast)


Lesenswert?

hat keiner ne Idee?

von Justus S. (jussa)


Lesenswert?

Beginner schrieb:
> ist die Spannung <= 7800
>
>
> wenn die Spannung aber <= 7400

öhm, den Widerspruch bemerkst du nicht?

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

die allgemeine Syntax für if Abfragen lautet:

if BEDINGUNG then ANWEISUNG

BEDINGUNG kann durchaus auch ein zusammengesetzter, mehrteiliger 
Ausdruck sein. Damit alles zusammen passt was zusammen gehört solltest 
du großzügig Klammern spendieren.

von Udo S. (urschmitt)


Lesenswert?

Die while (1) nach aussen.
Dann die Werte so abfragen, daß die erste Abfrage nicht gleich die 2te 
mit einschliesst.
Versuch das mal selbst, du kriegst das hin. Wenn wir dirs hier 
vorprogrammieren lernst du fast nix dabei.

von Beginner (Gast)


Lesenswert?

hab es jetzt so umgeschrieben funktioniert leider immer noch nicht. Ich 
sehe aber nicht warum..


int VoltageMonitoring (void)
{
 __disable_interrupt();

  uint16_t WandleWertIn16Bit (uint8_t Address)
  {
    uint16_t Wert;
    uint8_t  lowByte, highByte;
    smb_start_wait(AdresseSlave_1+SMB_WRITE);
    smb_write (Address);
    smb_rep_start(AdresseSlave_1+SMB_READ);

    lowByte = smb_readAck();
    highByte = smb_readNak();
    smb_stop();

    Wert = ( highByte << 8 ) | lowByte;

    return Wert;
  }

while (1){
uint16_t Akkuspannung;
Akkuspannung = WandleWertIn16Bit(0x09);

      if (Akkuspannung <=  7800)
      {
        PORTC |=  (1 << PC0 | 1 << PC4 | 1 << PC1 | 1 << PC5 | 1 << PC3 
| 1 << PC2);
        Akkuspannung = WandleWertIn16Bit(0x09);
        PORTB |= (1 << PB2);  // LED_ROT blinken
        _delay_ms(1000);
        PORTB &= ~ (1 << PB2);
        _delay_ms(50);
        PORTB |= (1 << PB1);
        _delay_ms(1000);
        PORTB &= ~ (1 << PB1);
        _delay_ms(50);
      }

      else
        {
          if (Akkuspannung <= 7400)
          {

            PORTC &=~  (1 << PC0 | 1 << PC4 | 1 << PC1 | 1 << PC5 | 1 << 
PC3 | 1 << PC2);
            PORTB |= (1 << PB1);  // LED_ROT blinken
            _delay_ms(500);
            PORTB &= ~ (1 << PB1);
            _delay_ms(500);

          }
        }


     }

__enable_interrupt();
}

von Justus S. (jussa)


Lesenswert?

weil du immer noch nicht checkst, dass ein Wert, der kleiner als 7400 
ist, auch kleiner als 7800 ist...

von Gerhard (Gast)


Lesenswert?

Vertausch mal die 7400 und die 7800, dann wird die 7400 zuerst behandelt 
und wenn Wert größer dann wird alles was kleiner 7800 ist behandelt.

von Claude M. (stoner)


Lesenswert?

Beginner schrieb:
> wie müsste ich denn die Abfrage gestalten?

Entweder du schaust, dass du nicht schon in den ersten Block fällst wenn 
die Akkuspannung kleiner gleich 7400 ist. Also:

if ((Akkuspannung <= 7800) && (Akkuspannung > 7400))
{
  ...
}
else if (Akkuspannung <= 7400)
{
  ...
}


oder du tauschst die Reihenfolge der if Statements (inkl. dem was 
zwischen den Klammern steht):

if (Akkuspannung <= 7400)
{
  ...
}
else if (Akkuspannung <= 7800) // d.h. 7400 < Akkuspannung <= 7800
{
  ...
}

D.h. ist Akkuspannung <= 7800 endest du in einer der beiden 
Endlosschleifen (von da geht's dann aber nie mehr raus). Ist 
Akkuspannung > 7800 kehrst du aus der Funktion zurück? Ist das das was 
du willst? Wenn ja, dann funktioniert das jetzt zwar, du solltest es 
aber trotzdem nicht tun. Eine Funktion, die manchmal endet und manchmal 
nicht, ist seeeehr hässlich und unbedingt zu vermeinden.


Gruss
Claude

von Bastler (Gast)


Lesenswert?

Normalerweise setzt man nur einen Status für die LED und handelt diesen 
in einem Timer ab.

_delay_ms(500); ist nur eine Notlösung, warum wirst du erkennen wenn der 
Controller noch etwas Anderes machen soll...

und die uint16_t Akkuspannung; muss nicht in der while(1) sein.

von Wegstaben V. (wegstabenverbuchsler)


Lesenswert?

Bastler schrieb:
> und die uint16_t Akkuspannung; muss nicht in der while(1) sein.

bitte präziser:

Die DEKLARATION der Variable sollte nicht in der While schlefe sein, 
sondern kann / soll außerhalb liegen

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.