Servus,
hab obriges durchgeführt, läuft auch relativ gut, aber nur relativ, weil
bei meiner SPI nur eine 77, also 1001101 zurückkommt, obwohl ich einfach
nur irgendwas sende (eine beliebige Zahl zwischen 0 - 2^(32-1)).
Nun, wenn ich mein SPI interrupt rauschmeise, kommt mal abundzu 153 in
dezimal zurück, mal 20, usw., obwohl ein beliebiges Zeichen oder ein
festes Zeichen gesendet wird.
das SPDR im ATmega32 ist 8Bit groß. Da der TMC428 aber ein Datagram mit
32Bit zurückgibt, muss ich diesen Bratzen irgendwie auf mein SPI legen
können, sodass ich über den SPI mit meinen ATmega32 das Ablese, in ein
Array speichere, und somit über die USart ausgebe.
Ich würde es gerne mit zwischenspeichern machen, also für nen uint32_t,
was theoretisch zurückkommt, immer jeweils 8 zeichen (dann die nächsten
8 usw.) bis die 32 Zeichen abgearbeitet sind, in mein Array
reinschmeisen, und dann zeichen für zeichen der usart geben.
Ist das zu umständlich, oder hat jemand eine passende idee?
Zurzeit ist mein Teil- Code wie folgt:
1
voidSPI_masterinit(void)
2
{
3
DDRB=(1<<MOSI)|(1<<SCK)|(1<<SS);//MOSI,SCK,SS auf 1 legen
4
DDRB&=~(1<<MISO);//MISO als Eingang definiert
5
6
PORTB|=(1<<SCK)|(1<<SS);
7
SPCR=(1<<SPE)|(1<<MSTR)|(1<<SPR0);//Enable SPI, Master, set clock rate fck/16 ~800khz
8
}
9
10
voidSPI_MasterTransmit(chardata)
11
{
12
PORTB&=~(1<<SS);//Signal SS auf 0 setzen -> Uebertragung beginnt
13
SPDR=data;//ACHTUNG!! Das Register SPDR ist nur 8bit Groß
14
while(!(SPSR&(1<<SPIF)))//wartet, bis die ÜBertragung fertig ist
15
{
16
;
17
}
18
PORTB|=(1<<SS);//Signal SS wieder auf high setzen -> Uebertragung beendet
19
}
20
21
charspi_slave_receive(void)
22
{
23
while(!(SPSR&(1<<SPIF)))
24
{
25
;
26
}
27
returnSPDR;
28
}
29
30
/*
31
ISR(SPI_STC_vect) //ISR vom SPI transfer complete
32
{
33
34
}*/
Danke euch schonmal.
Ich versuch das mal so zu realisieren, und wenn was besseres kommt,
schau ich mal, ob sich das einbauen lässt^^.
Mfg,
tommyProg
Tho Wes schrieb:> char spi_slave_receive(void)> {> while(!(SPSR&(1<<SPIF)))> {> ;> }> return SPDR;> }
Du hast SPI nicht verstanden.
SPI funktioniert nach dem Muster eines Datenaustausches.
Der Slave kann von sich aus überhaupt nichts tun, sondern die komplette
Kontrolle liegt beim Master. Damit der Slave 1 Byte bertragen kann, muss
der Master 1 Byte zum Slave übertragen.
Eine Analogie.
Du sitzt deinem Kumpel gegenüber am Tisch. Jeder hat einen Zettel vor
sich auf dem Tisch liegen. Jeder kann etwas auf den zettel schreiben.
Auf ein Kommando von dir (dem Master) nimmt jeder seinen Zettel mit der
rechten Hand und schiebt ihn zum Gegenüber hinüber während er mit der
linken Hand jeweils den ihm zugeschobenen Zettel entgegen nimmt.
Wie gesagt: du bist der Master. Selbst wenn dein Kumpel wollte, ohne
dass du deinen Zettel rüberschiebst, kann er dir seinen Zettel nicht
rüberschieben.
In diesem Sinne macht ihr immer einen gleichzeitigen Zettel-Tausch. Und
egal was passiert, die Aktivität geht immer von dir, dem Master aus.
Das ist das Prinzip von SPI. D.h. diee receive Funktion kann nicht
funktionieren, weil der Master zum Anleiern des Datenaustausches etwas
an SPDR zuweisen muss. Erst durch diese Zuweisung kommt der Austausch in
Gang.
In diesem Sinne brauchst du auch nicht eine Transmit und eine Receive
Funktkoin sondern eine einzige Exchange Funktion
1
uint8_tSPI_Exchange(uint8_tbyte)
2
{
3
SPDR=byte;
4
5
while(!(SPSR&(1<<SPIF)))
6
{
7
;
8
}
9
10
returnSPDR;
11
}
mit dieser einen Funktion wickelst du den ganzen Datentransfer ab.
> SPI funktioniert nach dem Muster eines Datenaustausches.> Der Slave kann von sich aus überhaupt nichts tun, sondern die komplette> Kontrolle liegt beim Master. Damit der Slave 1 Byte bertragen kann, muss> der Master 1 Byte zum Slave übertragen.
Danke Dir für den Hinweis, Karl Heinz, aber das System ist schon
verstanden, dass der TMC428 nur antwortet, wenn der µC was sendet.
Problem ist nur, dass der µC auch die Antwort des TMC428 aufnehmen muss,
und das über eine Schnittstelle (USART) an den PC über ein externes
Programm ausgeben muss.
>
1
>uint8_tSPI_Exchange(uint8_tbyte)
2
>{
3
>SPDR=byte;
4
>
5
>while(!(SPSR&(1<<SPIF)))
6
>{
7
>;
8
>}
9
>
10
>returnSPDR;
11
>}
12
>
>> mit dieser einen Funktion wickelst du den ganzen Datentransfer ab.
Die 32Bit in Binärdarstellung kommen als Paket vom TMC428, und diese
sollen genauso wie sie empfangen sind, zur USART raus.
Mit einem return von uint8_t würden doch nur die ersten empfangenen 8bit
rausgesendet werden, (ein zeichen), dann das nächste eingelesen, dann
das zweite zeichen raus, usw.
Ich verstehe nicht ganz, wie ich dann die Verkettung als reines Paket
mit dieser Funktion hinbekommen soll.
Aktuell bin ich grade dabei das mit einen Array zu realisieren, wenn das
nicht geht, probiere ich mal Deine Idee aus.
EDIT_1:
ZITAT: "Damit der Slave 1 Byte bertragen kann, muss
der Master 1 Byte zum Slave übertragen."
Das haut bei mir nicht hin, wenn ich 32 Stellen übertrage (4 Bytes),
kommt auch nur 77 zurück, also wahrscheinlich 1 Byte, wobei das 8te Bit
ne 0 ist.
Mfg,
tommyProg
Tho Wes schrieb:> Die 32Bit in Binärdarstellung kommen als Paket vom TMC428,
Nope.
32 Bit werden ausgetauscht, in dem man 4 mal 8 Bit austauscht.
Die Funktion für einen 8 Bit Austausch hast du schon. ALso wirst du
einen 32 Bit Austausch durch 4 maligen Aufurf der Funktion machen.
> und diese> sollen genauso wie sie empfangen sind, zur USART raus.> Mit einem return von uint8_t würden doch nur die ersten empfangenen 8bit> rausgesendet werden,
Niemand sagt, dass man die Funktion nur 1 mal zwischen dem Low-gehen des
Slave Select und dem High-gehen des Slave Select aufrufen darf. Der TMC
macht von sich auch gar nichts. Auch die Clock-Pulse kommen vom Master.
Dann macht eben der Master aus Sicht des TMC ein klitzekleines Päuschen
beim SPI-Clock nach jeweils 8 Bit. Das stört den nicht weiter. Mit dem
nächsten Clock-Puls geht das nächste Bit aus dem TMC raus. Und die Clock
Pulse kommen vom Master, also vom AVR
Servus,
hab nun die die Funktion so übernommen:
(entschuldige übrigens für die "sinnlosen" kommentare, aber für mich
brauche ich diese einfach zum lernen)
1
uint8_ttransceive(uint8_tbyte)
2
{
3
/*PORTB &=~(1<<SS); //SS Leitung auf 0 setzen, damit die Übertragung beginnen kann*/
4
SPDR=byte;//schreibt in das SPDR register das erste Zeichen
5
while(!(SPSR&(1<<SPIF)))
6
{
7
;
8
}
9
returnSPDR;
10
/*PORTB|=(1<<SS); //schalte deshalb die SS Leitung wieder auf high */
11
}
Mit einer selbst geschriebenen Funktion teile ich nun die Bytes auf,
sende diese Einzeln, und die empfangenen setze ich wieder in einen
uint32_t zusammen (was scheinbar nicht richtig funktioniert).
Diese Funktion ist wie folgt implementiert:
1
uint32_tlese_und_schreib_auf_spi(uint32_tdatensatz)//wobei Datensatz das trinamic_befehlslaenge ist, was von außen über die USART reinkommt
2
{
3
//aufteilung des Datensatzes in einzelne bytes
4
uint8_tspeicheraufteilung_array[4];
5
6
speicheraufteilung_array[0]=datensatz>>24;//zerlege das erste Byte, Position 31-24
7
speicheraufteilung_array[1]=datensatz>>16;//zerrlege das zweite Byte, Position 23 - 16
8
speicheraufteilung_array[2]=datensatz>>8;//zerlege das dritte Byte, Position 15-9
9
speicheraufteilung_array[3]=datensatz;//zerlege das vierte Byte, Position 7-0
10
11
//senden der einzelnen Bytes und auf Antwort warten //schalte die SS Leitung auf LOW, damit die Übertragung beginnen kann
PORTB&=~(1<<SS);//sende das erste Byste von 31-24 und speichere die Antwort in "0"
17
speicherzusammensetzung_array[1]=transceive(speicheraufteilung_array[1]);//sende das zweite Byte von 23-16 und speichere die Antwort auf die erste Position des arrays
18
PORTB|=(1<<SS);
19
PORTB&=~(1<<SS);
20
speicherzusammensetzung_array[2]=transceive(speicheraufteilung_array[2]);//sende das dritte Byte von 15-9 und speichere die Antwort auf die zweite Position des Arrays
21
PORTB|=(1<<SS);
22
PORTB&=~(1<<SS);
23
speicherzusammensetzung_array[3]=transceive(speicheraufteilung_array[3]);//sende das vierte Byte von 7-0 und speichere die Antwort auf die dritte Position des Arrays
24
PORTB|=(1<<SS);//setze die SS Leitung auf High, damit die Übertragung beginnen kann
25
26
// zusammensetzen von den einzelnen Bytes zu einen ganzen
27
test_datagram_empfangen_von_TMC=(uint32_t)speicherzusammensetzung_array[0]<<24;//das MSB zurückbekommen und speichern
28
test_datagram_empfangen_von_TMC=(uint32_t)speicherzusammensetzung_array[1]<<16;//das 23-16 bit zurückbekommen und abspeichern
Das Darstellen über die Uart ist problemlos, habe ich probehalber
geprüft.
(es können 32-bit zahlen dargestellt werden)
Mein Problem ist, dass, wenn ich einen Wert 436207907 sende, nur dezimal
77 zurückkommt, was 0b1001101 entspricht.
Der zurückkommende Wert soll aber (dez)2499805184 sein.
Nach meiner Recherche sendet und empfängt der TMC erst das MSB, also
31Bit abwärts.
Vermutlich habe ich mit meiner Speicherzusammensetzung probleme. Hättest
du grob eine Vermutung oder idee (bitte keine Union, das wäre zwar ein
vlt. besserer weg, aber ich würde gerne das nur mit shift- operatoren
lösen)?
Ich werde dies nochmals überprüfen, indem ich die shift- operatoren auf
die speicher ändere.
Mfg,
tommyProg
Ergänzend möchte ich noch hinzufügen, dass der TMC bei erstmaliger
Eingabe manchmal dez 452984832 mancchmal dez 69 und manchmal dez 101
zurückgibt, jedoch häufiger 77.
Keines dieser Bitmuster kommt in der Bitreihenfolge vor.
entsprechen würde.
Jedoch weiß ich nicht, was der Code genau macht. Im Thread stands auch
nicht ausführlich genug. (stand nur was low und high byte jeweils ist)
Genauer verstehe ich nicht, was
1
*((uint8_t*)&speicherzusammensetzung+0)
bewirkt.
Bitte um Aufklärung.
Danke.
Mfg,
tommyProg
P.s. habe durch Rekursion nun das senden von 4Bytes hinbekommen, nachdem
ich die putc in puti umgeschrieben habe, und noch ein wichtiges DDRB
vergessen habe, zu setzen.