Forum: Mikrocontroller und Digitale Elektronik HAL SPI TransmitReceive


von Sebastian T. (sebastian_tsch)


Lesenswert?

Hi,

Ich versuche gerade über den SPI einen Sensor auszulesen. Dazu verwende 
ich die HAL libraries und die funktion HAL_SPI_TransmitReceive_DMA(). 
Ich habe als Datengröße 16-bit im CubeMX eingestellt, doch anscheinden 
sind uint8_t *pTxData, uint8_t *pRxData nur 8-bit, wiso auch immer. Ich 
muss also zuerst den Wert SPI_CMD_READ | SPI_REG_DATA (16-bit) 
übertragen und dann einen 16-bit Wert empfangen, doch ich sehe nicht 
genau, wie ich das machen soll. Meine Idee war einfach 2x8-bit buffer zu 
übergeben, doch dies führt zu keinem Erfolg. Jemand eine Idee/Lösung?

Mein Code
1
uint16_t spi_getData(SPI_HandleTypeDef *hspi) {
2
  uint8_t tx_data[2];
3
  uint8_t rx_data[2];
4
  tx_data[0]=SPI_CMD_READ | SPI_REG_DATA; //each is 16-bit
5
  tx_data[1]=((SPI_CMD_READ | SPI_REG_DATA)>>8);
6
7
  HAL_SPI_TransmitReceive_DMA(hspi,tx_data,rx_data,2);
8
9
  uint16_t data=(rx_data[1]<<8)|(rx_data[0]);
10
  data&=0x3FFF;
11
12
  return data;
13
}

Definition von HAL_SPI_TransmitReceive_DMA():
1
{
2
  uint32_t tmp = 0U, tmp1 = 0U;
3
  HAL_StatusTypeDef errorcode = HAL_OK;
4
  
5
  /* check rx & tx dma handles */
6
  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
7
  assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
8
9
  /* Check Direction parameter */
10
  assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
11
12
  /* Process locked */
13
  __HAL_LOCK(hspi);
14
15
  tmp  = hspi->State;
16
  tmp1 = hspi->Init.Mode;
17
  if (!((tmp == HAL_SPI_STATE_READY) ||
18
        ((tmp1 == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) && (tmp == HAL_SPI_STATE_BUSY_RX))))
19
  {
20
    errorcode = HAL_BUSY;
21
    goto error;
22
  }
23
24
  if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
25
  {
26
    errorcode = HAL_ERROR;
27
    goto error;
28
  }
29
30
  /* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
31
  if (hspi->State != HAL_SPI_STATE_BUSY_RX)
32
  {
33
    hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
34
  }
35
36
  /* Set the transaction information */
37
  hspi->ErrorCode   = HAL_SPI_ERROR_NONE;
38
  hspi->pTxBuffPtr  = (uint8_t *)pTxData;
39
  hspi->TxXferSize  = Size;
40
  hspi->TxXferCount = Size;
41
  hspi->pRxBuffPtr  = (uint8_t *)pRxData;
42
  hspi->RxXferSize  = Size;
43
  hspi->RxXferCount = Size;
44
45
  /* Init field not used in handle to zero */
46
  hspi->RxISR       = NULL;
47
  hspi->TxISR       = NULL;
48
49
#if (USE_SPI_CRC != 0U)
50
  /* Reset CRC Calculation */
51
  if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
52
  {
53
    SPI_RESET_CRC(hspi);
54
  }
55
#endif /* USE_SPI_CRC */
56
57
58
#if defined (STM32F302xC) || defined (STM32F303xC) || defined (STM32F373xC) || defined (STM32F358xx) || defined (STM32F378xx)
59
  /* packing mode management is enabled by the DMA settings */
60
  if ((hspi->Init.DataSize <= SPI_DATASIZE_8BIT) && (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD))
61
  {
62
    /* Restriction the DMA data received is not allowed in this mode */
63
    errorcode = HAL_ERROR;
64
    goto error;
65
  }
66
#endif
67
68
  /* Reset the threshold bit */
69
  CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX | SPI_CR2_LDMARX);
70
71
  /* The packing mode management is enabled by the DMA settings according the spi data size */
72
  if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
73
  {
74
    /* Set fiforxthreshold according the reception data length: 16bit */
75
    CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
76
  }
77
  else
78
  {
79
    /* Set fiforxthresold according the reception data length: 8bit */
80
    SET_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
81
82
    if (hspi->hdmatx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
83
    {
84
      if ((hspi->TxXferSize & 0x1U) == 0x0U)
85
      {
86
        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
87
        hspi->TxXferCount = hspi->TxXferCount >> 1U;
88
      }
89
      else
90
      {
91
        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMATX);
92
        hspi->TxXferCount = (hspi->TxXferCount >> 1U) + 1U;
93
      }
94
    }
95
96
    if (hspi->hdmarx->Init.MemDataAlignment == DMA_MDATAALIGN_HALFWORD)
97
    {
98
      /* Set fiforxthresold according the reception data length: 16bit */
99
      CLEAR_BIT(hspi->Instance->CR2, SPI_RXFIFO_THRESHOLD);
100
101
      if ((hspi->RxXferCount & 0x1U) == 0x0U)
102
      {
103
        CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
104
        hspi->RxXferCount = hspi->RxXferCount >> 1U;
105
      }
106
      else
107
      {
108
        SET_BIT(hspi->Instance->CR2, SPI_CR2_LDMARX);
109
        hspi->RxXferCount = (hspi->RxXferCount >> 1U) + 1U;
110
      }
111
    }
112
  }
113
114
  /* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
115
  if (hspi->State == HAL_SPI_STATE_BUSY_RX)
116
  {
117
    /* Set the SPI Rx DMA Half transfer complete callback */
118
    hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
119
    hspi->hdmarx->XferCpltCallback     = SPI_DMAReceiveCplt;
120
  }
121
  else
122
  {
123
    /* Set the SPI Tx/Rx DMA Half transfer complete callback */
124
    hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
125
    hspi->hdmarx->XferCpltCallback     = SPI_DMATransmitReceiveCplt;
126
  }
127
128
  /* Set the DMA error callback */
129
  hspi->hdmarx->XferErrorCallback = SPI_DMAError;
130
131
  /* Set the DMA AbortCpltCallback */
132
  hspi->hdmarx->XferAbortCallback = NULL;
133
134
  /* Enable the Rx DMA Stream/Channel  */
135
  HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr, hspi->RxXferCount);
136
137
  /* Enable Rx DMA Request */
138
  SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
139
140
  /* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
141
  is performed in DMA reception complete callback  */
142
  hspi->hdmatx->XferHalfCpltCallback = NULL;
143
  hspi->hdmatx->XferCpltCallback     = NULL;
144
  hspi->hdmatx->XferErrorCallback    = NULL;
145
  hspi->hdmatx->XferAbortCallback    = NULL;
146
147
  /* Enable the Tx DMA Stream/Channel  */
148
  HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR, hspi->TxXferCount);
149
150
  /* Check if the SPI is already enabled */
151
  if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
152
  {
153
    /* Enable SPI peripheral */
154
    __HAL_SPI_ENABLE(hspi);
155
  }
156
  /* Enable the SPI Error Interrupt Bit */
157
  __HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
158
159
  /* Enable Tx DMA Request */
160
  SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
161
162
error :
163
  /* Process Unlocked */
164
  __HAL_UNLOCK(hspi);
165
  return errorcode;
166
}

von Klugscheißer (Gast)


Lesenswert?


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.