/** ****************************************************************************** * @file SPI/SPI_HalfDuplex_ComPolling/Src/main.c * @author MCD Application Team * @brief This sample code shows how to use STM32F3xx SPI HAL API to transmit * and receive a data buffer with a communication process based on * Polling transfer. * The communication is done using 2 Boards. ****************************************************************************** * @attention * *

© COPYRIGHT(c) 2017 STMicroelectronics

* * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * 3. Neither the name of STMicroelectronics nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ #include "main.h" /** @addtogroup STM32F3xx_HAL_Examples * @{ */ /** @addtogroup SPI_HalfDuplex_ComPolling * @{ */ /* Private typedef -----------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/ /* HalfDuplex communication direction */ #define RX 0 #define TX 1 /* Private macro -------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* SPI handler declaration */ SPI_HandleTypeDef SpiHandle; /* Buffer used for transmission */ uint8_t aTxBuffer[] = "**** SPI - Two Boards Half Duplex communication based on Polling **** SPI Message ******** "; /* Buffer used for reception */ uint8_t aRxBuffer[BUFFERSIZE]; /* Transmission status */ HAL_StatusTypeDef Errorcode = HAL_OK; /* Private function prototypes -----------------------------------------------*/ static void SystemClock_Config(void); static void Error_Handler(void); static void Timeout_Error_Handler(void); static uint16_t Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength); static void Check_Error (HAL_StatusTypeDef Errorcode, uint8_t Direction); /* Private functions ---------------------------------------------------------*/ /** * @brief Main program. * @param None * @retval None */ int main(void) { /* STM32F3xx HAL library initialization: - Configure the Flash prefetch - Configure the Systick to generate an interrupt each 1 msec - Set NVIC Group Priority to 4 - Low Level Initialization */ HAL_Init(); /* Configure the system clock to 64 MHz */ SystemClock_Config(); /* Configure LED1, LED2 and LED3 */ BSP_LED_Init(LED1); BSP_LED_Init(LED2); BSP_LED_Init(LED3); /*##-1- Configure the SPI peripheral #######################################*/ /* Set the SPI parameters */ SpiHandle.Instance = SPIx; SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_256; SpiHandle.Init.Direction = SPI_DIRECTION_1LINE; SpiHandle.Init.CLKPhase = SPI_PHASE_1EDGE; SpiHandle.Init.CLKPolarity = SPI_POLARITY_LOW; SpiHandle.Init.DataSize = SPI_DATASIZE_8BIT; SpiHandle.Init.FirstBit = SPI_FIRSTBIT_MSB; SpiHandle.Init.TIMode = SPI_TIMODE_DISABLE; SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE; SpiHandle.Init.CRCPolynomial = 7; SpiHandle.Init.CRCLength = SPI_CRC_LENGTH_8BIT; SpiHandle.Init.NSS = SPI_NSS_SOFT; SpiHandle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE; #ifdef MASTER_BOARD SpiHandle.Init.Mode = SPI_MODE_MASTER; #else SpiHandle.Init.Mode = SPI_MODE_SLAVE; #endif /* MASTER_BOARD */ if(HAL_SPI_Init(&SpiHandle) != HAL_OK) { /* Initialization Error */ Error_Handler(); } #ifdef MASTER_BOARD /* Configure User push-button */ BSP_PB_Init(BUTTON_USER, BUTTON_MODE_GPIO); /* Wait for User push-button press before starting the Communication */ while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET) { BSP_LED_Toggle(LED1); HAL_Delay(100); } BSP_LED_Off(LED1); /*##-2- MASTER : Start the Half Duplex Communication : TX ########################*/ /* Timeout is set to 5 seconds */ Errorcode = HAL_SPI_Transmit(&SpiHandle, (uint8_t*)aTxBuffer, BUFFERSIZE, 5000); Check_Error(Errorcode, TX); HAL_Delay(2000); /*##-3- MASTER : Start the Half Duplex Communication : RX ########################*/ /* Timeout is set to 5 seconds */ /* Disable SPI before changing direction */ __HAL_SPI_DISABLE(&SpiHandle); Errorcode = HAL_SPI_Receive(&SpiHandle, (uint8_t*)aRxBuffer, BUFFERSIZE, 5000); Check_Error(Errorcode, RX); #else /* SLAVE_BOARD */ /*##-2- SLAVE : Start the Half Duplex Communication : RX ########################*/ /* Timeout is set to 60 seconds to wait Push-Button press */ Errorcode = HAL_SPI_Receive(&SpiHandle, (uint8_t*)aRxBuffer, BUFFERSIZE, 60000); Check_Error(Errorcode, RX); /*##-3- SLAVE : Start the Half Duplex Communication : TX ########################*/ /* Timeout is set to 5 seconds */ /* Disable SPI before changing direction */ /* Transmission of the received buffer */ __HAL_SPI_DISABLE(&SpiHandle); Errorcode = HAL_SPI_Transmit(&SpiHandle, (uint8_t*)aRxBuffer, BUFFERSIZE, 5000); Check_Error(Errorcode, TX); #endif /* Infinite loop */ while (1) { } } /** * @brief This function is executed to test the transmission status * @param None * @retval None */ static void Check_Error (HAL_StatusTypeDef Errorcode, uint8_t Direction) { switch(Errorcode) { case HAL_OK: if (Direction == TX) { /* Turn LED1 on: Transmission complete */ BSP_LED_On(LED1); } else { if (Buffercmp((uint8_t *)aTxBuffer, (uint8_t *)aRxBuffer, BUFFERSIZE)) { /* Turn LED3 on : Transfer error in transmission process */ Error_Handler(); } else { /* Turn LED2 on: Reception complete */ BSP_LED_On(LED2); } } break; case HAL_TIMEOUT: /* Toggle LED3 : A timeout occur */ Timeout_Error_Handler(); break; case HAL_ERROR: /* Toggle LED3 on : An error occur */ Error_Handler(); break; default : break; } } /** * @brief This function is executed in case of timeout. * @param None * @retval None */ static void Timeout_Error_Handler(void) { /* Toggle LED3 */ while(1) { BSP_LED_Toggle(LED3); HAL_Delay(500); } } /** * @brief This function is executed in case of error occurrence. * @param None * @retval None */ static void Error_Handler(void) { /* Turn LED3 on */ BSP_LED_On(LED3); while(1); } /** * @brief Compares two buffers. * @param pBuffer1, pBuffer2: buffers to be compared. * @param BufferLength: buffer's length * @retval 0 : pBuffer1 identical to pBuffer2 * >0 : pBuffer1 differs from pBuffer2 */ static uint16_t Buffercmp(uint8_t* pBuffer1, uint8_t* pBuffer2, uint16_t BufferLength) { while (BufferLength--) { if((*pBuffer1) != *pBuffer2) { return BufferLength; } pBuffer1++; pBuffer2++; } return 0; } /** * @brief System Clock Configuration * The system Clock is configured as follow : * System Clock source = PLL (HSI) * SYSCLK(Hz) = 64000000 * HCLK(Hz) = 64000000 * AHB Prescaler = 1 * APB1 Prescaler = 2 * APB2 Prescaler = 1 * HSI Frequency(Hz) = 8000000 * PREDIV = RCC_PREDIV_DIV2 (2) * PLLMUL = RCC_PLL_MUL16 (16) * Flash Latency(WS) = 2 * @param None * @retval None */ void SystemClock_Config(void) { RCC_ClkInitTypeDef RCC_ClkInitStruct; RCC_OscInitTypeDef RCC_OscInitStruct; /* HSI Oscillator already ON after system reset, activate PLL with HSI as source */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_NONE; RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV2; RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL16; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK) { /* Initialization Error */ while(1); } /* Select PLL as system clock source and configure the HCLK, PCLK1 and PCLK2 clocks dividers */ RCC_ClkInitStruct.ClockType = (RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2); RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2)!= HAL_OK) { /* Initialization Error */ while(1); } } #ifdef USE_FULL_ASSERT /** * @brief Reports the name of the source file and the source line number * where the assert_param error has occurred. * @param file: pointer to the source file name * @param line: assert_param error line source number * @retval None */ void assert_failed(char* file, uint32_t line) { /* User can add his own implementation to report the file name and line number, ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ /* Infinite loop */ while (1) { } } #endif /** * @} */ /** * @} */ /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/