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();
@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
voidmeine_funktion(int*pVar1,int*pVar2)
2
{
3
*pVar1=0;
4
*pVar2=1;
5
}
6
7
voidmeine_andere_funktion(void)
8
{
9
intVar1;
10
intVar2;
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
intmeine_funktion(void)
2
{
3
return(15);
4
}
5
6
voidmeine_andere_funktion(void)
7
{
8
intwert;
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.
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
voidmain(void){
2
uint8_tmain_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...
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