Forum: Mikrocontroller und Digitale Elektronik STM32 -> SPI -> AD7142


von sakul (Gast)


Lesenswert?

Hallo,
ich möchte gerne einen AD7142 über einen STM32F103RB auslesen. Das ganze 
soll mit SPI geschehen. An dem AD7142 hängen mehrere Touch-Sensoren.
Es scheitert leider schon an der SPI-Verbindung. Ich habe da leider 
wenig Erfahrung und würde mich freuen wenn sich das jemand anschauen 
könnte. Das ganze bleibt immer in der GetFlagStatus-Schleife hängen.
1
u16 testspi = 0;
2
3
void touchTask(void) 
4
{
5
  int i;
6
  SPI_InitTypeDef SPI_SPI1_InitStructure;
7
  GPIO_InitTypeDef GPIOSPI1_InitStructure;
8
9
  RCC_Configuration();  
10
  
11
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  // 5 = SPI1_SCK, 6 = SPI1_MISO, 7 = SPI1_MOSI
12
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
13
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
14
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
15
  
16
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_4;             // 4 = SPI1_CS
17
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
18
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
19
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
20
  
21
  SPI_SPI1_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
22
  SPI_SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
23
  SPI_SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
24
  SPI_SPI1_InitStructure.SPI_CPOL = SPI_CPOL_Low;
25
  SPI_SPI1_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
26
  SPI_SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
27
  SPI_SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
28
  SPI_SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
29
  
30
  SPI_Init(SPI1, &SPI_SPI1_InitStructure);
31
  
32
  SPI_Cmd(SPI1, ENABLE);
33
  
34
  for (i=0;i<4000;i++);    // delay
35
  
36
  for(;;) 
37
  {
38
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
39
    //Read Silicon versions to check communication, It should read 0xE622
40
    
41
    SPI_I2S_SendData(SPI1, 0x17);  
42
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);      
43
    testspi = SPI_I2S_ReceiveData(SPI1);
44
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
45
    }
46
}

mfg
Lukas

von (prx) A. K. (prx)


Lesenswert?

Takte von GPIO und SPI eingeschaltet?

von THaala (Gast)


Lesenswert?

Nur als TIPP:

ich hatte beim Einlesen des Touchcontroller-Baustein meines Panels auch 
zu kämpfen. Bei dem ADx(watweißichnoch) habe ich gesehen, dass die nicht 
sofort antworten.

Ich hatte dann zunächst einen Test gemacht, der explizit mit den 
Portpins wackelt, ehe ich dann auf die "highsophisticated" STM32-SPI 
"ichmacheallesfürdich" - Version umgestiegen bin.

Gruß Thilo.

P.S. Dein Chip - Select weist in deiner Schleife nur einen Spike nach 
"H" hin auf. eine kleine Pause wäre gut....

von sakul (Gast)


Lesenswert?

Mit den Takten stimmte etwas nicht. Müsste jetzt aber passen:
1
void RCC_Configuration(void)
2
{
3
    /* RCC system reset(for debug purpose) */
4
    RCC_DeInit();
5
6
    /* Enable HSE */
7
    RCC_HSEConfig(RCC_HSE_ON);
8
9
    /* Wait till HSE is ready */
10
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
11
12
    if (HSEStartUpStatus == SUCCESS)
13
    {
14
        /* HCLK = SYSCLK */
15
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
16
17
        /* PCLK2 = HCLK/2 */
18
        RCC_PCLK2Config(RCC_HCLK_Div2);
19
20
        /* PCLK1 = HCLK/2 */
21
        RCC_PCLK1Config(RCC_HCLK_Div2);
22
23
        /* PLLCLK = 8MHz * 9 = 72 MHz */
24
        RCC_PLLConfig(0x00010000, RCC_PLLMul_9);
25
26
        /* Enable PLL */
27
        RCC_PLLCmd(ENABLE);
28
29
        /* Wait till PLL is ready */
30
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
31
32
        /* Select PLL as system clock source */
33
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
34
35
        /* Wait till PLL is used as system clock source */
36
        while (RCC_GetSYSCLKSource() != 0x08) {}
37
    }
38
39
    /* Enable peripheral clocks ----------------------------------------------*/
40
    /* GPIOA, GPIOB and SPI1 clock enable */
41
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
42
            | RCC_APB2Periph_SPI1, ENABLE);
43
    /* SPI2 Peripheral clock enable */
44
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
45
}

Hängen bleiben tut er nun nicht mehr. Bekomme aber leider nichts vom AD 
zurück.
@Thilo: Hat es denn mit der "highsophisticated" STM32-SPI
"ichmacheallesfürdich" - Version geklappt? Eine kleine Pause habe ich 
drin.

von THaala (Gast)


Lesenswert?

Ja, hat es!

Allerdings benutze ich ChibiOS. Die haben einen eigenen HAL, der es noch 
einfacher machen soll.

Wenn du dich zwei bis drei Stunden geduldest kann ich Dir beide 
Varianten hier posten.

Gruß Thilo

von sakul (Gast)


Lesenswert?

Da Gedulde ich mich gerne :)

von Matthias K. (matthiask)


Lesenswert?

>  SPI_SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;

sicher?

von sakul (Gast)


Lesenswert?

>>  SPI_SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
>
> sicher?

ja, Seite 31:
http://www.analog.com/static/imported-files/data_sheets/AD7142.pdf

von Gnubbel (Gast)


Lesenswert?

sakul schrieb:
1
> GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  // 5 = SPI1_SCK, 6 = SPI1_MISO, 7 = SPI1_MOSI
2
>   GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
3
>   GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
4
>   GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);

Den MOSI als PP zu konfigurieren wird bestimmt nich richtig sein.

Versuch mal das:
1
//MISO
2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_OD;       
3
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;              
4
    GPIO_Init(GPIOA, &GPIO_InitStructure);

von vaid (Gast)


Lesenswert?

Gnubbel schrieb:
> Den MOSI als PP zu konfigurieren wird bestimmt nich richtig sein.

Ist aber richtig!

von vaid (Gast)


Lesenswert?

Hab den Code noch mal mit meinem funktionierenden SPI-Code verglichen. 
Sowohl Initialisierung als auch Ansteuerung sehen korrekt aus.

Ich tippe auf eine falsche Ansteuerung des AD...

von (prx) A. K. (prx)


Lesenswert?

Gnubbel schrieb:

> Den MOSI als PP zu konfigurieren wird bestimmt nich richtig sein.

Verwechselst du hier SPI mit I2C? PP ist für SPI richtig.

von sakul (Gast)


Angehängte Dateien:

Lesenswert?

> Ich tippe auf eine falsche Ansteuerung des AD...
siehe PDF

von vaid (Gast)


Lesenswert?

sakul schrieb:
> siehe PDF

So meinte ich das nicht ;-)

Leitungen scheinen richtig angeschlossen zu sein (hatte mal einen bösen 
Fehler, weil die MISO/MOSI Leitung zu einer SD-Karte vertauscht war...).

Ich meinte, dass die Einstellung des SPI vielleicht nicht richtig ist.

von (prx) A. K. (prx)


Lesenswert?

Yep, der AD scheint dem Datasheet nach zu schliessen eher CPOL=1/CPHA=1 
zu bevorzugen.

von THaala (Gast)


Lesenswert?

Falls es Dich noch interessiert:

Das hier ist der Controller:

http://www.ti.com/lit/ds/symlink/ads7843.pdf

und hier der minimal-code für das SPI bitbanging:
1
#define  CHX   0x90
2
#define  CHY   0xD0
3
4
#define ADS7843_CS_LOW()     GPIO_ResetBits(GPIO_ADS7843_CS_PORT, RCC_ADS7843_CS)
5
#define ADS7843_CS_HIGH()    GPIO_SetBits(GPIO_ADS7843_CS_PORT, RCC_ADS7843_CS)
6
7
#define SPI1_SCK_LOW()       GPIO_ResetBits(SPI1_PORT, SPI1_SCK)
8
#define SPI1_SCK_HIGH()      GPIO_SetBits(SPI1_PORT, SPI1_SCK)
9
10
#define SPI1_MISO_READ()     GPIO_ReadInputDataBit(SPI1_PORT, SPI1_MISO)
11
12
#define SPI1_MOSI_LOW()      GPIO_ResetBits(SPI1_PORT, SPI1_MOSI)
13
#define SPI1_MOSI_HIGH()     GPIO_SetBits(SPI1_PORT, SPI1_MOSI)
14
15
static void ADS7843_SPI_Start( void )
16
{
17
    ADS7843_CS_HIGH();
18
    SPI1_MOSI_HIGH();
19
    SPI1_SCK_LOW();
20
    ADS7843_CS_LOW();
21
}
22
23
static void SPI_MOSI(u8 data)
24
{
25
    if(data)
26
        SPI1_MOSI_HIGH();
27
    else
28
        SPI1_MOSI_LOW();
29
}
30
31
static void ADS7843_WrCmd(u8 cmd)
32
{
33
    u8 buf, i;
34
35
    for( i = 0; i < 8; i++ ){
36
        buf = (cmd >> (7-i)) & 0x1 ;
37
        SPI_MOSI(buf);
38
        SPI1_SCK_HIGH();
39
        SPI1_SCK_LOW();
40
    }
41
42
}
43
44
static u16 ADS7843_Read(void)
45
{
46
    u16 buf = 0 ;
47
    u8 i;
48
49
    SPI1_SCK_HIGH(); 
50
    SPI1_SCK_LOW();
51
    for( i = 0; i < 12; i++ ){
52
        buf = buf << 1 ;
53
        SPI1_SCK_HIGH();
54
        if ( SPI1_MISO_READ() ){
55
            buf = buf + 1 ;
56
        }
57
        SPI1_SCK_LOW();
58
    }
59
    for( i = 0; i < 3; i++ ){
60
        SPI1_SCK_HIGH();
61
        SPI1_SCK_LOW();
62
    }
63
    return( buf ) ;
64
}

ich nehme an das Dir der endgültige ChibiOS-Code nichts nutzt. Wenn Du 
Ihn doch haben willst dann melde dich nochmals.

Gruß Thilo

von sakul (Gast)


Lesenswert?

Habe CPOL/CPHA angepasst. Ich erzeuge nun auch das richtige 
Controll-Word, doch leider bekomme ich noch immer nichts zurück :(
1
u16 ControlValue;
2
u16 Register;
3
u16 testspi = 0xAAAA;
4
5
void touchTask(void) 
6
{
7
  int i;  
8
9
  SPI_InitTypeDef SPI_SPI1_InitStructure;
10
  GPIO_InitTypeDef GPIOSPI1_InitStructure;
11
12
  RCC_Configuration();
13
14
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  // 5 = SPI1_SCK, 6 = SPI1_MISO, 7 = SPI1_MOSI
15
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
16
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
17
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
18
  
19
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_4;             // 4 = SPI1_CS
20
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
21
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
22
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
23
  
24
  SPI_SPI1_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
25
  SPI_SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
26
  SPI_SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
27
  SPI_SPI1_InitStructure.SPI_CPOL = SPI_CPOL_High;
28
  SPI_SPI1_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
29
  SPI_SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
30
  SPI_SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
31
  SPI_SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
32
  
33
  SPI_Init(SPI1, &SPI_SPI1_InitStructure);
34
  
35
  SPI_Cmd(SPI1, ENABLE);
36
37
  //Read Silicon versions to check communication, It should read 0xE622
38
39
  //Create the 16-bit header   
40
  Register = 0x17;                    // I.D. Register  
41
  ControlValue   = 0xE400 | (Register & 0x03FF);      
42
        //   = 0xE417   =   1110 0100 0001 0111
43
        // [15:11] = 11100  -> enable word
44
        // [10] = 0  -> R/W
45
        // [9:0] = [AD9, AD8, AD7, AD6, AD5, AD4, AD3, AD2, AD1, AD0] (STARTING MSB JUSTIFIED REGISTER ADDRESS)        
46
  
47
  for (i=0;i<4000;i++);    // delay
48
  
49
  for(;;) 
50
  {
51
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
52
    SPI_I2S_SendData(SPI1, ControlValue);  
53
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);  
54
    testspi = SPI_I2S_ReceiveData(SPI1);      // should read 0xE622 
55
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
56
    }
57
}

Gruß
Lukas

von (prx) A. K. (prx)


Lesenswert?

sakul schrieb:

> Habe CPOL/CPHA angepasst.

Aber ob richtig? Es gibt 4 Möglichkeiten, 3 davon sind falsch.

von sakul (Gast)


Lesenswert?

Ich habe vorsichtshalber alle 4 durchgetanzt

von Gnubbel (Gast)


Lesenswert?

A. K. schrieb:
> Verwechselst du hier SPI mit I2C? PP ist für SPI richtig.

Nee, denn MISO heißt Master-Input und sollte somit im Regelfall kein
Push-Pull-Ausgang sein. Aber gemäß der Doku zur Library ist das hier 
i.O. .

@sakul

Bist du sicher ob alle Leitungen :
 1. Im Schaltplan korrekt angeschlossen sind? (bewege ggf. mal die 
beiden Bausteine hin und her, dann siehst du das)
2. Im Board geroutet sind? (Layer angezeigt)

Was steht denn im Eingangsbuffer? 0xFFFF, 0x0000?

von (prx) A. K. (prx)


Lesenswert?

Gnubbel schrieb:

> Nee, denn MISO heißt Master-Input und sollte somit im Regelfall kein
> Push-Pull-Ausgang sein.

Nur hattest du oben moniert, dass MOSI OD sein solle, nicht MISO:
Beitrag "Re: STM32 -> SPI -> AD7142"

MISO wiederum sollte m.E. weder PP noch OD sein, sondern ein Eingang.

von THaala (Gast)


Lesenswert?

Du hast auf CS noch immer kaum einen "H" - Zustand.

Mach zwischen Schreiben des Kommandos und dem Einlesen des Ergebnisses 
mal eine Pause!

Hast Du ein Oszilloskop ? Regen sich irgendwelche Pins ?
Oder mindestens einen Debugger ? Dann könntest Du auch explizit mit den 
Pins wackeln.

Bist Du sicher das das Wort genau so rausgeht ?
Unter ChibiOS wurde DMA genutzt. Dabei waren High und Low vertauscht.
Teste mal 0x17E4....

Gruß Thilo

von (prx) A. K. (prx)


Lesenswert?

sakul schrieb:

>   GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 |
> GPIO_Pin_7;  // 5 = SPI1_SCK, 6 = SPI1_MISO, 7 = SPI1_MOSI
>   GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
>   GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
>   GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);

An der Stelle hat Gnubbel auf falsche Art Recht: Solange der Eingang 
MISO ein Ausgang ist wird das sicher nix werden.

von THaala (Gast)


Lesenswert?

Gnubbel hat Recht,

MISO is ein Input!

Gruß

von sakul (Gast)


Lesenswert?

Habe den MISO nun als GPIO_Mode_IN_FLOATING. Auf was muss ich 
SPI_BaudRatePrescaler stellen?

> Mach zwischen Schreiben des Kommandos und dem Einlesen des Ergebnisses
> mal eine Pause!
Wie lange?

von THaala (Gast)


Lesenswert?

Ich weiß das auch nicht - was sage das Datenblatt dazu ?

Ich habe Dir oben den Pintoggle - trivial - code gepostet. Tritt mal 
einen Schritt zurück und versuche nicht gleich das Maximum 
hinzubekommen. Schön wenn man sofort fertig ist, aber meistens läuft es 
nicht so.

Wäre es nicht gut erst mal irgendeine Reaktion von dem Chip zu bekommen 
- und sei es nur das der MISO mal auf Low geht ?

Nochmal die Frage - was hast du für Hilfsmittel ?
OSKAR ? DEBUGGER ? Kannst Du sehen ob auf dem MOSI überhaupt was 
rausgeht ? Siehst Du denn Clock - Signale ?

Es gibt für SPI keine Baudratenuntergrenze. Du kannst die Zeiten 
beliebig groß ziehen - sogar so groß das Du LED's zur Kontrolle 
anbringen kannst.

Wenn du mal eine Reaktion des Chips bekommst - dann melde dich wieder! 
Wenn wir dann zusammen nach der richtigen SPI - Konfiguration suchen 
wissen wir wenigstens das die Hardwaresignale richtig geschaltet sind!

Gruß Thilo

von Gnubbel (Gast)


Lesenswert?

Natürlich meinte ich MISO, aber ich habe nochmal in der Doku zur Library 
nachgeschaut, und das Beispiel welches ich gesehen habe hat tatsächlich 
den Eingang als AF_PP konfiguriert.
Es kann natürlich auch sein dass in den Beispielen der Library ein 
Fehler ist.

IN_FLOATING ist aber auch nicht unbedingt richtig, da es ja eine 
alternative Funktion-> AF sein soll, nämlich nicht GPIO sondern SPI.

Ich benutze wie oben angegeben AF_OD und das funktioniert definitiv.

RM0008 S.157: For alternate function inputs, the port must be configured 
in Input mode (floating, pull-
up or pull-down) and the input pin must be driven externally.

von THaala (Gast)


Lesenswert?

Gnubbel hat mal wieder Recht,

mindestens drei SPI - Pins müssen auf den Alternate - Mode (5) 
geschaltet sein. Sonst rühren die sich nicht. Es sind MOSI, MISO und 
CLK...

Trotzdem bleibe ich dabei - Mach erst mal den Toggle - Pin - Test. Wenn 
da eine Antwort kommt weiß man mehr....

von sakul (Gast)


Lesenswert?

Ich schaue mir das morgen mal an einem Oszilloskop an und gebe Bescheid 
was dabei rauskam.

Gruß
Lukas

von (prx) A. K. (prx)


Lesenswert?

Gnubbel schrieb:

> IN_FLOATING ist aber auch nicht unbedingt richtig, da es ja eine
> alternative Funktion-> AF sein soll, nämlich nicht GPIO sondern SPI.
>
> RM0008 S.157: For alternate function inputs, the port must be configured
> in Input mode (floating, pull-up or pull-down) and the input pin must be
> driven externally.

Ähm... und in diesen beiden Aussagen siehst du keinen Widerspruch? Du 
behauptest, die Programmierung als Input sei nicht unbedingt richtig - 
und die Referenz behauptet, es wäre genau richtig.

Es gibt bei den Pins keinen Modus für AF-Input. Der ist auch nicht 
erforderlich, weil der Input-Zweig des Pins auch ohne explizite Schalte 
zum Funktionsmodul geleitet wird. Nur bei Ausgängen muss man die interne 
Signalquelle umschalten. Kann man recht hübsch in Chapter 9 Figure 13 
erkennen.

THaala schrieb:

> mindestens drei SPI - Pins müssen auf den Alternate - Mode (5)
> geschaltet sein. Sonst rühren die sich nicht. Es sind MOSI, MISO und
> CLK...

Seltsamerweise funktionierte SPI bei mir auch dann, wenn MISO als 
normaler Input geschaltet ist.

von (prx) A. K. (prx)


Lesenswert?

Update: Bei SPI besteht für die Pinfunktion die Besonderheit, dass 
SCLK/MOSI/MISO durch die Master/Slave-Umschaltung ihre Richtung 
wechseln. Es wird also so sein, dass im Fall von SPI auch AF-Output für 
den Eingang spezifiziert werden kann und die vom SPI-Modul kommende 
AF-Steuerung dafür sorgt, dass der Ausgangstreiber bei Funktion als 
Eingang automatisch abgeschaltet wird.

sakul kann also weitersuchen, ob er MISO als Eingang oder Ausgang 
konfiguriert ist bei einem reinen SPI-Master egal.

von Gnubbel (Gast)


Lesenswert?

A. K. schrieb:
> Es gibt bei den Pins keinen Modus für AF-Input. Der ist auch nicht
> erforderlich, weil der Input-Zweig des Pins auch ohne explizite Schalte
> zum Funktionsmodul geleitet wird.

Ja OK, da gebe ich mich mal geschlagen.

Bleiben aber immernoch folgende Fragen offen:

Bist du sicher ob alle Leitungen :
 1. Im Schaltplan korrekt angeschlossen sind? (bewege ggf. mal die
beiden Bausteine hin und her, dann siehst du das)
2. Im Board geroutet sind? (Layer angezeigt)

Was steht denn im Eingangsbuffer? 0xFFFF, 0x0000?

von sakul (Gast)


Lesenswert?

> 1. Im Schaltplan korrekt angeschlossen sind? (bewege ggf. mal die
> beiden Bausteine hin und her, dann siehst du das)
> 2. Im Board geroutet sind? (Layer angezeigt)
beides Ok, habe Vcc,Gnd,CS,CLK,Miso,Mosi durchgeklingelt -> passt
> Was steht denn im Eingangsbuffer? 0xFFFF, 0x0000?
0x0000

Ich denke in ein paar stunden weiss ich dank Oszilloskop mehr.

Gruß
Lukas

von THaala (Gast)


Lesenswert?

Wenn es um die generelle Vorgehensweise geht ist ST selbst die beste 
Quelle.

z.B die Resource für deren EVAL Board 3210B
http://www.st.com/internet/evalboard/product/176090.jsp

in der Demonstration Firmware findest Du mehr als eine SPI - Config - 
Funktion.

Schaust Du hier:
um0435.zip\STM3210B-EVAL_FW_V2.0.0\Project\Demo\src\stm3210b_lcd.c
Funktion LCD_SPIConfig();

oder....
um0435.zip\STM3210B-EVAL_FW_V2.0.0\Project\Demo\src\spi_flash.c
void SPI_FLASH_Init(void);

Gruß Thilo

von vaid (Gast)


Lesenswert?

Ich möchte nochmal betonen... hab den SPI mit den oben beschriebenen 
Einstellungen am Laufen. AF-PP ist definitiv die richtige Konfiguration.

Schau dir die Datenübertragung auf dem Oszilloskop an. Ich tippe darauf, 
dass das Datenwort bereits gesendet wird während der Chip Select noch 
nicht aktiv ist.

von Gnubbel (Gast)


Lesenswert?

Wenn du kein Oszi hast kannst du ja den Eingang mal als
GPIO anlegen und den Pin dann ständig abfragen und die Led einschalten 
wenn sich der Pegel ändert.

von Gnubbel (Gast)


Lesenswert?

Nicht erschlagen bitte,

aber hast du vielleicht einen AD7142-1?

von sakul (Gast)


Lesenswert?

> aber hast du vielleicht einen AD7142-1?
Ne, ist wirklich der mit SPI. Gerade nochmal nachgeschaut.

von sakul (Gast)


Lesenswert?

Habe nun am Oskar gesehen, dass der Clock nur während des Sendens da 
ist. Beim Empfangen ist er Null. Woran kann das liegen?

von THaala (Gast)


Lesenswert?

Schon mal nachgesehene was SPI_I2S_ReceiveData()
so macht ?
1
uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx)
2
{
3
  /* Check the parameters */
4
  assert_param(IS_SPI_ALL_PERIPH(SPIx));
5
  
6
  /* Return the data in the DR register */
7
  return SPIx->DR;
8
}


siehst Du auch den Pointer im Prototype ?

Gruß T.

von THaala (Gast)


Lesenswert?

In den Beispielen die ich ganannt habe wird das Senden immer abgewartet 
mit der Prüfung auf _BSY

[c]
    SPI_I2S_SendData(SPI2, 0xFF);
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET)
    {
    }
    /* One byte of invalid dummy data read after the start byte */
    while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
    {
    }
    SPI_I2S_ReceiveData(SPI2);
  }

  SPI_I2S_SendData(SPI2, 0xFF);
  /* Read upper byte */
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) != RESET)
  {
  }
  /* Read lower byte */
  while(SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)
  {
  }
  tmp = SPI_I2S_ReceiveData(SPI2);
[/c}

gruß T.
P.S. Vergiss das mit dem Pointer - ich habe mich da vertan!

von sakul (Gast)


Lesenswert?

Habe ich angepasst:
1
  for(;;) 
2
  {
3
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
4
    SPI_I2S_SendData(SPI1, ControlValue);
5
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET){}  
6
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
7
    testspi = SPI_I2S_ReceiveData(SPI1);      // should read 0xE622 
8
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
9
    }
Leider immer noch nur ein CLK beim Senden

von THaala (Gast)


Lesenswert?

Ja Moment, aus den Beispielen lese ich, das Du selbst für das Clocking 
sorgst, indem Du ein 0xFF (bzw 0xFFFF in deinem Fall) schreibst. Die 
Konsequenz:
Clock Zappelt, MOSI beleibt auf 1 und MISO rappelt - oder ?

Gruß T.

von THaala (Gast)


Lesenswert?

P.S.

Du hast noch immer kein vernünftiges High auf deinem CS.
Bau doch mal ganz unten ein kleines Warten ein!

Gruß T.

von (prx) A. K. (prx)


Lesenswert?

sakul schrieb:

> Habe nun am Oskar gesehen, dass der Clock nur während des Sendens da
> ist. Beim Empfangen ist er Null. Woran kann das liegen?

An der Arbeitsweise von SPI. Es gibt darin kein getrenntes Senden und 
Empfangen. Wann immer gesendet wird, wird auch gleichzeitig empfangen.

Wenn man also 16 Bits senden und anschliessend als Antwort 16 Bits 
empfangen will, dann werden insgesamt 32 Bits gesendet und 32 Bits 
empfangen.

von THaala (Gast)


Lesenswert?

Also:
1
  for(;;) 
2
  {
3
    GPIO_ResetBits(GPIOA, GPIO_Pin_4);
4
    SPI_I2S_SendData(SPI1, ControlValue);
5
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET){}  
6
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
7
    testspi = SPI_I2S_ReceiveData(SPI1); // read trash.....
8
9
    WarteBisDerChipDieAntwortHat_fallsNoetig();
10
11
    SPI_I2S_SendData(SPI1, 0xFFFF);
12
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET){}  
13
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
14
    testspi = SPI_I2S_ReceiveData(SPI1); // read expected data.....
15
    GPIO_SetBits(GPIOA, GPIO_Pin_4);
16
    WarteEinBischenHier(); // CS mal auf High gehen lassen....
17
  }

von sakul (Gast)


Lesenswert?

Es funktioniert! :) Vielen Dank für die Hilfe!!!
Dann werde ich mal loslegen und mich mit dem Parametrieren von dem Ding 
rumschlagen

von vaid (Gast)


Lesenswert?

Viel Erfolg! :-)

von sakul (Gast)


Lesenswert?

So um das ganze zu vervollständigen, hier der funktionierende Code:

SPI-Initialisierung:
1
void spi1init(void) 
2
{  
3
  SPI_InitTypeDef SPI_SPI1_InitStructure;
4
  GPIO_InitTypeDef GPIOSPI1_InitStructure;
5
6
  RCC_Configuration();
7
8
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_6 | GPIO_Pin_7;  // 5 = SPI1_SCK, 6 = SPI1_MISO, 7 = SPI1_MOSI
9
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
10
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
11
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
12
  
13
  GPIOSPI1_InitStructure.GPIO_Pin = GPIO_Pin_4;      // 4 = SPI1_CS
14
  GPIOSPI1_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
15
  GPIOSPI1_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
16
  GPIO_Init(GPIOA, &GPIOSPI1_InitStructure);
17
  
18
  SPI_I2S_DeInit(SPI1);
19
20
  SPI_SPI1_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
21
  SPI_SPI1_InitStructure.SPI_Mode = SPI_Mode_Master;
22
  SPI_SPI1_InitStructure.SPI_DataSize = SPI_DataSize_16b;
23
  SPI_SPI1_InitStructure.SPI_CPOL = SPI_CPOL_High;
24
  SPI_SPI1_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
25
  SPI_SPI1_InitStructure.SPI_NSS = SPI_NSS_Soft;
26
  SPI_SPI1_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_4;
27
  SPI_SPI1_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
28
    SPI_SPI1_InitStructure.SPI_CRCPolynomial = 7;  
29
  
30
  SPI_Init(SPI1, &SPI_SPI1_InitStructure);  
31
  SPI_Cmd(SPI1, ENABLE);
32
}

Clock-Konfiguration:
1
void RCC_Configuration(void)
2
{
3
    /* RCC system reset(for debug purpose) */
4
    RCC_DeInit();
5
6
    /* Enable HSE */
7
    RCC_HSEConfig(RCC_HSE_ON);
8
9
    /* Wait till HSE is ready */
10
    HSEStartUpStatus = RCC_WaitForHSEStartUp();
11
12
    if (HSEStartUpStatus == SUCCESS)
13
    {
14
        /* HCLK = SYSCLK */
15
        RCC_HCLKConfig(RCC_SYSCLK_Div1);
16
17
        /* PCLK2 = HCLK/2 */
18
        RCC_PCLK2Config(RCC_HCLK_Div2);
19
20
        /* PCLK1 = HCLK/2 */
21
        RCC_PCLK1Config(RCC_HCLK_Div2);
22
23
        /* PLLCLK = 8MHz * 9 = 72 MHz */
24
        RCC_PLLConfig(0x00010000, RCC_PLLMul_9);
25
26
        /* Enable PLL */
27
        RCC_PLLCmd(ENABLE);
28
29
        /* Wait till PLL is ready */
30
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {}
31
32
        /* Select PLL as system clock source */
33
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
34
35
        /* Wait till PLL is used as system clock source */
36
        while (RCC_GetSYSCLKSource() != 0x08) {}
37
    }
38
39
    /* Enable peripheral clocks ----------------------------------------------*/
40
    /* GPIOA enable */
41
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
42
    
43
    /* SPI1 enable */
44
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
45
}

Lesen/Schreiben:
1
void ReadFromAD7142ViaSpi(const u16 RegisterStartAddress, const u8 NumberOfRegisters, u16 *DataBuffer, const u16 OffsetInBuffer)
2
{
3
  u16 ControlValue;
4
  u8 i,j, RegisterIndex;
5
  u16 InputValue;
6
  
7
  ControlValue = 0xE400 | (RegisterStartAddress & 0x03FF);    //Create the 16-bit header
8
  
9
  for (i=0;i<100;i++);    // delay
10
11
  //Write out the control word
12
  GPIO_ResetBits(GPIOA, GPIO_Pin_4);    // CS low
13
  SPI_I2S_SendData(SPI1, ControlValue);
14
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET);  
15
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
16
  InputValue = SPI_I2S_ReceiveData(SPI1);   // Read dummy
17
18
  //Copy each register in the buffer contiguously.
19
  //Read data in.
20
  for (RegisterIndex=0; RegisterIndex<NumberOfRegisters; RegisterIndex++)
21
  {
22
    SPI_I2S_SendData(SPI1, 0xFFFF);
23
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET); 
24
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
25
    InputValue = SPI_I2S_ReceiveData(SPI1);   // read data
26
    *(DataBuffer+OffsetInBuffer+RegisterIndex)=(u16)InputValue;
27
  }
28
  GPIO_SetBits(GPIOA, GPIO_Pin_4);    // CS high
29
  for (j=0;j<5;j++);      // delay
30
}
31
32
void WriteToAD7142ViaSpi(const u16 RegisterAddress, const u8 NumberOfRegisters, u16 *DataBuffer, const u8 OffsetInBuffer)
33
{
34
  u16 ControlValue;
35
  u16 ValueToWrite;
36
  u16 RegisterIndex;
37
  u8 j;
38
  
39
  ControlValue = 0xE000 | (RegisterAddress & 0x03FF);    //Create the 16-bit header
40
41
  //Write out the control word
42
  GPIO_ResetBits(GPIOA, GPIO_Pin_4);    // CS low
43
  SPI_I2S_SendData(SPI1, ControlValue);
44
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET);  
45
  while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
46
47
  //And then the data
48
  for (RegisterIndex=0; RegisterIndex<NumberOfRegisters; RegisterIndex++)
49
  {
50
    ValueToWrite= *(DataBuffer+RegisterIndex+OffsetInBuffer);
51
    SPI_I2S_SendData(SPI1, ValueToWrite);
52
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_BSY) != RESET); 
53
    while(SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
54
  }
55
  GPIO_SetBits(GPIOA, GPIO_Pin_4);    // CS high
56
  for (j=0;j<5;j++);            // delay
57
}

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.