I send commands to the modem via USART1 and copy them to USART2. I copy the modem response to USART2. USART2 displays the modem's response to the first AT command (AT\r\n) "AT OK". The response to the second command (AT CSCS?\r\n) is not displayed by USART2, or USART1 for some reason does not read the second response from the modem. Why? The code:
{
char Test[]="AT\r\n";
char Reply[]="";
char Text[]="Module Connected";
char Text1[]="SMS with GSM Module";
char Text2[]="Checking Module...";
char Text3[]="Module Unconnected";
char NewLine[]="\r\n";
char Line[]="--------------------------------------------";
uint8_t flag = 1;
uint8_t flag1=1;
char STM32Req[]="STM32 request: ";
char MdmAnswr[]="Modem Answer: ";
char GsmTest[6] = "AT\r\n";
char SmsEncoding[] = "AT CSCS?\r\n";
/* Infinite loop */
for(;;)
{
HAL_UART_Transmit(&huart2, (uint8_t*)Text1, strlen(Text1), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
osDelay(500);
HAL_UART_Transmit(&huart2, (uint8_t*)Text2, strlen(Text2), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
osDelay(500);
while(flag==1){
HAL_UART_Transmit(&huart2, (uint8_t*)STM32Req, strlen(STM32Req), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)Test, strlen(Test), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1, (uint8_t*)Test, strlen(Test), HAL_MAX_DELAY);
HAL_UART_Receive(&huart1, (uint8_t*)Reply, 10, 100);
osDelay(1000);
HAL_UART_Transmit(&huart2, (uint8_t*)MdmAnswr, strlen(MdmAnswr), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)Reply, 10, HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
osDelay(500);
if (strstr(Reply,"OK\r\n"))
{
HAL_UART_Transmit(&huart2, (uint8_t*)Text, strlen(Text), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
osDelay(500);
HAL_UART_Transmit(&huart2, (uint8_t*)Line, strlen(Line), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)Line, strlen(Line), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
osDelay(500);
flag=0;
}
}
}
while(flag1==1){
HAL_UART_Transmit(&huart2, (uint8_t*)STM32Req, strlen(STM32Req), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)SmsEncoding, strlen(SmsEncoding), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart1, (uint8_t*)SmsEncoding, strlen(SmsEncoding), HAL_MAX_DELAY);
HAL_UART_Receive(&huart1, (uint8_t*)Reply, 500, 100);
osDelay(1000);
HAL_UART_Transmit(&huart2, (uint8_t*)MdmAnswr, strlen(MdmAnswr), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)Reply, strlen(Reply), HAL_MAX_DELAY);
HAL_UART_Transmit(&huart2, (uint8_t*)NewLine, strlen(NewLine), HAL_MAX_DELAY);
}
CodePudding user response:
You have some things that are correct and some things that needs improvement or are wrong. The correct thing is to wait for a final result code like OK
like you do, however you cannot wait for OK just some of the commands. You need to wait for a final result code from the modem every single time you send an AT command line. No exceptions! And also you need to check for more than just OK
, there are several other final result codes like ERROR
and more.
Also regarding how to receive data from the modem your attempt to read up till 10 bytes with HAL_UART_Receive
into the Reply
buffer of only size 1 will cause some memory corruption when more than one byte is read. That bug by itself makes all bets off with regards to behaviour since it is of type undefined behaviour (that phrase has very specific meaning in the C standard and is something that demands attention to avoid invoking).
But regardless, reading 10 bytes at the time is the wrong approach. The serial connection is just a stream of bytes with no inherent structure. I assume HAL_UART_Receive
uses/implements a small (say 16 bytes) FIFO buffer, and exactly how bytes received on the wire are grouped and forwarded to your program code you do not know and you cannot depend on any specific behaviour here.
If the modem sends four bytes O
, K
, \r
and \n
, calling HAL_UART_Receive
might return "OK\r\n" if you are lucky however it might also first return just "O" and then on the next call return "K\r\n".
This is perfectly valid behaviour by the USART and your code must be able to handle this. The simplest way to do this properly is to just read one character at the time and then copy that character into a temporary buffer until you have received a complete line of data because all responses (final and intermediate) ends with "\r\n", and then process that response line (where checking for if the line is a final result code is the first thing that should be done).
This problem is in data communication protocols known as framing. See this answer for some more information.
Related to what I wrote above about ALWAYS reading and parsing responses from the modem for every single command line send, your calls to osDelay
must be thrown out and permanently banished to never return.
Your lack of waiting for a final result code from the modem before sending the next command line will likely trigger abort behaviour. Abortion of AT commands is defined in chapter "5.6.1 Aborting commands" in V.250.
So the answer to your "why" question is probably AT command abortion, but you have several issues you need to fix before you can have any hope of having reliable behaviour (and please do before asking a new question with the same unfixed code), so without those things fixed guesses of causes of problems are of little value.