cancel
Showing results for 
Search instead for 
Did you mean: 

Reading AT command response

IDavo.1
Associate II

Hi,

I would like to read AT Command responses back from my ESP2866, as I want to check whether the response is "OK" or "Error". I made a function as below but it doesn't work properly.

The plan is to send AT commands on USART3 and right after that, receiving n expected bytes from USART3. Then, search into the received bytes for expected response ("OK" for example). If it was "OK", returning 'y' and if not 'n'.

It doesn't work properly, for example when I use "response = IMAN_USART_LookupForKeywordInReceivedDataInByteout(USART3 , buffer , sizeof(buffer) , keyword_to_search, byteout); " and the response is "OK", for the first time, the function returns 'y' and after that when I use " response = IMAN_USART_LookupForKeywordInReceivedDataInByteout(USART3 , buffer , sizeof(buffer) , keyword_to_search, byteout); " and the response is "ERROR", again the function returns 'y' while I expect 'n'.

It's making me crazy, I would really appreciate if someone help me with that.

char IMAN_USART_LookupForKeywordInReceivedDataInByteout(USART_TypeDef *USARTx , char *rx_buffer , int size_of_buffer , char *word, int byteout_cnt)
{
	static char keyword[50];
	static uint8_t char_counter;
	static uint8_t keyword_num_of_letters;
	static char *ret;
	static char return_value;
 
	if(!(LL_USART_IsEnabledIT_RXNE(USARTx)))
	{
                char_counter=0;
                return_value = 'n';
                keyword_num_of_letters = 0;
                ret = NULL;
                sprintf(keyword,word);
                 
                for(int i=0;i<sizeof(keyword);i++)
                {
                        if(keyword[i] != 0)
                        {
                               keyword_num_of_letters++;
                         }
                }
 
                for(int i=0;i<size_of_buffer;i++)
                {
                        rx_buffer[i]=0;
                }
                
                LL_USART_EnableIT_RXNE(USARTx);
 	}
 
	else
        {
               if(char_counter <= byteout_cnt)
               {
                       rx_buffer[char_counter++] = USARTx->DR;
               }
               else
               {
                        ret = strstr(rx_buffer, keyword);
 
                        if (ret != NULL)
                        {
                                for(int i=0;i<size_of_buffer;i++)
                                {
                                       rx_buffer[i]=0;
                                 }
                        
                                 char_counter = 0;
                                 return_value = 'y';
                         }
                         else
                         {
                                 for(int i=0;i<size_of_buffer;i++)
                                 {
                                        rx_buffer[i]=0;
                                 }
 
                                 char_counter = 0;
                                 return_value = 'n';
                          }
                  }
           }
 
	return return_value;
} 

3 REPLIES 3

The lack of formatting is not helping your case, but the thinking looks very muddled.

Use the </> icon to add a formatted code block.

What you need to do is turn the thinking on it head, and build a routine that accepts a byte at a time from the IRQHandler, adding it to an accumulated string, and process that once you have enough to inspect, ie you've seen CR/LF terminating the line.

For the code as it is, I'm pretty sure you can't check/enable interrupts, and expect the data to magically be available. You should perhaps do this in a polled mode, where you wait of RXNE in SR and then collect one byte from DR

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..
ryan rusty
Associate II

You should handle receiving USART one character at a time and build a circular buffer in the interrupt routine.

Don't re-invent things, I've used the library you'll find into:

C:\Users\yourname\STM32Cube\Repository\STM32Cube_FW_F7_V1.16.0\Projects\STM32F723E-Discovery\Applications\WiFi\Esp8266_IAP_Client

Take a look at esp8266.h/c and esp8266_io.h/c driver, it use USART Rx circular buffer and parse all ESP8266 "ok" "error" " /' sequence.

I've used in the pas with STM32L4 and F4 device to send data to Thingspeak.

It's very easy to adapt the driver for different device.

Thanks @Community member​  for really quick response. Yeah sorry my code was so unformatted.

I did what you said and now I added another function that helps to parse the received bytes and returns a char indicating whether the function has been successfully found the "OK" or not. Now the process is, sending AT command and then, by enabling the RXNE, waiting to receive data and accumulating those received bytes into a char buffer. The problem is, since each AT command depends on situation responds different amount of data, it's hard to find when to stop receiving and start parsing. Even CR/LF doesn't help that much since there are many CR/LF in between. Like this: "AT#CR#CR#LF#CR#LFOK#CR#LF".

Following is what that being used to first receive data and then parse data :

but still I have the terminator issue.

for (int j=0; j<=esp_config_attempt ;j++)
{
	IMAN_USART_TransmitString(USART3,"AT\r\n", 4);
	IMAN_USART_ReceiveCharIT(USART3, buffer, sizeof(buffer));
	usart_parsing_response = IMAN_USART_ParseReceivedBytes(buffer , sizeof(buffer) , "OK");
	if (usart_parsing_response == 'y')
	{
		sprintf(esp_config_status , "AT=>OK");
		break;
	}
	LL_mDelay(4000);
}
 
.
.
.
.
 
void IMAN_USART_ReceiveCharIT(USART_TypeDef *USARTx , char *rx_buffer , int size_of_buffer)
{
	static int char_counter;
 
	if(!(LL_USART_IsEnabledIT_RXNE(USARTx)))
	{
		char_counter = 0;
		for(int i=0;i<size_of_buffer;i++)
		{
			rx_buffer[i]=0;
		}
		LL_USART_EnableIT_RXNE(USARTx);
	}
	else
	{
		if((usart_parsing_response == 'y') || (char_counter >= size_of_buffer))
		{
			char_counter = 0;
			usart_parsing_response = 'n';
		}
 
		rx_buffer[char_counter++] = USARTx->DR;
	}
}
 
char IMAN_USART_ParseReceivedBytes(char *rx_buffer , int size_of_buffer , char *keyword)
{
	char return_value;
 
	if (strstr(rx_buffer, keyword) != NULL)
	{
		for(int i=0;i<size_of_buffer;i++)
		{
			rx_buffer[i]=0;
		}
		return_value = 'y';
	}
	else
	{
		return_value = 'n';
	}
 
	return return_value;
}

By the way I have enabled the RXNE interrupt and into its IRQHandler, I'm calling "IMAN_USART_ReceiveCharIT" function.