Hallo Leute,
ich habe ein Problem mit der SPI Übertragung, habe da noch nicht viel
gemacht.
Also nach einem Reset des Controllers wird vom Slave Chip, ein LIS3DH
Beschleunigungssensor nach Anforderung der richtige Registerinhalt
gesendet. Wenn ich jetzt ein anderes Register auslesen will kommt
trotzdem immer wieder der gleiche Registerinhalt des alten Registers.
Das stimmt natürlich nicht so.
Weiterhin weis ich nicht genau an welcher Stelle ich den Wechsel von Low
auf High der CS Leitung rein packe. Die soll ja laut Diagramm im
Datenblatt(S.22) high werden wenn SCK auch gerade high wird.
Falls wer Zeit hat kann mal jemand über meinen code schauen und den oder
die bösen Fehler suchen?
Die Kommunikation läuft zum testen einfach so, ich schicke über die
serielle 3 Bytes, das erste ist die Adresse, das zweite ist der Wert
welcher eventuell geschrieben werden soll, das dritte Byte gibt an ob
schreiben, dann 1 oder lesen dann 0.
Verwendeter Controller ist ein Atmega16 mit 8MHz Takt.
1
#include<stdlib.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<avr/pgmspace.h>
5
#include<inttypes.h>
6
#include<avr/eeprom.h>
7
#include<string.h>
8
#include<util/delay.h>
9
#include<avr/wdt.h>
10
#include<string.h>
11
#include<stdlib.h>
12
13
/* define CPU frequency in Mhz here if not defined in Makefile */
Chris T. schrieb:> Die soll ja laut Diagramm im> Datenblatt(S.22) high werden wenn SCK auch gerade high wird.
Wahre Gleichzeitigkeit gibt es nicht.
Bei der stiegenden Flanke von SPC müssen die Daten stabil sein. CS muss
rechtzeitig vor der Übertragung auf Low liegen und geht irgendwann
danach wieder auf High.
holger schrieb:> In seinem Programm geht es nie High.
Was zur Folge hat, dass immer wieder das gleiche Register ausgelesen
wird, weil die Adresse nur im ersten Byte nach Beginn einer Übertragung
gesetzt wird. Die Übertragung endet aber erst durch CS auf HIGH, was
nicht passiert.
Nils Z. schrieb:> Was zur Folge hat, dass immer wieder das gleiche Register ausgelesen> wird, weil die Adresse nur im ersten Byte nach Beginn einer Übertragung> gesetzt wird. Die Übertragung endet aber erst durch CS auf HIGH, was> nicht passiert.
Ganz so einfach ist das auch nicht. Da gibt es noch das MS Bit.
Seite 23:
"In multiple read/write commands further blocks of 8 clock periods is
added. When MS bit is ‘0’ the address used to read/write data remains
the same for every block. When MS bit is ‘1’ the address used to
read/write data is increased at every block."
Jetzt bekomme ich nach der ersten Übertragung (Gesendet 0f 00 00):
FF 33 7C --> Stimmt.
Wenn ich das gleiche aber nochmal sende, erhalte ich dann immer:
FF FF 7C egal welches Register ich anspreche (7C ist der |)
Also so ganz läufts immer noch nicht.
Das MS Bit ist bisher immer 0 da ich ja nur ein Byte lesen will
Chris T. schrieb:> Jetzt bekomme ich nach der ersten Übertragung (Gesendet 0f 00 00):> FF 33 7C --> Stimmt.> Wenn ich das gleiche aber nochmal sende, erhalte ich dann immer:> FF FF 7C egal welches Register ich anspreche (7C ist der |)
Kannst du mal mit Oszilloskop oder Logic-Analyser nachsehen, was beim
zweiten mal auf den Leitungen am Sensor wirklich gesendet / empfangen
wird? Dann wüsste man, ob der Fehler in deiner Sende- oder in der
Empfangsroutine zu suchen ist.
Wolfgang schrieb:> Ganz so einfach ist das auch nicht. Da gibt es noch das MS Bit.>> Seite 23:> "In multiple read/write commands further blocks of 8 clock periods is> added. When MS bit is ‘0’ the address used to read/write data remains> the same for every block. When MS bit is ‘1’ the address used to> read/write data is increased at every block."
Da hast du natürlich recht, ich bin stillschweigend davon ausgegangen,
dass er das Bit nicht gesetzt hat, weil keine Multibytezugriffe erfolgt
sind.
Willsz du beim ersten Auslesen nur 0F ausgelesen ? Wenn ja warum
sendest du zwei Dummybytes. Vor allem sind die direkten Register mit der
nachfolgenden Adresse ja "reserved"
Gruß JackFrost
Das dritte Byte diente nur um auszuwählen zwischen lesen und schreiben
es werden nur zwei Bytes gesendet.
Jetzt hab ich auch meinen Logiganalyzer zum laufen bekommen.
Leider wird schon nichts mehr gesendet, obwohl ich gar nicht viel am
Code verändert habe.
Hier jetzt mal der aktuelle Code:
1
#include<stdlib.h>
2
#include<avr/io.h>
3
#include<avr/interrupt.h>
4
#include<avr/pgmspace.h>
5
#include<inttypes.h>
6
#include<avr/eeprom.h>
7
#include<string.h>
8
#include<util/delay.h>
9
#include<avr/wdt.h>
10
#include<string.h>
11
#include<stdlib.h>
12
13
/* define CPU frequency in Mhz here if not defined in Makefile */
Bist du sicher mit dem Protokoll? Auf den ersten Blick sieht es so aus
als werden die Werte bei steigender Clock Flanke übernommen, scheint bei
dir nicht so zu sein.
Ja danke für den Hinweis, hab das CPOL Bit mal gelöscht und siehe da, er
antwortet wie er soll, oh man das war wieder ein Hickhack, da war an
mehreren Stellen ein kleiner Fehler...
Ich weis ja ich habe jetzt hier schon einige Nerven strapaziert, aber
ich treibs mal noch ein Stück weiter.
Ich kann die Register lesen und schreiben aber wie müssen die Register
gesetzt werden damit ich mal einen Beschleunigungswert bekomme?
Also ich schnipse mit dem Finger gegen den Sensor da sollte doch ein
Wert ungleich 0 mal auszulesen sein...
EDIT: Ok es gibt eine Application note, die wird ich mir erstmal rein
ziehen.
Chris T. schrieb:> Ich kann die Register lesen und schreiben aber wie müssen die Register> gesetzt werden damit ich mal einen Beschleunigungswert bekomme?
Ich arbeite auch gerade mit dem Sensor, die Aufteilung und Gliederung
von Datenblatt und Appnote finde ich nicht gelungen, leider sind da auch
mehrere grobe Fehler drinnen, Register werden unterschiedlich
bezeichnet. Pass mit den Beispielen in der Appnote auf, da muss man alle
Werte hinterfragen, die sind nicht immer richtig.
Um vom Sensor Werte zu bekommen, musst du als minimale Konfiguration in
CTRL_REG1 die Bits ODR3-0 setzen. Default ist 0000 (binär). Im
Datenblatt steht auf S.29 "0000:50 Hz; ", das ist falsch, sieht man in
der Tabelle auf S.30. 0000 ist power down, daher kannst du nichts
auslesen.
Noch ein Beispiel für einen Fehler:
AN3308, S.24: "Write A7h into CTRL_REG1// ODR = 100 Hz"
0xA = 1010 (bin), wieder mit der Tabelle im Datenblatt auf S. 30
vergleichen, 1010 kommt da für ODR3-0 garnicht vor. Richtig für 100Hz
wäre 0101 = 0x5. Der gleiche Fehler ist noch öfter in der Appnote, bin
selbst darüber gestolpert.
Ich behaupte wirklich ungern, dass der Hersteller hier so viele Fehler
gemacht hat, wenn ich mich geirrt haben sollte, wäre ich dankbar, wenn
mir jemand zeigt, warum.
Hallo Nils,
danke für die Hinweise :-)
Habe das alles jetzt soweit laufen das ich
einen Interrupt am pin bekomme wenn ein bestimmtes Threshold
überschritten wurde gemäß Anleitung aus der AP nur die Werte in den
Register ein wenig abgeändert, da mich nur die Werte für die
Beschleunigung in Z-Richtung interessieren:
1
Write A7h into CTRL_REG1
2
// Turn on the sensor and enable X, Y, and Z
3
// ODR = 100 Hz
4
2 Write 00h into CTRL_REG2 // High-pass filter disabled
5
3 Write 40h into CTRL_REG3 // Interrupt driven to INT1 pad
6
4 Write 00h into CTRL_REG4 // FS = 2 g
7
5 Write 08h into CTRL_REG5 // Interrupt latched
8
6 Write10h into INT1_THS // Threshold = 250 mg
9
7 Write 00h into INT1_DURATION // Duration = 0
10
8 Write 0Ah into INT1_CFG // Enable XH and YH interrupt generation
11
9 Poll INT1 pad; if INT1=0 then go to 8
12
// Poll RDY/INT pin waiting for the
13
// wake-up event
14
10 Read INT1_SRC
15
// Return the event that has triggered the
16
// interrupt
Kannst du mir sagen wie ich an den größten Wert welche bei Überschreiten
der Schwelle detektiert wurde?
Wenn ich dann nach dem Interruptregister manuell die Register OUT_1_L
etc. auslesen bekomme ich da 0 Werte.
Auch hab ich noch nicht geblickt welches Register ich genau auslesen
muss wenn ich den Wert von der Z-Beschleunigung möchte.
Muss ich da OUT_3_L und OUT_3_H auslesen? Ist dort der Wert für die Z
Achse gespeichert?
So habe das jetzt so angepasst das ich so bald der Interrupt kommt
direkt das entsprechende Register auslese. Das funktioniert schon mal
prinzipiell.
Nur wie ich jetzt auf den Beschleunigungswert komme ist mir trotz
appnote noch schleierhaft. Wie muss man das denn rechnen das man da auf
den Wert kommt?
Hier erstmal der Code:
Chris T. schrieb:> In der Appnote steht auf Seite 14 dazu eine Tabelle aber ich weis nicht> wie die da auf den g Wert kommen mit den Zahlen...
Per Dreisatz und Kalibrierkoeffizienten?
Ich glaub ich habe es, das müssten schon zweierkomplemente sein, da der
Wert ein INT -Wert ist...
Hab das jetzt so gelöst und erhalte auch Werte welche durchaus stimmen
könnten.
Sorry, habe nicht viel Zeit, daher nur recht knapp:
Um an die Beschleunigungen zu kommen, musst du die Register OUT_Z_L / H
auslesen (0x2c, 0x2d, aus der Tabelle im Datenblatt auf S.26). Die Werte
sind im Zweierkomplement (steht auf S.33).
Die Register OUT_x_L/H sind für die zusätzlichen ADC-Kanäle (in der
Tabelle auf S. 26 steht auch ADC im Namen dabei, die Namen sind leider
nichtmal im Datenblatt einheitlich :( ).
Die Interpretation der Werte ist in der Appnote auf S.14 halbwegs
ersichtlich. Der maximale/minimale Wert einer Achse in g ergibt sich
durch die Full Scale selection (2, 4, 8 oder 16g, Datenblatt S.31).
Der Wert pro digit auch, siehe Tabelle im Datenblatt auf S. 10.
Um die Werte auf Plausibilität zu prüfen, einfach den Sensor in Bezug
auf die Achse passen hinlegen, dann müsste die Beschleunigung je nach
Lage +1g, 0g oder -1g sein.