In this example, the SPI is configured to have communication in master mode, full-duplex with an eeprom memory, enable writing and reading of data in it. Since the SPI communication always will transmit a data when receive and vice-versa, there is a special function to take care of the information send and received, HAL_SPI_TransmitReceive
it is necessary to specify both buffers for Tx and Rx and the number of transactions to perform.
#include "bsp.h"
SPI_HandleTypeDef SpiHandle; /*Structure to handle SPI*/
GPIO_InitTypeDef GPIO_InitStruct; /*Structure to init GPIOs*/
uint8_t RxBuffer[5];
uint8_t TxBuffer[4];
int main(void)
{
HAL_Init(); /*Library Initialization*/
__GPIOD_CLK_ENABLE(); /*Enable port D clock*/
GPIO_InitStruct.Pin = GPIO_PIN_9; /*CS pin to start/finish SPI transmition */
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; /*Output push-pull Type */
GPIO_InitStruct.Pull = GPIO_NOPULL; /*Pin without pull-up or pull-down */
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; /*Pin in low speed */
/*Initialize pins with the previous parameters*/
HAL_GPIO_Init( GPIOD, &GPIO_InitStruct );
/*Ensures slave is disabled pin D9 high*/
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, SET );
/*Configuration of SPI in master mode, Full-Duplex communication, Clock polarity in Low,
clock phase in rising edge and CLK frecc of 4 MHz*/
SpiHandle.Instance = SPI1;
SpiHandle.Init.Mode = SPI_MODE_MASTER;
SpiHandle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_4;
SpiHandle.Init.Direction = SPI_DIRECTION_2LINES;
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.NSS = SPI_NSS_SOFT;
SpiHandle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLED;
SpiHandle.Init.TIMode = SPI_TIMODE_DISABLED;
/*Apply configuration to SPI1*/
HAL_SPI_Init( &SpiHandle );
/*Enable writing instructions in the eeprom memory by sending a 0x06*/
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, RESET );
TxBuffer[0] = 0x06; /*WREN Instruction value*/
HAL_SPI_Transmit( &SpiHandle, TxBuffer, 1, 500 );
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, SET );
/*Send to write the value 0x35 in the address 0x0000 of the memory*/
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, RESET );
TxBuffer[0] = 0x02; /*Write instruction */
TxBuffer[1] = 0x00; /*16 bit - address */
TxBuffer[2] = 0x00; /*16 bit - address */
TxBuffer[3] = 0x35; /*Data byte */
HAL_SPI_Transmit( &SpiHandle, TxBuffer, 4, 500 );
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, SET );
/*Wait for the data to be recorded in memory, it is not the best way to
do it, so it's just for demonstration purposes*/
HAL_Delay( 5 );
/*Read a byte from direccion 0 of eeprom memory, TransmitReceive() Function needs as parameters structure
to handle SPI , buffer where data to transmit is stored, buffer where data received is stored, total amount
of bytes to transmit and receive, value of timeout to accomplish transmision*/
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, RESET );
TxBuffer[0] = 0x03; /*Read instruction*/
TxBuffer[1] = 0x00; /*16 bit - address */
TxBuffer[2] = 0x00; /*16 bit - address */
/*Instead of calling Transmit and then Receive functions we can use only one function to perform
both operations*/
HAL_SPI_TransmitReceive( &SpiHandle, TxBuffer, RxBuffer, 4, 500 );
HAL_GPIO_WritePin( GPIOD, GPIO_PIN_9, SET );
while (1)
{
}
}
msps.c
/*This function will be called inside the HAL_SPI_Init function*/
void HAL_SPI_MspInit( SPI_HandleTypeDef *hspi )
{
/* pins D8, D6 and D5 in alternate function spi1 for CLK, MOSI and MISO*/
GPIO_InitTypeDef GPIO_InitStruct;
__GPIOD_CLK_ENABLE();
__SPI1_CLK_ENABLE();
GPIO_InitStruct.Pin = GPIO_PIN_8 | GPIO_PIN_6 | GPIO_PIN_5; /*Function of pin: CLK , MOSI , MISO */
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; /*Alternate Function mode for pins*/
GPIO_InitStruct.Pull = GPIO_PULLUP; /*Pull-Up activation for selected pins*/
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; /*High speed selected for pins*/
GPIO_InitStruct.Alternate = GPIO_AF1_SPI1; /*Alternate function for selected pins*/
HAL_GPIO_Init( GPIOD, &GPIO_InitStruct );
}