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
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.
> 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
@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
@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
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.
> 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
@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...
@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();
@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
@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
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.
> 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
@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
> 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.
oh, dann hatte Stefan(Gast) das ja vorhin schon beantwortet, is denn wohl in der SPI-Geschichte untergegangen Danke Euch nochmal! greetz Danny
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
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
@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
>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
@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...
@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
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.
@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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.