STM32 -> SPI -> AD7142

Gast #2559717
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
Gast #2559748
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....
Gast #2559772
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.
Gast #2559786
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
Gast #2559837
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);
Gast #2559926
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.
Gast #2560056
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
Gast #2560189
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
Gast #2560290
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?
Gast #2560297
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
#2560305
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.
Gast #2560464
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
Gast #2560489
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.
Gast #2560560
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....
#2560649
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.
#2560657
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.
Gast #2560717
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?
Gast #2560760
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
Gast #2560764
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
Gast #2560801
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.
Gast #2561164
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.
Gast #2561184
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!
Gast #2561256
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
Gast #2561266
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.
#2561344
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.
Gast #2561378
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
  }
Gast #2568405
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
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren