2024-01-15 04:42 AM
Hello guys. I'm fairly new to stm and i've mostly worked on a pico.
The thing is that i want to create a programm with the following function.
The user sends a character and then a string from a python app on my pc. The first character is a pseudo handshake, meaning that if the received character is lets say 'A', the stm should store the string on a buffer array and print it.
I've implemented this program by using the get_char function on the pico. Can i implement this on an stm by using something similar or do i have to use multiple instances of the HAL_UART_RECEIVE_IT function , since i also want the super loop to also implement an adc reading, and the HAL_UART_RECEIVE is blocking ?
2024-01-15 05:31 AM - edited 2024-01-15 06:00 AM
Hi,
> I'm fairly new to stm and i've mostly worked on a pico.
No basic difference there, some have even same core (M0+ afair).
> or do i have to use multiple instances of the HAL_UART_RECEIVE_IT function
Not multiple - just one.
>and the HAL_UART_RECEIVE is blocking ?
Right. So use the interrupt version...blocking is a bad idea, when the cpu should do anything else. :)
I do it this way :
set in Cube the uart (port, speed etc.) and enable INT and callback for it.
(generate code..)
Then in program just start it :
HAL_UART_RegisterCallback(&huart7, HAL_UART_RX_COMPLETE_CB_ID, HAL_UART_RxCpltCallback);
HAL_UART_RegisterCallback(&huart7, HAL_UART_ERROR_CB_ID, HAL_UART_ErrorCallback);
// prepare ...error might happen..
fresult = HAL_UART_Init(&huart7);
HAL_UART_Receive_IT(&huart7, ESP_RX, 1); // set receive 1 char -> to buf , 120 char. max
and do with the received char (analyze...whatever) in callback function :
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
ESP_RX_COUNT ++;
if(ESP_RX_COUNT>180) ESP_RX_COUNT=0 ; // limit overflow !
else if(ESP_RX[ESP_RX_COUNT-1]==0x0A) // \n = string end found
{
if (ESP_RX_LINE==0) // string end found + can copy
{
ESP_RX_LINE = ESP_RX_COUNT;
strncpy(ESP_RXb, (char *)ESP_RX, ESP_RX_COUNT); // copy to buffer
ESP_RX_COUNT = 0; // ready for new string receive
}
else
printf("string overflow ESP_rx %d \n ",ESP_RX_COUNT); // string end found + can NOT copy
}
HAL_UART_Receive_IT(&huart7, &ESP_RX[ESP_RX_COUNT], 1); // set receive for next 1 char. on INT
}
-> here i copy on a string "end" (0x0A ) the complete string , set global (volatile !!) marker ( ESP_RX_LINE = we have a string now) and prepare wait for next .
And for an error - that might happen on remote things... i just kick it away:
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{ testvari++;
printf("testvar hex %ld \n ",testvari); // error count debug info
// shiit happens...
HAL_UART_Receive_IT(&huart7, &ESP_RX[ESP_RX_COUNT], 1);// go on , set receive buf to 120 char. max
}
2024-01-15 09:59 AM
@AScha.3 wrote:do with the received char (analyze...whatever) in callback function
Remember that the callback is called from within the ISR - so not a good idea to be doing things like printf in the callback!
2024-01-15 10:14 AM - edited 2024-01-15 10:16 AM
Right!
But this printf only on/after error -> SWV debug message ( at 15 Mbit speed i have it);
so no microsecond wasted in normal program flow. :)
+ only some us on error , for info message.
2024-01-17 01:29 AM
In the end i tried something like this and it seems to work
while (1)
{
if (HAL_UART_Receive(&huart3, &getChar, 1, 1000) == HAL_OK && (getChar==73) )
{
if (HAL_UART_Receive(&huart3, messagerx, 3, HAL_MAX_DELAY) == HAL_OK)
{
printf("Command is = %d, %d, %d\r\n", messagerx[0], messagerx[1], messagerx[2]);
}
else
{
printf("error\r\n");
}
}
}
The first if makes sure that the stm receives the specific character and if it does, it receives the string and stores it into an array. I'll try to find the best possible timeout for the first uart_receive, so that it wont affect the rest of the program.
2024-01-17 02:03 AM
If it works for you, that's great.
But note that this method means your system is blocked from doing anything else at all for possibly as long as HAL_MAX_DELAY...
It also assumes that the remote system sends only while this code is "listening" ...
@AlexandrosAA wrote:
if (HAL_UART_Receive(&huart3, &getChar, 1, 1000) == HAL_OK && (getChar==73) )
Rather than the Magic Number 73, would be better style to write 'I' - or give it a meaningful symbolic name...
2024-01-17 02:45 AM
What would the best way to implement this through the interrupts be ?
Also, what is the best way to detect when a connection is established between the pc and your stm? Ise there a function available or should i implement a pseudo handshake ?
2024-01-17 03:00 AM
@AlexandrosAA wrote:What would the best way to implement this through the interrupts be ?
Again, the same way you'd do it on any microcontroller.
The classic way is to have your receive interrupt just fill a circular buffer (aka ring buffer), and handle processing the received data in your main loop.
@AScha.3 showed an example where the interpretation is done in the ISR.
@AlexandrosAA wrote:Also, what is the best way to detect when a connection is established between the pc and your stm?
That all depends on the nature of your system - again, not specific to STM32 or PC.
Is it just a plain UART connection, or USB?
With USB, there would be status to show when you're connected;
With just a plain UART connection, you would have to implement some sort of handshake.
2024-01-17 03:11 AM
I'm currently using the usart interface, which is connected to the onboard st-link.
What libraries do ia have to include in order to use the aforementioned status ?
2024-01-17 03:19 AM
So, as far as your STM32 is concerned, it's just a plain UART connection.
You will have to devise a handshake mechanism of your own, so suit your particular requirements.