2019-09-13 04:11 AM
Hi guys.
I have a problem with this hal function.The problem is that every time I use this function the first byte received is not what I transfer to it.For example when I send AT (ESP8266 AT command) to the module it must return AT OK,but every time(except the first time)the first byte is not A!
2019-09-13 04:19 AM
int main(void)
{
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/* MCU Configuration--------------------------------------------------------*/
/* Reset of all peripherals, Initializes the Flash interface and the Systick. */
HAL_Init();
/* USER CODE BEGIN Init */
/* USER CODE END Init */
/* Configure the system clock */
SystemClock_Config();
/* USER CODE BEGIN SysInit */
/* USER CODE END SysInit */
/* Initialize all configured peripherals */
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
/* Initialize interrupts */
MX_NVIC_Init();
/* USER CODE BEGIN 2 */
ESP_Enable;
ESP_Set;
delay_ms(5000);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE);
__HAL_UART_ENABLE_IT(&huart1,UART_IT_TC);
/* USER CODE END 2 */
/* Infinite loop */
/* USER CODE BEGIN WHILE */
while (1)
{
sprintf(data_tx,"AT\r\n");
HAL_UART_Receive_DMA(&huart1,data_rx,10);
HAL_UART_Transmit_DMA(&huart1,data_tx,4);
delay_ms(5000);
/* USER CODE END WHILE */
/* USER CODE BEGIN 3 */
}
/* USER CODE END 3 */
}
2019-09-13 07:14 AM
Why are you explicitly enabling UART_IT_RXNE and UART_IT_TC? If you are using HAL_UART_***_DMA() calls, they will handle enabling and disabling whatever interrupts they need. Since you are enabling interrupts, have you added code to the interrupt handlers? Do you have any code in the UART transmit complete and receive complete callback functions? What exactly are you seeing in the "data_rx" buffer? And finally, how do you get 10 characters from "AT OK"? Its been a loooooong time since I've done modem work, but even it that is really "AT\r\nOK\r\n", that is only 8 bytes.
2019-09-13 08:35 AM
One is normally expected to parse/synchronize the stream, you can't just request "10" characters and hope. Good chance you won't be getting exactly 10 characters in response to any given request, nor that the first byte will be what you want.
You might want to get the mechanics down using interrupts, collecting and processing one byte at a time.
2019-09-13 10:51 AM
"Why are you explicitly enabling UART_IT_RXNE and UART_IT_TC? "
I removed this.
After ESP_Set when i use uart_receive dma the uart receive 'r',the esp sends it.I checked and the other devices dont send this and everything is ok.I think its a bug in my esp module.
2019-09-13 11:13 AM
Whats the problem?After each time I call uart receive dma an extra byte is received from the ESP8266!!!
2019-09-13 12:02 PM
Don't be so quick to presume a bug in a mass-produced device to which your untested software is trying to communicate.
I suspect this problem goes back to my original post and @Community member 's post. The code you posted originally will NEVER work unless the device you are talking to always responds with exactly 10 bytes whenever you send "AT\r\n". And even if you know for sure the number of bytes the device was SUPPOSED to reply with, relying on a fixed size response is asking for trouble if there is every an error on the serial lines. For example, if the HAL code detects a framing error, noise error, etc. on the receiver, it will abort the DMA receive (well, this is an option in CobeMX to have it so this, and I don't recall if that is the default behavior). And any noise glitch of unexpected/extra character will throw off your synchronization.
In your code as posted, I suspect this is what is happening:
As quick bandaid patch to your current code, check the return values from HAL_UART_Receive_DMA() and HAL_UART_Transmit_DMA(). And make the size of your receive the EXACT number of bytes that the device responds with.
But this is only a kludge . The real answer is to stop trying to do fixed-count receive. Either use circular DMA mode with a larger buffer, or interrupt mode (NOT!!! the HAL_UART_Receive_IT, but your own interrupt code) to process bytes as they are received so you can re-synchronize to the incoming data as needed. Personally I prefer the circular DMA. Using HAL_UART_Receive_DMA() works for getting this running, but you need your own "read from the buffer" pointer and figure out how many bytes are available in the DMA buffer. This has been discussed several times in this forum. A search for UART DMA hopefully should find it (I have mixed luck with this forum's search function).
2019-09-14 07:08 AM
I checked the response size of each command and there was no problem with that.Each time the uart receive dma is called the buffer will completely get full.
Watch the code below:
In this code after cube initialization I enabled the esp and after 5 seconds(to make sure that nothing remained,because esp sends data after a hardware reset) I just put a receive function and did nothing else in the program.But there is a 'r' received!
This 'r' is the first character each time the hardware reset is done. When I put the ESP enable before MX_USART1_UART_Init(); this extra character wont be received.
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_DMA_Init();
MX_I2C1_Init();
MX_USART1_UART_Init();
MX_NVIC_Init();
ESP_Set;
ESP_Enable;
delay_ms(5000);
HAL_UART_Receive_DMA(&huart1,data_rx,9);
while (1)
{
}
}
2019-09-14 07:10 AM
https://imghostr.com/tGHM6F4NZ
This is what is received.
2019-09-14 08:18 AM
There are many AT command examples out there, including cellular modems which are also "AT command" such as X-CUBE-CELLULAR.
Missing the first byte smells like activation sequence (including initial GPIO state and level) is wrong. Fully agree with Clive, when data goes through wire(s) rugged SW will tacle it.