The master always controls the clock. In the most basic SPI implementation, the master clocks 8 times and the slave outputs a single byte. If the slave has more output, the master must ask for it.
It is possible to have an external interrupt that the slave triggers when it has data for the master, but again the master controls the clock and must clock the data out of the slave. But this only works if the master supports such an interrupt, which the FT232H does not.
This works in main of the master-board:
SPI2_MOSI (PC3) to SPI2_MOSI (PC3)
SPI2_NSS (PB12) to SPI2_NSS (PB12)
SPI2_SCK (PB10) to SPI2_SCK (PB10)
Termainalprogram running on each PC connected to each board. Baud:115200,
No-parity, CTS/RTS
void MX_NVIC_Init(void)
{
/* USART2_IRQn interrupt configuration */
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);
}
/* SPI2 init function */
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_MASTER;
hspi2.Init.Direction = SPI_DIRECTION_2LINES;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_OUTPUT;
hspi2.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi2);
__HAL_SPI_ENABLE(&hspi2);
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
__HAL_UART_HWCONTROL_RTS_ENABLE(&huart2);
}
On stm32f4xx_it.c for the master
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
uint8_t data1;
HAL_UART_Receive_IT(&huart2,&data1,sizeof(data1));
data1++; //Icrementing 'A' to 'B'
HAL_SPI_Transmit(&hspi2,&data1, (uint16_t)sizeof(data1),HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2,&data1,(uint16_t)sizeof(data1),HAL_MAX_DELAY);//echoing back to PC
}
On the slave side in main
void MX_NVIC_Init(void)
{
HAL_NVIC_SetPriority(SPI2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(SPI2_IRQn);
__HAL_SPI_ENABLE_IT(&hspi2, SPI_IT_RXNE);
HAL_NVIC_SetPriority(USART2_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART2_IRQn);
__HAL_UART_ENABLE_IT(&huart2,UART_IT_RXNE);
__HAL_UART_HWCONTROL_RTS_ENABLE(&huart2);
}
/* SPI2 init function */
void MX_SPI2_Init(void)
{
hspi2.Instance = SPI2;
hspi2.Init.Mode = SPI_MODE_SLAVE;
hspi2.Init.Direction = SPI_DIRECTION_2LINES_RXONLY;
hspi2.Init.DataSize = SPI_DATASIZE_8BIT;
hspi2.Init.CLKPolarity = SPI_POLARITY_HIGH;
hspi2.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi2.Init.NSS = SPI_NSS_HARD_INPUT;
hspi2.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi2.Init.TIMode = SPI_TIMODE_DISABLE;
hspi2.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi2.Init.CRCPolynomial = 10;
HAL_SPI_Init(&hspi2);
__HAL_SPI_ENABLE(&hspi2);
}
/* USART2 init function */
void MX_USART2_UART_Init(void)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_RTS;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
HAL_UART_Init(&huart2);
__HAL_UART_HWCONTROL_RTS_ENABLE(&huart2);
}
In slave stm32f4xx_it.c
void SPI2_IRQHandler(void)
{
HAL_SPI_IRQHandler(&hspi2);
uint8_t data1;
HAL_SPI_Receive_IT(&hspi2,&data1,sizeof(data1));
HAL_UART_Transmit(&huart2,&data1,(uint16_t)sizeof(data1),HAL_MAX_DELAY);
}
void USART2_IRQHandler(void)
{
HAL_UART_IRQHandler(&huart2);
uint8_t data1;
HAL_UART_Receive_IT(&huart2,&data1,sizeof(data1));
data1++;
HAL_UART_Transmit(&huart2,&data1,(uint16_t)sizeof(data1),HAL_MAX_DELAY);
}
Best Answer
No, with SPI, all communications are driven by the master device. You are correct that the master cannot simply provide a continuous clock; there would be no way to detect the byte boundaries.
A slave device will often have a separate output pin to signal to the master that it has data available. This pin is connected to an input on a microcontroller and is often used as an interrupt.
Then, the device can assert the pin, causing the microcontroller to spin up the SPI bus.
For more detailed information, please read on :) This is a slightly-modified version of an explanation found here:
That describes the general case. There can be additional complexities. For example, some slave ICs will actually output some sort of status byte at the same time they are receiving a command from the master. So, in this case, the master shouldn't discard the first received byte.