2020-10-18 02:49 AM
Hi all, how are you?. I'm doing a program where I need to send several separated messages over the serial port using the UART 1 of a STM32F401VE after receiven a specific message through the serial port too, right now I'm capable of send the first rsponse message without problem using HAL_UART_Transmit_IT(...), the problem that I have here is that I need to wait for a complete transfer before sending the new one but as the IT function is not blocking (this is one of many things the code will do) then I used the function HAL_UART_GetState() to check if the transfer was completed, the GetState function didn't work because the Transmit_IT() function establish the state as HAL_OK just after finish the configuration of the port and the related interrupt.
After that I looked into the examples included at the HAL library for the STM32F4 discovery and the developers used the following definition
UART_HandleTypeDef UartHandle;
__IO ITStatus UartReady = RESET;
then they send the message by using
if(HAL_UART_Transmit_IT(&UartHandle, (uint8_t*)aTxBuffer, TXBUFFERSIZE)!= HAL_OK)
{
Error_Handler();
}
and the program waits for the transfer to complete with the following code
/*##-3- Wait for the end of the transfer ###################################*/
while (UartReady != SET)
{
}
and they have all the definitions in the main.c file. In my code then I've instantiatde the UART_HandleTypeDef in usart.c and then I declare the following in main.c
extern UART_HandleTypeDef huart1;
__IO ITStatus UartReady = RESET;
most of my response code is inside the function HAL_UART_RxCpltCallback(...) and is the following
strcpy(mEnviar, "vis emer1,1");
sendCommand((char *) mEnviar);
// while (UartReady != SET)
// {
// }
while(HAL_UART_STATE_READY != HAL_UART_GetState(&huart1))/* Aquí debe ir el */
{ /* comando de comprobación de la mensaje */
/* recibido y espera a que se envíe el */
} /* mensaje completo de envío para poder
* enviar otro mensaje. */
// memset(mEnviar, 0, Long_Rec);
// strcpy(mEnviar, "emer1.txt=");
// strcpy(mEnviar,"Restantes: ");
// strcpy(mEnviar,(char *) ('0' + claveIntentos));
// sendCommand((char *) mEnviar);
The function sendCommand(...) works without problem but as you can see in the commented lines after the first sendCommand(...) above I need to send another message but if I don't wait for the first sendCommand(...) to finish the transfer then the following sendCommand(...) starts to send the next message before the first message was sended and the disaster occurs.
the sendCommand(...) function is the following
void sendCommand(char *cmd) /*Envía comando con la terminación */
{ /*para que la pantalla la reconozca. */
static uint8_t cEnviar[Long_Rec] = {0};
sprintf((char *) cEnviar, "%s\xFF\xFF\xFF\xFF", cmd);/* Solo se deben */
/* enviar tres \xFF pero no se por qué el
* macro no está enviando el último. */
nexSerialE(cEnviar);
}
and nexSerialE(...) is a macro with the following content (I'm adapting a library for Arduino to STM32 devices too)
#define nexSerialE(a) HAL_UART_Transmit_IT(&nexSerial1, a, strlen((char *) a))
the __IO definition that the developers used in their example code doesn't works with my code in the way that I defined it so I think I'm doing something wrong here but I don't know what it is. If you see two pieces of code above I have both options to wait for the transfer, one with UartReady (commented) and another with GetState (the active right now), both options mantains the code stuck in that line of code and the message is not sent if I use them (I don't know why).
I know that I can put a custom flag inside the function HAL_UART_TxCpltCallback(...) and set it when the trnasfer completes but is not clear to me if doing that will be the correct implementation or If I must use the blocking HAL_UART_Transmit(...) to send the message because the problem with the last one is precisely that is blocking and it can stop another process.
How can I solve this problem?.
Thanks in advance for the help.
Solved! Go to Solution.
2020-10-18 07:57 AM
The code you posted is segmented and it's a bit hard to understand precisely what you're doing. But here's my guess:
> most of my response code is inside the function HAL_UART_RxCpltCallback(...) and is the following
HAL_UART_RxCpltCallback is called in an interrupt context. In order for the state to change, the interrupt needs to fire, and it can't do so because it's already in that interrupt.
You'll need to wait for the state to change within the main loop.
2020-10-18 07:57 AM
The code you posted is segmented and it's a bit hard to understand precisely what you're doing. But here's my guess:
> most of my response code is inside the function HAL_UART_RxCpltCallback(...) and is the following
HAL_UART_RxCpltCallback is called in an interrupt context. In order for the state to change, the interrupt needs to fire, and it can't do so because it's already in that interrupt.
You'll need to wait for the state to change within the main loop.
2020-10-18 06:22 PM
Thanks for your answer @TDK , I realized that about two hours after publish the original post, for that time I didn't remember that the CplTCallback was called inside the ISR of the USART, now is working.
Can you make me the favor of explain me the following line of code:
__IO ITStatus UartReady = RESET;
I couldn't understand that part of the example.
Thanks again for the help.
NOTE: the segmented code was because I published only the relevant parts.
2020-10-18 07:36 PM
I'm guessing you are looking at this example:
UartReady is used as a flag to indicate the transfer is complete and the code can continue on to the next segment. It's set to SET in the Tx/Rx complete callback functions and then to RESET in the main loop. The __IO expands to "volatile" which makes the mcu reload it from memory each time. ITStatus is basically just a boolean value.
2020-10-23 08:56 PM
Sorry for the delay @TDK and thanks again for your help.