cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART Receive Problem

Kuttay
Associate III

Hi, I am using STM 32 STLINK-V3. Thereis a problem with following UART receiver function. 

 

	__HAL_UART_CLEAR_FLAG(&huart5, UART_CLEAR_NEF|UART_CLEAR_OREF);
	HAL_UART_Receive(&huart5, rx_buffer, ROVER_MSG_LEN, 1000);




	 __HAL_UART_DISABLE_IT(&huart5,UART_IT_RXNE);

 

. Without clearing the flag rx_buffer remains empty even though there is a data observed from hardware with oscilloscope. I stept into the function and see flag remains up constantly but now only varying few initial bits of the buffer gets the data still rest remians empty. Is this a bug does any one knows ? 

12 REPLIES 12

Please give details of your hardware setup:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

 


@Kuttay wrote:

there is a data observed from hardware with oscilloscope. 


Show on your schematic where you observe that

There's been a lot of "UART can't receive" threads lately; eg,

https://community.st.com/t5/stm32-mcus-boards-and-hardware/i-cannot-receive-data-while-using-usb-to-uart-for-nucleo-f411re/m-p/690154

 

PSure, I am using two gnss which are ZED-FP9P-04B-01. They are connected to STM32H735IGKx and uart5 is used. I am attaching the pin diagram.  This is how I tried to take the data as rx_buffer.

static void tcpsend_thread (void *arg)
{

	MX_UART5_Init();
	while (1)
		{
		  TickType_t xLastWakeTime = xTaskGetTickCount();
		//rx_buffer[1]=1;
		//tcpsend(rx_buffer[1]);
		osDelay(1000); //2000 or 5000

		// Enter task section
		 //__disable_irq();

	  //  UART reception
	//	__HAL_UART_ENABLE_IT(&huart5,UART_IT_RXNE); // Exit critical task section
//		__HAL_UART_CLEAR_IT(&huart5, UART_CLEAR_NEF|UART_CLEAR_OREF);
//		HAL_UARTEx_ReceiveToIdle_IT(&huart5, rx_buffer, ROVER_MSG_LEN);
		__HAL_UART_CLEAR_FLAG(&huart5, UART_CLEAR_NEF|UART_CLEAR_OREF);
		HAL_UART_Receive(&huart5, rx_buffer, ROVER_MSG_LEN, 10000);
//		HAL_UART_Receive_IT(&huart5, rx_buffer, ROVER_MSG_LEN);



	 __HAL_UART_DISABLE_IT(&huart5,UART_IT_RXNE);


		//ulTaskNotifyTake(pdTRUE , portMAX_DELAY);

			if (g_rxSize <= 0)
				continue;
			//__HAL_UART_ENABLE_IT(&huart5,UART_IT_RXNE); // Exit critical task section

			int i;
			int j;
			volatile int len_gpgga=0;
			volatile int len_gpgst=0;
			for(int x=1;x<ROVER_MSG_LEN; x++){
				if(rx_buffer[x]==0x24){
					len_gpgga=x;

					for(int y=len_gpgga; y<ROVER_MSG_LEN;y++){
						if(rx_buffer[y]==0xB5){
							len_gpgst=y- len_gpgga;

							break;
						}
					}
					break;
				}

			}


			for(i=0; i<ROVER_MSG_LEN; i++){

				if (rx_buffer[i] == 0x24 && rx_buffer[i+1] == 0x47){
								 if (rx_buffer[i+3] == 0x47 && rx_buffer[i+4]== 0x47 ){
									 if(rx_buffer[i+5]== 0x41){

												memcpy(&gpgga, &rx_buffer[i], len_gpgga);
												gpgga[2]= 'P';


									 }
								 }
				}
				if (rx_buffer[i] == 0x24 && rx_buffer[i+1] == 0x47){
											 if (rx_buffer[i+3] == 0x47 && rx_buffer[i+4]== 0x53 ){
												 if(rx_buffer[i+5]== 0x54){
															 // Packet is valid, copy the data
															memcpy(&gpgst, &rx_buffer[i], len_gpgst);
															gpgst[2]= 'P';


												 }
											 }
							}
				if(rx_buffer[i] == 0xB5){

					if(rx_buffer[i+1] == 0x62){

						if(rx_buffer[i+2] == 0x01){

							if(rx_buffer[i+3] == 0x3c){

								if (rx_buffer[i+4] == 64){

									uint8_t calculatedCK_A = 0;
									uint8_t calculatedCK_B = 0;

								for (j = i+2; j < i+72 - 2; j++)
									{
										calculatedCK_A += rx_buffer[j];
										calculatedCK_B += calculatedCK_A;
									}

									if (calculatedCK_A == rx_buffer[i+72 - 2] && calculatedCK_B == rx_buffer[i+72 -1])
									{
										memcpy(&zedf9pData, &rx_buffer[i+6], sizeof(ZEDF9P_Data));


										uint8_t message[100];

										sprintf(message,"$GPHDT,%lu,T",zedf9pData.relPosHeading);
										int crc = nmea_checksum(message);
										sprintf(message+strlen(message),"*%X\r\n",crc);
										 sys_arch_sem_wait(&tcpsem, 500);
										 memset(rx_buffer, 0, sizeof(rx_buffer));



										 for (int e = 0; e<len_gpgst;e++){
											 merged[e] = gpgst[e];
										 }
										 for (int e = 0; e<300;e++){
											 merged[e+len_gpgst] = message[e];
										 }


										if (gpgga[3]=='G'){
											tcpsend(gpgga);
											osDelay(200);
											if (merged[3]=='G'){
												tcpsend(merged);
												osDelay(200);
											}

										}



										memset(gpgga, 0, sizeof(gpgga));
										memset(gpgst, 0, sizeof(gpgst));
										memset(message, 0, sizeof(message));

										break;

									}
								}
							}
						}
					}
				}
			}

	vTaskDelayUntil(&xLastWakeTime, 1000);


}

}

Please show a schematic - #3 in the guidelines:

https://community.st.com/t5/community-guidelines/how-to-write-your-question-to-maximize-your-chances-to-find-a/ta-p/575228

 


@Kuttay wrote:

I am using two gnss which are ZED-FP9P-04B-01. They are connected to STM32H735IGKx and uart5 is used.  


So how do you connect two GNSS units to one UART ?
The pin list doesn't show this (even if it were legible) - that's why you need to give a schematic.

 

>So how do you connect two GNSS units to one UART ?

THIS is a really good question... :)

How about: having two (expensive) GPS , giving EACH a serial / uart connection?

H735 has more than one uart - for free. :)

 

 

If you feel a post has answered your question, please click "Accept as Solution".

The pin diagram isn't at a usable resolution.

This honestly is a mess, there are much better ways to do stream processing of data, especially NMEA/UBX streams from a GNSS Receiver.

The arbitrary buffer read from the serial is a problem, the content isn't likely to be aligned to your request, and the request blocks execution. Should really have some buffering via interrupt so the processing is not expected to occur within one byte's time.

Look at what HAL_UART_Receive() returns for an error/status code, and if it's not functioning check the UART register states to see why its not accepting new data that you can see on the wire.

Going off and doing TCP sends and delaying for 100's milliseconds is not conducive to catching continuous streams of data from a serial port in real time.

Would start by recommending using interrupts to acquire and queue/buffer received data, in its own thread/context, and then consume that data in this thread

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
  • You should not be using HAL_UART_Receive_IT  inside a while loop.
  • You're doing a lot of unnecessary byte comparison when you're working with strings. Just do a string comparison using strncmp 

 

See this project https://github.com/karlyamashita/Nucleo_G431RB_GNSS_12_Click/wiki

It'll queue each message using HAL_UART_Receive_IT by looking for the CR/LF. Then you can parse the messages in a polling routine. When you find the specific NMEA message, you can tokenize each parameter since you'll know what parameters there will be available. It also validates the checksum. 

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

Can you connect the specified uart to a ttl to usb converter and see if it transmit to the specified uart5 pins. Use any terminal emulator on computer. Same say you can type in some characters and see if receive works.  Receive is level sensitive. 

If you feel a post has answered your question, please click "Accept as Solution".

One of them works as base while the other one is act as rover. These two gnss are connected to each other with uart2 but final data is taken from uart5. Taking these datas seperately breaks the rover base method and decrease the efficiency and increase the error rate of the taken data. I need nearly absolute data and the algorithm does that through uart 2.

Thanks I currently trying the method you recomment but still some bugs and errors occur. I am checking them. With HAL_UART_Receive I could only get one byte of data once. I believe it is because of a flag bug which I am working on.