Moin,
ich bin leider noch ein ziemlicher Anfänger in der Programmierung der
SPI eines Arduinos. Deswegen möchte ich im ersten Schritt lediglich
erstmal sehen, dass ich einzelne Befehle aussenden kann. Das Ganze gucke
ich mir dann über ein digitales Oszilloskop an.
(Der Arduino empfängt Befehle per Bluetooth über MATLAB.)
Ich habe dazu folgenden Code geschrieben:
1
#include<SoftwareSerial.h>
2
#include<SPI.h>
3
4
intTxD;
5
intRxD;
6
intdata;
7
constbyteWAKEUP=0b00000010;
8
unsignedlongnextMillis=0;
9
SoftwareSerialbluetooth(TxD,RxD);
10
11
/* SPI pin numbers:
12
SCK 13 // Serial Clock.
13
MISO 12 // Master In Slave Out.
14
MOSI 11 // Master Out Slave In.
15
SS 10 // Slave Select*/
16
17
voidsetup(){
18
Serial.begin(9600);
19
nextMillis=millis();
20
bluetooth.begin(9600);
21
SPI.begin();
22
SPI.setClockDivider(SPI_CLOCK_DIV128);
23
}
24
25
voidloop()
26
{
27
if(bluetooth.available()>0)
28
{
29
data=bluetooth.read();
30
Serial.print(data);
31
Serial.print("\n");
32
33
if(data=='H')
34
{
35
digitalWrite(SS,LOW);/* Turn SlaveSelect Level to low*/
36
delay(5);/* all delays for stability*/
37
}
38
elseif(data=='U')
39
{
40
SPI.transfer(WAKEUP);/* Turn off standby mod*/
41
Serial.println("Turn off standby Sent.");
42
delay(5);
43
}
44
elseif(data=='Z')
45
{
46
digitalWrite(SS,HIGH);/* Turn SlaveSelect Level to high*/
47
}
48
}
49
}
Der Teil, bei dem ich das Level vom SlaveSelect verändere funktioniert.
Aber ich kann mittels des Oszilloskops nicht sehen, dass Daten
ausgesendet werden. Kann mir jemand sagen, was ich dafür ändern muss?
Nach meinem Verständnis müsste bei jedem Takt ja ein Bit gesendet
werden.
Vielen Dank im voraus!
M
Mgns schrieb:> Der Teil, bei dem ich das Level vom SlaveSelect verändere funktioniert.
Genau da liegt der Irrtum!
Es sieht auf dem Oszi so aus, als wenn es funktioniert.
Macht aber was anderes, als du glaubst.
> digitalWrite(SS, LOW);
Wenn du deinen SS nicht vorher zum Output machst, dann schaltet der SPI
"Baustein" bei Low an SS in den Slavemode.
Dann kommt kein Takt und auch keine Daten.
Steht auch so im Datenblatt deines Prozessors.
Auch in der Arduino SPI Doku wird es erwähnt.
Also in setup():
> digitalWrite(SS, HIGH);> pinMode(SS,Output);
(ja, in dieser Reihenfolge)
Dann tuts das auch.
Vielen Danke! Habe ich hinzugefügt!
Ich kann eine Veränderung des Levels des SS weiterhin sehen, allerdings
nicht, dass irgendwelche Bits übertragen werden.
Ich habe mit "SPI.setClockDivider(SPI_CLOCK_DIV128);" meine CLK auf
125kHz gesetzt oder? Das müssten doch ca. 8µs für jeden Takt sein.
Deswegen habe ich mein Oszilloskop auf 1µs/div gestellt. (Bin auch
andere Auflösungen durchgegangen, nur immer sicher zugehen).
Habt ihr 'ne Idee, was ich anders einstellen müsste?
Benutze ein "AnalogDiscovery 2" von Digilent.
Hallo,
dein SlaveSelect Pin muss an der richtigen Stelle schalten.
Du weißt vorher nicht welche Daten empfangen wurden, dann verheddert
sich der SS Pegel.
Wenn jetzt kein 'U' kommt, geht der SS nur kurz auf Low und wieder auf
High.
Kommt ein 'U' rein wird dazwischen noch kurz etwas gesendet.
Es ist sichergestellt das der SS Pin immer auf dem richtigen Pegel
steht.
Das delay kann auch raus. Meistens benötigen die ICs 50ns Verzögerung.
Ein Takt dauert aber schon 62,5ns. Das DigitalWrite dauert ca. 4µs.
Einheiten beachten. Da musst du dir keine Sorgen machen.
Das Serial bei 'U' würde ich rausnehmen. Fürs debuggen noch okay.
Okay, es ist etwas merkwürdig. Aber mit meinem Code funktioniert das
ganze ebenfalls, wenn ich den SS als Output vorher definiere.
Allerdings nur, wenn ich über MATLAB beispielsweise
1
fprintf(bt,'UU')
schicke. Sende ich hingegen
1
fprintf(bt,'U')
geht es nicht.
Ich habe das mit jeder beliebigen Kombination und unterschiedlichen
Befehlen ausprobiert. Immer, wenn ich ein "U" vor dem nächsten Buchstabe
setze, sendet er den Befehl... Kann mir das jemand erklären? Ich bin
ziemlich verwirrt.
Veit D. schrieb:> na klar, hier fehlen noch die Pinangaben.
Scheinen irgendwie nicht wichtig genug zu sein.....
TxD und RxD von SoftwareSerial und RxD von HardwareSerial alle drei
Funktionalitäten auf dem gleichen Pin.
Naja... wer es mag....
Der jeweiligen Funktion tut es sicherlich nicht gut.
Zumindest habe ich keinerlei Ahnung, wie das ordentlich funktionieren
soll.
Denn die Serielle ist kein Bus.
Mgns schrieb:> Danke für eure Hilfe!
Bitte bitte, gerne doch!
Hast du denn mittlerweile das
> int TxD;> int RxD;> SoftwareSerial bluetooth(TxD, RxD);
Problem verstanden und behoben?
Ja, ich denke schon, dass das jetzt klar geworden ist!
Kurze Frage noch, mit SPI.transfer() kann ich auch Daten empfangen oder?
Aktiviert sich die Clock nur, wenn man dem Arduino mitgibt, dass er
jetzt Daten lesen muss? Ich benötige ja die Clocktakte am Chip ebenfalls
zum Daten ausgeben.
Sorry für die vermutlich sehr dummen Fragen! :D
Mgns schrieb:> Sorry für die vermutlich sehr dummen Fragen! :D
Ob sie dumm sind, weiß ich nicht!
Aber, ich verstehe sie nicht.
Wikipedia: SPI
Schon gelesen?
Mgns schrieb:> Kurze Frage noch, mit SPI.transfer() kann ich auch Daten empfangen oder?
Natürlich!
So sagt es die Spezifikation.
Die Arduino Doku betätigt es.
Und so wird es auch in der Praxis getan.
Mgns schrieb:> Ja, ich denke schon, dass das jetzt klar geworden ist!
Und auch behoben?
Arduino Fanboy D. schrieb:> Und auch behoben?
Ja, so geändert wie ihr es geschrieben habt.
Habe Wikipedia und mehr dazu durchgestöbert, ich glaube grundsätzlich
weiß ich was ich will, nur bin ich noch limitiert in meiner Denkweise,
vielleicht macht es ja noch "klick".
Ich verstehe noch nicht ganz, wie das mit dem Datenaustausch
funktiniert. Also folgendes, wenn ich mit Hilfe des Arduino den Befehl
xxxx xxxx sende, dann sehe ich gleichzeitig, dass SCLK 8 Takte anliegt.
Damit mein Chip aber jetzte korrekt darauf reagieren kann, so müsste ich
diesem ja wieder die Takte meiner SCLK zur Verfügung stellen. Geht das
darüber, dass ich ihm beispielsweise hiermit "receivedVal =
SPI.transfer(val)" sage, "ließ mal aus, was so da sein könnte?"
Hallo,
lese andere Quellen um den Ablauf von SPI zu verstehen. Die Auswahl ist
riesig. Hier im Forum gibts auch ein Tutorial Fundus.
Ob ein SPI Device einen Wert gesendet bekommt oder ob ein Wert
ausgelesen wird, darum kümmert sich die SPI.transfer Methode. Schau dir
die Bsp. an. Du kannst das natürlich auch zu Fuss machen, lernste noch
mehr.
Zu deiner letzte Frage. SPI arbeitet Byteweise. Du musst dann das
empfangene Byte auf dein Bit abfragen. Alles nach der Übertragung.
Danke, dass ihr so geduldig mit mir seid! :)
Ich wühle mich gerade durchs Forum und diversen anderen Seiten und habe
auf jeden Fall schon einiges durch euch gelernt.
Eine kleine Verständnisfrage.
Wenn ich über die MOSI-Leitung meine Steuersignale ausgebe (bspw. 0000
0010 oder so), dann wird über den Takt von SCLK meinem ADS1299
mitgeteilt, jetzt kommt ein Befehl. Damit der IC nun darauf reagieren
kann und die Möglichkeit zu antworten bekommt, muss ich nun über SCLK
und MOSI (0000 0000 oder so) senden, damit dieser 8 Takte hat und die
Bits seinerseits senden kann oder?
Mgns schrieb:> Danke, dass ihr so geduldig mit mir seid! :)
Danke auch.
Hauptsache du schreibst nicht "der Uhr" oder "die Takt".
Mgns schrieb:> muss ich nun über SCLK> und MOSI (0000 0000 oder so) senden, damit dieser 8 Takte hat und die> Bits seinerseits senden kann oder?
Ja. dabei ist das Datum was du schickst nicht relevant,
Hauptsache du schickst was.
Moin!
Ich habe eine weitere Frage, wer hätte das gedacht! :D
Momentan schicke ich ziemlich unelegant immer einen Byte über die
Leitung warte kurz schicke den nächsten usw. ... Kann man auch
Bytepakete schicken und genau definieren, wie viel Pause zwischen den
einzelnen Paketen sein soll?
Mein Oszilloskop zeigt mir logischerweise immer nur einen Byte an und
dann den nächsten. Gucke ich mir beispielsweise andere SPI-Protokolle
an, bspw. das vom ADS1299 mit der ursprünglichen Software erzeugte
Protokoll beim auslesen der Daten, dann wird mir mit denselben
Einstellungen immer "mehr" angezeigt.
Das kommt auf die Partner an: so kann z.B. ein ATmega mit der
USART-Schnittstelle im SPI-Mode "am Stück", also ohne Unterbrechung,
einen Datenblock (514 Bytes) an eine SDCard schicken - danach benötigt
die SDC eine Pause.
Mgns schrieb:> Ich habe eine weitere Frage, wer hätte das gedacht!
Ich hätte da auch noch was ....
Mgns schrieb:> einen Byte
--> ein Byte (das Byte)
Mgns schrieb:> den nächsten
--> das nächste
Sorry Jo Mei!?
Du hast ja recht!
Wie programmiert man das korrekt? Die Dokumentation von SPI.transfer()
ist ja mehr als überschaubar...
Also angenommen ich möchte 3 mal das Byte (0000 0001) hintereinander
wegschicken, dann eine Pause von 3 Takten oder so haben und dann erneut
das ganze, bis ich 216 Bits verschickt habe.
Also wenn ich den "Dreierblock" habe, würde ich den Rest vermutlich über
die Delay-Funktion und eine for-Schleife oder while-Schleife regeln.?
Ach ja und noch eine Frage, wieso kann ich nicht 0000 0000 verschicken?
Jedes andere Byte geht.