Forum: Mikrocontroller und Digitale Elektronik STM32 SPI DMA


von STMSPISucks (Gast)


Angehängte Dateien:

Lesenswert?

Hey,

ich versuche gerade mit einem STM32F091 SPI mit Hilfe von DMA zum laufen 
zu bringen und es klappt... nicht wirklich gut.
Auf den Bildern sieht man zum einen einen Mitschnitt vom Oscilloscope 
und zum einen was ich beim Debuggen im RxBuffer zu stehen habe.
Dabei stört mich gerade weniger die Abweichung bei dem einen Wert (18 
statt 19) sondern viel mehr, wie die Daten im Buffer angeordnet sind.

Man sieht ja in welcher Reihenfolge die Daten im Buffer liegen und in 
welcher Reihenfolge die Daten auf dem Bus ankamen. Im Anhang poste ich 
mal die wichtigsten Teile vom Code, evtl. entdeckt jemand einen Fehler. 
Im idealfall stelle ich es mir so vor, dass ich Adresse, von der ich 
lesen will an den anderen IC schicke und während ich mein 0x00 dummy 
Byte schicke ich die Antwort kriege und diese Antwort nach und nach im 
Array an Stelle 0, 1, 2, ... gespeichert wird.
1
void SPI_init()
2
{
3
  SPI_InitTypeDef SPI_InitStructure;
4
5
  // clk
6
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN;
7
  RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;
8
9
  // set af mode
10
  GPIOA->MODER = ( GPIOA->MODER & ~(GPIO_MODER_MODER5 | GPIO_MODER_MODER6 | GPIO_MODER_MODER7));
11
  GPIOA->MODER |= ( GPIO_MODER_MODER5_1 | GPIO_MODER_MODER6_1 | GPIO_MODER_MODER7_1);
12
13
  GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRL_AFR5)) | (0 << GPIO_AFR_POS5);
14
  GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRL_AFR6)) | (0 << GPIO_AFR_POS6);
15
  GPIOA->AFR[1] = (GPIOA->AFR[1] &~ (GPIO_AFRL_AFR7)) | (0 << GPIO_AFR_POS7);
16
17
  SPIx_PORT->MODER |= ( GPIO_MODER_MODER4_0);
18
  SPIx_PORT->OTYPER &= ~( GPIO_OTYPER_OT_4); 
19
  SPIx_PORT->OSPEEDR |= ( GPIO_OSPEEDER_OSPEEDR4);
20
  SPIx_PORT->PUPDR &= ~( GPIO_PUPDR_PUPDR4);
21
22
  SPIx_PORT->BSRR = GPIO_BSRR_BS_4; //High - Deselect ACC
23
24
  /*SPI1-Konfigurieren*/
25
  SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
26
  SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
27
  SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
28
  SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
29
  SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
30
  SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
31
  SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_64;
32
  SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
33
  SPI_InitStructure.SPI_CRCPolynomial = 7;
34
  SPI_Init(SPIx,&SPI_InitStructure);
35
36
  //Use DMA for SPI
37
  SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Tx, ENABLE);
38
  SPI_I2S_DMACmd(SPIx, SPI_I2S_DMAReq_Rx, ENABLE);
39
40
  //SPI aktivieren
41
  SPI_Cmd(SPIx, ENABLE);
42
43
  //Init DMA
44
  DMA_Config();
45
46
  //Init the buffer with the needed registers of the acc
47
  AccelerationRequest[0] = ACCELEROMETER_OUT_X_L;
48
  AccelerationRequest[1] = 0x00; //dummy
49
  AccelerationRequest[2] = ACCELEROMETER_OUT_X_H;
50
  AccelerationRequest[3] = 0x00;
51
  AccelerationRequest[4] = ACCELEROMETER_OUT_Y_L;
52
  AccelerationRequest[5] = 0x00;
53
  AccelerationRequest[6] = ACCELEROMETER_OUT_Y_H;
54
  AccelerationRequest[7] = 0x00;
55
  AccelerationRequest[8] = ACCELEROMETER_OUT_Z_L;
56
  AccelerationRequest[9] = 0x00;
57
  AccelerationRequest[10] = ACCELEROMETER_OUT_Z_H;
58
  AccelerationRequest[11] = 0x00;
59
}
60
61
void DMA_Config()
62
{
63
    DMA_InitTypeDef DMA_InitStructure;
64
    NVIC_InitTypeDef NVIC_InitStructure;
65
66
    DMA_DeInit(DMA1_Channel2);
67
    DMA_DeInit(DMA1_Channel3);
68
69
    DMA_StructInit(&DMA_InitStructure);
70
71
    // Enable DMA1 Peripheral Clock (SPI_DECAWAVE and SPI_BUS)
72
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
73
74
    // Configure SPI_BUS RX Channel
75
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC; // From SPI to memory
76
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
77
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
78
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
79
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)RxBuffer;
80
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
81
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
82
    DMA_InitStructure.DMA_BufferSize = sizeof(RxBuffer);
83
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
84
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
85
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
86
    DMA_Init(DMA1_Channel2, &DMA_InitStructure);
87
88
    // Configure SPI_BUS TX Channel
89
    DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST; // From memory to SPI
90
    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI1->DR;
91
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
92
    DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
93
    DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)TxBuffer;
94
    DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
95
    DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
96
    DMA_InitStructure.DMA_BufferSize = sizeof(TxBuffer);;
97
    DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
98
    DMA_InitStructure.DMA_Priority = DMA_Priority_High;
99
    DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
100
    DMA_Init(DMA1_Channel3, &DMA_InitStructure);
101
102
    DMA_ITConfig(DMA1_Channel2, DMA_IT_TC, ENABLE);
103
104
    NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_3_IRQn;
105
    NVIC_InitStructure.NVIC_IRQChannelPriority = 0;
106
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
107
    NVIC_Init(&NVIC_InitStructure);
108
}
109
110
//Hier übergebe ich AccelerationRequest mit einer Size von 12 (Jeweils Register + DummyByte)
111
void SPI_ReadRegisters(uint8_t* ReadAddrBuffer, uint8_t Size)
112
{
113
  for (uint8_t i=0; i < Size; i++)
114
  {
115
    if (ReadAddrBuffer[i] > 0x00)
116
      TxBuffer[i] = ReadAddrBuffer[i] | READ_FLAG;
117
    else
118
      TxBuffer[i] = 0x00;
119
  }
120
121
  DMA_Cmd(DMA1_Channel2, DISABLE);
122
  DMA_Cmd(DMA1_Channel3, DISABLE);
123
124
  DMA_SetCurrDataCounter(DMA1_Channel2, Size);
125
  DMA_SetCurrDataCounter(DMA1_Channel3, Size);
126
127
  SPI_SelectChip();
128
129
  DMA_Cmd(DMA1_Channel2, ENABLE);
130
  DMA_Cmd(DMA1_Channel3, ENABLE);
131
}
132
133
134
void DMA1_Channel2_3_IRQHandler(void)
135
{
136
  if (DMA_GetITStatus(DMA1_IT_TC2) != RESET)
137
  {
138
    SPI_DeselectChip();
139
140
    int16_t x = (int16_t)((RxBuffer[1] << 8) | RxBuffer[0]); // / 16384.0f;
141
    int16_t y = (int16_t)((RxBuffer[3] << 8) | RxBuffer[2]); // / 16384.0f;
142
    int16_t z = (int16_t)((RxBuffer[5] << 8) | RxBuffer[4]); // / 16384.0f;
143
144
    DMA_ClearFlag(DMA1_FLAG_TC2);
145
  }
146
}

von Christopher J. (christopher_j23)


Lesenswert?

STMSPISucks schrieb:
> sizeof(TxBuffer);

Das gibt dir immer die Pointergröße, also 4 Byte zurück, egal wie groß 
dein Buffer ist.  Das gleiche gilt natürlich für RxBuffer.

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.