STM32F03x - SPI via DMA - Clock fehlt auf MISO

Gast #4393005
Lesenswert?

Hallo zusammen,

ich habe schon einige Beiträge hier im Forum zu diesem Thema gelesen - 
bin aber irgendwie noch nicht auf den Richtigen Tread gestoßen, deswegen 
hier meine Frage.

Ich versuche gerade für ein Projekt einen STM32F030C mit jeweils 2 HC595 
und HC165 zur IO Erweiterung zu verbinden. Für Senden und Empfangen 
würde ich gerne den DMA benutzen. Dabei macht mich das Empfangen gerade 
ziemlich verrückt.

Die SPI ist als Fullduplex konfiguriert. MISO als Eingangspin. Die 
anderen beiden als AF. Speed ist 2MHz, die SPI ist sehr herunter 
getaktet, so dass der Takt auf dem Daten etwa 8Khz beträgt.
Als DMA nehme ich DMA1 Channel 2 (RX) und 3 (TX) im Interrupt Modus. Die 
laufen auf dem selben Interrupt zusammen, was aber auch nicht so das 
Problem ist. Damit kann ich leben.
DMA ist für beide Channel gleich konfiguriert, lediglich RX und TX 
Buffer sind verschieden.

Problem an der Sache: Sende an die HC595 funktioniert via DMA perfekt. 
Die Clock geht raus, die Daten werden geschrieben.
Empfangen über MISO funktioniert aber nicht. Irgendwie wird keine Clock 
geniert. Ohne Clock bekomme ich aber die Daten nicht aus den HC165 
Bausteinen heraus.

Leider kann ich den Code von der Initialisierung nicht einstellen, da 
ich jetzt zu Hause sitze und den Code im Büro habe.

Hat jemand eine Idee woran das liegen könnte?

Grüße

Jens
Gast #4393836
Lesenswert?

Hallo,

erst mal Danke für die Antworten. War ja auch irgendwie klar. Hätte ich 
auch selbst drauf kommen können bzw. müssen.

Jetzt kommt aber ein Nachfolgeproblem mit dem ich gerade Kämpfe. 
Mittlerweile habe ich die Hardware soweit, dass sendet und auch 
Empfangsdaten von den Erweiterungen zurück an den Controller gehen. Ich 
kann die Daten auf dem Ozsiloskop sehen, die ändern sich auch wenn ich 
was ändere. Physikalisch also soweit wohl erst mal alles Takko.

Nur dummerweiße kommt in meinen Eingangspuffer nichts an. Ich habe es 
sowohl manuell versucht in dem ich die SPI direkt angesprochen habe, als 
auch via DMA - jedes mal bleibt meine Eingangsvariable leer.

Hier mal meine Initialisierung:
1
void SPI1_Init(void)
2
{
3
    GPIO_InitTypeDef GPIO_InitStructure;
4
    SPI_InitTypeDef  SPI_InitStructure;
5

6
    /* enable GPIO clock */
7
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
8

9
    /*enable SPI1 clock*/
10
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
11

12

13
    /* Configure SPI1 IO Pin's */
14
    GPIO_InitStructure.GPIO_Pin = SPI_SCK | SPI_MOSI; // | SPI_MISO;
15
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
16
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
17
    GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
18
    GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_DOWN;
19
    GPIO_Init(GPIOB, &GPIO_InitStructure);
20

21
    GPIO_StructInit (&GPIO_InitStructure);
22

23
    GPIO_InitStructure.GPIO_Pin = SPI_MISO;
24
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
25
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
26
    GPIO_Init(GPIOB, &GPIO_InitStructure);
27

28
    GPIO_PinAFConfig(GPIOB, SPI_SCK_AF,  GPIO_AF_0);
29
  //GPIO_PinAFConfig(GPIOB, SPI_MISO_AF, GPIO_AF_0);
30
    GPIO_PinAFConfig(GPIOB, SPI_MOSI_AF, GPIO_AF_0);
31

32
     /*Configure SPI1*/
33
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
34
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
35

36
    #ifdef WRITE_SPI_VIA_8BIT_SPI
37
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
38
  #else
39
    SPI_InitStructure.SPI_DataSize = SPI_DataSize_16b;
40
  #endif
41

42
    SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
43
    SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
44
    SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
45
    SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_256;
46
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_LSB; // SPI_FirstBit_MSB;
47
    SPI_InitStructure.SPI_CRCPolynomial = 16;
48
    SPI_Init(SPI1, &SPI_InitStructure);
49

50
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE);
51
    SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Rx, ENABLE);
52
    SPI_Cmd(SPI1, ENABLE);
53
}
54

55
void SPI1_DMA_Config(unsigned char* rx_buff,unsigned char* tx_buff)
56
{
57
  DMA_InitTypeDef DMA_InitStructure;
58
  NVIC_InitTypeDef NVIC_InitStructure;
59

60
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  // enable DMA clock
61

62
  #ifdef READ_SPI_VIA_DMA
63
  /*Configure DMA channel 2 to SPI1 -> memory -> Rx*/
64
  DMA_DeInit(DMA1_Channel2);
65
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI1_DR_Address;
66
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)rx_buff;
67
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
68
  DMA_InitStructure.DMA_BufferSize = SPI1_BUFFER_SIZE;
69
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
70
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
71
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
72
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
73
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
74
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
75
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
76
  DMA_Init(DMA1_Channel2, &DMA_InitStructure);
77

78
  DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);    // enable DMA interrupt
79
  DMA_Cmd(DMA1_Channel2, DISABLE);          // enable DMA
80

81
  /*Configure NVIC for DMA interrupt*/
82
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
83
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
84
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
85
  NVIC_Init(&NVIC_InitStructure);
86

87
  DMA_SetCurrDataCounter(DMA1_Channel2, 0);
88
  DMA_Cmd(DMA1_Channel2, ENABLE);
89
  #endif
90

91
  #ifdef WRITE_SPI_VIA_DMA
92
  /*Configure DMA channel 3 to memory -> SPI1 -> Tx*/
93
  DMA_DeInit(DMA1_Channel3);
94
  DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)SPI1_DR_Address;
95
  DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)tx_buff;
96
  DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
97
  DMA_InitStructure.DMA_BufferSize = SPI1_BUFFER_SIZE;
98
  DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
99
  DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
100
  DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
101
  DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
102
  DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
103
  DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
104
  DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
105
  DMA_Init(DMA1_Channel3, &DMA_InitStructure);
106

107
  DMA_ITConfig(DMA1_Channel3, DMA_IT_TC, ENABLE);
108
  DMA_Cmd(DMA1_Channel3, DISABLE);
109

110

111
  NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
112
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
113
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
114
  NVIC_Init(&NVIC_InitStructure);
115

116
  DMA_SetCurrDataCounter(DMA1_Channel3, 0);
117
  DMA_Cmd(DMA1_Channel3, ENABLE);
118
  #endif
119
}

Die DMA Funktion wird aber ausgeführt beim lesen, ich sehe die Daten auf 
dem Oscar, kann sie aber im Debuger nicht sehen. DA steuert Interrupt am 
Ende an.

Dann habe ich das ganze noch mal versucht indem ich direkt auf die SPI 
zugreife. Das gleiche Spiel - ich seh die Daten auf dem Oscar, die Änder 
sich auch passend - im Eingangspuffer liegen sie aber nicht.

read via dma
1
signed char SPI1_DMA_Start_Transmit(unsigned char len,SPI1_call_back_funcptr p_func)
2
{
3
  if(DMA_GetCurrDataCounter(DMA1_Channel3) == 0)
4
  {
5
    SPI1_CallBackFunc = p_func;    // initialize the function pointer
6
    DMA_Cmd(DMA1_Channel2, DISABLE);
7
    DMA_Cmd(DMA1_Channel3, DISABLE);
8
    DMA_SetCurrDataCounter(DMA1_Channel2, len);
9
    DMA_SetCurrDataCounter(DMA1_Channel3, len);
10
    DMA_Cmd(DMA1_Channel2, ENABLE);
11
    DMA_Cmd(DMA1_Channel3, ENABLE);
12
    spi_busy_flag = 1;
13
    return 1;
14
  }
15
  return 0;
16
}

Jemand eine Idee?

Grüße

Jens
Gast #4393957
Lesenswert?

Hatte das mal in einem anderem Forum gelesen, dass man das machen soll.

Ich habs in beiden Variaten versucht - sowohl als AF, als auch als GPIO, 
das hat aber bisher keinen Unterschied gemacht. 0x0000 bleibt eben 0!

Jens

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