cancel
Showing results for 
Search instead for 
Did you mean: 

USART DMA Rx for ESP8266 module

RomainR.
ST Employee
Posted on August 03, 2016 at 10:48

Hi All,

Well, I started playing with a ESP8266-01 module with the latest firmware AT Expressive. Now I did communicate a STM32L476 (UART 115200 which is the default baud rate of ESP8266). I use a code generated by IAR Cube HAL Drivers. I configured my project with USART1 RX DMA circular mode. I wrote a SendATCommand () function works properly. And a large variable rxBuffer [] to read the DMA. I correctly get responses rxBuffer module ['A', 'T', '\ r', '\ r', '\ n', '\ r', '\ n', 'O', 'K' , \ r \ n ') for example an AT command \ r \ n Now how can I handle the DMA buffer data (ie OK or ready Rx command) ? Thank you in advance for your assistance.

/* Includes ------------------------------------------------------------------*/
#include ''stm32l4xx_hal.h''
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#define BUFFER_SIZE 32
#ifdef __GNUC__
/* With GCC/RAISONANCE, small printf (option LD Linker->Libraries->Small printf
set to 'Yes') calls __io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __GNUC__ */
/* Private variables ---------------------------------------------------------*/
UART_HandleTypeDef huart1;
UART_HandleTypeDef huart2;
DMA_HandleTypeDef hdma_usart1_rx;
/* Private variables ---------------------------------------------------------*/
uint8_t rxBuffer[BUFFER_SIZE];
char
esp8266_reset[] = 
''AT+RST\r\n''
;
char
esp8266_AT[] = 
''AT\r\n''
;
char
esp8266_CWMODE1[] = 
''AT+CWMODE=1\r\n''
;
char
esp8266_CWMODE2[] = 
''AT+CWMODE=2\r\n''
;
char
esp8266_CWMODE3[] = 
''AT+CWMODE=3\r\n''
;
int
main(
void
)
{
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* Configure the system clock 24MHz HSI + PLL */
SystemClock_Config();
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_USART2_UART_Init();
MX_USART1_UART_Init();
HAL_UART_Receive_DMA(&huart1, rxBuffer, BUFFER_SIZE);
HAL_UART_DMAPause(&huart1);
esp_Reset();
HAL_Delay(1000);
printf
(
''ESP Module HW Reset Done\r\n''
);
/* Send Reset AT command */
send_ATCommand(esp8266_reset, 1000);
HAL_Delay(1000);
printf
(
''Send AT cmd AT+RST\r\n''
);
HAL_UART_DMAResume(&huart1);
/* Infinite loop */
while
(1)
{
/* Wait for user Button is pressed and released */
while
(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) != GPIO_PIN_RESET);
while
(HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_13) != GPIO_PIN_SET);
send_ATCommand(esp8266_AT, 1000);
printf
(
''Send AT cmd AT\r\n''
);
}
}
/* USART1 init function */
static
void
MX_USART1_UART_Init(
void
)
{
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if
(HAL_UART_Init(&huart1) != HAL_OK)
{
Error_Handler();
}
}
/* USART2 init function */
static
void
MX_USART2_UART_Init(
void
)
{
huart2.Instance = USART2;
huart2.Init.BaudRate = 115200;
huart2.Init.WordLength = UART_WORDLENGTH_8B;
huart2.Init.StopBits = UART_STOPBITS_1;
huart2.Init.Parity = UART_PARITY_NONE;
huart2.Init.Mode = UART_MODE_TX_RX;
huart2.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart2.Init.OverSampling = UART_OVERSAMPLING_16;
huart2.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart2.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if
(HAL_UART_Init(&huart2) != HAL_OK)
{
Error_Handler();
}
}
/** 
* Enable DMA controller clock
*/
static
void
MX_DMA_Init(
void
) 
{
/* DMA controller clock enable */
__HAL_RCC_DMA1_CLK_ENABLE();
/* DMA interrupt init */
/* DMA1_Channel5_IRQn interrupt configuration */
HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn);
}
/**
* @brief Retargets the C library printf function to the USART.
* @param None
* @retval None
*/
PUTCHAR_PROTOTYPE
{
/* Place your implementation of fputc here */
/* e.g. write a character to the EVAL_COM1 and Loop until the end of transmission */
HAL_UART_Transmit(&huart2, (uint8_t *)&ch, 1, 0xFFFF); 
return
ch;
}
/**
* @brief Perform a Hard RESET of ESP module
* @param None
* @retval None
*/
static
void
esp_Reset(
void
)
{
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
/* Reset pin go low for 200ms */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_RESET);
HAL_Delay(200);
/* Reset pin go high again */
HAL_GPIO_WritePin(GPIOD, GPIO_PIN_2, GPIO_PIN_SET);
}
/**
* @brief Send an AT command string to ESP module
* @param String command
* @param Timeout in ms
* @retval None
*/
static
void
send_ATCommand(
char
*cmd, uint32_t esp_timeout)
{
if
(esp_timeout > 2000)
esp_timeout = 2000;
uint16_t cmd_len = 
strlen
(cmd);
HAL_UART_Transmit(&huart1, (uint8_t *)cmd, cmd_len, esp_timeout);
}
void
HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct;
if
(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
/**USART1 GPIO Configuration 
PB6 ------> USART1_TX
PB7 ------> USART1_RX 
*/
GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral DMA init*/
hdma_usart1_rx.Instance = DMA1_Channel5;
hdma_usart1_rx.Init.Request = DMA_REQUEST_2;
hdma_usart1_rx.Init.Direction = DMA_PERIPH_TO_MEMORY;
hdma_usart1_rx.Init.PeriphInc = DMA_PINC_DISABLE;
hdma_usart1_rx.Init.MemInc = DMA_MINC_ENABLE;
hdma_usart1_rx.Init.PeriphDataAlignment = DMA_PDATAALIGN_BYTE;
hdma_usart1_rx.Init.MemDataAlignment = DMA_MDATAALIGN_BYTE;
hdma_usart1_rx.Init.Mode = DMA_NORMAL;
hdma_usart1_rx.Init.Priority = DMA_PRIORITY_MEDIUM;
if
(HAL_DMA_Init(&hdma_usart1_rx) != HAL_OK)
{
Error_Handler();
}
__HAL_LINKDMA(huart,hdmarx,hdma_usart1_rx);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else
if
(huart->Instance==USART2)
{
/* USER CODE BEGIN USART2_MspInit 0 */
/* USER CODE END USART2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART2_CLK_ENABLE();
/**USART2 GPIO Configuration 
PA2 ------> USART2_TX
PA3 ------> USART2_RX 
*/
GPIO_InitStruct.Pin = USART_TX_Pin|USART_RX_Pin;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}
}

#hal

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

3 REPLIES 3
AvaTar
Lead
Posted on August 03, 2016 at 14:45

> I configured my project with USART1 RX DMA circular mode.

 

IMHO not the best choice for a protocol with arbitrary-length commands.

Fixed length reception (DMA or FIFO) only coincidentally (read: never) matches the command length, thus commands get stuck in the FIFO/DMA buffer, to get ''pushed through'' only by the next command.

Almost impossible to get reception an processing in sync that way.

I always use single-character interrupts for such protocols.

RomainR.
ST Employee
Posted on August 03, 2016 at 15:53

I always use single-character interrupts for such protocols.

Yep, that's what I'm trying to implement (USART Rx interrupt, one byte at a time)

The problem is that in the response of the ESP8266, the first character is '\ n' (followed by '\ r' 'O' 'K' '\ r' '\ n', so I just wanted to detect this '\ n' to complete the handling of the packet in the Rx interrupt routine.

To continue...

Thank you Avatar

To give better visibility on the answered topics, please click on Accept as Solution on the reply which solved your issue or answered your question.

AvaTar
Lead
Posted on August 04, 2016 at 10:03

> The problem is that in the response of the ESP8266, the first character is '\ n' (followed by '\ r' 'O' 'K' '\ r' '\ n', so I just wanted to detect this '\ n' to complete the handling of the packet in the Rx interrupt routine.

 

I have not yet worked with this - or similar - WiFi modems, so I can hardly claim much experience. However, starting a packet with the termination character ('\n') seems a bit like a break of protocol to me.

Perhaps you could just ignore such starting terminators, i.e. drop '\n' characters for buffer index zero.

If I understood your issue correctly ...