?? stm32l1xx_spi.c
字號:
/**
******************************************************************************
* @file stm32l1xx_spi.c
* @author MCD Application Team
* @version V1.0.0
* @date 31-December-2010
* @brief This file provides firmware functions to manage the following
* functionalities of the Serial peripheral interface (SPI):
* - Initialization and Configuration
* - Data transfers functions
* - Hardware CRC Calculation
* - DMA transfers management
* - Interrupts and flags management
*
* @verbatim
*
* The I2S feature is not implemented in STM32L1xx Ultra Low Power
* Medium-density devices and will be supported in future products.
*
* ===================================================================
* How to use this driver
* ===================================================================
* 1. Enable peripheral clock using RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE)
* function for SPI1 or using RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE)
* function for SPI2.
*
* 2. Enable SCK, MOSI, MISO and NSS GPIO clocks using RCC_AHBPeriphClockCmd()
* function.
*
* 3. Peripherals alternate function:
* - Connect the pin to the desired peripherals' Alternate
* Function (AF) using GPIO_PinAFConfig() function
* - Configure the desired pin in alternate function by:
* GPIO_InitStruct->GPIO_Mode = GPIO_Mode_AF
* - Select the type, pull-up/pull-down and output speed via
* GPIO_PuPd, GPIO_OType and GPIO_Speed members
* - Call GPIO_Init() function
*
* 4. Program the Polarity, Phase, First Data, Baud Rate Prescaler, Slave
* Management, Peripheral Mode and CRC Polynomial values using the SPI_Init()
* function.
*
* 5. Enable the NVIC and the corresponding interrupt using the function
* SPI_ITConfig() if you need to use interrupt mode.
*
* 6. When using the DMA mode
* - Configure the DMA using DMA_Init() function
* - Active the needed channel Request using SPI_I2S_DMACmd() function
*
* 7. Enable the SPI using the SPI_Cmd() function.
*
* 8. Enable the DMA using the DMA_Cmd() function when using DMA mode.
*
* 9. Optionally you can enable/configure the following parameters without
* re-initialization (i.e there is no need to call again SPI_Init() function):
* - When bidirectional mode (SPI_Direction_1Line_Rx or SPI_Direction_1Line_Tx)
* is programmed as Data direction parameter using the SPI_Init() function
* it can be possible to switch between SPI_Direction_Tx or SPI_Direction_Rx
* using the SPI_BiDirectionalLineConfig() function.
* - When SPI_NSS_Soft is selected as Slave Select Management parameter
* using the SPI_Init() function it can be possible to manage the
* NSS internal signal using the SPI_NSSInternalSoftwareConfig() function.
* - Reconfigure the data size using the SPI_DataSizeConfig() function
* - Enable or disable the SS output using the SPI_SSOutputCmd() function
*
* 10. To use the CRC Hardware calculation feature refer to the Peripheral
* CRC hardware Calculation subsection.
*
* @endverbatim
*
******************************************************************************
* @attention
*
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
*
* <h2><center>© COPYRIGHT 2010 STMicroelectronics</center></h2>
******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
#include "stm32l1xx_spi.h"
#include "stm32l1xx_rcc.h"
/** @addtogroup STM32L1xx_StdPeriph_Driver
* @{
*/
/** @defgroup SPI
* @brief SPI driver modules
* @{
*/
/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* SPI registers Masks */
#define CR1_CLEAR_MASK ((uint16_t)0x3040)
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/
/** @defgroup SPI_Private_Functions
* @{
*/
/** @defgroup SPI_Group1 Initialization and Configuration functions
* @brief Initialization and Configuration functions
*
@verbatim
===============================================================================
Initialization and Configuration functions
===============================================================================
This section provides a set of functions allowing to initialize the SPI Direction,
SPI Mode, SPI Data Size, SPI Polarity, SPI Phase, SPI NSS Management, SPI Baud
Rate Prescaler, SPI First Bit and SPI CRC Polynomial.
The SPI_Init() function follows the SPI configuration procedures for Master mode
and Slave mode (details for these procedures are available in reference manual
(RM0038)).
@endverbatim
* @{
*/
/**
* @brief Deinitializes the SPIx peripheral registers to their default
* reset values.
* @param SPIx: where x can be 1 or 2 to select the SPI peripheral.
* @retval None
*/
void SPI_I2S_DeInit(SPI_TypeDef* SPIx)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
if (SPIx == SPI1)
{
/* Enable SPI1 reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, ENABLE);
/* Release SPI1 from reset state */
RCC_APB2PeriphResetCmd(RCC_APB2Periph_SPI1, DISABLE);
}
else
{
if (SPIx == SPI2)
{
/* Enable SPI2 reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, ENABLE);
/* Release SPI2 from reset state */
RCC_APB1PeriphResetCmd(RCC_APB1Periph_SPI2, DISABLE);
}
}
}
/**
* @brief Initializes the SPIx peripheral according to the specified
* parameters in the SPI_InitStruct.
* @param SPIx: where x can be 1 or 2 to select the SPI peripheral.
* @param SPI_InitStruct: pointer to a SPI_InitTypeDef structure that
* contains the configuration information for the specified SPI peripheral.
* @retval None
*/
void SPI_Init(SPI_TypeDef* SPIx, SPI_InitTypeDef* SPI_InitStruct)
{
uint16_t tmpreg = 0;
/* check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
/* Check the SPI parameters */
assert_param(IS_SPI_DIRECTION_MODE(SPI_InitStruct->SPI_Direction));
assert_param(IS_SPI_MODE(SPI_InitStruct->SPI_Mode));
assert_param(IS_SPI_DATASIZE(SPI_InitStruct->SPI_DataSize));
assert_param(IS_SPI_CPOL(SPI_InitStruct->SPI_CPOL));
assert_param(IS_SPI_CPHA(SPI_InitStruct->SPI_CPHA));
assert_param(IS_SPI_NSS(SPI_InitStruct->SPI_NSS));
assert_param(IS_SPI_BAUDRATE_PRESCALER(SPI_InitStruct->SPI_BaudRatePrescaler));
assert_param(IS_SPI_FIRST_BIT(SPI_InitStruct->SPI_FirstBit));
assert_param(IS_SPI_CRC_POLYNOMIAL(SPI_InitStruct->SPI_CRCPolynomial));
/*---------------------------- SPIx CR1 Configuration ------------------------*/
/* Get the SPIx CR1 value */
tmpreg = SPIx->CR1;
/* Clear BIDIMode, BIDIOE, RxONLY, SSM, SSI, LSBFirst, BR, MSTR, CPOL and CPHA bits */
tmpreg &= CR1_CLEAR_MASK;
/* Configure SPIx: direction, NSS management, first transmitted bit, BaudRate prescaler
master/salve mode, CPOL and CPHA */
/* Set BIDImode, BIDIOE and RxONLY bits according to SPI_Direction value */
/* Set SSM, SSI and MSTR bits according to SPI_Mode and SPI_NSS values */
/* Set LSBFirst bit according to SPI_FirstBit value */
/* Set BR bits according to SPI_BaudRatePrescaler value */
/* Set CPOL bit according to SPI_CPOL value */
/* Set CPHA bit according to SPI_CPHA value */
tmpreg |= (uint16_t)((uint32_t)SPI_InitStruct->SPI_Direction | SPI_InitStruct->SPI_Mode |
SPI_InitStruct->SPI_DataSize | SPI_InitStruct->SPI_CPOL |
SPI_InitStruct->SPI_CPHA | SPI_InitStruct->SPI_NSS |
SPI_InitStruct->SPI_BaudRatePrescaler | SPI_InitStruct->SPI_FirstBit);
/* Write to SPIx CR1 */
SPIx->CR1 = tmpreg;
/*---------------------------- SPIx CRCPOLY Configuration --------------------*/
/* Write to SPIx CRCPOLY */
SPIx->CRCPR = SPI_InitStruct->SPI_CRCPolynomial;
}
/**
* @brief Fills each SPI_InitStruct member with its default value.
* @param SPI_InitStruct : pointer to a SPI_InitTypeDef structure which will be initialized.
* @retval None
*/
void SPI_StructInit(SPI_InitTypeDef* SPI_InitStruct)
{
/*--------------- Reset SPI init structure parameters values -----------------*/
/* Initialize the SPI_Direction member */
SPI_InitStruct->SPI_Direction = SPI_Direction_2Lines_FullDuplex;
/* initialize the SPI_Mode member */
SPI_InitStruct->SPI_Mode = SPI_Mode_Slave;
/* initialize the SPI_DataSize member */
SPI_InitStruct->SPI_DataSize = SPI_DataSize_8b;
/* Initialize the SPI_CPOL member */
SPI_InitStruct->SPI_CPOL = SPI_CPOL_Low;
/* Initialize the SPI_CPHA member */
SPI_InitStruct->SPI_CPHA = SPI_CPHA_1Edge;
/* Initialize the SPI_NSS member */
SPI_InitStruct->SPI_NSS = SPI_NSS_Hard;
/* Initialize the SPI_BaudRatePrescaler member */
SPI_InitStruct->SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
/* Initialize the SPI_FirstBit member */
SPI_InitStruct->SPI_FirstBit = SPI_FirstBit_MSB;
/* Initialize the SPI_CRCPolynomial member */
SPI_InitStruct->SPI_CRCPolynomial = 7;
}
/**
* @brief Enables or disables the specified SPI peripheral.
* @param SPIx: where x can be 1 or 2 to select the SPI peripheral.
* @param NewState: new state of the SPIx peripheral.
* This parameter can be: ENABLE or DISABLE.
* @retval None
*/
void SPI_Cmd(SPI_TypeDef* SPIx, FunctionalState NewState)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_FUNCTIONAL_STATE(NewState));
if (NewState != DISABLE)
{
/* Enable the selected SPI peripheral */
SPIx->CR1 |= SPI_CR1_SPE;
}
else
{
/* Disable the selected SPI peripheral */
SPIx->CR1 &= (uint16_t)~((uint16_t)SPI_CR1_SPE);
}
}
/**
* @brief Configures the data size for the selected SPI.
* @param SPIx: where x can be 1 or 2 to select the SPI peripheral.
* @param SPI_DataSize: specifies the SPI data size.
* This parameter can be one of the following values:
* @arg SPI_DataSize_16b: Set data frame format to 16bit
* @arg SPI_DataSize_8b: Set data frame format to 8bit
* @retval None
*/
void SPI_DataSizeConfig(SPI_TypeDef* SPIx, uint16_t SPI_DataSize)
{
/* Check the parameters */
assert_param(IS_SPI_ALL_PERIPH(SPIx));
assert_param(IS_SPI_DATASIZE(SPI_DataSize));
/* Clear DFF bit */
SPIx->CR1 &= (uint16_t)~SPI_DataSize_16b;
/* Set new DFF bit value */
SPIx->CR1 |= SPI_DataSize;
}
/**
* @brief Selects the data transfer direction in bidirectional mode for the specified SPI.
* @param SPIx: where x can be 1 or 2 to select the SPI peripheral.
* @param SPI_Direction: specifies the data transfer direction in bidirectional mode.
* This parameter can be one of the following values:
* @arg SPI_Direction_Tx: Selects Tx transmission direction
* @arg SPI_Direction_Rx: Selects Rx receive direction
* @retval None
*/
void SPI_BiDirectionalLineConfig(SPI_TypeDef* SPIx, uint16_t SPI_Direction)
{
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -