STM32F - SPI with DMA "ErrorCallback" and frames shifted - stm32

I am communicating 2 uC (an arduino display as MASTER and STM32F429 as slave).Its communication consists of 10 bytes in full duplex through SPI using DMA, every 150ms.
During some minutes the communication goes very good, both uC are sending their 10 bytes properly. During this time, I have noted that "HAL_SPI_ErrorCallback" function is called becasue I have added a counter within and it is increased little by little, but the comminication still goes well.
My first question is: Is it normal that sometimes ErrorCallback function is called randomly? due to noise or whatever the communication has an instantaneous error... I guess..
Here are a capture of the MISO signal in green, CLK in whie and CS in yellow
On the other hand, after a while (randomly 10 min, 1h ...) the communication is corrupted just in the MISO signal , the STM32 sends the 10 bytes frame but instead of sending Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 Byte9 Byte10, (LSB first)
it sends:
Byte10 Byte0 Byte1 Byte2 Byte3 Byte4 Byte5 Byte6 Byte7 Byte8 Byte9, IT IS MOVED TO RIGTH 1 byte!?!?
Attached you can see the capture "Working.jpg" with byte0 = 0x02 and the rest of the bytes = 0. In the other capture "NOT_working.jpg" is a capture with the problem. Both uC were working properly for a while and suddenly the STM32 uC started to send this frame all the time (the communication frame is byte = 0x02 and the rest of the bytes = 0 in order to see easily this error).
Working.jpg - which is MISO signal sending the frame properly
NOT_working.jpg - which is MISO signal sending the frame incorrectly
I have tried the communication in:
"Init.Mode = DMA_NORMAL" and "DMA_CIRCULAR", and both configuration have the same behaviour.
I have creaged the 2 variables in order to find out the problem:
DMA_counter_RX = __HAL_DMA_GET_COUNTER(&hdma_spi6_rx);
DMA_counter_TX = __HAL_DMA_GET_COUNTER(&hdma_spi6_tx);
And the the comunications goes well, DMA_counter_RX = 10 BUT DMA_counter_TX = 9. This values are normal. But as soon as the shift error occurs, both DMA counters are = 10.
Also this problem always happens in debug mode when I click on "suspend" (pause) and "resume"(play) as soon as I click on "resume" and the processor continues with the program, the MISO signal is shifted forever.
Additionally I am using TIM1, TIM5, TIM2, TIM3 and TIM4 for other things like PWM and interruptions but not related to SPI...
I have tried to solve this problem modifying all the NVIC priorities for all interruptions and so on but the problem get worst.
I am using System Workbench for STM32 latest version.
Any help is appreciate! Thanks in advance and best regards.
Alejandro
Sorry for long question... :(
Bellow you can see my configuration for SPI and DMA if it can help you:
void MX_DMA_Init(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();
HAL_NVIC_SetPriority(DMA2_Stream5_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream5_IRQn);
HAL_NVIC_SetPriority(DMA2_Stream6_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(DMA2_Stream6_IRQn);
}
void MX_SPI6_Init(void)
{
hspi6.Instance = SPI6;
hspi6.Init.Mode = SPI_MODE_SLAVE;
hspi6.Init.Direction = SPI_DIRECTION_2LINES;
hspi6.Init.DataSize = SPI_DATASIZE_8BIT;
hspi6.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi6.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi6.Init.NSS = SPI_NSS_HARD_INPUT;
hspi6.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi6.Init.TIMode = SPI_TIMODE_DISABLE;
hspi6.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi6.Init.CRCPolynomial = 10;
if (HAL_SPI_Init(&hspi6) != HAL_OK)
{
Error_Handler();
}
}
void HAL_SPI_MspInit(SPI_HandleTypeDef* hspi)
{
GPIO_InitTypeDef GPIO_InitStruct;
if(hspi->Instance==SPI6)
{
__HAL_RCC_SPI6_CLK_ENABLE();
/**SPI6 GPIO Configuration
PG8 ------> SPI6_NSS
PG12 ------> SPI6_MISO
PG13 ------> SPI6_SCK
PG14 ------> SPI6_MOSI
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_MEDIUM;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI6;
HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
hdma_spi6_rx.Instance = DMA2_Stream6;
hdma_spi6_rx.Init.Channel = DMA_CHANNEL_1;
hdma_spi6_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_spi6_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi6_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi6_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi6_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi6_rx.Init.Mode = DMA_NORMAL;
hdma_spi6_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_spi6_rx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi6_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmarx,hdma_spi6_rx);
hdma_spi6_tx.Instance = DMA2_Stream5;
hdma_spi6_tx.Init.Channel = DMA_CHANNEL_1;
hdma_spi6_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_spi6_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_spi6_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_spi6_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_spi6_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_spi6_tx.Init.Mode = DMA_NORMAL;
hdma_spi6_tx.Init.Priority = DMA_PRIORITY_MEDIUM;
hdma_spi6_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_spi6_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(hspi,hdmatx,hdma_spi6_tx);
/* Peripheral interrupt init */
HAL_NVIC_SetPriority(SPI6_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(SPI6_IRQn);
}
}
During initialization code, I configure SPI6 and DMA as it is described before, just after that I enable communication using:
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data, 10);
Also it were added the following 2 functions related to SPI communication:
void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data, 10);
}
}
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data,10);
}
}
STM cube mx automatically created:
void DMA2_Stream5_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream5_IRQn 0 */
/* USER CODE END DMA2_Stream5_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi6_tx);
/* USER CODE BEGIN DMA2_Stream5_IRQn 1 */
/* USER CODE END DMA2_Stream5_IRQn 1 */
}
/**
* #brief This function handles DMA2 stream6 global interrupt.
*/
void DMA2_Stream6_IRQHandler(void)
{
/* USER CODE BEGIN DMA2_Stream6_IRQn 0 */
/* USER CODE END DMA2_Stream6_IRQn 0 */
HAL_DMA_IRQHandler(&hdma_spi6_rx);
/* USER CODE BEGIN DMA2_Stream6_IRQn 1 */
/* USER CODE END DMA2_Stream6_IRQn 1 */
}
void SPI6_IRQHandler(void)
{
/* USER CODE BEGIN SPI6_IRQn 0 */
/* USER CODE END SPI6_IRQn 0 */
HAL_SPI_IRQHandler(&hspi6);
/* USER CODE BEGIN SPI6_IRQn 1 */
/* USER CODE END SPI6_IRQn 1 */
}
------------------------------EDITED----------------------------
I add 2 captures of the SPI register
SPI registers WORKING
SPI registers ERROR

I finally got the solution, I found what the problem was!
Usually, the CS signal goes from 1 to 0, then MISO and MOSI communicates, and once the communication finishes CS signal goes from 0 to 1, and the STM32F429 continues with the rest of the tasks...
This was happening every 150 ms, that's the period of thime both uC are communicating. But the STM32 uC has another tasks with more priority than SPI communication.
When one of this higher priority starts during SPI communication, and once this higher priority is done then the uC continues with the task was doing ( it was SPI), obviouslythis frame is lost and "HAL_SPI_ErrorCallback" is executed, and then SPI is restarted.If SPI is restarted when CS signal is 1, (spi idle), then there is no problem, SPI is restarted properly and the next frame will be received without problem. BUT if SPI is restarted when CS signal is 0 (STM32 SPI is selected and ready to communicate) then the STM32 is waiting to send and receive an amount of bytes but it will receives less, so an a mismatch of communication bytes is the key of the PROBLEM.
I have solved this issue just adding:
void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
{
if(hspi -> Instance == SPI6)
{
while(HAL_GPIO_ReadPin(GPIOG, GPIO_PIN_8) != GPIO_PIN_SET) // CS signal
{
}
HAL_SPI_TransmitReceive_DMA(&hspi6, (uint8_t*)HMI_slave_TX_data, (uint8_t*)HMI_slave_RX_data,10);
}
}
I have to modify "WHILE" in order to not stop the processor , but it is the first approximation.
Now the communication is working all the time, but some times a frame is lost (and " HAL_SPI_ErrorCallback" is called) due to higher priority task. But it is normal, a CRC is implemented to note that.
Thanks for helping me and support the support.
I hope this helps to other people.
Best regards.
Alejandro.

Related

Modify the example named UART_HyperTerminal_IT to enable UART reception interrupts on STM32F4?

I'm developing a project with STM32F4 and I need to enable the UART6 receive interrupt. I have used STM32CubeMX to enable the UART6 and in the STM32CubeMX I have enabled the NVIC USART6 global interrupt.
The example UART_HyperTerminal_IT
I have followed the example UART_HyperTerminal_IT which is installed by the package STM32Cube_FW_F4_V1.27.0.
The code is more recent but not so different from this example code.
I would like to modify the example to send back every character received from UART6 on the same UART6 (echo). So I have removed all the code of the example that sends data by the UART and wait data from the UART.
I have initialized the UART6 by the following code:
UartHandle.Instance = USART6;
UartHandle.Init.BaudRate = 115200;
UartHandle.Init.WordLength = UART_WORDLENGTH_8B;
UartHandle.Init.StopBits = UART_STOPBITS_1;
UartHandle.Init.Parity = UART_PARITY_NONE;
UartHandle.Init.HwFlowCtl = UART_HWCONTROL_NONE;
UartHandle.Init.Mode = UART_MODE_TX_RX;
UartHandle.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&UartHandle) != HAL_OK) {
/* Initialization Error */
Error_Handler();
}
The previous code is very similar to the example code (I have changed only baud rate and the parity).
My interrupt routine
I have defined the function USART6_IRQHandler in the file stm32f4xx_it.c as in the code below:
void USART6_IRQHandler(void) {
unsigned char ch;
uint32_t isrflags = READ_REG(huart6.Instance->SR);
uint32_t cr1its = READ_REG(huart6.Instance->CR1);
if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
huart6.Instance->SR;
ch = huart6.Instance->DR;
HAL_UART_Transmit(&huart6, &ch, 1, 1000);
}
HAL_UART_IRQHandler(&huart6);
}
In the readme file of the example I have found this sentence:
This example shows how to ensure UART Data buffer transmission and reception with
Interrupt.
The sentence says that in the example the Interrupt is enabled, but if I try to send data to the UART6 the interrupt routine USART6_IRQHandler() is not called.
I think that the UART6 Receive Interrupt is not enabled, but how can I enable it? Is there a specific bit in some register that must be set?
Thanks
This post on SO speak about this topic but I think is too old for my STM32F4.
This other post is old too.
Thanks to #pmacfarlane's comment I solved the problem of the lack of reception interrupts in the example UART_HyperTerminal_IT.
So I confirm that the only modification needed to obtain the echo of the characters receives from UART6 is the addition of the instruction huart6.Instance->CR1 |= USART_CR1_RXNEIE;.
Initialization of UART6 with reception interrupts enabled
So the initialization code for the UART6 becomes:
huart6.Instance = USART6;
huart6.Init.BaudRate = 115200;
huart6.Init.WordLength = UART_WORDLENGTH_8B;
huart6.Init.StopBits = UART_STOPBITS_1;
huart6.Init.Parity = UART_PARITY_NONE;
huart6.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart6.Init.Mode = UART_MODE_TX_RX;
huart6.Init.OverSampling = UART_OVERSAMPLING_16;
if(HAL_UART_Init(&huart6) != HAL_OK) {
/* Initialization Error */
Error_Handler();
}
// ---> enable reception interruptions
huart6.Instance->CR1 |= USART_CR1_RXNEIE;
Note. In the previous code I have substituted the variable UART_HandleTypeDef UartHandle used in the UART_HyperTerminal_IT example with the variable:
UART_HandleTypeDef huart6;
Interrupt routine implements echo
The code of the interrupt routine presented in the question remains exactly the same:
void USART6_IRQHandler(void) {
unsigned char ch;
uint32_t isrflags = READ_REG(huart6.Instance->SR);
uint32_t cr1its = READ_REG(huart6.Instance->CR1);
if (((isrflags & USART_CR1_RXNEIE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)){
huart6.Instance->SR;
ch = huart6.Instance->DR;
HAL_UART_Transmit(&huart6, &ch, 1, 1000);
}
HAL_UART_IRQHandler(&huart6);
}
The USART6_IRQHandler() function retrieves the received char and sends it immediately back implementing the echo of every char received.
While loop empty
That's all, the while(1) loop is completly empty:
while(1) {
// empty loop
}

Stm32f407 Uart Dma Multiple Array Tx

I tried to send Buffer from stm32f407 to terminal.Type is uint8_t and array is 15000. My code is works. but when i try to send 2 buffer like 5000 array, there is problem for second buffer. I use normal mode.What i should do to sending succesfully?
/* USART3 DMA Init */
/* USART3_TX Init */
hdma_usart3_tx.Instance = DMA1_Stream3;
hdma_usart3_tx.Init.Channel = DMA_CHANNEL_4;
hdma_usart3_tx.Init.Direction = DMA_MEMORY_TO_PERIPH;
hdma_usart3_tx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart3_tx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart3_tx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart3_tx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart3_tx.Init.Mode = DMA_NORMAL;
hdma_usart3_tx.Init.Priority = DMA_PRIORITY_VERY_HIGH;
hdma_usart3_tx.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
if (HAL_DMA_Init(&hdma_usart3_tx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(huart,hdmatx,hdma_usart3_tx);
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
void Send_Dataa(void)
{
HAL_UART_Transmit_DMA(wifi_uart, buf1, 5000);
HAL_UART_Transmit_DMA(wifi_uart, buf2, 5000);
}
If you check the return code from HAL_UART_Transmit_DMA(), you'll probably see it is returning HAL_BUSY. (Note you should always be checking the return codes from HAL functions.)
You'll need to wait until the first transmit is complete before starting the second transmit. You can use HAL_UART_GetState() to monitor the state of the UART.
The HAL does not chain together multiple DMA requests.

STM32 SPI slave mode doesn't transmit properly

I am using an STM32G030C8T6 as an SPI (Slave device) which receives characters from a Raspberry pi (Master device), receiving works perfectly! no problems there, however when i try to send data from STM32 to Pi, it seems that the STM32 gets stuck for a while and Pi rx buffer is filled with only one bit in repeat e.g., if i send char buf[6] = {0,1,2,3,4,5}; Pi receives (111111) or (333333) depending on how many characters i am sending.
What do i actually want to do?
I want to transmit ADC data from STM32(slave mode) to Pi(master mode), so far it only receives one bit i repeat.
Can someone please help me achieve this?
Here's my SPI config:
void MX_SPI1_Init(void)
{
/* USER CODE BEGIN SPI1_Init 0 */
/* USER CODE END SPI1_Init 0 */
/* USER CODE BEGIN SPI1_Init 1 */
/* USER CODE END SPI1_Init 1 */
/* SPI1 parameter configuration*/
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_SLAVE;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
hspi1.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi1.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI1_Init 2 */
/* USER CODE END SPI1_Init 2 */
}
then the functions to read characters, send data and string
char SPI_read(void)
{
// SPI1->SR is the STATUS REGISTER on SPI1 Bus
// SPI1->DR is the DATA REGISTER on SPI1 Bus
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
while(SPI1->SR & SPI_SR_BSY);
data = SPI1->DR;
printmsg("%c",data);
return data;
}
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
SPI1->DR = caracSend;
}
void spi_send_string(char* stringSend)
{
int i=0;
unsigned int sizeChar = 0;
sizeChar = strlen(stringSend);
__NOP();
for(i=0;i<sizeChar;i++)
{
spi_Send(stringSend[i]);
}
}
Here's my function to receive data from Pi which i call in the main while loop.
void SPI_Receive_Commands(void)
{
while(HAL_GPIO_ReadPin(SPI_SS_GPIO_Port, SPI_SS_Pin) == GPIO_PIN_RESET);
{
HAL_SPI_Receive(&hspi1, (uint8_t *)spi_buf, 10, 100);
if(spi_buf[0] == 'v')
{
memset(spi_buf,'*',10);
printmsg("Character V received\r\n");
Battery_Voltage();
spi_send_string(batteryVoltage);
spi_Send('v');
printmsg("Sending battery voltage\r\n");
}
}
}
Thank you so much for helping me out in advance.
Initialisation. You need set the RX FIFO threshold to 1/4 as you read and write bytes. I do not know how to do it in HAL. Register level simply set FRXTH bit in the CR2 register
DR register has to be accessed in 8 bits operations.
You do not need to use BSY bit in polling mode unless you want to disable the SPI peripheral.
void spi_Send(char caracSend)
{
while(!(SPI1->SR & SPI_SR_TXE));
*(volatile uint8_t *)&SPI1->DR = caracSend;
}
void spi_send_string(char* str)
{
if(str) while(*str) spi_Send(*str++);
}
char SPI_read(void)
{
char data;
while(!(SPI1->SR & SPI_SR_RXNE));
data = *(volatile uint8_t *)&SPI1->DR;
return data;
}
Remember that raspberry pi HAS TO send dummy data to allow slave to send information. Slave does not generate the clock signal and clock has to be supplied by the Master

STM32 spi receive procedure without hal

Good afternoon,
I am a newbie in the programing of stm32. Just working on a project, where is a serious problem with timing. Trying to implement FOC on the PMSM motor where I need to do a calculation in 50us loop, which is fast to communicate with angle sensor via SPI and HAL. Let me explain the situation.
I tried to work with HAL, but as I read everywhere and explored by myself: if you need speed put it away. So my plan is to use CubeMX to configure all necessary registers and read data directly from the register DR. One small thing, that sensor communicates with a 16-bit frame.
Code that I produce:
__HAL_SPI_ENABLE(&hspi3);
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //switch off the pin
hspi3.Instance->DR = 0;
while ((hspi3.Instance->SR & SPI_FLAG_RXNE) == 0){} //Wait for Data Ready to Read
RxData = hspi3.Instance->DR; //Read Data Register Directly
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); // switch on the pin
__HAL_SPI_DISABLE(&hspi3);
Configuration of spi periphery:
/**
* #brief SPI3 Initialization Function
* #param None
* #retval None
*/
static void MX_SPI3_Init(void)
{
/* USER CODE BEGIN SPI3_Init 0 */
/* USER CODE END SPI3_Init 0 */
/* USER CODE BEGIN SPI3_Init 1 */
/* USER CODE END SPI3_Init 1 */
/* SPI3 parameter configuration*/
hspi3.Instance = SPI3;
hspi3.Init.Mode = SPI_MODE_MASTER;
hspi3.Init.Direction = SPI_DIRECTION_2LINES;
hspi3.Init.DataSize = SPI_DATASIZE_16BIT;
hspi3.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi3.Init.CLKPhase = SPI_PHASE_2EDGE;
hspi3.Init.NSS = SPI_NSS_SOFT;
hspi3.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_8;
hspi3.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi3.Init.TIMode = SPI_TIMODE_DISABLE;
hspi3.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi3.Init.CRCPolynomial = 7;
hspi3.Init.CRCLength = SPI_CRC_LENGTH_DATASIZE;
hspi3.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
if (HAL_SPI_Init(&hspi3) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN SPI3_Init 2 */
/* USER CODE END SPI3_Init 2 */
}
In this state, it isn't working, has anyone idea how to solve this issue? Thank you
You have two mistakes:
First, you are reading the data register in the wait loop. You should have an empty loop that does nothing repeatedly until RXNE becomes 1, then read the data.
Second you don't do anything to trigger the clock. In master mode the clock starts when you write data for transmission. After driving the chip-select low, write something to DR:
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET); //switch off the pin
hspi3.Instance->DR = 0; // output something on MOSI while reading MISO
while ((hspi3.Instance->SR & SPI_FLAG_RXNE) == 0){} //Wait for Data Ready to Read
RxByte[0] = hspi3.Instance->DR; //Read Data Register Directly
HAL_GPIO_WritePin_Fast(GPIOD, GPIO_PIN_2, GPIO_PIN_SET); // switch on the pin

STM32F303 Discovery - USART_IT_RXNE Never recieve antyhing (No DMA/No HAL)

I'm very new to both C code, and the STM platform; Im using it for a school project.
I have two card communication via USART (Specifically USART3). The Sensor card (Slave)'s job is to only send their current distance measurement. I have managed to set this up.
Via Scope, using RS232/UART communication mode, I can see the hexe's being sent is "STX M 2 3 ETX"
Where the M is code for what kind of package it is, and the 2 and 3 is the hex 0x23 = 35 (cm). It sends a new measurement every 15ms.
Now to my problem. I cant seem to configure the Master's USART3 to recieve these packages.
This is my current code:
void USARTInit(void)
{
USART_InitTypeDef USART_InitStructure;
USART_ClockInitTypeDef USART_ClockInitStructure;
GPIO_InitTypeDef GPIO_InitStructure_UART,GPIO_InitStructure_UART_PD9;
//RCC_APB1Periph_AFIO;
//UART3 for communication with other STM (Master -> Slave / Master <- Slave)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
USART_ClockStructInit(&USART_ClockInitStructure);
USART_ClockInit(USART3, &USART_ClockInitStructure);
USART_InitStructure.USART_BaudRate = 9600; //115200; //19200;//57600;//19200; //9600;
USART_InitStructure.USART_WordLength = USART_WordLength_8b; //Word lenght, 8b = 8bit = 1byte
USART_InitStructure.USART_StopBits = USART_StopBits_1; //Num stoppbits
USART_InitStructure.USART_Parity = USART_Parity_No ; //USART_Parity_Odd;
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //Full duplex mode
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
USART_Init(USART3, &USART_InitStructure);
//GPIO pins configuration
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE); //UART3 + TIM4
GPIO_InitStructure_UART.GPIO_Pin = GPIO_Pin_8;
GPIO_InitStructure_UART.GPIO_Mode = GPIO_Mode_AF; //Alternative func, here UART
GPIO_InitStructure_UART.GPIO_Speed = GPIO_Speed_Level_1;
GPIO_InitStructure_UART.GPIO_OType = GPIO_OType_PP; //PushPull
GPIO_Init(GPIOD, &GPIO_InitStructure_UART); //Tx - Transmit
GPIO_PinAFConfig(GPIOD, GPIO_PinSource8, GPIO_AF_7); //GPIO_AF_7 -> U(S)ART mode
GPIO_InitStructure_UART.GPIO_Pin = GPIO_Pin_9;
GPIO_InitStructure_UART.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure_UART.GPIO_PuPd = GPIO_PuPd_NOPULL;
GPIO_Init(GPIOD, &GPIO_InitStructure_UART); //Rx - Recieve
GPIO_PinAFConfig(GPIOD, GPIO_PinSource9, GPIO_AF_7);
USART_Cmd(USART3, ENABLE);
USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitTypeDef nvicStructure; //Create a "extern" interupt base
nvicStructure.NVIC_IRQChannel = USART3_IRQn; //Link it to the global interupt of usart3
nvicStructure.NVIC_IRQChannelPreemptionPriority = 0; //Unsure
nvicStructure.NVIC_IRQChannelSubPriority = 0; //The priority of this interupt if you have other external interupts
nvicStructure.NVIC_IRQChannelCmd = ENABLE; //enables it
NVIC_Init(&nvicStructure); //Sends it to the Interupt handler
}
And my Handler code is :
void USART3_IRQHandler(void)
{
volatile uint16_t temp;
if (USART_GetITStatus(USART3, USART_IT_RXNE) != RESET)
{
temp = USART_ReceiveData(USART3) & 0xff; //0xFF ??? From datasheet
USART_ClearITPendingBit(USART3, USART_IT_RXNE);
}
**CODE TO COUNT BINARY USING 7 DIODEs**
}
The problem seems to be the USART_ReceiveData(USART3), if I remove is I see that all the diodes are on constantly meaning something must must be going through this code over and over very quickly , but if I leave like it is, the first light turns on (ie first iteration) then nothing happens. Using my computer and adding a breakporints in the handler shows the temp variable always being empty. It only runs once then nothing. I suspect that a flag isnt being propely handled so Ive tried... some solutions.
//USART_ClearITPendingBit(USART3,USART_IT_ORE);
//USART_ClearITPendingBit(USART3, USART_IT_LBD);
//USART_ClearITPendingBit(USART3, USART_IT_CTS);
//USART_ClearITPendingBit(USART3, USART_IT_TC);
I had this code earlier but it made no difference.
Ive been trying now for 2 days to figure out whats wrong, but Im no closer than I was at the start.
Ive tried googling it and have countless of different answers, but I cant ssem to find any that fixes my issue. Im sorry if the solution super obvious...