Hallo, ich versuche einen String den ich über einen Mega32 sende mit
einem mega8 zu einem display zu senden. Leider hab ich absolut keine
Ahnung was mein Denkfehler in der Empfangsroutine ist.
1
// sende routine atmega 32
2
voidMaster_Send(char*wert)
3
{
4
PORTD|=(1<<PD7);
5
while(*wert)
6
{
7
SPDR=*wert;// send Character
8
while(!(SPSR&(1<<SPIF)));// wait until Char is sent
9
wert++;// Point to next char in String
10
}
11
PORTD&=~(1<<PD7);
12
}
13
14
// empfangsroutine Atmega8
15
voidSlave_Receive(void)
16
{
17
char*text="";
18
while(SPDR)
19
{
20
while(!(SPSR&(1<<SPIF)));// Wait until Char is received
> void Slave_Receive (void)> {> char* text="";
No.
Du hast keinen Speicher, in den du die empfangenen Character ablegen
könntest, brauchst aber einen.
Ein Pointer ist einfach nur ein Zeiger, ein Verweis auf den echten
Speicher. Er ist aber NICHT der Speicher selber
char text[80]; // Platz für 80 Charcater
Jetzt hast du tatsächlich ein Speicherfeld, in dem du Daten ablegen
kannst. In deinem Fall eben einen String.
while(!(SPSR&(1<<SPIF)));// Wait until Char is received
4
// Check if Char (Byte) is received correctly
5
*text=SPDR;
6
text++;// Set Pointer on next Character
7
}
geht so auch nicht.
Aus mehreren Gründen.
ZUm einen ist es deine Verwendung von text, die es dir unmöglich macht
im Nachhinein text zu benutzen um den Anfang des Textes wiederzufinden.
Zum anderen kannst du die while Schleife so nicht machen. Wenn du einen
String empfängst, dann muss dir der Sender in irgendeiner Form
signalisieren, wann der String zu Ende ist. Das kann es zb machen, indem
er vorab bekannt gibt, wieviele Zeichen er zu senden gedenkt. Oder aber
er kann es zb machen, in dem vereinbart wird, mit welchem Zeichen ein
String beendet wird. C benutzt üblicherweise die letzte Vereinbarung, in
dem dem \0 Characer diese spezielle Bedeutung zu kommt. Das muss nicht
so sein, man könnte auch jedes andere Zeichen nehmen, welches im
eigentlichen Text niemals vorkommen wird. Du zb benuzt ein spezielles
Zeichen, wenn du deinen Computer über die Command Line benutzt. Die
Return Taste erfüllt diese Aufgabe, in dem sie das Zeichen \n generiert,
welches dem mithörenden Programm anzeigt: Jetzt ist eine Eingabezeile zu
Ende und es wird erwartet, dass sie vom Programm bearbeitet wird.
maxod schrieb:>> Erst mal vielen Dank für eure umfangreichen Antworten. Hab ich das nun> korrekt?
nein
> void Slave_Receive (void)> {> char buffer[8];> char* text=buffer;> while(*text != '\0')
wie kannst du an dieser Stelle *text schon abfragen, wenn du *text noch
gar nicht empfangen hast?
> {> while (!(SPSR & (1<<SPIF))); // Wait until Char is> received> // Check if Char (Byte)> is received correctly> *text = SPDR ;> text++; // Set Pointer on next> Character> }> // output result transmission status on Port D> lcd_gotopos(2,1);> lcd_writetext(text);
an dieser Stelle: wo zeigt text hin und was müsstest du eigentlich an
lcd_writetext übergeben.
Es gibt nicht nur
while( ... ) {
...
}
Schleifen. Es gibt auch
do {
...
} while( ... )
Schleifen.
Zu Pointer
Das ist dein Array. Mal es dir mit Bleistift auf Papier auf
buffer
+---+---+---+---+---+---+---+---+
| | | | | | | | |
+---+---+---+---+---+---+---+---+
Jetzt nimmst du dir einen Kugelschreiber und legst ihn aufs Papier, so
dass die Spitze auf das erste Kästchen zeigt. Das ist dein Pointer
'text' und er zeigt deswegen auf das erste Kästchen, weil du genau das
mittels
char* text=buffer;
erzwungen hast. Wenn du text++ machst, schiebst du den Kugelschreiber um
ein Kästchen nach rechts. Wenn in deinem Programmtext *text steht, dann
bedeutet das, das der Inhalt des Kästchens gemeint ist, auf das gerade
der Kugelschreiber zeigt.
Würde in deinem Programm also
*text = 'g';
stehen, dann schreibst du mit dem Bleistift in das Kästchen auf das der
Kugelschreiber verweist, ein 'g' hinein. Wenn in deinem Programmtext
steht
if( *text == 'r' )
dann liest du das Kästchen aus, auf das der Kugelschreiber zeigt. Und
immer dran denken: lokale Variablen haben keinen definierten
Defaultwert. Ein leeres Kästchen steht hier nicht für ein Leerzeichen
oder ein \0 Zeichen, sondern dafür dass du gerade auf Speicher
zugreifst, dessen Inhalt zufällig ist.
Wenn du je in die Situation kommst, dass dein Kugelschreiber nach ein
paar ++ Operationen auf kein Kästchen mehr zeigt und du trotzdem einen *
ausführen musst, dann hast du soeben einen weiteren schweren Fehler
entdeckt. Das darf dir nie passieren (genausowenig, wie der Zugriff auf
uninitialisierten Speicher).
So weit so gut. Und jetzt geh deine Funktion durch und simuliere auf dem
Papier dessen Funktion. Als Zeichen, die aus der SPI herauskommen,
kannst du erst mal welche erfinden, die deiner Meinung nach da
rauskommen müssten.
(Dadurch dass du die Senderoutine schreibst, kannst du dann ja auch
sicher stellen, dass genau das dann auch tatsächlich übertragen wird)
max b. schrieb:> while(SPDR)> {> while (!(SPSR & (1<<SPIF))); // Wait until Char is received
Und wovon, glaubst du, würde der SPI-Block überhaupt anfangen, hier
etwas zu empfangen? Intuition? Blitzschlag?
Eine SPI-Schnittstelle ist inhärent eine Zweirichtungs-Schnittstelle.
Damit man Daten empfangen kann, muss der Master Taktimpulse senden.
Wenn der Master Daten empfangen will, muss man folglich das Aussenden
von Taktimpulsen dadurch triggern, dass man irgendwelche Daten
rausschreibt. Ob diese geschriebenen Daten nun für den Slave bereits
ein neues Kommando darstellt (das er nach der aktuellen Datenlieferung
bearbeitet) oder ob man einfach nur Dummydaten sendet (in der Regel
einfach ein Nullbyte), das ist abhängig von der Implementierung deines
Slaves.
while(!(SPSR&(1<<SPIF)));// Wait until Char is received
10
11
buffer[i]=SPDR;
12
*text=buffer[i];
13
i++;
14
15
}while(*text!='z');
16
i--;
17
buffer[i]='\0';
18
}
habs jetz so gelöst, da ich mir nicht besser zu helfen wusste.
das der string mit '\0' abgeschlossen werden soll, hab ich nicht
hinbekommen, liegt wohl an meinen 4 jahren pause von der schule ^^
aber herzlichen dank :)
while(!(SPSR&(1<<SPIF)));// Wait until Char is received
4
5
buffer[i]=SPDR;
6
*text=buffer[i];
7
i++;
8
9
}while(*text!='z');
überhaupt noch den Pointer?
Abgesehen davon, dass das so schon wieder nicht geht, weil der Pointer
wieder auf keinen gültigen Speicher zeigt, in dem man ein Zeichen
ablegen könnte. Auf diesen Punkt MUSST du achten! Du kannst nicht
einfach einen Pointer anlegen und den dann dereferenzieren. Wann immer
du einen * auf einen Pointer machst, musst du dich fragen: "Wo zeigt
mein Pointer hin? Gibt es dort überhaupt den Speicher um dort etwas zu
speichern?". Dein 'Kugelschreiber' Pointer MUSS auf ein Kästchen
zeigen. Alles andere ist ein schwerer Fehler.
Du willst einen Character zwischenspeichern, damit du ihn nachher beim
Vergleich benutzen kannst. Na dann mach das doch! Definiere dir eine
char Variable und dort schreibst du das Zeichen hinein. Kein Mensch
braucht dazu einen Pointer.
Du könntest natürlich auch hergehen und sagen: Ok ich weiss, dass wenn
ich das zuletzt empfangene Zeichen in buffer[3] (weil i gerade den Wert
3 hatte) gespeichert habe, und ich danach i um 1 erhöhe (i hat dann den
Wert 4), dann kann ich immer noch beim testen der while Bedingung ganz
einfach auf das Zeichen zugreifen, weil es ja in buffer[i-1] stehen
muss. Also brauch ich gar keine Hilfsvariable um dort das Zeichen
zwischenzuspeichern. Solange ich das Array buffer und i habe, weiß ich
immer welches Zeichen zuletzt wo gespeichert wurde.