spi.c 9.58 KB
Newer Older
李俭双's avatar
李俭双 committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341
/**
  ******************************************************************************
  * @file    spi.c
  * @author  CMS Application Team
  * @version Vx.x.x
  * @date    24-April-2022
  * @brief   This file provides firmware functions to manage the following 
  *          functionalities of the Serial Peripheral interface (SPI):           
  @verbatim       
 ===============================================================================
                        ##### How to use this driver #####
 ===============================================================================
    [..]
            
    @endverbatim        
  ******************************************************************************
  * @attention
  *
  *
  ******************************************************************************
  */

/* Includes ------------------------------------------------------------------*/
#include "spi.h"
#include "cgc.h"

/* Private typedef -----------------------------------------------------------*/
/* Private define ------------------------------------------------------------*/
/* Private macro -------------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
/* Private function prototypes -----------------------------------------------*/
/* Private functions ---------------------------------------------------------*/

/** @defgroup SPI_Private_Functions
  * @{
  */
NSS_FUNC_T NSS;
/**
  * @brief  De-initialize the SPI peripheral registers to their default reset values.
  * @note   None
  * @retval None
  */
void SPI_DeInit(void)
{
	CGC_PER1PeriphClockCmd(CGC_PER1Periph_SPI, DISABLE);
}

/**
  * @brief  Initializes the SPIx peripheral according to the specified 
  *         parameters in the SPI_InitStruct.
  * @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_InitTypeDef* SPI_InitStruct)
{
	uint32_t tmpreg = 0;

	/* Check the SPI parameters */
	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));

	/*---------------------------- SPI Clock gate control enable -----------------*/
	CGC_PER1PeriphClockCmd(CGC_PER1Periph_SPI, ENABLE);

	/*---------------------------- SPI SPIM flag clear ---------------------------*/
	SPI->SPIM &= ~(SPI_FLAG_RXNE);
	SPI->SPIM &= ~(SPI_FLAG_RUNNING);

	/*---------------------------- SPI SPIC Configuration ------------------------*/
	/* Get the SPIC value */
	tmpreg = SPI->SPIC;

	/* The SPI Master or Slave mode selected by clock setting */
	if (SPI_Mode_Master == SPI_InitStruct->SPI_Mode)
	{
		tmpreg |= SPI_InitStruct->SPI_BaudRatePrescaler;
	}
	else
	{
		/* When SPI mode is slave, select the ext clock */
		tmpreg |= SPI_BaudRatePrescaler_Ext;
	}

	/* SPI_Clock_Polarity setting */
	tmpreg |= SPI_InitStruct->SPI_CPOL;

	/* SPI_Clock_Phase setting */
	tmpreg |= SPI_InitStruct->SPI_CPHA;

	/* Set the SPIC value */
	SPI->SPIC = tmpreg;

	/*---------------------------- SPI SPIM Configuration ------------------------*/
	/* Get the SPIM value */
	tmpreg = SPI->SPIM;

	tmpreg |= SPI_InitStruct->SPI_DataSize;
	tmpreg |= SPI_InitStruct->SPI_NSS;
	tmpreg |= SPI_InitStruct->SPI_FirstBit;

	/* Set the SPIM value */
	SPI->SPIM = tmpreg;
}

/**
  * @brief  Enables or disables the specified SPI peripheral.
  * @param  NewState: new state of the SPI peripheral. 
  *          This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void SPI_Cmd(FunctionalState NewState)
{
	/* Check the parameters */
	assert_param(IS_FUNCTIONAL_STATE(NewState));
	if (NewState != DISABLE)
	{
		/* Enable the selected SPI peripheral */
		SPI->SPIM |= (uint32_t)SPI_SPIM_SPIE_Msk;
		if(NSS.Active)
		{
			NSS.Active();
		}
	}
	else
	{
		/* Disable the selected SPI peripheral */
		SPI->SPIM &= (uint32_t)~((uint32_t)SPI_SPIM_SPIE_Msk);
		if(NSS.Inactive)
		{
			NSS.Inactive();	
		}
	}
}

/**
  * @brief  Configures the data size for the selected SPI.
  * @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(uint8_t SPI_DataSize)
{
	/* Check the parameters */
	assert_param(IS_SPI_DATASIZE(SPI_DataSize));
	/* Clear DLS bit */
	SPI->SPIM &= (uint32_t)~((uint32_t)SPI_SPIM_DLS_Msk);
	/* Set new DLS bit value */
	SPI->SPIM |= (uint32_t)SPI_DataSize;
}

/**
  * @brief  Selects the data transfer direction in bidirectional mode for the specified SPI.
  * @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(uint8_t SPI_Direction)
{
	/* Check the parameters */
	assert_param(IS_SPI_DIRECTION(SPI_Direction));
	if (SPI_Direction == SPI_Direction_TxRx)
	{
		/* Set the Tx/Rx mode */
		SPI->SPIM |= (uint32_t)SPI_Direction_TxRx;
	}
	else
	{
		/* Set the Rx only mode */
		SPI->SPIM &= (uint32_t)SPI_Direction_Rx;
	}
}

/**
  * @}
  */

/** @defgroup SPI_Group2 Data transfers functions
 *  @brief   Data transfers functions
 *
@verbatim   
 ===============================================================================
                      ##### Data transfers functions #####
 ===============================================================================  

 [..] This section provides a set of functions allowing to manage the SPI data 
      transfers. In reception, data are received and then stored into an internal 
      Rx buffer while. In transmission, data are first stored into an internal Tx 
      buffer before being transmitted.

 [..] The read access of the SPI_SDRI register can be done using the SPI_I2S_ReceiveData()
      function and returns the Rx buffered value. Whereas a write access to the SPI_SDRO 
      can be done using SPI_I2S_SendData() function and stores the written data into 
      Tx buffer.

@endverbatim
  * @{
  */

/**
  * @brief  Returns the most recent received data by the SPI peripheral. 
  * @retval The value of the received data.
  */
uint16_t SPI_ReceiveData(void)
{
	/* Return the data in the DR register */
	return (uint16_t)SPI->SDRI;
}

/**
  * @brief  Transmits a Data through the SPI peripheral. 
  * @param  Data: Data to be transmitted.
  * @retval None
  */
void SPI_SendData(uint16_t Data)
{
	/* Write in the DR register the data to be sent */
	SPI->SDRO = Data;
}

/**
  * @brief  Transmits one Byte Data through the SPI peripheral. 
  * @param  Data: Data to be transmitted.
  * @retval tmp: Receive the data by transmit.
  */
uint8_t SPI_TransmitByte(uint8_t Data)
{
	uint8_t tmp;
	
	/* Write in the DR register the data to be sent */
	SPI->SDRO = Data;
	
	/* Wait the Byte data transmit completed */
	while((SPI->SPIM & ((uint16_t)SPI_SPIM_SPTF_Msk)) != RESET);
	
	/* Receive Byte data */
	tmp = (uint8_t)SPI_ReceiveData();
	
	return tmp;
}


/**
  * @brief  Transmits one Byte Data through the SPI peripheral. 
  * @param  Data: Data to be transmitted.
  * @retval tmp: Receive the data by transmit.
  */
uint8_t SPI_ReceiveByte(void)
{
	uint8_t tmp;
	/* Write in the DR register the data to be sent */
	SPI->SDRO = 0xFF;
	
	/* Wait the Byte data transmit completed */
	while((SPI->SPIM & ((uint16_t)SPI_SPIM_SPTF_Msk)) != SET);
	
	/* Receive Byte data */
	tmp = (uint8_t)SPI_ReceiveData();
	
	return tmp;
}

/**
  * @brief  Transmits one Word Data through the SPI peripheral. 
  * @param  Data: Data to be transmitted.
  * @retval tmp: Receive the data by transmit.
  */
uint16_t SPI_TransmitWord(uint16_t Data)
{
	uint16_t tmp;
	
	/* Write in the DR register the data to be sent */
	SPI->SDRO = Data;
	
	/* Wait the Byte data transmit completed */
	while((SPI->SPIM & ((uint16_t)SPI_SPIM_SPTF_Msk)) != RESET);
	
	/* Receive Byte data */
	tmp = (uint16_t)SPI_ReceiveData();
	
	return tmp;
}

/**
  * @brief  Transmits one Word Data through the SPI peripheral. 
  * @param  Data: Data to be transmitted.
  * @retval tmp: Receive the data by transmit.
  */
uint16_t SPI_ReceiveWord(void)
{
	uint16_t tmp;
	
	/* Write in the DR register the data to be sent */
	SPI->SDRO = 0xFFFF;
	
	/* Wait the Byte data transmit completed */
	while((SPI->SPIM & ((uint16_t)SPI_SPIM_SPTF_Msk)) != SET);
	
	/* Receive Byte data */
	tmp = (uint16_t)SPI_ReceiveData();
	
	return tmp;
}

/**
  * @brief  Checks whether the specified SPI flag is set or not.
  * @param  SPI_FLAG: specifies the SPI flag to check. 
  *          This parameter can be one of the following values:
  *            @arg SPI_FLAG_RXNE: Receive buffer not empty flag.
  * 		   @arg SPI_FLAG_RUNNING: Communication status flag.
  * @retval The new state of SPI_FLAG (SET or RESET).
  */
FlagStatus SPI_GetFlagStatus(uint8_t SPI_FLAG)
{
	FlagStatus bitstatus = RESET;
	/* Check the parameters */
	assert_param(IS_SPI_GET_FLAG(SPI_FLAG));

	/* Check the status of the specified SPI flag */
	if ((SPI->SPIM & SPI_FLAG) != (uint16_t)RESET)
	{
		/* SPI_I2S_FLAG is set */
		bitstatus = SET;
	}
	else
	{
		/* SPI_I2S_FLAG is reset */
		bitstatus = RESET;
	}
	/* Return the SPI_I2S_FLAG status */
	return  bitstatus;
}