amiro-blt / Target / Demo / ARMCM4_STM32F405_Power_Management_GCC / Boot / lib / stdperiphlib / STM32F4xx_StdPeriph_Driver / src / stm32f4xx_spi.c @ 69661903
History | View | Annotate | Download (51.1 KB)
1 | 69661903 | Thomas Schöpping | /**
|
---|---|---|---|
2 | ******************************************************************************
|
||
3 | * @file stm32f4xx_spi.c
|
||
4 | * @author MCD Application Team
|
||
5 | * @version V1.1.0
|
||
6 | * @date 11-January-2013
|
||
7 | * @brief This file provides firmware functions to manage the following
|
||
8 | * functionalities of the Serial peripheral interface (SPI):
|
||
9 | * + Initialization and Configuration
|
||
10 | * + Data transfers functions
|
||
11 | * + Hardware CRC Calculation
|
||
12 | * + DMA transfers management
|
||
13 | * + Interrupts and flags management
|
||
14 | *
|
||
15 | @verbatim
|
||
16 | |||
17 | ===================================================================
|
||
18 | ##### How to use this driver #####
|
||
19 | ===================================================================
|
||
20 | [..]
|
||
21 | (#) Enable peripheral clock using the following functions
|
||
22 | RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE) for SPI1
|
||
23 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE) for SPI2
|
||
24 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE) for SPI3
|
||
25 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE) for SPI4
|
||
26 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE) for SPI5
|
||
27 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE) for SPI6.
|
||
28 |
|
||
29 | (#) Enable SCK, MOSI, MISO and NSS GPIO clocks using RCC_AHB1PeriphClockCmd()
|
||
30 | function. In I2S mode, if an external clock source is used then the I2S
|
||
31 | CKIN pin GPIO clock should also be enabled.
|
||
32 |
|
||
33 | (#) Peripherals alternate function:
|
||
34 | (++) Connect the pin to the desired peripherals' Alternate Function (AF)
|
||
35 | using GPIO_PinAFConfig() function
|
||
36 | (++) Configure the desired pin in alternate function by:
|
||
37 | GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
|
||
38 | (++) Select the type, pull-up/pull-down and output speed via GPIO_PuPd,
|
||
39 | GPIO_OType and GPIO_Speed members
|
||
40 | (++) Call GPIO_Init() function In I2S mode, if an external clock source is
|
||
41 | used then the I2S CKIN pin should be also configured in Alternate
|
||
42 | function Push-pull pull-up mode.
|
||
43 |
|
||
44 | (#) Program the Polarity, Phase, First Data, Baud Rate Prescaler, Slave
|
||
45 | Management, Peripheral Mode and CRC Polynomial values using the SPI_Init()
|
||
46 | function.
|
||
47 | In I2S mode, program the Mode, Standard, Data Format, MCLK Output, Audio
|
||
48 | frequency and Polarity using I2S_Init() function. For I2S mode, make sure
|
||
49 | that either:
|
||
50 | (++) I2S PLL is configured using the functions
|
||
51 | RCC_I2SCLKConfig(RCC_I2S2CLKSource_PLLI2S), RCC_PLLI2SCmd(ENABLE) and
|
||
52 | RCC_GetFlagStatus(RCC_FLAG_PLLI2SRDY); or
|
||
53 | (++) External clock source is configured using the function
|
||
54 | RCC_I2SCLKConfig(RCC_I2S2CLKSource_Ext) and after setting correctly
|
||
55 | the define constant I2S_EXTERNAL_CLOCK_VAL in the stm32f4xx_conf.h file.
|
||
56 |
|
||
57 | (#) Enable the NVIC and the corresponding interrupt using the function
|
||
58 | SPI_ITConfig() if you need to use interrupt mode.
|
||
59 |
|
||
60 | (#) When using the DMA mode
|
||
61 | (++) Configure the DMA using DMA_Init() function
|
||
62 | (++) Active the needed channel Request using SPI_I2S_DMACmd() function
|
||
63 |
|
||
64 | (#) Enable the SPI using the SPI_Cmd() function or enable the I2S using
|
||
65 | I2S_Cmd().
|
||
66 |
|
||
67 | (#) Enable the DMA using the DMA_Cmd() function when using DMA mode.
|
||
68 |
|
||
69 | (#) Optionally, you can enable/configure the following parameters without
|
||
70 | re-initialization (i.e there is no need to call again SPI_Init() function):
|
||
71 | (++) When bidirectional mode (SPI_Direction_1Line_Rx or SPI_Direction_1Line_Tx)
|
||
72 | is programmed as Data direction parameter using the SPI_Init() function
|
||
73 | it can be possible to switch between SPI_Direction_Tx or SPI_Direction_Rx
|
||
74 | using the SPI_BiDirectionalLineConfig() function.
|
||
75 | (++) When SPI_NSS_Soft is selected as Slave Select Management parameter
|
||
76 | using the SPI_Init() function it can be possible to manage the
|
||
77 | NSS internal signal using the SPI_NSSInternalSoftwareConfig() function.
|
||
78 | (++) Reconfigure the data size using the SPI_DataSizeConfig() function
|
||
79 | (++) Enable or disable the SS output using the SPI_SSOutputCmd() function
|
||
80 |
|
||
81 | (#) To use the CRC Hardware calculation feature refer to the Peripheral
|
||
82 | CRC hardware Calculation subsection.
|
||
83 |
|
||
84 |
|
||
85 | [..] It is possible to use SPI in I2S full duplex mode, in this case, each SPI
|
||
86 | peripheral is able to manage sending and receiving data simultaneously
|
||
87 | using two data lines. Each SPI peripheral has an extended block called I2Sxext
|
||
88 | (ie. I2S2ext for SPI2 and I2S3ext for SPI3).
|
||
89 | The extension block is not a full SPI IP, it is used only as I2S slave to
|
||
90 | implement full duplex mode. The extension block uses the same clock sources
|
||
91 | as its master.
|
||
92 | To configure I2S full duplex you have to:
|
||
93 |
|
||
94 | (#) Configure SPIx in I2S mode (I2S_Init() function) as described above.
|
||
95 |
|
||
96 | (#) Call the I2S_FullDuplexConfig() function using the same strucutre passed to
|
||
97 | I2S_Init() function.
|
||
98 |
|
||
99 | (#) Call I2S_Cmd() for SPIx then for its extended block.
|
||
100 |
|
||
101 | (#) To configure interrupts or DMA requests and to get/clear flag status,
|
||
102 | use I2Sxext instance for the extension block.
|
||
103 |
|
||
104 | [..] Functions that can be called with I2Sxext instances are: I2S_Cmd(),
|
||
105 | I2S_FullDuplexConfig(), SPI_I2S_ReceiveData(), SPI_I2S_SendData(),
|
||
106 | SPI_I2S_DMACmd(), SPI_I2S_ITConfig(), SPI_I2S_GetFlagStatus(),
|
||
107 | SPI_I2S_ClearFlag(), SPI_I2S_GetITStatus() and SPI_I2S_ClearITPendingBit().
|
||
108 |
|
||
109 | Example: To use SPI3 in Full duplex mode (SPI3 is Master Tx, I2S3ext is Slave Rx):
|
||
110 |
|
||
111 | RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
|
||
112 | I2S_StructInit(&I2SInitStruct);
|
||
113 | I2SInitStruct.Mode = I2S_Mode_MasterTx;
|
||
114 | I2S_Init(SPI3, &I2SInitStruct);
|
||
115 | I2S_FullDuplexConfig(SPI3ext, &I2SInitStruct)
|
||
116 | I2S_Cmd(SPI3, ENABLE);
|
||
117 | I2S_Cmd(SPI3ext, ENABLE);
|
||
118 | ...
|
||
119 | while (SPI_I2S_GetFlagStatus(SPI2, SPI_FLAG_TXE) == RESET)
|
||
120 | {}
|
||
121 | SPI_I2S_SendData(SPI3, txdata[i]);
|
||
122 | ...
|
||
123 | while (SPI_I2S_GetFlagStatus(I2S3ext, SPI_FLAG_RXNE) == RESET)
|
||
124 | {}
|
||
125 | rxdata[i] = SPI_I2S_ReceiveData(I2S3ext);
|
||
126 | ...
|
||
127 |
|
||
128 | [..]
|
||
129 | (@) In I2S mode: if an external clock is used as source clock for the I2S,
|
||
130 | then the define I2S_EXTERNAL_CLOCK_VAL in file stm32f4xx_conf.h should
|
||
131 | be enabled and set to the value of the source clock frequency (in Hz).
|
||
132 |
|
||
133 | (@) In SPI mode: To use the SPI TI mode, call the function SPI_TIModeCmd()
|
||
134 | just after calling the function SPI_Init().
|
||
135 |
|
||
136 | @endverbatim
|
||
137 | *
|
||
138 | ******************************************************************************
|
||
139 | * @attention
|
||
140 | *
|
||
141 | * <h2><center>© COPYRIGHT 2013 STMicroelectronics</center></h2>
|
||
142 | *
|
||
143 | * Licensed under MCD-ST Liberty SW License Agreement V2, (the "License");
|
||
144 | * You may not use this file except in compliance with the License.
|
||
145 | * You may obtain a copy of the License at:
|
||
146 | *
|
||
147 | * http://www.st.com/software_license_agreement_liberty_v2
|
||
148 | *
|
||
149 | * Unless required by applicable law or agreed to in writing, software
|
||
150 | * distributed under the License is distributed on an "AS IS" BASIS,
|
||
151 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
152 | * See the License for the specific language governing permissions and
|
||
153 | * limitations under the License.
|
||
154 | *
|
||
155 | ******************************************************************************
|
||
156 | */
|
||
157 | |||
158 | /* Includes ------------------------------------------------------------------*/
|
||
159 | #include "stm32f4xx_spi.h" |
||
160 | #include "stm32f4xx_rcc.h" |
||
161 | |||
162 | /** @addtogroup STM32F4xx_StdPeriph_Driver
|
||
163 | * @{
|
||
164 | */
|
||
165 | |||
166 | /** @defgroup SPI
|
||
167 | * @brief SPI driver modules
|
||
168 | * @{
|
||
169 | */
|
||
170 | |||
171 | /* Private typedef -----------------------------------------------------------*/
|
||
172 | /* Private define ------------------------------------------------------------*/
|
||
173 | |||
174 | /* SPI registers Masks */
|
||
175 | #define CR1_CLEAR_MASK ((uint16_t)0x3040) |
||
176 | #define I2SCFGR_CLEAR_MASK ((uint16_t)0xF040) |
||
177 | |||
178 | /* RCC PLLs masks */
|
||
179 | #define PLLCFGR_PPLR_MASK ((uint32_t)0x70000000) |
||
180 | #define PLLCFGR_PPLN_MASK ((uint32_t)0x00007FC0) |
||
181 | |||
182 | #define SPI_CR2_FRF ((uint16_t)0x0010) |
||
183 | #define SPI_SR_TIFRFE ((uint16_t)0x0100) |
||
184 | |||
185 | /* Private macro -------------------------------------------------------------*/
|
||
186 | /* Private variables ---------------------------------------------------------*/
|
||
187 | /* Private function prototypes -----------------------------------------------*/
|
||
188 | /* Private functions ---------------------------------------------------------*/
|
||
189 | |||
190 | /** @defgroup SPI_Private_Functions
|
||
191 | * @{
|
||
192 | */
|
||
193 | |||
194 | /** @defgroup SPI_Group1 Initialization and Configuration functions
|
||
195 | * @brief Initialization and Configuration functions
|
||
196 | *
|
||
197 | @verbatim
|
||
198 | ===============================================================================
|
||
199 | ##### Initialization and Configuration functions #####
|
||
200 | ===============================================================================
|
||
201 | [..] This section provides a set of functions allowing to initialize the SPI
|
||
202 | Direction, SPI Mode, SPI Data Size, SPI Polarity, SPI Phase, SPI NSS
|
||
203 | Management, SPI Baud Rate Prescaler, SPI First Bit and SPI CRC Polynomial.
|
||
204 |
|
||
205 | [..] The SPI_Init() function follows the SPI configuration procedures for Master
|
||
206 | mode and Slave mode (details for these procedures are available in reference
|
||
207 | manual (RM0090)).
|
||
208 |
|
||
209 | @endverbatim
|
||
210 | * @{
|
||
211 | */
|
||
212 | |||
213 | /**
|
||
214 | * @brief De-initialize the SPIx peripheral registers to their default reset values.
|
||
215 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
216 | * in SPI mode or 2 or 3 in I2S mode.
|
||
217 | *
|
||
218 | * @note The extended I2S blocks (ie. I2S2ext and I2S3ext blocks) are de-initialized
|
||
219 | * when the relative I2S peripheral is de-initialized (the extended block's clock
|
||
220 | * is managed by the I2S peripheral clock).
|
||
221 | *
|
||
222 | * @retval None
|
||
223 | */
|
||
224 | void SPI_I2S_DeInit(SPI_TypeDef* SPIx)
|
||
225 | { |
||
226 | /* Check the parameters */
|
||
227 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
228 | |||
229 | if (SPIx == SPI1)
|
||
230 | { |
||
231 | /* Enable SPI1 reset state */
|
||
232 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE); |
||
233 | /* Release SPI1 from reset state */
|
||
234 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE); |
||
235 | } |
||
236 | else if (SPIx == SPI2) |
||
237 | { |
||
238 | /* Enable SPI2 reset state */
|
||
239 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE); |
||
240 | /* Release SPI2 from reset state */
|
||
241 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE); |
||
242 | } |
||
243 | else if (SPIx == SPI3) |
||
244 | { |
||
245 | /* Enable SPI3 reset state */
|
||
246 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, ENABLE); |
||
247 | /* Release SPI3 from reset state */
|
||
248 | RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI3, DISABLE); |
||
249 | } |
||
250 | else if (SPIx == SPI4) |
||
251 | { |
||
252 | /* Enable SPI4 reset state */
|
||
253 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI4, ENABLE); |
||
254 | /* Release SPI4 from reset state */
|
||
255 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI4, DISABLE); |
||
256 | } |
||
257 | else if (SPIx == SPI5) |
||
258 | { |
||
259 | /* Enable SPI5 reset state */
|
||
260 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI5, ENABLE); |
||
261 | /* Release SPI5 from reset state */
|
||
262 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI5, DISABLE); |
||
263 | } |
||
264 | else
|
||
265 | { |
||
266 | if (SPIx == SPI6)
|
||
267 | { |
||
268 | /* Enable SPI6 reset state */
|
||
269 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI6, ENABLE); |
||
270 | /* Release SPI6 from reset state */
|
||
271 | RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI6, DISABLE); |
||
272 | } |
||
273 | } |
||
274 | } |
||
275 | |||
276 | /**
|
||
277 | * @brief Initializes the SPIx peripheral according to the specified
|
||
278 | * parameters in the SPI_InitStruct.
|
||
279 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
280 | * @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure that
|
||
281 | * contains the configuration information for the specified SPI peripheral.
|
||
282 | * @retval None
|
||
283 | */
|
||
284 | void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
|
||
285 | { |
||
286 | uint16_t tmpreg = 0;
|
||
287 | |||
288 | /* check the parameters */
|
||
289 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
290 | |||
291 | /* Check the SPI parameters */
|
||
292 | assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction)); |
||
293 | assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode)); |
||
294 | assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize)); |
||
295 | assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL)); |
||
296 | assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA)); |
||
297 | assert_param(IS_SPI_NSS(SPI_InitStruct->SPI_NSS)); |
||
298 | assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler)); |
||
299 | assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit)); |
||
300 | assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->SPI_CRCPolynomial)); |
||
301 | |||
302 | /*---------------------------- SPIx CR1 Configuration ------------------------*/
|
||
303 | /* Get the SPIx CR1 value */
|
||
304 | tmpreg = SPIx->CR1; |
||
305 | /* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */
|
||
306 | tmpreg &= CR1_CLEAR_MASK; |
||
307 | /* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
|
||
308 | master/salve mode, CPOL and CPHA */
|
||
309 | /* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */
|
||
310 | /* Set SSM, SSI and MSTR bits according to SPI_Mode and SPI_NSS values */
|
||
311 | /* Set LSBFirst bit according to SPI_FirstBit value */
|
||
312 | /* Set BR bits according to SPI_BaudRatePrescaler value */
|
||
313 | /* Set CPOL bit according to SPI_CPOL value */
|
||
314 | /* Set CPHA bit according to SPI_CPHA value */
|
||
315 | tmpreg |= (uint16_t)((uint32_t)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode | |
||
316 | SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL | |
||
317 | SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS | |
||
318 | SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit); |
||
319 | /* Write to SPIx CR1 */
|
||
320 | SPIx->CR1 = tmpreg; |
||
321 | |||
322 | /* Activate the SPI mode (Reset I2SMOD bit in I2SCFGR register) */
|
||
323 | SPIx->I2SCFGR &= (uint16_t)~((uint16_t)SPI_I2SCFGR_I2SMOD); |
||
324 | /*---------------------------- SPIx CRCPOLY Configuration --------------------*/
|
||
325 | /* Write to SPIx CRCPOLY */
|
||
326 | SPIx->CRCPR = SPI_InitStruct->SPI_CRCPolynomial; |
||
327 | } |
||
328 | |||
329 | /**
|
||
330 | * @brief Initializes the SPIx peripheral according to the specified
|
||
331 | * parameters in the I2S_InitStruct.
|
||
332 | * @param SPIx: where x can be 2 or 3 to select the SPI peripheral (configured in I2S mode).
|
||
333 | * @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that
|
||
334 | * contains the configuration information for the specified SPI peripheral
|
||
335 | * configured in I2S mode.
|
||
336 | *
|
||
337 | * @note The function calculates the optimal prescaler needed to obtain the most
|
||
338 | * accurate audio frequency (depending on the I2S clock source, the PLL values
|
||
339 | * and the product configuration). But in case the prescaler value is greater
|
||
340 | * than 511, the default value (0x02) will be configured instead.
|
||
341 | *
|
||
342 | * @note if an external clock is used as source clock for the I2S, then the define
|
||
343 | * I2S_EXTERNAL_CLOCK_VAL in file stm32f4xx_conf.h should be enabled and set
|
||
344 | * to the value of the the source clock frequency (in Hz).
|
||
345 | *
|
||
346 | * @retval None
|
||
347 | */
|
||
348 | void I2S_Init(SPI_TypeDef* SPIx, I2S_InitTypeDef* I2S_InitStruct)
|
||
349 | { |
||
350 | uint16_t tmpreg = 0, i2sdiv = 2, i2sodd = 0, packetlength = 1; |
||
351 | uint32_t tmp = 0, i2sclk = 0; |
||
352 | #ifndef I2S_EXTERNAL_CLOCK_VAL
|
||
353 | uint32_t pllm = 0, plln = 0, pllr = 0; |
||
354 | #endif /* I2S_EXTERNAL_CLOCK_VAL */ |
||
355 | |||
356 | /* Check the I2S parameters */
|
||
357 | assert_param(IS_SPI_23_PERIPH(SPIx)); |
||
358 | assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode)); |
||
359 | assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard)); |
||
360 | assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); |
||
361 | assert_param(IS_I2S_MCLK_OUTPUT(I2S_InitStruct->I2S_MCLKOutput)); |
||
362 | assert_param(IS_I2S_AUDIO_FREQ(I2S_InitStruct->I2S_AudioFreq)); |
||
363 | assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL)); |
||
364 | |||
365 | /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/
|
||
366 | /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||
367 | SPIx->I2SCFGR &= I2SCFGR_CLEAR_MASK; |
||
368 | SPIx->I2SPR = 0x0002;
|
||
369 | |||
370 | /* Get the I2SCFGR register value */
|
||
371 | tmpreg = SPIx->I2SCFGR; |
||
372 | |||
373 | /* If the default value has to be written, reinitialize i2sdiv and i2sodd*/
|
||
374 | if(I2S_InitStruct->I2S_AudioFreq == I2S_AudioFreq_Default)
|
||
375 | { |
||
376 | i2sodd = (uint16_t)0;
|
||
377 | i2sdiv = (uint16_t)2;
|
||
378 | } |
||
379 | /* If the requested audio frequency is not the default, compute the prescaler */
|
||
380 | else
|
||
381 | { |
||
382 | /* Check the frame length (For the Prescaler computing) *******************/
|
||
383 | if(I2S_InitStruct->I2S_DataFormat == I2S_DataFormat_16b)
|
||
384 | { |
||
385 | /* Packet length is 16 bits */
|
||
386 | packetlength = 1;
|
||
387 | } |
||
388 | else
|
||
389 | { |
||
390 | /* Packet length is 32 bits */
|
||
391 | packetlength = 2;
|
||
392 | } |
||
393 | |||
394 | /* Get I2S source Clock frequency ****************************************/
|
||
395 | |||
396 | /* If an external I2S clock has to be used, this define should be set
|
||
397 | in the project configuration or in the stm32f4xx_conf.h file */
|
||
398 | #ifdef I2S_EXTERNAL_CLOCK_VAL
|
||
399 | /* Set external clock as I2S clock source */
|
||
400 | if ((RCC->CFGR & RCC_CFGR_I2SSRC) == 0) |
||
401 | { |
||
402 | RCC->CFGR |= (uint32_t)RCC_CFGR_I2SSRC; |
||
403 | } |
||
404 | |||
405 | /* Set the I2S clock to the external clock value */
|
||
406 | i2sclk = I2S_EXTERNAL_CLOCK_VAL; |
||
407 | |||
408 | #else /* There is no define for External I2S clock source */ |
||
409 | /* Set PLLI2S as I2S clock source */
|
||
410 | if ((RCC->CFGR & RCC_CFGR_I2SSRC) != 0) |
||
411 | { |
||
412 | RCC->CFGR &= ~(uint32_t)RCC_CFGR_I2SSRC; |
||
413 | } |
||
414 | |||
415 | /* Get the PLLI2SN value */
|
||
416 | plln = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SN) >> 6) & \
|
||
417 | (RCC_PLLI2SCFGR_PLLI2SN >> 6));
|
||
418 | |||
419 | /* Get the PLLI2SR value */
|
||
420 | pllr = (uint32_t)(((RCC->PLLI2SCFGR & RCC_PLLI2SCFGR_PLLI2SR) >> 28) & \
|
||
421 | (RCC_PLLI2SCFGR_PLLI2SR >> 28));
|
||
422 | |||
423 | /* Get the PLLM value */
|
||
424 | pllm = (uint32_t)(RCC->PLLCFGR & RCC_PLLCFGR_PLLM); |
||
425 | |||
426 | /* Get the I2S source clock value */
|
||
427 | i2sclk = (uint32_t)(((HSE_VALUE / pllm) * plln) / pllr); |
||
428 | #endif /* I2S_EXTERNAL_CLOCK_VAL */ |
||
429 | |||
430 | /* Compute the Real divider depending on the MCLK output state, with a floating point */
|
||
431 | if(I2S_InitStruct->I2S_MCLKOutput == I2S_MCLKOutput_Enable)
|
||
432 | { |
||
433 | /* MCLK output is enabled */
|
||
434 | tmp = (uint16_t)(((((i2sclk / 256) * 10) / I2S_InitStruct->I2S_AudioFreq)) + 5); |
||
435 | } |
||
436 | else
|
||
437 | { |
||
438 | /* MCLK output is disabled */
|
||
439 | tmp = (uint16_t)(((((i2sclk / (32 * packetlength)) *10 ) / I2S_InitStruct->I2S_AudioFreq)) + 5); |
||
440 | } |
||
441 | |||
442 | /* Remove the flatting point */
|
||
443 | tmp = tmp / 10;
|
||
444 | |||
445 | /* Check the parity of the divider */
|
||
446 | i2sodd = (uint16_t)(tmp & (uint16_t)0x0001);
|
||
447 | |||
448 | /* Compute the i2sdiv prescaler */
|
||
449 | i2sdiv = (uint16_t)((tmp - i2sodd) / 2);
|
||
450 | |||
451 | /* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
|
||
452 | i2sodd = (uint16_t) (i2sodd << 8);
|
||
453 | } |
||
454 | |||
455 | /* Test if the divider is 1 or 0 or greater than 0xFF */
|
||
456 | if ((i2sdiv < 2) || (i2sdiv > 0xFF)) |
||
457 | { |
||
458 | /* Set the default values */
|
||
459 | i2sdiv = 2;
|
||
460 | i2sodd = 0;
|
||
461 | } |
||
462 | |||
463 | /* Write to SPIx I2SPR register the computed value */
|
||
464 | SPIx->I2SPR = (uint16_t)((uint16_t)i2sdiv | (uint16_t)(i2sodd | (uint16_t)I2S_InitStruct->I2S_MCLKOutput)); |
||
465 | |||
466 | /* Configure the I2S with the SPI_InitStruct values */
|
||
467 | tmpreg |= (uint16_t)((uint16_t)SPI_I2SCFGR_I2SMOD | (uint16_t)(I2S_InitStruct->I2S_Mode | \ |
||
468 | (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \ |
||
469 | (uint16_t)I2S_InitStruct->I2S_CPOL)))); |
||
470 | |||
471 | /* Write to SPIx I2SCFGR */
|
||
472 | SPIx->I2SCFGR = tmpreg; |
||
473 | } |
||
474 | |||
475 | /**
|
||
476 | * @brief Fills each SPI_InitStruct member with its default value.
|
||
477 | * @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure which will be initialized.
|
||
478 | * @retval None
|
||
479 | */
|
||
480 | void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
|
||
481 | { |
||
482 | /*--------------- Reset SPI init structure parameters values -----------------*/
|
||
483 | /* Initialize the SPI_Direction member */
|
||
484 | SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex; |
||
485 | /* initialize the SPI_Mode member */
|
||
486 | SPI_InitStruct->SPI_Mode = SPI_Mode_Slave; |
||
487 | /* initialize the SPI_DataSize member */
|
||
488 | SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b; |
||
489 | /* Initialize the SPI_CPOL member */
|
||
490 | SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low; |
||
491 | /* Initialize the SPI_CPHA member */
|
||
492 | SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge; |
||
493 | /* Initialize the SPI_NSS member */
|
||
494 | SPI_InitStruct->SPI_NSS = SPI_NSS_Hard; |
||
495 | /* Initialize the SPI_BaudRatePrescaler member */
|
||
496 | SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; |
||
497 | /* Initialize the SPI_FirstBit member */
|
||
498 | SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB; |
||
499 | /* Initialize the SPI_CRCPolynomial member */
|
||
500 | SPI_InitStruct->SPI_CRCPolynomial = 7;
|
||
501 | } |
||
502 | |||
503 | /**
|
||
504 | * @brief Fills each I2S_InitStruct member with its default value.
|
||
505 | * @param I2S_InitStruct: pointer to a I2S_InitTypeDef structure which will be initialized.
|
||
506 | * @retval None
|
||
507 | */
|
||
508 | void I2S_StructInit(I2S_InitTypeDef* I2S_InitStruct)
|
||
509 | { |
||
510 | /*--------------- Reset I2S init structure parameters values -----------------*/
|
||
511 | /* Initialize the I2S_Mode member */
|
||
512 | I2S_InitStruct->I2S_Mode = I2S_Mode_SlaveTx; |
||
513 | |||
514 | /* Initialize the I2S_Standard member */
|
||
515 | I2S_InitStruct->I2S_Standard = I2S_Standard_Phillips; |
||
516 | |||
517 | /* Initialize the I2S_DataFormat member */
|
||
518 | I2S_InitStruct->I2S_DataFormat = I2S_DataFormat_16b; |
||
519 | |||
520 | /* Initialize the I2S_MCLKOutput member */
|
||
521 | I2S_InitStruct->I2S_MCLKOutput = I2S_MCLKOutput_Disable; |
||
522 | |||
523 | /* Initialize the I2S_AudioFreq member */
|
||
524 | I2S_InitStruct->I2S_AudioFreq = I2S_AudioFreq_Default; |
||
525 | |||
526 | /* Initialize the I2S_CPOL member */
|
||
527 | I2S_InitStruct->I2S_CPOL = I2S_CPOL_Low; |
||
528 | } |
||
529 | |||
530 | /**
|
||
531 | * @brief Enables or disables the specified SPI peripheral.
|
||
532 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
533 | * @param NewState: new state of the SPIx peripheral.
|
||
534 | * This parameter can be: ENABLE or DISABLE.
|
||
535 | * @retval None
|
||
536 | */
|
||
537 | void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
|
||
538 | { |
||
539 | /* Check the parameters */
|
||
540 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
541 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
542 | if (NewState != DISABLE)
|
||
543 | { |
||
544 | /* Enable the selected SPI peripheral */
|
||
545 | SPIx->CR1 |= SPI_CR1_SPE; |
||
546 | } |
||
547 | else
|
||
548 | { |
||
549 | /* Disable the selected SPI peripheral */
|
||
550 | SPIx->CR1 &= (uint16_t)~((uint16_t)SPI_CR1_SPE); |
||
551 | } |
||
552 | } |
||
553 | |||
554 | /**
|
||
555 | * @brief Enables or disables the specified SPI peripheral (in I2S mode).
|
||
556 | * @param SPIx: where x can be 2 or 3 to select the SPI peripheral (or I2Sxext
|
||
557 | * for full duplex mode).
|
||
558 | * @param NewState: new state of the SPIx peripheral.
|
||
559 | * This parameter can be: ENABLE or DISABLE.
|
||
560 | * @retval None
|
||
561 | */
|
||
562 | void I2S_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
|
||
563 | { |
||
564 | /* Check the parameters */
|
||
565 | assert_param(IS_SPI_23_PERIPH_EXT(SPIx)); |
||
566 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
567 | |||
568 | if (NewState != DISABLE)
|
||
569 | { |
||
570 | /* Enable the selected SPI peripheral (in I2S mode) */
|
||
571 | SPIx->I2SCFGR |= SPI_I2SCFGR_I2SE; |
||
572 | } |
||
573 | else
|
||
574 | { |
||
575 | /* Disable the selected SPI peripheral in I2S mode */
|
||
576 | SPIx->I2SCFGR &= (uint16_t)~((uint16_t)SPI_I2SCFGR_I2SE); |
||
577 | } |
||
578 | } |
||
579 | |||
580 | /**
|
||
581 | * @brief Configures the data size for the selected SPI.
|
||
582 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
583 | * @param SPI_DataSize: specifies the SPI data size.
|
||
584 | * This parameter can be one of the following values:
|
||
585 | * @arg SPI_DataSize_16b: Set data frame format to 16bit
|
||
586 | * @arg SPI_DataSize_8b: Set data frame format to 8bit
|
||
587 | * @retval None
|
||
588 | */
|
||
589 | void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize)
|
||
590 | { |
||
591 | /* Check the parameters */
|
||
592 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
593 | assert_param(IS_SPI_DATASIZE(SPI_DataSize)); |
||
594 | /* Clear DFF bit */
|
||
595 | SPIx->CR1 &= (uint16_t)~SPI_DataSize_16b; |
||
596 | /* Set new DFF bit value */
|
||
597 | SPIx->CR1 |= SPI_DataSize; |
||
598 | } |
||
599 | |||
600 | /**
|
||
601 | * @brief Selects the data transfer direction in bidirectional mode for the specified SPI.
|
||
602 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
603 | * @param SPI_Direction: specifies the data transfer direction in bidirectional mode.
|
||
604 | * This parameter can be one of the following values:
|
||
605 | * @arg SPI_Direction_Tx: Selects Tx transmission direction
|
||
606 | * @arg SPI_Direction_Rx: Selects Rx receive direction
|
||
607 | * @retval None
|
||
608 | */
|
||
609 | void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction)
|
||
610 | { |
||
611 | /* Check the parameters */
|
||
612 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
613 | assert_param(IS_SPI_DIRECTION(SPI_Direction)); |
||
614 | if (SPI_Direction == SPI_Direction_Tx)
|
||
615 | { |
||
616 | /* Set the Tx only mode */
|
||
617 | SPIx->CR1 |= SPI_Direction_Tx; |
||
618 | } |
||
619 | else
|
||
620 | { |
||
621 | /* Set the Rx only mode */
|
||
622 | SPIx->CR1 &= SPI_Direction_Rx; |
||
623 | } |
||
624 | } |
||
625 | |||
626 | /**
|
||
627 | * @brief Configures internally by software the NSS pin for the selected SPI.
|
||
628 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
629 | * @param SPI_NSSInternalSoft: specifies the SPI NSS internal state.
|
||
630 | * This parameter can be one of the following values:
|
||
631 | * @arg SPI_NSSInternalSoft_Set: Set NSS pin internally
|
||
632 | * @arg SPI_NSSInternalSoft_Reset: Reset NSS pin internally
|
||
633 | * @retval None
|
||
634 | */
|
||
635 | void SPI_NSSInternalSoftwareConfig(SPI_TypeDef* SPIx, uint16_t SPI_NSSInternalSoft)
|
||
636 | { |
||
637 | /* Check the parameters */
|
||
638 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
639 | assert_param(IS_SPI_NSS_INTERNAL(SPI_NSSInternalSoft)); |
||
640 | if (SPI_NSSInternalSoft != SPI_NSSInternalSoft_Reset)
|
||
641 | { |
||
642 | /* Set NSS pin internally by software */
|
||
643 | SPIx->CR1 |= SPI_NSSInternalSoft_Set; |
||
644 | } |
||
645 | else
|
||
646 | { |
||
647 | /* Reset NSS pin internally by software */
|
||
648 | SPIx->CR1 &= SPI_NSSInternalSoft_Reset; |
||
649 | } |
||
650 | } |
||
651 | |||
652 | /**
|
||
653 | * @brief Enables or disables the SS output for the selected SPI.
|
||
654 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
655 | * @param NewState: new state of the SPIx SS output.
|
||
656 | * This parameter can be: ENABLE or DISABLE.
|
||
657 | * @retval None
|
||
658 | */
|
||
659 | void SPI_SSOutputCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
|
||
660 | { |
||
661 | /* Check the parameters */
|
||
662 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
663 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
664 | if (NewState != DISABLE)
|
||
665 | { |
||
666 | /* Enable the selected SPI SS output */
|
||
667 | SPIx->CR2 |= (uint16_t)SPI_CR2_SSOE; |
||
668 | } |
||
669 | else
|
||
670 | { |
||
671 | /* Disable the selected SPI SS output */
|
||
672 | SPIx->CR2 &= (uint16_t)~((uint16_t)SPI_CR2_SSOE); |
||
673 | } |
||
674 | } |
||
675 | |||
676 | /**
|
||
677 | * @brief Enables or disables the SPIx/I2Sx DMA interface.
|
||
678 | *
|
||
679 | * @note This function can be called only after the SPI_Init() function has
|
||
680 | * been called.
|
||
681 | * @note When TI mode is selected, the control bits SSM, SSI, CPOL and CPHA
|
||
682 | * are not taken into consideration and are configured by hardware
|
||
683 | * respectively to the TI mode requirements.
|
||
684 | *
|
||
685 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6
|
||
686 | * @param NewState: new state of the selected SPI TI communication mode.
|
||
687 | * This parameter can be: ENABLE or DISABLE.
|
||
688 | * @retval None
|
||
689 | */
|
||
690 | void SPI_TIModeCmd(SPI_TypeDef* SPIx, FunctionalState NewState)
|
||
691 | { |
||
692 | /* Check the parameters */
|
||
693 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
694 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
695 | |||
696 | if (NewState != DISABLE)
|
||
697 | { |
||
698 | /* Enable the TI mode for the selected SPI peripheral */
|
||
699 | SPIx->CR2 |= SPI_CR2_FRF; |
||
700 | } |
||
701 | else
|
||
702 | { |
||
703 | /* Disable the TI mode for the selected SPI peripheral */
|
||
704 | SPIx->CR2 &= (uint16_t)~SPI_CR2_FRF; |
||
705 | } |
||
706 | } |
||
707 | |||
708 | /**
|
||
709 | * @brief Configures the full duplex mode for the I2Sx peripheral using its
|
||
710 | * extension I2Sxext according to the specified parameters in the
|
||
711 | * I2S_InitStruct.
|
||
712 | * @param I2Sxext: where x can be 2 or 3 to select the I2S peripheral extension block.
|
||
713 | * @param I2S_InitStruct: pointer to an I2S_InitTypeDef structure that
|
||
714 | * contains the configuration information for the specified I2S peripheral
|
||
715 | * extension.
|
||
716 | *
|
||
717 | * @note The structure pointed by I2S_InitStruct parameter should be the same
|
||
718 | * used for the master I2S peripheral. In this case, if the master is
|
||
719 | * configured as transmitter, the slave will be receiver and vice versa.
|
||
720 | * Or you can force a different mode by modifying the field I2S_Mode to the
|
||
721 | * value I2S_SlaveRx or I2S_SlaveTx indepedently of the master configuration.
|
||
722 | *
|
||
723 | * @note The I2S full duplex extension can be configured in slave mode only.
|
||
724 | *
|
||
725 | * @retval None
|
||
726 | */
|
||
727 | void I2S_FullDuplexConfig(SPI_TypeDef* I2Sxext, I2S_InitTypeDef* I2S_InitStruct)
|
||
728 | { |
||
729 | uint16_t tmpreg = 0, tmp = 0; |
||
730 | |||
731 | /* Check the I2S parameters */
|
||
732 | assert_param(IS_I2S_EXT_PERIPH(I2Sxext)); |
||
733 | assert_param(IS_I2S_MODE(I2S_InitStruct->I2S_Mode)); |
||
734 | assert_param(IS_I2S_STANDARD(I2S_InitStruct->I2S_Standard)); |
||
735 | assert_param(IS_I2S_DATA_FORMAT(I2S_InitStruct->I2S_DataFormat)); |
||
736 | assert_param(IS_I2S_CPOL(I2S_InitStruct->I2S_CPOL)); |
||
737 | |||
738 | /*----------------------- SPIx I2SCFGR & I2SPR Configuration -----------------*/
|
||
739 | /* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||
740 | I2Sxext->I2SCFGR &= I2SCFGR_CLEAR_MASK; |
||
741 | I2Sxext->I2SPR = 0x0002;
|
||
742 | |||
743 | /* Get the I2SCFGR register value */
|
||
744 | tmpreg = I2Sxext->I2SCFGR; |
||
745 | |||
746 | /* Get the mode to be configured for the extended I2S */
|
||
747 | if ((I2S_InitStruct->I2S_Mode == I2S_Mode_MasterTx) || (I2S_InitStruct->I2S_Mode == I2S_Mode_SlaveTx))
|
||
748 | { |
||
749 | tmp = I2S_Mode_SlaveRx; |
||
750 | } |
||
751 | else
|
||
752 | { |
||
753 | if ((I2S_InitStruct->I2S_Mode == I2S_Mode_MasterRx) || (I2S_InitStruct->I2S_Mode == I2S_Mode_SlaveRx))
|
||
754 | { |
||
755 | tmp = I2S_Mode_SlaveTx; |
||
756 | } |
||
757 | } |
||
758 | |||
759 | |||
760 | /* Configure the I2S with the SPI_InitStruct values */
|
||
761 | tmpreg |= (uint16_t)((uint16_t)SPI_I2SCFGR_I2SMOD | (uint16_t)(tmp | \ |
||
762 | (uint16_t)(I2S_InitStruct->I2S_Standard | (uint16_t)(I2S_InitStruct->I2S_DataFormat | \ |
||
763 | (uint16_t)I2S_InitStruct->I2S_CPOL)))); |
||
764 | |||
765 | /* Write to SPIx I2SCFGR */
|
||
766 | I2Sxext->I2SCFGR = tmpreg; |
||
767 | } |
||
768 | |||
769 | /**
|
||
770 | * @}
|
||
771 | */
|
||
772 | |||
773 | /** @defgroup SPI_Group2 Data transfers functions
|
||
774 | * @brief Data transfers functions
|
||
775 | *
|
||
776 | @verbatim
|
||
777 | ===============================================================================
|
||
778 | ##### Data transfers functions #####
|
||
779 | ===============================================================================
|
||
780 | |||
781 | [..] This section provides a set of functions allowing to manage the SPI data
|
||
782 | transfers. In reception, data are received and then stored into an internal
|
||
783 | Rx buffer while. In transmission, data are first stored into an internal Tx
|
||
784 | buffer before being transmitted.
|
||
785 | |||
786 | [..] The read access of the SPI_DR register can be done using the SPI_I2S_ReceiveData()
|
||
787 | function and returns the Rx buffered value. Whereas a write access to the SPI_DR
|
||
788 | can be done using SPI_I2S_SendData() function and stores the written data into
|
||
789 | Tx buffer.
|
||
790 | |||
791 | @endverbatim
|
||
792 | * @{
|
||
793 | */
|
||
794 | |||
795 | /**
|
||
796 | * @brief Returns the most recent received data by the SPIx/I2Sx peripheral.
|
||
797 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
798 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
799 | * @retval The value of the received data.
|
||
800 | */
|
||
801 | uint16_t SPI_I2S_ReceiveData(SPI_TypeDef* SPIx) |
||
802 | { |
||
803 | /* Check the parameters */
|
||
804 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
805 | |||
806 | /* Return the data in the DR register */
|
||
807 | return SPIx->DR;
|
||
808 | } |
||
809 | |||
810 | /**
|
||
811 | * @brief Transmits a Data through the SPIx/I2Sx peripheral.
|
||
812 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
813 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
814 | * @param Data: Data to be transmitted.
|
||
815 | * @retval None
|
||
816 | */
|
||
817 | void SPI_I2S_SendData(SPI_TypeDef* SPIx, uint16_t Data)
|
||
818 | { |
||
819 | /* Check the parameters */
|
||
820 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
821 | |||
822 | /* Write in the DR register the data to be sent */
|
||
823 | SPIx->DR = Data; |
||
824 | } |
||
825 | |||
826 | /**
|
||
827 | * @}
|
||
828 | */
|
||
829 | |||
830 | /** @defgroup SPI_Group3 Hardware CRC Calculation functions
|
||
831 | * @brief Hardware CRC Calculation functions
|
||
832 | *
|
||
833 | @verbatim
|
||
834 | ===============================================================================
|
||
835 | ##### Hardware CRC Calculation functions #####
|
||
836 | ===============================================================================
|
||
837 | |||
838 | [..] This section provides a set of functions allowing to manage the SPI CRC hardware
|
||
839 | calculation
|
||
840 | |||
841 | [..] SPI communication using CRC is possible through the following procedure:
|
||
842 | (#) Program the Data direction, Polarity, Phase, First Data, Baud Rate Prescaler,
|
||
843 | Slave Management, Peripheral Mode and CRC Polynomial values using the SPI_Init()
|
||
844 | function.
|
||
845 | (#) Enable the CRC calculation using the SPI_CalculateCRC() function.
|
||
846 | (#) Enable the SPI using the SPI_Cmd() function
|
||
847 | (#) Before writing the last data to the TX buffer, set the CRCNext bit using the
|
||
848 | SPI_TransmitCRC() function to indicate that after transmission of the last
|
||
849 | data, the CRC should be transmitted.
|
||
850 | (#) After transmitting the last data, the SPI transmits the CRC. The SPI_CR1_CRCNEXT
|
||
851 | bit is reset. The CRC is also received and compared against the SPI_RXCRCR
|
||
852 | value.
|
||
853 | If the value does not match, the SPI_FLAG_CRCERR flag is set and an interrupt
|
||
854 | can be generated when the SPI_I2S_IT_ERR interrupt is enabled.
|
||
855 | |||
856 | [..]
|
||
857 | (@) It is advised not to read the calculated CRC values during the communication.
|
||
858 | |||
859 | (@) When the SPI is in slave mode, be careful to enable CRC calculation only
|
||
860 | when the clock is stable, that is, when the clock is in the steady state.
|
||
861 | If not, a wrong CRC calculation may be done. In fact, the CRC is sensitive
|
||
862 | to the SCK slave input clock as soon as CRCEN is set, and this, whatever
|
||
863 | the value of the SPE bit.
|
||
864 | |||
865 | (@) With high bitrate frequencies, be careful when transmitting the CRC.
|
||
866 | As the number of used CPU cycles has to be as low as possible in the CRC
|
||
867 | transfer phase, it is forbidden to call software functions in the CRC
|
||
868 | transmission sequence to avoid errors in the last data and CRC reception.
|
||
869 | In fact, CRCNEXT bit has to be written before the end of the transmission/reception
|
||
870 | of the last data.
|
||
871 | |||
872 | (@) For high bit rate frequencies, it is advised to use the DMA mode to avoid the
|
||
873 | degradation of the SPI speed performance due to CPU accesses impacting the
|
||
874 | SPI bandwidth.
|
||
875 | |||
876 | (@) When the STM32F4xx is configured as slave and the NSS hardware mode is
|
||
877 | used, the NSS pin needs to be kept low between the data phase and the CRC
|
||
878 | phase.
|
||
879 | |||
880 | (@) When the SPI is configured in slave mode with the CRC feature enabled, CRC
|
||
881 | calculation takes place even if a high level is applied on the NSS pin.
|
||
882 | This may happen for example in case of a multi-slave environment where the
|
||
883 | communication master addresses slaves alternately.
|
||
884 | |||
885 | (@) Between a slave de-selection (high level on NSS) and a new slave selection
|
||
886 | (low level on NSS), the CRC value should be cleared on both master and slave
|
||
887 | sides in order to resynchronize the master and slave for their respective
|
||
888 | CRC calculation.
|
||
889 | |||
890 | (@) To clear the CRC, follow the procedure below:
|
||
891 | (#@) Disable SPI using the SPI_Cmd() function
|
||
892 | (#@) Disable the CRC calculation using the SPI_CalculateCRC() function.
|
||
893 | (#@) Enable the CRC calculation using the SPI_CalculateCRC() function.
|
||
894 | (#@) Enable SPI using the SPI_Cmd() function.
|
||
895 | |||
896 | @endverbatim
|
||
897 | * @{
|
||
898 | */
|
||
899 | |||
900 | /**
|
||
901 | * @brief Enables or disables the CRC value calculation of the transferred bytes.
|
||
902 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
903 | * @param NewState: new state of the SPIx CRC value calculation.
|
||
904 | * This parameter can be: ENABLE or DISABLE.
|
||
905 | * @retval None
|
||
906 | */
|
||
907 | void SPI_CalculateCRC(SPI_TypeDef* SPIx, FunctionalState NewState)
|
||
908 | { |
||
909 | /* Check the parameters */
|
||
910 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
911 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
912 | if (NewState != DISABLE)
|
||
913 | { |
||
914 | /* Enable the selected SPI CRC calculation */
|
||
915 | SPIx->CR1 |= SPI_CR1_CRCEN; |
||
916 | } |
||
917 | else
|
||
918 | { |
||
919 | /* Disable the selected SPI CRC calculation */
|
||
920 | SPIx->CR1 &= (uint16_t)~((uint16_t)SPI_CR1_CRCEN); |
||
921 | } |
||
922 | } |
||
923 | |||
924 | /**
|
||
925 | * @brief Transmit the SPIx CRC value.
|
||
926 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
927 | * @retval None
|
||
928 | */
|
||
929 | void SPI_TransmitCRC(SPI_TypeDef* SPIx)
|
||
930 | { |
||
931 | /* Check the parameters */
|
||
932 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
933 | |||
934 | /* Enable the selected SPI CRC transmission */
|
||
935 | SPIx->CR1 |= SPI_CR1_CRCNEXT; |
||
936 | } |
||
937 | |||
938 | /**
|
||
939 | * @brief Returns the transmit or the receive CRC register value for the specified SPI.
|
||
940 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
941 | * @param SPI_CRC: specifies the CRC register to be read.
|
||
942 | * This parameter can be one of the following values:
|
||
943 | * @arg SPI_CRC_Tx: Selects Tx CRC register
|
||
944 | * @arg SPI_CRC_Rx: Selects Rx CRC register
|
||
945 | * @retval The selected CRC register value..
|
||
946 | */
|
||
947 | uint16_t SPI_GetCRC(SPI_TypeDef* SPIx, uint8_t SPI_CRC) |
||
948 | { |
||
949 | uint16_t crcreg = 0;
|
||
950 | /* Check the parameters */
|
||
951 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
952 | assert_param(IS_SPI_CRC(SPI_CRC)); |
||
953 | if (SPI_CRC != SPI_CRC_Rx)
|
||
954 | { |
||
955 | /* Get the Tx CRC register */
|
||
956 | crcreg = SPIx->TXCRCR; |
||
957 | } |
||
958 | else
|
||
959 | { |
||
960 | /* Get the Rx CRC register */
|
||
961 | crcreg = SPIx->RXCRCR; |
||
962 | } |
||
963 | /* Return the selected CRC register */
|
||
964 | return crcreg;
|
||
965 | } |
||
966 | |||
967 | /**
|
||
968 | * @brief Returns the CRC Polynomial register value for the specified SPI.
|
||
969 | * @param SPIx: where x can be 1, 2, 3, 4, 5 or 6 to select the SPI peripheral.
|
||
970 | * @retval The CRC Polynomial register value.
|
||
971 | */
|
||
972 | uint16_t SPI_GetCRCPolynomial(SPI_TypeDef* SPIx) |
||
973 | { |
||
974 | /* Check the parameters */
|
||
975 | assert_param(IS_SPI_ALL_PERIPH(SPIx)); |
||
976 | |||
977 | /* Return the CRC polynomial register */
|
||
978 | return SPIx->CRCPR;
|
||
979 | } |
||
980 | |||
981 | /**
|
||
982 | * @}
|
||
983 | */
|
||
984 | |||
985 | /** @defgroup SPI_Group4 DMA transfers management functions
|
||
986 | * @brief DMA transfers management functions
|
||
987 | *
|
||
988 | @verbatim
|
||
989 | ===============================================================================
|
||
990 | ##### DMA transfers management functions #####
|
||
991 | ===============================================================================
|
||
992 | |||
993 | @endverbatim
|
||
994 | * @{
|
||
995 | */
|
||
996 | |||
997 | /**
|
||
998 | * @brief Enables or disables the SPIx/I2Sx DMA interface.
|
||
999 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1000 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1001 | * @param SPI_I2S_DMAReq: specifies the SPI DMA transfer request to be enabled or disabled.
|
||
1002 | * This parameter can be any combination of the following values:
|
||
1003 | * @arg SPI_I2S_DMAReq_Tx: Tx buffer DMA transfer request
|
||
1004 | * @arg SPI_I2S_DMAReq_Rx: Rx buffer DMA transfer request
|
||
1005 | * @param NewState: new state of the selected SPI DMA transfer request.
|
||
1006 | * This parameter can be: ENABLE or DISABLE.
|
||
1007 | * @retval None
|
||
1008 | */
|
||
1009 | void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState NewState)
|
||
1010 | { |
||
1011 | /* Check the parameters */
|
||
1012 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1013 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
1014 | assert_param(IS_SPI_I2S_DMAREQ(SPI_I2S_DMAReq)); |
||
1015 | |||
1016 | if (NewState != DISABLE)
|
||
1017 | { |
||
1018 | /* Enable the selected SPI DMA requests */
|
||
1019 | SPIx->CR2 |= SPI_I2S_DMAReq; |
||
1020 | } |
||
1021 | else
|
||
1022 | { |
||
1023 | /* Disable the selected SPI DMA requests */
|
||
1024 | SPIx->CR2 &= (uint16_t)~SPI_I2S_DMAReq; |
||
1025 | } |
||
1026 | } |
||
1027 | |||
1028 | /**
|
||
1029 | * @}
|
||
1030 | */
|
||
1031 | |||
1032 | /** @defgroup SPI_Group5 Interrupts and flags management functions
|
||
1033 | * @brief Interrupts and flags management functions
|
||
1034 | *
|
||
1035 | @verbatim
|
||
1036 | ===============================================================================
|
||
1037 | ##### Interrupts and flags management functions #####
|
||
1038 | ===============================================================================
|
||
1039 |
|
||
1040 | [..] This section provides a set of functions allowing to configure the SPI Interrupts
|
||
1041 | sources and check or clear the flags or pending bits status.
|
||
1042 | The user should identify which mode will be used in his application to manage
|
||
1043 | the communication: Polling mode, Interrupt mode or DMA mode.
|
||
1044 |
|
||
1045 | *** Polling Mode ***
|
||
1046 | ====================
|
||
1047 | [..] In Polling Mode, the SPI/I2S communication can be managed by 9 flags:
|
||
1048 | (#) SPI_I2S_FLAG_TXE : to indicate the status of the transmit buffer register
|
||
1049 | (#) SPI_I2S_FLAG_RXNE : to indicate the status of the receive buffer register
|
||
1050 | (#) SPI_I2S_FLAG_BSY : to indicate the state of the communication layer of the SPI.
|
||
1051 | (#) SPI_FLAG_CRCERR : to indicate if a CRC Calculation error occur
|
||
1052 | (#) SPI_FLAG_MODF : to indicate if a Mode Fault error occur
|
||
1053 | (#) SPI_I2S_FLAG_OVR : to indicate if an Overrun error occur
|
||
1054 | (#) I2S_FLAG_TIFRFE: to indicate a Frame Format error occurs.
|
||
1055 | (#) I2S_FLAG_UDR: to indicate an Underrun error occurs.
|
||
1056 | (#) I2S_FLAG_CHSIDE: to indicate Channel Side.
|
||
1057 | |||
1058 | (@) Do not use the BSY flag to handle each data transmission or reception. It is
|
||
1059 | better to use the TXE and RXNE flags instead.
|
||
1060 | |||
1061 | [..] In this Mode it is advised to use the following functions:
|
||
1062 | (+) FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
|
||
1063 | (+) void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG);
|
||
1064 | |||
1065 | *** Interrupt Mode ***
|
||
1066 | ======================
|
||
1067 | [..] In Interrupt Mode, the SPI communication can be managed by 3 interrupt sources
|
||
1068 | and 7 pending bits:
|
||
1069 | (+) Pending Bits:
|
||
1070 | (##) SPI_I2S_IT_TXE : to indicate the status of the transmit buffer register
|
||
1071 | (##) SPI_I2S_IT_RXNE : to indicate the status of the receive buffer register
|
||
1072 | (##) SPI_IT_CRCERR : to indicate if a CRC Calculation error occur (available in SPI mode only)
|
||
1073 | (##) SPI_IT_MODF : to indicate if a Mode Fault error occur (available in SPI mode only)
|
||
1074 | (##) SPI_I2S_IT_OVR : to indicate if an Overrun error occur
|
||
1075 | (##) I2S_IT_UDR : to indicate an Underrun Error occurs (available in I2S mode only).
|
||
1076 | (##) I2S_FLAG_TIFRFE : to indicate a Frame Format error occurs (available in TI mode only).
|
||
1077 | |||
1078 | (+) Interrupt Source:
|
||
1079 | (##) SPI_I2S_IT_TXE: specifies the interrupt source for the Tx buffer empty
|
||
1080 | interrupt.
|
||
1081 | (##) SPI_I2S_IT_RXNE : specifies the interrupt source for the Rx buffer not
|
||
1082 | empty interrupt.
|
||
1083 | (##) SPI_I2S_IT_ERR : specifies the interrupt source for the errors interrupt.
|
||
1084 | |||
1085 | [..] In this Mode it is advised to use the following functions:
|
||
1086 | (+) void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState);
|
||
1087 | (+) ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
|
||
1088 | (+) void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT);
|
||
1089 | |||
1090 | *** DMA Mode ***
|
||
1091 | ================
|
||
1092 | [..] In DMA Mode, the SPI communication can be managed by 2 DMA Channel requests:
|
||
1093 | (#) SPI_I2S_DMAReq_Tx: specifies the Tx buffer DMA transfer request
|
||
1094 | (#) SPI_I2S_DMAReq_Rx: specifies the Rx buffer DMA transfer request
|
||
1095 | |||
1096 | [..] In this Mode it is advised to use the following function:
|
||
1097 | (+) void SPI_I2S_DMACmd(SPI_TypeDef* SPIx, uint16_t SPI_I2S_DMAReq, FunctionalState
|
||
1098 | NewState);
|
||
1099 | |||
1100 | @endverbatim
|
||
1101 | * @{
|
||
1102 | */
|
||
1103 | |||
1104 | /**
|
||
1105 | * @brief Enables or disables the specified SPI/I2S interrupts.
|
||
1106 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1107 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1108 | * @param SPI_I2S_IT: specifies the SPI interrupt source to be enabled or disabled.
|
||
1109 | * This parameter can be one of the following values:
|
||
1110 | * @arg SPI_I2S_IT_TXE: Tx buffer empty interrupt mask
|
||
1111 | * @arg SPI_I2S_IT_RXNE: Rx buffer not empty interrupt mask
|
||
1112 | * @arg SPI_I2S_IT_ERR: Error interrupt mask
|
||
1113 | * @param NewState: new state of the specified SPI interrupt.
|
||
1114 | * This parameter can be: ENABLE or DISABLE.
|
||
1115 | * @retval None
|
||
1116 | */
|
||
1117 | void SPI_I2S_ITConfig(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT, FunctionalState NewState)
|
||
1118 | { |
||
1119 | uint16_t itpos = 0, itmask = 0 ; |
||
1120 | |||
1121 | /* Check the parameters */
|
||
1122 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1123 | assert_param(IS_FUNCTIONAL_STATE(NewState)); |
||
1124 | assert_param(IS_SPI_I2S_CONFIG_IT(SPI_I2S_IT)); |
||
1125 | |||
1126 | /* Get the SPI IT index */
|
||
1127 | itpos = SPI_I2S_IT >> 4;
|
||
1128 | |||
1129 | /* Set the IT mask */
|
||
1130 | itmask = (uint16_t)1 << (uint16_t)itpos;
|
||
1131 | |||
1132 | if (NewState != DISABLE)
|
||
1133 | { |
||
1134 | /* Enable the selected SPI interrupt */
|
||
1135 | SPIx->CR2 |= itmask; |
||
1136 | } |
||
1137 | else
|
||
1138 | { |
||
1139 | /* Disable the selected SPI interrupt */
|
||
1140 | SPIx->CR2 &= (uint16_t)~itmask; |
||
1141 | } |
||
1142 | } |
||
1143 | |||
1144 | /**
|
||
1145 | * @brief Checks whether the specified SPIx/I2Sx flag is set or not.
|
||
1146 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1147 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1148 | * @param SPI_I2S_FLAG: specifies the SPI flag to check.
|
||
1149 | * This parameter can be one of the following values:
|
||
1150 | * @arg SPI_I2S_FLAG_TXE: Transmit buffer empty flag.
|
||
1151 | * @arg SPI_I2S_FLAG_RXNE: Receive buffer not empty flag.
|
||
1152 | * @arg SPI_I2S_FLAG_BSY: Busy flag.
|
||
1153 | * @arg SPI_I2S_FLAG_OVR: Overrun flag.
|
||
1154 | * @arg SPI_FLAG_MODF: Mode Fault flag.
|
||
1155 | * @arg SPI_FLAG_CRCERR: CRC Error flag.
|
||
1156 | * @arg SPI_I2S_FLAG_TIFRFE: Format Error.
|
||
1157 | * @arg I2S_FLAG_UDR: Underrun Error flag.
|
||
1158 | * @arg I2S_FLAG_CHSIDE: Channel Side flag.
|
||
1159 | * @retval The new state of SPI_I2S_FLAG (SET or RESET).
|
||
1160 | */
|
||
1161 | FlagStatus SPI_I2S_GetFlagStatus(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG) |
||
1162 | { |
||
1163 | FlagStatus bitstatus = RESET; |
||
1164 | /* Check the parameters */
|
||
1165 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1166 | assert_param(IS_SPI_I2S_GET_FLAG(SPI_I2S_FLAG)); |
||
1167 | |||
1168 | /* Check the status of the specified SPI flag */
|
||
1169 | if ((SPIx->SR & SPI_I2S_FLAG) != (uint16_t)RESET)
|
||
1170 | { |
||
1171 | /* SPI_I2S_FLAG is set */
|
||
1172 | bitstatus = SET; |
||
1173 | } |
||
1174 | else
|
||
1175 | { |
||
1176 | /* SPI_I2S_FLAG is reset */
|
||
1177 | bitstatus = RESET; |
||
1178 | } |
||
1179 | /* Return the SPI_I2S_FLAG status */
|
||
1180 | return bitstatus;
|
||
1181 | } |
||
1182 | |||
1183 | /**
|
||
1184 | * @brief Clears the SPIx CRC Error (CRCERR) flag.
|
||
1185 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1186 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1187 | * @param SPI_I2S_FLAG: specifies the SPI flag to clear.
|
||
1188 | * This function clears only CRCERR flag.
|
||
1189 | * @arg SPI_FLAG_CRCERR: CRC Error flag.
|
||
1190 | *
|
||
1191 | * @note OVR (OverRun error) flag is cleared by software sequence: a read
|
||
1192 | * operation to SPI_DR register (SPI_I2S_ReceiveData()) followed by a read
|
||
1193 | * operation to SPI_SR register (SPI_I2S_GetFlagStatus()).
|
||
1194 | * @note UDR (UnderRun error) flag is cleared by a read operation to
|
||
1195 | * SPI_SR register (SPI_I2S_GetFlagStatus()).
|
||
1196 | * @note MODF (Mode Fault) flag is cleared by software sequence: a read/write
|
||
1197 | * operation to SPI_SR register (SPI_I2S_GetFlagStatus()) followed by a
|
||
1198 | * write operation to SPI_CR1 register (SPI_Cmd() to enable the SPI).
|
||
1199 | *
|
||
1200 | * @retval None
|
||
1201 | */
|
||
1202 | void SPI_I2S_ClearFlag(SPI_TypeDef* SPIx, uint16_t SPI_I2S_FLAG)
|
||
1203 | { |
||
1204 | /* Check the parameters */
|
||
1205 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1206 | assert_param(IS_SPI_I2S_CLEAR_FLAG(SPI_I2S_FLAG)); |
||
1207 | |||
1208 | /* Clear the selected SPI CRC Error (CRCERR) flag */
|
||
1209 | SPIx->SR = (uint16_t)~SPI_I2S_FLAG; |
||
1210 | } |
||
1211 | |||
1212 | /**
|
||
1213 | * @brief Checks whether the specified SPIx/I2Sx interrupt has occurred or not.
|
||
1214 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1215 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1216 | * @param SPI_I2S_IT: specifies the SPI interrupt source to check.
|
||
1217 | * This parameter can be one of the following values:
|
||
1218 | * @arg SPI_I2S_IT_TXE: Transmit buffer empty interrupt.
|
||
1219 | * @arg SPI_I2S_IT_RXNE: Receive buffer not empty interrupt.
|
||
1220 | * @arg SPI_I2S_IT_OVR: Overrun interrupt.
|
||
1221 | * @arg SPI_IT_MODF: Mode Fault interrupt.
|
||
1222 | * @arg SPI_IT_CRCERR: CRC Error interrupt.
|
||
1223 | * @arg I2S_IT_UDR: Underrun interrupt.
|
||
1224 | * @arg SPI_I2S_IT_TIFRFE: Format Error interrupt.
|
||
1225 | * @retval The new state of SPI_I2S_IT (SET or RESET).
|
||
1226 | */
|
||
1227 | ITStatus SPI_I2S_GetITStatus(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT) |
||
1228 | { |
||
1229 | ITStatus bitstatus = RESET; |
||
1230 | uint16_t itpos = 0, itmask = 0, enablestatus = 0; |
||
1231 | |||
1232 | /* Check the parameters */
|
||
1233 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1234 | assert_param(IS_SPI_I2S_GET_IT(SPI_I2S_IT)); |
||
1235 | |||
1236 | /* Get the SPI_I2S_IT index */
|
||
1237 | itpos = 0x01 << (SPI_I2S_IT & 0x0F); |
||
1238 | |||
1239 | /* Get the SPI_I2S_IT IT mask */
|
||
1240 | itmask = SPI_I2S_IT >> 4;
|
||
1241 | |||
1242 | /* Set the IT mask */
|
||
1243 | itmask = 0x01 << itmask;
|
||
1244 | |||
1245 | /* Get the SPI_I2S_IT enable bit status */
|
||
1246 | enablestatus = (SPIx->CR2 & itmask) ; |
||
1247 | |||
1248 | /* Check the status of the specified SPI interrupt */
|
||
1249 | if (((SPIx->SR & itpos) != (uint16_t)RESET) && enablestatus)
|
||
1250 | { |
||
1251 | /* SPI_I2S_IT is set */
|
||
1252 | bitstatus = SET; |
||
1253 | } |
||
1254 | else
|
||
1255 | { |
||
1256 | /* SPI_I2S_IT is reset */
|
||
1257 | bitstatus = RESET; |
||
1258 | } |
||
1259 | /* Return the SPI_I2S_IT status */
|
||
1260 | return bitstatus;
|
||
1261 | } |
||
1262 | |||
1263 | /**
|
||
1264 | * @brief Clears the SPIx CRC Error (CRCERR) interrupt pending bit.
|
||
1265 | * @param SPIx: To select the SPIx/I2Sx peripheral, where x can be: 1, 2, 3, 4, 5 or 6
|
||
1266 | * in SPI mode or 2 or 3 in I2S mode or I2Sxext for I2S full duplex mode.
|
||
1267 | * @param SPI_I2S_IT: specifies the SPI interrupt pending bit to clear.
|
||
1268 | * This function clears only CRCERR interrupt pending bit.
|
||
1269 | * @arg SPI_IT_CRCERR: CRC Error interrupt.
|
||
1270 | *
|
||
1271 | * @note OVR (OverRun Error) interrupt pending bit is cleared by software
|
||
1272 | * sequence: a read operation to SPI_DR register (SPI_I2S_ReceiveData())
|
||
1273 | * followed by a read operation to SPI_SR register (SPI_I2S_GetITStatus()).
|
||
1274 | * @note UDR (UnderRun Error) interrupt pending bit is cleared by a read
|
||
1275 | * operation to SPI_SR register (SPI_I2S_GetITStatus()).
|
||
1276 | * @note MODF (Mode Fault) interrupt pending bit is cleared by software sequence:
|
||
1277 | * a read/write operation to SPI_SR register (SPI_I2S_GetITStatus())
|
||
1278 | * followed by a write operation to SPI_CR1 register (SPI_Cmd() to enable
|
||
1279 | * the SPI).
|
||
1280 | * @retval None
|
||
1281 | */
|
||
1282 | void SPI_I2S_ClearITPendingBit(SPI_TypeDef* SPIx, uint8_t SPI_I2S_IT)
|
||
1283 | { |
||
1284 | uint16_t itpos = 0;
|
||
1285 | /* Check the parameters */
|
||
1286 | assert_param(IS_SPI_ALL_PERIPH_EXT(SPIx)); |
||
1287 | assert_param(IS_SPI_I2S_CLEAR_IT(SPI_I2S_IT)); |
||
1288 | |||
1289 | /* Get the SPI_I2S IT index */
|
||
1290 | itpos = 0x01 << (SPI_I2S_IT & 0x0F); |
||
1291 | |||
1292 | /* Clear the selected SPI CRC Error (CRCERR) interrupt pending bit */
|
||
1293 | SPIx->SR = (uint16_t)~itpos; |
||
1294 | } |
||
1295 | |||
1296 | /**
|
||
1297 | * @}
|
||
1298 | */
|
||
1299 | |||
1300 | /**
|
||
1301 | * @}
|
||
1302 | */
|
||
1303 | |||
1304 | /**
|
||
1305 | * @}
|
||
1306 | */
|
||
1307 | |||
1308 | /**
|
||
1309 | * @}
|
||
1310 | */
|
||
1311 | |||
1312 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/
|