cancel
Showing results for 
Search instead for 
Did you mean: 

Sending AT command to esp8266 using stm32F103 through usart

SIDRI.1
Associate III

0693W00000BZddpQAD.jpgi'm trying to communicate with a Wifi module (esp8266) using STM32F103, on keil IDE. As described in the schematic : i want making my stm32 send AT command to esp8266 through usart1 (Tx1), and getting the esp response (Rx1), then display the esp response on computer serial monitor using usart2 ( Tx2).

After configuring usart1 and usart2, and writing the functions to send an receive data, i'm getting only the ECHO of the command, rather than the response which should be "OK"

 . when i'm sending "AT\r\n", i'm receiving only AT on serial monitor. i will share the code i have wrote, and the traces on logic analyzer. if there is any suggestion i will be thankful.

0693W00000BZdduQAD.png0693W00000BZde4QAD.png

 int len=0;
char buff[256];
 
int main(void){
    
     __disable_irq();
    
    
    systick_init();
  UART1_Init();
    UART2_Init();
 
  Delayms(100);
    
printMsg1("AT\r\n");
    
    Delayms(100);
    
    NVIC_EnableIRQ(USART1_IRQn);
    
    __enable_irq();
    
while(1){}
 
}
 
 
void USART1_IRQHandler(){
 
if (USART1->SR & USART_SR_RXNE) // if received data (RXNE event flag is set) is ready to be read -->RXNE
            {
    
             buff[len] = USART1->DR;
                            
                Delayms(100);
                
                printMsg2(buff);
 
    }
                
}
 
void printMsg1(char *msg, ...)  // Sending AT command to ESP  ( Stm32-> ESP8266)
{
 
 va_list args;
 va_start(args,msg); 
 vsprintf(buff,msg,args);
 
 for(int i=0;i<strlen(buff);i++)
 {
 
 
   USART1->DR = (buff[i]&0xFF);
     while(!(USART1->SR & USART_SR_TXE)); //wait for TXE, 1 = data transferred
   
  }
}
 
void printMsg2(char *msg, ...)  // Sending ESP response to Serial Monitor ( STM32-> PC)
{
 
 va_list args;
 va_start(args,msg); 
 vsprintf(buff,msg,args);
 
 for(int i=0;i<strlen(buff);i++)
 {
   USART2->DR = buff[i];
   while(!(USART2->SR & USART_SR_TXE)); //wait for TXE, 1 = data transferred
  }
}

1 ACCEPTED SOLUTION

Accepted Solutions
SIDRI.1
Associate III

This is the code modifed : it works fine :

#include "stm32f10x.h" // Device header
#include <stdio.h>
#include "stdint.h"
#include "stdarg.h"
#include "string.h"
#include "Msg_Handle.h"
#include <string.h>
 
 
void UART2_Init(void);
void UART1_Init(void);
void USART1_IRQHandler(void);
void DelayTimerUs(int n);
 
//UART1 --> MCU to Wifi
//UART2 --> MCU to Serial monitor
 
 
 
void UART2_Init(){
	
	//1) Enable USART2 clock and Porta clock (PA2-->Tx & PA3-->Rx)
 
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;	
 
 
//2) Configuring Tx2 to be used as Alternate function (Special I/O)  push-pull output
 
GPIOA->CRL &=~ GPIO_CRL_CNF2_0;
GPIOA->CRL |= GPIO_CRL_CNF2_1;
GPIOA->CRL |= (GPIO_CRL_MODE2_1 | GPIO_CRL_MODE2_0);
	
	
//3) Configuring Rx3 to be used as Alternate function (Special I/O)  Float input	
	
	GPIOA->CRL &=~ GPIO_CRL_MODE3_0 | GPIO_CRL_MODE3_1;  // 10MHz   Rx PA3
	GPIOA->CRL &=~ GPIO_CRL_CNF3_1 ;
	GPIOA->CRL |=  GPIO_CRL_CNF3_0;	
	
//3)	Set the Baud rate
 
// USART2->BRR = 0XEA6;					// 9600
 USART2->BRR = 0X138;        // 115200
 
//4) CR1 register (Enable usart)
 
	
	USART2->CR1 |= USART_CR1_TE;
  USART2->CR1 |= USART_CR1_RE ;	
  USART2->CR1 |= USART_CR1_UE;
	
}
 
void UART1_Init(){
 
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN; //clock to GPIO A enabled, alt.funct.en, USART1 clock enabled
 GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1; //port A9
 GPIOA->CRH &= ~GPIO_CRH_CNF9_0; //port A9 is TX pin
 GPIOA->CRH &= ~(GPIO_CRH_MODE10_0|GPIO_CRH_MODE10_1); //port A10 is RX pin
 GPIOA->CRH |= GPIO_CRH_CNF10_0; //port A10 is RX pin*/
 
USART1->BRR = 0X271; // 115200
	
USART1->CR1 |= USART_CR1_TE;
USART1->CR1 |= USART_CR1_RE ;
USART1->CR1 |= USART_CR1_UE;
 
 USART1->CR1 |= USART_CR1_RXNEIE | USART_CR1_TXEIE ;
	
}
 
void USART1_IRQHandler(){
 
if (USART1->SR & USART_SR_RXNE) // if received data (RXNE event flag is set) is ready to be read -->RXNE
			{
	
		     buff_read[len] = USART1->DR;
 
		 printMsg2(buff_read);
			
 
	}
	
			
}
 
 
int len=0;
char buff[256];
char buff_read[256];
 
void DelayTimerUs(int n){
	// 1 Mhz ---> 1Us
	//ARR = n (n=1 --> 1us) (n=2 --> 2us) ....
 
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	TIM2->PSC = 36;
	TIM2->ARR = n;
	TIM2->CNT = 0;
	TIM2->CR1 = TIM_CR1_CEN;
	
	for( int i =0; i<n; i++){
		
		  while (!(TIM2->SR & (1<<0))) {}
		}
	TIM2->SR &=~ (1<<0);
		
	TIM2->CR1 &=~ TIM_CR1_CEN;
		
		
	}
 
int main(void){
	
	 __disable_irq();
		
	systick_init();
  UART1_Init();
	UART2_Init();
 
  printMsg1("AT\r\n");
	DelayTimerUs(1000);
	
	printMsg1("AT+RESTORE\r\n");
       DelayTimerUs(1000);
	printMsg1("AT+CWMODE=1\r\n");
	DelayTimerUs(1000);
		
	 NVIC_EnableIRQ(USART1_IRQn);
	
    __enable_irq();
		
while(1){}
 
}
 

View solution in original post

9 REPLIES 9
TDK
Guru

I don't see "AT\r\n\" or "OK" in your logic analyzer plot. I do see that it indicates frame errors on the RX line. Doesn't seem like your baud rate matches what the logic analyzer is set to expect.

0693W00000BZghkQAD.png 

Probably not a problem here, but generally you should reverse the order here so it waits for TXE before sending a byte instead of blocking until the transmission is finished.

   USART2->DR = buff[i];
   while(!(USART2->SR & USART_SR_TXE)); //wait for TXE, 1 = data transferred

You're also sending "AT\r\n" without interrupts enabled, so any response is going to get ignored, unless it's sent 100+ms after the message ends.

    __disable_irq();
    ...
    printMsg1("AT\r\n");
    Delayms(100);
    NVIC_EnableIRQ(USART1_IRQn);
    __enable_irq();

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

deleted

SIDRI.1
Associate III

Thank's for reply,

The baud rate is set at 115200 for stm32, esp8266 and logic analyzer.

I've tried these suggestions, when enabling interrupt then sending "AT\r\n", i get nothing on serial monitor, Rx, Tx are held high (logic analyzer)

You're saying the values match, but your plot suggests otherwise. Possible your HSE_VALUE is incorrect. Put out a known frequency signal such as MCO on a pin and verify the clock is what you think it is.

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

TXE indicates the buffer is empty, and can take data, you should be FRONT CHECKING it, not back checking

I don't understand the delay in the interrupt, or the non-incrementing buffer pointer, and the use of string, lack of NUL termination, and then reuse of the same buffer in printMsg2

Why can't you do a simple echo of each byte received from USART1 in the IRQ handler to USART2?

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

it turns out that the "Delayms" function corrupted or caused the losses of the received data , perhaps this is due to the fact that the long waiting time leads to the loss of data.

Furthemore:

 the same buffer is used for sending the AT command and receiving the response "buff[len]", 

which place the receiving data also in buff[len] and seems to be ignored, 

this is why i'm receiving the command echo.

it turns out that the "Delayms" function corrupted or caused the losses of the received data , perhaps this is due to the fact that the long waiting time leads to the loss of data.

Furthemore:

 the same buffer is used for sending the AT command and receiving the response "buff[len]", 

which place the receiving data also in buff[len] and seems to be ignored, 

this is why i'm receiving the command echo.

SIDRI.1
Associate III

This is the code modifed : it works fine :

#include "stm32f10x.h" // Device header
#include <stdio.h>
#include "stdint.h"
#include "stdarg.h"
#include "string.h"
#include "Msg_Handle.h"
#include <string.h>
 
 
void UART2_Init(void);
void UART1_Init(void);
void USART1_IRQHandler(void);
void DelayTimerUs(int n);
 
//UART1 --> MCU to Wifi
//UART2 --> MCU to Serial monitor
 
 
 
void UART2_Init(){
	
	//1) Enable USART2 clock and Porta clock (PA2-->Tx & PA3-->Rx)
 
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;	
 
 
//2) Configuring Tx2 to be used as Alternate function (Special I/O)  push-pull output
 
GPIOA->CRL &=~ GPIO_CRL_CNF2_0;
GPIOA->CRL |= GPIO_CRL_CNF2_1;
GPIOA->CRL |= (GPIO_CRL_MODE2_1 | GPIO_CRL_MODE2_0);
	
	
//3) Configuring Rx3 to be used as Alternate function (Special I/O)  Float input	
	
	GPIOA->CRL &=~ GPIO_CRL_MODE3_0 | GPIO_CRL_MODE3_1;  // 10MHz   Rx PA3
	GPIOA->CRL &=~ GPIO_CRL_CNF3_1 ;
	GPIOA->CRL |=  GPIO_CRL_CNF3_0;	
	
//3)	Set the Baud rate
 
// USART2->BRR = 0XEA6;					// 9600
 USART2->BRR = 0X138;        // 115200
 
//4) CR1 register (Enable usart)
 
	
	USART2->CR1 |= USART_CR1_TE;
  USART2->CR1 |= USART_CR1_RE ;	
  USART2->CR1 |= USART_CR1_UE;
	
}
 
void UART1_Init(){
 
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN; //clock to GPIO A enabled, alt.funct.en, USART1 clock enabled
 GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9_0 | GPIO_CRH_MODE9_1; //port A9
 GPIOA->CRH &= ~GPIO_CRH_CNF9_0; //port A9 is TX pin
 GPIOA->CRH &= ~(GPIO_CRH_MODE10_0|GPIO_CRH_MODE10_1); //port A10 is RX pin
 GPIOA->CRH |= GPIO_CRH_CNF10_0; //port A10 is RX pin*/
 
USART1->BRR = 0X271; // 115200
	
USART1->CR1 |= USART_CR1_TE;
USART1->CR1 |= USART_CR1_RE ;
USART1->CR1 |= USART_CR1_UE;
 
 USART1->CR1 |= USART_CR1_RXNEIE | USART_CR1_TXEIE ;
	
}
 
void USART1_IRQHandler(){
 
if (USART1->SR & USART_SR_RXNE) // if received data (RXNE event flag is set) is ready to be read -->RXNE
			{
	
		     buff_read[len] = USART1->DR;
 
		 printMsg2(buff_read);
			
 
	}
	
			
}
 
 
int len=0;
char buff[256];
char buff_read[256];
 
void DelayTimerUs(int n){
	// 1 Mhz ---> 1Us
	//ARR = n (n=1 --> 1us) (n=2 --> 2us) ....
 
	RCC->APB1ENR |= RCC_APB1ENR_TIM2EN;
	TIM2->PSC = 36;
	TIM2->ARR = n;
	TIM2->CNT = 0;
	TIM2->CR1 = TIM_CR1_CEN;
	
	for( int i =0; i<n; i++){
		
		  while (!(TIM2->SR & (1<<0))) {}
		}
	TIM2->SR &=~ (1<<0);
		
	TIM2->CR1 &=~ TIM_CR1_CEN;
		
		
	}
 
int main(void){
	
	 __disable_irq();
		
	systick_init();
  UART1_Init();
	UART2_Init();
 
  printMsg1("AT\r\n");
	DelayTimerUs(1000);
	
	printMsg1("AT+RESTORE\r\n");
       DelayTimerUs(1000);
	printMsg1("AT+CWMODE=1\r\n");
	DelayTimerUs(1000);
		
	 NVIC_EnableIRQ(USART1_IRQn);
	
    __enable_irq();
		
while(1){}
 
}
 

Mohamed Aymen HZAMI
ST Employee

Hello @SIDRI.1​,

Please mark the helped reply as Best answer (click on "Select as Best"), to help others get the answer quickly.

Mohamed Aymen.