Forum: Mikrocontroller und Digitale Elektronik STM32F03x - SPI via DMA - Clock fehlt auf MISO


von Jens (Gast)


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

von holger (Gast)


Lesenswert?

>Empfangen über MISO funktioniert aber nicht. Irgendwie wird keine Clock
>geniert.

SPI generiert nur einen Clock wenn man etwas sendet.
Also sende Dummy Bytes wenn du etwas empfangen möchtest.

von A. Horn (Gast)


Lesenswert?


von Jens (Gast)


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

von Jim M. (turboj)


Lesenswert?

Du konigurierst MISO auf GPIO Input. Muss der nicht auch auf AF 
konfiguriert werden, damit die Daten bei der SPI HW ankommen?

von Jens (Gast)


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

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.