Forum: Mikrocontroller und Digitale Elektronik LIS331H (Beschleunigungssensor) über SPI/SSI mit TI-Stellaris auslesen?


von Heinrich F. (Gast)


Angehängte Dateien:

Lesenswert?

Hallo ihr :),

hat jemand von euch Erfahrung mit SPI bzw. SSI in Verbindung mit dem 
Cortex-M3 von Stellaris bzw. den Beschleunigungssensoren von ST?

Ich habe hier einen solchen ST-Sensor und würde ihn gerne über SPI 
auslesen.
Es gibt auf dem Sensor z. B. ein Register mit dem High-Byte der Z-Achse 
und eines mit dem Low-Byte. Diese Adressen sind 0x2C und 0x2D.

Zunächst muss man den Sensor noch "starten" und ihm sagen, welche Achsen 
gemessen werden sollen. Dazu muss ins CTRL_REG1 z.B. ein 0xC4 
geschrieben werden (Low Power Mode, Z-Achse aktiv).
Das CTRL_REG1 hat die Adresse 0x20.

Laut dem Datenblatt des Sensors ist die Clock wenn sie idle ist High 
(also Pol = 1) und gelesen wird immer beim zweiten Clock-Übergang, also 
von Low nach High (also Phase = 1)

Mit diesen Infos habe ich einen kurzen Code geschrieben.

In meine beiden Variablen für High- und Low-Byte steht aber jeweils nach 
dem SSIDataGet nur ein 0x000000FF. Das kann nicht stimmen.
Ich hab die SPI-Clock auch mal sehr langsam gewählt, um auszuschließen, 
dass es daran liegt.
Irgendwo muss also noch ein Fehler sein (einen Hardwarefehler schließe 
ich zu 95% aus...)

Habt ihr eine Idee?
Würde mich sehr über jegliche Hilfe freuen!!

Das hier ist mein Code - hab ihn auch als Datei nochmal angehängt

1
#include "inc/hw_ints.h"
2
#include "inc/hw_memmap.h"
3
#include "inc/hw_types.h"
4
#include "driverlib/debug.h"
5
#include "driverlib/gpio.h"
6
#include "driverlib/interrupt.h"
7
#include "driverlib/rom.h"
8
#include "driverlib/rom_map.h"
9
#include "driverlib/sysctl.h"
10
#include "driverlib/timer.h"
11
#include "driverlib/uart.h"
12
#include "driverlib/gpio.h"
13
#include "inc/lm3s5y36.h"
14
#include "driverlib/ssi.h"
15
16
17
volatile long lEmpfangeneDatenH=0;
18
volatile long lEmpfangeneDatenL=0;
19
20
/* Hauptprogramm */
21
int main(void)
22
{    
23
  /* Initialisierung */
24
  unsigned long ul_SSIEmpfang;
25
26
  /* Set the clocking to run directly from the crystal. */
27
  SysCtlClockSet(SYSCTL_SYSDIV_1 | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN | SYSCTL_XTAL_6MHZ);
28
                 
29
  //Enable the needed peripherals
30
  MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_GPIOA);  //PORT A für SSI-Kommunikation
31
  MAP_SysCtlPeripheralEnable(SYSCTL_PERIPH_SSI0);    //SSI-0 Modul
32
  
33
  //SSI_RX als Input (vermutlich nicht benötigt)
34
  GPIOPinTypeGPIOInput(GPIO_PORTA_BASE, GPIO_PIN_4);
35
  //SSI_TX und SSI_CLK als Output (vermutlich nicht benötigt)
36
  GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_2 | GPIO_PIN_5);
37
38
  //PINs SSI0 zuordnen
39
  GPIOPinTypeSSI(GPIO_PORTA_BASE,GPIO_PIN_2 | GPIO_PIN_4 | GPIO_PIN_5);
40
  
41
  //CS-Pins als Output setzen
42
  GPIOPinTypeGPIOOutput(GPIO_PORTA_BASE, GPIO_PIN_6 | GPIO_PIN_7);  //Pin A6 und Pin A7 für die beiden SSI-Beschleunigungssensoren
43
  
44
  //LIS331HH  deaktivieren (CS jauf High);
45
  GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_6,GPIO_PIN_6); 
46
  
47
  //SSI konfigurieren
48
  SSIConfigSetExpClk(SSI0_BASE, SysCtlClockGet(), SSI_FRF_MOTO_MODE_3,  SSI_MODE_MASTER, 20000, 8); //MODE_3 bedeutet Polarity 1 (Clock Idle High) und Phase 1 (Bei der Transistion von Low nach High wird gelesen)
49
  //SSI0 master modul initialisieren
50
  SSIEnable(SSI0_BASE);
51
52
  /* Initialisierung abgeschlossen */
53
  
54
  
55
  /* Los geht's: */
56
  
57
  /* Sensor aktivieren - zugehörigen ChipSelect auf low */
58
  GPIOPinWrite(GPIO_PORTA_BASE,GPIO_PIN_6,0); 
59
60
  /* Contrl_Reg 1 auswählen */
61
  SSIDataPut(SSI0_BASE,0x20);
62
  /* Warten bis Transfer beendet*/
63
  while(SSIBusy(SSI0_BASE));
64
65
  /* In Control Register 1 0xC4 schreiben zum Aktivieren des Sensors und zum Aktivieren der Z-Achse */
66
  SSIDataPut(SSI0_BASE,0xC4);
67
  /* Warten bis Transfer beendet*/
68
  while(SSIBusy(SSI0_BASE));
69
  
70
  /* Immer wieder Daten lesen*/
71
  while(1)
72
  {
73
    lEmpfangeneDatenL = 0;
74
    lEmpfangeneDatenH = 0;
75
    /* Low-Byte Z-Achse auswählen und Lesebefehl mitschicken*/
76
    SSIDataPut(SSI0_BASE,0xAC);
77
    while(SSIBusy(SSI0_BASE));
78
    /* Register Lesen */
79
    SSIDataGet(SSI0_BASE, &ul_SSIEmpfang);
80
    lEmpfangeneDatenL = ul_SSIEmpfang ;
81
    
82
    /* High-Byte Z-Achse auswählen*/
83
    SSIDataPut(SSI0_BASE,0xAD);
84
    while(SSIBusy(SSI0_BASE));
85
    /* Register Lesen */
86
    SSIDataGet(SSI0_BASE,&ul_SSIEmpfang);
87
    lEmpfangeneDatenH  = ul_SSIEmpfang ;
88
      
89
  }
90
}

von Heinrich F. (Gast)


Lesenswert?

Keiner ne Idee?

von PittyJ (Gast)


Lesenswert?

Ich benutze dann immer ein Oszilloskop, um zu sehen, ob ich wirklich 
korrekte Befehle an den Sensor sende, und was er zurück schickt.

Da kann man oft schon sehen, ob die Software-Probleme beim Senden oder 
beim Empfangen liegen.

von Heinrich F. (Gast)


Lesenswert?

Ok, danke. Ich habe ein Oszi aufgetrieben und hingehängt.
Der Master schickt bei den SSIDataPuts zunächst schön die richtigen 
Befehle raus (Clock und MOSI).
Aber wennn der Befehl SSIDataGet kommt, wird keine Clock ausgegeben. 
Insofern kann der Slave ja gar nicht antworten.
Woran könnte es liegen, dass da keine Clock mehr rausgeht?

von e in anderen S (Gast)


Lesenswert?

>Aber wennn der Befehl SSIDataGet kommt

Ohne, dass ich den TI Chip kennen würde:
DataGet liest nur aus, was während DataSend empfangen
wurde. SPI ist voll-duplex (normalerweise), Senden und
Empfangen finden gleichzeitig statt.

Interessant wäre, was Du auf MISO siehst, während Du sendest.

von Heinrich F. (Gast)


Lesenswert?

Danke für den Hinweis.
Das heißt ich muss nachdem ich meinen Lesebefehl und mein Register 
gesendet hab nochmal eine Art Dummybyte (z.B. 0x00) schicken?

Das hab ich jetzt mal eingebaut. Jetzt seh ich folglich noch mal acht 
Clockzyklen mehr auf dem Oszi. Blöderweise kommt während dieser Zyklen 
immer noch nichts zurück.

Ich schau jetzt nochmal ins Datenblatt vom Sensor, vielleicht muss man 
da noch irgendwas konfigurieren.

von e in anderen S (Gast)


Lesenswert?

Doc ID 16366, Kap 5.2, Fig 6 bis 11.

>Ich schau jetzt nochmal ins Datenblatt vom Sensor, vielleicht muss man
>da noch irgendwas konfigurieren.

Grandiose Idee!

Schau auch mal in's Controller-Datenblatt, vielleicht unterstützt
er auch eine Art Halb-Duplex Mode oder den 3-Wire SPI Mode.

von Heinrich F. (Gast)


Lesenswert?

e in anderen S schrieb:
> Grandiose Idee!

So war es nicht gemeint. Ich habe natürlich schon vorher ins Datenblatt 
geschaut als ich mir das Platinendesign überlegt habe und als ich die 
"Software" geschrieben habe.
Auch jetzt ist mir nichts weiter aufgefallen. Das Ding unterstützt im 
übrigen wie die meisten Sensoren auch 3-Wire SPI aber das bringt mir 
nichts, da mein Controller das nicht unterstüzt bzw. die Leitungen auf 
der Platine ja fest sind.

Ich bin irgendwie mit meinem Latein am Ende.

Ich habe an dem selben Bus noch einen zweiten SPI-Beschleunigungssensor 
von AD hängen (natürlich mit einem separaten CS Signal). Dort habe ich 
auch keinen Erfolg gehabt.

Beide Sensoren können auch I2C und sind wohl automatisch in I2C mode, 
wenn CS High ist. Vielleicht funkt bei der SPI-Kommuniktion der jeweils 
andere Sensor der im I2C Mode ist irgendwie dazwischen - aber das kann 
doch auch nicht sein, denn man müsste dann ja zumindest am Oszi auch 
etwas sehen und die Wahrscheinlichkeit das zufällig eine I2C 
Startkondition gefolgt von der richtigen Deviceadresse erwischt wird 
(also ein gültiger IC2-Frame entsteht) ist auch gering.

Dennoch könnte ich natürlich mal versuchen, den zweiten Sensor 
rauszulöten...

von Heinrich F. (Gast)


Lesenswert?

Ich glaube die stören sich wirklcih gegenseitig. Wenn ich beide CS auf 
low setze tut sich zumindest irgendwas (nicht das Richtige) auf der 
MISO-Leitung, was davor nicht der Fall war.....

von e in anderen S (Gast)


Lesenswert?

Hast Du schon überprüft, ob Du den richtigen SPI-Clock
Mode eingestellt hast (habe Deinen Code jetzt nicht im Detail studiert)?
Es gibt 4 davon, die sich im Ruhepegel und der aktiven Taktflanke 
unterscheiden.

Bei Deinem Sensor ist das high, bzw. die steigende Flanke.

von Heinrich F. (Gast)


Lesenswert?

Hatte ich geprüft und richtig eingestellt, ja, aber danke. Beide 
Sensoren am Bus hatten übrigens auch den selben Clock-Mode.

Ich hab jetzt einen der beiden Sensoren mal vom Board runter gerissen 
(anders gings nicht).
Vorher war SDI und SDO idle immer High (dachte, das hängt mit dem Clock 
mode zusammen) - Jetzt ist SDI und SDO idle Low...so wie man es kennt. 
Also irgendwas war davor echt dick falsch.

Ich versteh nur nicht was.

Ein Signal krieg ich jetzt aber immer noch nicht. Vielleicht ist der 
verbleibende Sensor irgendwie kaputt gegangen, weil er "zuviel treiben 
musste" oder was weiß ich...

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.