AVR C - Rückgabewert von Funktion nicht richtig

OP #6506964
Lesenswert?

Hallo zusammen,

ich habe folgenden Code, der in der while-Schleife hängen bleibt (auch 
wenn ENFG = 1 ist):
1
void at90can_can_controller_activate(void)
2
{
3
  // -- CAN General Control Register --
4
  CANGCON |= (1 << ENASTB);  // enable mode -> activate CAN controller
5
  //wait for controller to be enabled  
6
        while(at90can_can_controller_get_status() != 1);
7
}
8

9
uint8_t at90can_can_controller_get_status(void)
10
{
11
  return CANGSTA & (1 << ENFG);
12
}
Füge ich jetzt die Abfrage direkt ein, dann funktioniert es:
1
void at90can_can_controller_activate(void)
2
{
3
  // -- CAN General Control Register --
4
  CANGCON |= (1 << ENASTB);  // enable mode -> activate CAN controller
5
  //wait for controller to be enabled  
6
        while(CANGSTA & (1 << ENFG) != 1);
7
}
Hat jemand eine Erklärung dafür?
Danke im vorraus!
Beitrag #6507018 wurde von einem Moderator gelöscht.
Gast #6507034
Lesenswert?

my2ct schrieb:
> Das ist ein boolscher Ausdruck.

Falls du das & meinst: Nein, das ist eine bitweise Verknüpfung:4

1
    CANGSTA = 2 = 0b00000010
2
(1 << ENFG) = 2 = 0b00000010
3
                 ------------
4
Ergebnis von &:   0b00000010

Das Ergebnis ist 2, wenn beide Operanden = 2 sind. Und zwei ist wahr, 
wenn man es in einem booleschen Ausdruck verwendet. Kleiner Test mit 
if():

1
#include <stdio.h>
2

3
int main()
4
{
5
    int ENFG=1;
6
    
7
    int CANGSTA=0;
8
    if (CANGSTA & (1 << ENFG))
9
    {
10
        printf("CANGSTA=0 ist wahr \n");
11
    }
12
    
13
    CANGSTA=1;
14
    if (CANGSTA & (1 << ENFG))
15
    {
16
        printf("CANGSTA=1 ist wahr \n");
17
    }
18
    
19
    CANGSTA=2;
20
    if (CANGSTA & (1 << ENFG))
21
    {
22
        printf("CANGSTA=2 ist wahr \n");
23
    }
24
}

Erzeugt die Ausgabe:
1
CANGSTA=2 ist wahr


Aber: Beim TO ist das kein Boolescher Ausdruck. Er liefert das Ergebnis 
als uint8_t zurück. Deswegen ist sein Ergebnis immer 0 oder 2, also 
niemals 1.
Moderator (Firma: Titel) Persönliche Seite #6507555
Lesenswert?

J. B. schrieb:
> Füge ich jetzt die Abfrage direkt ein, dann funktioniert es:
Wenn du "bleibt nicht hängen" als "funktioniert es" definierst, dann 
schon.

J. B. schrieb:
> auch wenn ENFG = 1 ist
ENFG ist laut Datenblatt das Bit 2 im Register CANGSTA und damit ist der 
#define ENFG auch immer 2.
Du meinst vermutlich den Pegel des Flags ENFG.

Peter D. schrieb:
> Zuerst wird != ausgeführt, danach erst das &.
Und weil 1<<2 = 4 und damit 4 != 1 ist, ist das Ergebnis dieses 
Vergleichs 1. Und deshalb wird mit der Abfrage:
while(CANGSTA & (1 << ENFG) != 1);
tatsächlich das abgefragt:
while(CANGSTA & 1);
und das betrifft das ERRP Bit, das nur dann 1 wird, wenn der Controller 
in den Fehlermodus geht.

@  J. B. (jbme)
Im Grunde musst du deine Abfrage also so schreiben, dann passiert das, 
was du eigentlich wollltest:
while( (CANGSTA&(1<<ENFG)) != (1<<ENFG) );

Und natürlich musst du diese Geschichte auch bei dem 
Funktionsrückgabewert beachten.

my2ct schrieb:
>> CANGSTA & (1 << ENFG)
> Das ist ein boolscher Ausdruck.
Du verwechselst das binäre "&" mit dem logischen "&&"
Angehängte Dateien:
OP #6507690
Lesenswert?

Vielen Dank für eure Antworten! Ich habe meinen Code entsprechend 
angepasst:
1
void at90can_can_controller_activate(void)
2
{
3
  // -- CAN General Control Register --
4
  CANGCON |= (1 << ENASTB);  // enable mode -> activate CAN controller
5
  //wait for controller to be enabled  
6
  while(at90can_can_controller_get_status() == false);
7
}
1
bool at90can_can_controller_get_status(void)
2
{
3
  return CANGSTA & (1 << ENFG);
4
}
Moderator (Firma: Titel) Persönliche Seite #6507701
Lesenswert?

J. B. schrieb:
> return CANGSTA & (1 << ENFG);
Diese Rechung ergibt 4, wenn das ENFG Flag gesetzt ist.
Wenn aber ein bool mit 1=true und 0=false ist, was ist dann mit diesen 
4?

Wenn du also schon einen boolschen Rückgabewert definierst, dann 
solltest du korrekterweise auch einen boolschen Wert für die Rückgabe 
berechnen:
1
return (CANGSTA & (1<<ENFG)) != 0; // gibt true zurück, wenn das Flag gesetzt ist

Und dann liest sich sowas natürlich doof:
1
if (at90can_can_controller_get_status() == false)
Wenn du das nämlich in einem Jahr liest, dann denkst du dir:
Was zum Senkel soll denn an dem Controllerstatus "falsch" oder "wahr" 
sein?
Gast #6507763
Lesenswert?

>> return CANGSTA & (1 << ENFG);

Lothar M. schrieb:
> Diese Rechung ergibt 4, wenn das ENFG Flag gesetzt ist.
> Wenn aber ein bool mit 1=true und 0=false ist, was ist dann mit diesen
> 4?

Er liefert true zurück, wenn der Ausdruck wahr ist. Und 4 ist wahr.

Das ist eine Besondertheit bei bool.
Beitrag #6507765 wurde von einem Moderator gelöscht.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren