Forum: Compiler & IDEs Anfägerfrage Variablenübergabe


von Danny P. (Gast)


Lesenswert?

Hi zusammen :-)

Nun ham´se mich in nem anderen Thread wild gemacht noch mal in C 
reinzuschnuppern (bisher nur mit ASM gearbeitet)....

da hab ich doch gleich mal ´ne Frage:

mit folgender Routine wird ein Byte welches in "SPI_Byte" steht per SPI 
aus-/eingetaktet und anschliessend der Inhalt von SPDR zurückgegeben.

// SPI Senderoutine
int  SPI(uint8_t SPI_Byte)
{
  SPDR = SPI_Byte;
  while( !( SPSR & (1<<SPIF) ) );
  return  SPDR;
}

// Abfrage CANINTF von MCP2515
void MCP_Interrupt(uint8_t FlagRegister )
{
  MCP_akt();
    SPI  (SPI_READ); // LeseBefehl
    SPI  (CANINTF);  // InterruptFlagRegister vom MCP2515 lesen
    SPI  (0x00);     // DummyByte
  MCP_deakt();

         if(bit_is_set(FlagRegister,RX0IF))
//  Nachricht im Rx0 vorhanden
    {

    }
}


Hiermit lese ich ein Byte aus dem Speicher eines MCP2515 ein. Mir gehts 
um die Variablenübergabe der beiden Routinen.
Ist definitiv sicher gestellt das wenn ich SPI() mit einem Byte aufrufe 
dieses innerhalb der Routine als "SPI_Byte" verfügbar ist?

Und noch wichtiger: Ist definitiv sicher gestellt das durch mein "return 
SPDR" das per SPI eingelesene Byte an "MCP_Interrupt" übergeben wird un 
innerhalb der Routine als "FlagRegister" verfügbar ist?

Ich hab mir das Listfile angesehen, und er machts genau wie ich will.
Nur hab ich mit C bisher nich viel am Hut und möcht das gern noch mal 
bestätigt wissen, kann ja in diesem Miniprogramm auch Zufall sein.

Also stell ich mir das so richtig vor? Die Reihenfolge übergebener oder 
zurückgegebener Werte entspricht genau der Reihenfolge meiner 
Definitionen in der Klammer hinter z.B. "int SPI"?

thx & greetz
Danny

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Du solltest Dir sofort abgewöhnen, Funktionsnamen (oder auch Variablen) 
komplett in GROSSBUCHSTABEN zu schreiben. Diese Notation ist für 
Präprozessordefinitionen (#define) vorgesehen.

Deine Funktion "SPI" gibt zwar einen Wert zurück, Dein Aufruf dieser 
Funktion  (in der Interruptroutine) wertet den Rückgabewert der Funktion 
gar nicht aus.

Hingegen ist Deine Annahme über den der Funktion "SPI" übergebenen 
Parameter richtig, der ist in der Tat während der Laufzeit der Funktion 
mit dem Namen "SPI_Byte" verfügbar.



von Stefan (Gast)


Lesenswert?

> Ist definitiv sicher gestellt das wenn ich SPI() mit einem Byte aufrufe
> dieses innerhalb der Routine als "SPI_Byte" verfügbar ist?

Ja.

> Und noch wichtiger: Ist definitiv sicher gestellt das durch mein "return
> SPDR" das per SPI eingelesene Byte an "MCP_Interrupt" übergeben wird un
> innerhalb der Routine als "FlagRegister" verfügbar ist?

Nein. Du machst nirgends eine Zuweisung an FlagRegister. Ist der 
Rückgabewert von SPI() tatsächlich int oder eher uint8_t bzw. int8_t?

> Also stell ich mir das so richtig vor? Die Reihenfolge übergebener oder
> zurückgegebener Werte entspricht genau der Reihenfolge meiner
> Definitionen in der Klammer hinter z.B. "int SPI"?

Teilweise. Übergeben ja. Zurück bekommst du nie was; da bräuchtest du 
eine Zeile in der Art:

FlagRegister = SPI(CANINTF);  // InterruptFlagRegister vom MCP2515 lesen




von Danny P. (Gast)


Lesenswert?

@Rufus t. Firefly: mh... mit der Groß-/Kleinschreibung werd´ ich mal 
versuchen :-)

> Deine Funktion "SPI" gibt zwar einen Wert zurück, Dein Aufruf dieser
> Funktion  (in der Interruptroutine) wertet den Rückgabewert der Funktion
> gar nicht aus.

Wie müsste denn ein Aufruf der Funktion SPI lauten um den Rückgabewert 
auszuwerten, bzw. in der MCP_interrupt verfügbar zu haben?

Denn wars ja doch Zufall das es geklappt hat, denn im Listfile fragt er 
bei
>   if(bit_is_set(FlagRegister,RX0IF))
das gleiche Register ab in das er bei Verlassen der Funktion SPI das 
SPDR geschrieben hat



thx & greetz
Danny

von Danny P. (Gast)


Lesenswert?

@Stefan:
> eine Zeile in der Art:
mh... in der Art? oder genau so eine? :-)

also wäre es so richtig:


// Abfrage CANINTF von MCP2515
void MCP_Interrupt(uint8_t FlagRegister )
{
  MCP_akt();
    SPI  (SPI_READ); // LeseBefehl
    SPI  (CANINTF);  // InterruptFlagRegister vom MCP2515 lesen
    Flagregister = SPI  (0x00);     // DummyByte
  MCP_deakt();

  if(bit_is_set(FlagRegister,RX0IF))
//  Nachricht im Rx0 vorhanden
    {

    }
}

warum der es im asm-Listing dennoch geklappt hat frag ich mich 
immenroch... grübel  na, wohl Zufall

aber wie schreibe ich es wenn ich z.B. zwei Variablen (uint8_t) 
übergeben will?

thx & greetz
Danny

von Stefan (Gast)


Lesenswert?

Ich kenne mich mit SPI nicht aus und bin von deinem Kommentar bei 
"meiner" Zeile ausgegangen. Meine Lesart des Kommentars war, dass du 
einen Wert lesen willst. Zum Lesen gehört meistens, dass der Wert 
irgendwo gespeichert wird. Irgendwo habe ich angekommen, soll das 
FlagRegister sein, weil der Kommentar verdammt danach aussieht.

> warum der es im asm-Listing dennoch geklappt hat frag ich mich
> immenroch... grübel  na, wohl Zufall

Was hat im ASM-Listing geklappt? Definitiv nicht, dass FlagRegister 
einen Wert aus SPI() erhält.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> aber wie schreibe ich es wenn ich z.B. zwei Variablen (uint8_t)
> übergeben will?

int meine_funktion(uint8_t variable1, uint8_t variable2)
{
  return (variable1 * variable2);
}


Literaturempfehlung:
Kernighan & Ritchie, Programmieren in C, zweite Auflage, Hanser-Verlag

von Danny P. (Gast)


Lesenswert?

@Stefan: SPI hat ein Datenregister SDPR. Wird ein Byte hineingeschrieben 
wird dies einerseits Bit für Bit per MOSI ausgetaktet und gleichzeitig 
die Bits per MISO eingetaktet.

Das bedeutet durch senden des dummybytes habe ich die gewünschte 
Speicherstelle des MCP (die ich vorher ja per SPI ausgewäjöt habe) im 
SPDR - rein hardwaremässig und das läuft auch alles...

von Danny P. (Gast)


Lesenswert?

@Rufus t. Firefly: ja ok, ich meinte die Stelle an der ich die Werte 
verwenden möchte

muss ich dann zwei Zeilen schreiben:

variable1_af = meine_funktion();
variable2_af = meine_funktion();


von Stefan K. (_sk_)


Lesenswert?

@Danny:
Was Du willst, ist 2 Werte ZURÜCKBEKOMMEN.

Das geht in C nur mit "call by reference". Auf Deutsch: Du musst die 
Adresse des Wertes angeben:
1
// Diese Funktion gibt zwar NICHTS zurück, verändert die beiden
2
// übergebenen Variablen aber trotzdem:
3
// zu beachten: die Sternchen (*) vor den Variablen im Header geben an,
4
// dass hier duie Adressen die Variablen übergeben werden:
5
6
void meine_funktion(uint8_t *variable1_af_ptr, uint8_t *variable2_af_ptr){
7
  *variable1_af_ptr = 10;  // das Sternchen zeigt: die Variable, auf die
8
  *variable1_af_ptr = 20;  // dieser Pointer zeigt, wird beschrieben
9
}
So sieht dann der Aufruf aus:
1
void main(){
2
  uint8_t var1;
3
  uint8_t var2;
4
5
  var1 = 1;
6
  var2 = 2;
7
8
  meine_funktion(&var1, &var2);
9
 
10
  // jetzt ist var1 == 10 und var2 == 20
11
  while(1);
12
}

Viele Grüße, Stefan

von Danny P. (Gast)


Lesenswert?

@Stefan: Mensch... nun hab ich den steinigen Weg den ich gestern meinte 
:-D
es scheint so einfach aber ich hab voll das Brett vorm Kopf, hab echt 
gelesen aber ich schnalls nich...

in deinem Beispiel sollte ich doch
>  *variable1_af_ptr = 10;  // das Sternchen zeigt: die Variable, auf die
durch "variable1_af_ptr = 10;" ersetzen können, oder? Die an 
"meine_funktion" übergebenen Variablen sind doch eh innerhalb der 
Funktion unter dem Namen verfügbar?

>  meine_funktion(&var1, &var2);
>
>  // jetzt ist var1 == 10 und var2 == 20
ja... das sind sie nun, aber wie lese ich diese nun ein? ich stecke in 
deinem Beispiel nun wieder in der main. sagen wir mal die Funktion 
"meine_funktion" wurde mit

"return (variable1_af_ptr, variable2_af_ptr)" beendet.

wie komme ich in der main an diese übergebenen Bytes?


thx & greetz
Danny

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Hier das ganze mal ohne Rückgabewerte, rein als "call-by-reference" mit 
Pointern implementiert:
1
void meine_funktion(int* pVar1, int* pVar2)
2
{
3
  *pVar1 = 0;
4
  *pVar2 = 1;
5
}
6
7
void meine_andere_funktion(void)
8
{
9
  int Var1;
10
  int Var2;
11
12
  meine_funktion(&Var1, &Var2);
13
}

Ansonsten wiederhole ich mich, indem ich DRINGENDST dazu rate, ein Buch 
über die Grundlagen der Programmierung in C wie "Programmieren in C" von 
Kernighan & Ritchie in der durchaus passablen deutschen Übersetzung der 
zweiten Auflage zu lesen.
Wirklich. Dringendst.




von Stefan (Gast)


Lesenswert?

> sagen wir mal die Funktion "meine_funktion" wurde mit
> "return (variable1_af_ptr, variable2_af_ptr)" beendet.

Geht nicht. Eine Funktion kann mit return keinen oder exakt einen Wert 
zurückgeben.

Funktionen sind z.B. hier erklärt:
http://www.pronix.de/pronix-620.html

Deshalb der Umweg über die Zeiger. Die Funktion bekommt als Eingangsinfo 
zwei Adressen, wo was gespeichert werden sollen. Damit kann die Funktion 
dann auch zwei Ergebnisse liefern.

Zeiger sind z.B. hier erklärt:
http://www.pronix.de/pronix-623.html

von Danny P. (Gast)


Lesenswert?

@Stefan: danke für den Link, nun grab ich mich da ersmal durch.
Ok, es kann also max. ein Wert per return zurückgeliefert werden.

mach ich in meinem Beispiel aus dem ersten Posting ja auch (return 
SPDR;)
wie komme ich in der main, bzw. in der Funktion die SPI aufgerufen hat 
an den zurückgelieferten Wert?

Anfänger hin oder her :-) aber die Funktionen liefern doch nich was 
zurück was dann umständlich mit nem Zeiger gelesen werden muß? Das muß 
doch ähnlich einfach gehen wie die Datenübergabe bei Aufruf einer 
Funktion, oder?  wein

@Rufus t. Firefly: habe dein Hinweis auf die Literatur nicht übersehen 
oder ignoriert. Ich beginne nur grad ein etwas umfangreicheres Projekt, 
habe die minimalen Grundfunktionen in asm fertig und will das nun einmal 
in C machen um zu entscheiden ob ich mit C weitermach oder doch lieber 
in asm.
Sollte das Reinschnuppern in C geschmeckt haben ist Literatur sicher 
sinnvoll, das stimmt.
Und als Neuling einfach da stehendes C-Code zu verstehn ist nicht schön 
:-D daher meine ganzen Fragen ;-)

thx & greetz
Danny

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> wie komme ich in der main, bzw. in der Funktion die SPI aufgerufen hat
> an den zurückgelieferten Wert?

Na, ganz einfach:
1
int meine_funktion(void)
2
{
3
  return (15);
4
}
5
6
void meine_andere_funktion(void)
7
{
8
  int wert;
9
10
  wert = meine_funktion();
11
}

Auf diesem "Level" solltest Du vielleicht erstmal in ein Buch (oder 
meinetwegen ein Tutorial) 'reinschnuppern, da sonst hier massive 
Frustrationen freigesetzt werden. Einen Literaturtip habe ich Dir schon 
gegeben, jetzt setz Dich mal hin und lies ein paar Stunden lang.

Hier weitere Fragen zu stellen mit offensichtlichem 
nicht-selbst-lernen-wollen wird zu zunehmend ruppigeren bis massiv 
unhöflichen Kommentaren führen.

von Danny P. (Gast)


Lesenswert?

oh, dann hatte Stefan(Gast) das ja vorhin schon beantwortet, is denn 
wohl in der SPI-Geschichte untergegangen

Danke Euch nochmal!

greetz
Danny

von Stefan K. (_sk_)


Lesenswert?

Ich glaube, Du hast gerade einen Knoten im Kopf. Es ist viel einfacher, 
als Du denkst:

>mach ich in meinem Beispiel aus dem ersten Posting ja auch (return
>SPDR;)
>wie komme ich in der main, bzw. in der Funktion die SPI aufgerufen hat
>an den zurückgelieferten Wert?

1
void main(void){
2
  uint8_t main_var;
3
4
  main_var =  SPI (SPI_READ);
5
6
  // jetzt steht in main_var der Wert, den Du gerade in der
7
  // Funktion SPI() aus SPDR ausgelesen hast

Schwieriger wird es nur, wenn Du MEHERERE Werte von einer Funktion 
zurück haben willst.

Hoffe, ich habe Dein Problem richtig verstanden ...

Schick doch mal Dein .asm-File.


Gruß, Stefan

von Stefan K. (_sk_)


Lesenswert?

Hi Rufus,

>Auf diesem "Level" solltest Du vielleicht erstmal in ein Buch (oder
>meinetwegen ein Tutorial) 'reinschnuppern, da sonst hier massive
>Frustrationen freigesetzt werden. Einen Literaturtip habe ich Dir schon
>gegeben, jetzt setz Dich mal hin und lies ein paar Stunden lang.

Ist auch ein bischen meine Schuld - weil ich ihm (in einem anderen 
Thread) geraten hatte, so ein Projekt doch besser in C anzugehen.

Gruß, Stefan


von Danny P. (Gast)


Lesenswert?

@Stefan: Warum Deine Schuld? Vielleicht bin ich dir in zwei Wochen ja 
auch unendlich dankbar für diesen Stoß ins kalte Wasser ;-)

naja... man kann geteilter Meinung sein... der eine findet man müllt 
dadurch das Forum voll... der andere (ich z.B.) findet es total Klasse 
hier drüber zu "schnacken"

mh, welches asm-File meinst Du genau Stefan?

so, nun erst ma wieder zum Bau, später hier weiter :-)


greetz
Danny

von Stefan K. (_sk_)


Lesenswert?

>Vielleicht bin ich dir in zwei Wochen ja
>auch unendlich dankbar für diesen Stoß ins kalte Wasser ;-)

Wenn Du Assembler kannst, ist es nur halb so schlimm, meine eigene 
Erfahrung:
Bei vielen C-Konstrukten siehst Du (nach einer Weile) den 
Assemblerbefehl, der dahintersteht. Vor allem beim ATmega, weil der 
viele C-Konstrukte gut unterstützt.

Beispiel:

  uint8_t mein_wert;
  uint8_t *mein_pointer = &irgendwas;

  mein_wert = *mein_pointer++;

wenn Du Assembler kannst, mag es beim Lernen sinnvoll sein, den 
Assembler-Output des gcc anzuschauen. Da wird oft vieles klarer. 
Ausserdem bekommt man mit der Zeit ein Gefühl dafür, was der Compiler so 
macht.


>mh, welches asm-File meinst Du genau Stefan?

Das .asm File, das Du nach C übersetzen willst ...

Gruß, Stefan

von Danny P. (Gast)


Lesenswert?

@Rufus t. Firefly :

danke für Deine Hilfe... aber wenn du
> offensichtlichem nicht-selbst-lernen-wollen
ernst meinst... naja...

Ich hab keine Lust mich zu hier zu verteidigen, aber ich lese seit 
gestern Abend inkl. der halben Nacht. Den "Schnuppergrund" habe ich auch 
dargelegt.
Mir das so zu unterstellen naja... denn überlies doch "Anfängerfragen" 
in Zukunft besser. Und Warum gibts denn so ein Forum hier? ALLES was 
hier besprochen wird ist IRGENDWO nachzulesen...





von Danny P. (Gast)


Lesenswert?

@Stefan: per Mail oder hier?  nich das ich wieder unnütz das Forum 
zumülle :-D

mach ich nachher, ok? muss mich nun echt erstmal losreissen


greetz
Danny

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Bevor Du jetzt trotzig reagierst:
Du hast schon mitbekommen, daß ich Dir den einen oder anderen Hinweis 
gegeben habe? Und daß ich erst nach mehreren Beiträgen nach einem 
weiteren Hinweis vorsichtig angedeutet habe, daß Du auch etwas 
Eigeninitiative zeigen solltest.

Außerdem gewann ich zunehmend den Eindruck, daß Du Dir gegebene 
Antworten nicht sehr genau gelesen hast ...

Werteübergabe an Funktionen und Werterückgabe von Funktionen ist 
absoluter Urschleim in so ziemlich jeder Programmiersprache, erst bei so 
Dingen wie "call-by-reference" wird es je nach Programmiersprache 
kompliziert bzw. unübersichtlich.

von Danny P. (Gast)


Lesenswert?

@Rufus t. Firefly: trotzig? ich habe mich doch für deine Hilfe bedankt 
und weiß sie zu schätzen.
Nur bevor du das -offensichtlich-nicht-selbst...." geschrieben hast war 
ich schon auf dein Literaturvorschlag eingegangen und hatte erklärt das 
ich in diesem Moment nur was kleines schnell zum Laufen bringen 
wollte... dazu habe ich mich halt nach 12Std. Inet-Suche und Tests mal 
des Forums bedient.

Stefan wird bestätigen können wann der "Startschuß" des Ganzen war :-D

zum "nicht genau durchgelesen"... glaub mir das habe ich. Nur fertiger 
C-Code für nen absoluten Neuling... es ist wirklich nicht einfach, ich 
glaub das würden andere auch so sehen


mh... also... Frieden? :-D


greetz
Danny

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.