cancel
Showing results for 
Search instead for 
Did you mean: 

Sending AT commands to GSM via STM32, Answer with characters omitted

MatheusMarkies
Associate III
I'm developing a system with a GMS module, where AT commands are sent to the module via an STM32L0.
In this case, I'm having problems with the AT+CSTT command, which was giving me an ERROR. After a lot of thought, I realized that the error was due to the fact that the command was going to the module with the T for AT missing (A+CSTT).
 
I'm working with the commands like this:
void sendAT(char command[], char answer[], int waitForAnswer) {
char ATcommand[500];
uint8_t buffer[500] = { 0 };
uint8_t ATisOK = 0;

sprintf(ATcommand, "%s\r\n", command);

    DEBUG_PRINT("Sending AT Command: ");
    DEBUG_PRINT(ATcommand);

while (!ATisOK) {
HAL_UART_Transmit(&huart2, (uint8_t*) ATcommand, strlen(ATcommand),
2000);


HAL_UART_Receive(&huart2, buffer, sizeof(buffer) - 1, 300);
buffer[sizeof(buffer) - 1] = '\0';

HAL_Delay(500);

ATisOK = !waitForAnswer;

if (strstr((char*) buffer, "OK")) {
ATisOK = 1;
}

DEBUG_PRINT("GSM: ");
DEBUG_PRINT((char* ) buffer);
HAL_Delay(1000);
memset(buffer, 0, sizeof(buffer));
}
}

char* sendATWithReturn(char command[]) {
char ATcommand[500];
uint8_t buffer[300] = { 0 };
char *returnBuffer = malloc(300 * sizeof(char));

if (returnBuffer == NULL) {
return NULL;
}

sprintf(ATcommand, "%s\r\n", command);
HAL_UART_Transmit(&huart2, (uint8_t*) ATcommand, strlen(ATcommand), 1000);
HAL_UART_Receive(&huart2, buffer, 300, 100);
HAL_Delay(500);

DEBUG_PRINT("GSM: ");
DEBUG_PRINT((char* ) buffer);

strncpy(returnBuffer, (char*) buffer, 300);

return returnBuffer;
}
And my command sequence goes like this:
void modemStart(char *apn, char *user, char *pwd) {
sendATWithReturn("AT");

HAL_Delay(1000);
sendATWithReturn("AT+CPIN?");

HAL_Delay(1000);
sendATWithReturn("AT+CREG?");

HAL_Delay(1000);
sendATWithReturn("AT+CGATT?");

HAL_Delay(1000);
sendATWithReturn("AT+CSQ");

HAL_Delay(1000);
    char command[500];
    snprintf(command, sizeof(command), "AT+CGDCONT=1,\"IP\",\"%s\"", apn);
    sendAT(command, "OK", 1);
    memset(command, 0, sizeof(command));

    HAL_Delay(1000);
    sendAT("AT+CGATT=1", "OK", 0);
    HAL_Delay(1000);
    sendATWithReturn("AT+CSTT?");

    HAL_Delay(1000);
    snprintf(command, sizeof(command), "AT+CSTT=\"%s\",\"%s\",\"%s\"", apn, user, pwd);
    sendAT(command, "OK", 1);
    memset(command, 0, sizeof(command));

HAL_Delay(1000);
sendATWithReturn("AT+CIICR");

HAL_Delay(1000);
sendATWithReturn("AT+CIFSR");

HAL_Delay(1000);
sendATWithReturn("AT+CIPMUX=1");

/*
AT+CPIN?: Verifica o status do PIN do SIM.
AT+CREG?: Verifica o status de registro na rede.

Sequência de Inicialização:

AT+NETCLOSE: Fecha qualquer conexão de rede existente.
AT+CGATT=0: Desativa o GPRS.
AT+CGATT=1: Ativa o GPRS.
AT+CGDCONT: Define o contexto PDP.
AT+CSTT: Define o APN, usuário e senha.
AT+CIICR: Inicia a conexão sem fio.
AT+CIFSR: Obtém o endereço IP.
AT+CIPMUX=1: Habilita o modo de múltiplas conexões.
*/
}
SERIAL LOG:
19:37:54.671 -> Serial2: Send AT:
19:37:54.671 -> Sending AT Command: AT
19:37:54.671 -> GSM: AT

19:37:54.671 -> OK
19:37:54.671 -> 
19:37:56.282 -> Serial2: GSM: AT

19:37:56.282 -> OK
19:37:56.282 -> 
19:37:57.878 -> Serial2: GSM: AT+CPIN?

19:37:57.878 -> +CPIN: READY
19:37:57.878 -> 
19:37:57.878 -> OK
19:37:57.878 -> 
19:37:59.455 -> Serial2: GSM: AT+CREG?

19:37:59.455 -> +CREG: 0,1
19:37:59.455 -> 
19:37:59.455 -> OK
19:37:59.455 -> 
19:38:01.060 -> Serial2: GSM: AT+CGATT?

19:38:01.060 -> +CGATT: 1
19:38:01.060 -> 
19:38:01.060 -> OK
19:38:01.060 -> 
19:38:04.242 -> Serial2: GSM: AT+CSQ

19:38:04.242 -> +CSQ: 18,0
19:38:04.242 -> 
19:38:04.242 -> OK
19:38:04.242 -> Sending AT Command: AT+CGDCONT=1,"IP","zap.vivo.com.br"
19:38:04.287 -> GSM: AT+CGDCONT=1,"IP","zap.vivo.com.br"

19:38:04.287 -> OK
19:38:04.287 -> 
19:38:06.839 -> Serial2: Sending AT Command: AT+CGATT=1
19:38:06.839 -> GSM: AT+CGATT=1

19:38:06.885 -> OK
19:38:06.885 -> 
19:38:11.069 -> Serial2: GSM: AT+CSTT?

19:38:11.069 -> ERROR
19:38:11.069 -> Sending AT Command: AT+CSTT="zap.vivo.com.br","vivo","vivo"
19:38:11.069 -> GSM: A+CSTT="zap.vivo.com.br","vivo","vivo"

19:38:11.069 -> ERROR
19:38:11.069 -> 
19:38:12.670 -> Serial2: GSM: A+CSTT="zap.vivo.com.br","vivo","vivo"

19:38:12.670 -> ERROR
In other words, the error is when the command is sent to the module, more precisely in the byte buffer conversion line, but I'm not sure how to fix it.
 
Apparently with two characters in the password the command is sent correctly, but with more than two the AT loses its T, I tested it this way: 
 
19:28:09.621 -> Serial2: GSM: AT+CSTT=“zap.vivo.com.br”,“vivo”,"dd”
19:28:09.621 -> ERROR
 
Note that AT+CSTT is correct.
 
Doing some more tests, I realized that the error is in the part of sending and receiving the data by Serial, since even the DEBUG_PRINT that occurs before the while click to send the command is correct.
13 REPLIES 13
BarryWhit
Senior III

I'm starting to doubt this question has anything to do with STM32.

 

Can you share a link to the AT command manual you're using for this module? None of the ones I've found list AT+CSTT as a valid command.

 

@Pavel A. cool idea. could also just use a second USB-serial cable, and connect its RX alternately to either direction to see what's going on. no custom SW needed. But really, a Chinese clone 24Mhz LA costs ~10$ and does the job perfectly.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.

@BarryWhit wrote: 

Can you share a link to the AT command manual you're using for this module? None of the ones I've found list AT+CSTT as a valid command. 

 

 

But At+CSTT is a listed command for the much older SIM900 module from the same company, which was used in older shields for arduino.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.
MatheusMarkies
Associate III

Well... Apparently the CSTT command doesn't really exist, I ended up basing it on an old library and not paying attention to the manual.
But thank you all, I got a good result by implementing the buffer and the interrupts.
Here's the code for anyone who wants to deal with a stack of AT commands and GSM modems:

uint8_t Rx_buffer[100];
uint8_t rx_answer[100];
uint8_t Rx_data = 0;
int rx_index = 0;
uint16_t lastRxTick = 0;
int gsmStatus = 0;

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart->Instance == huart1.Instance) {

	}
	if (huart->Instance == huart2.Instance) {

		Rx_buffer[rx_index++] = Rx_data;
		lastRxTick = HAL_GetTick();
		gsmStatus = 2;
		HAL_UART_Receive_IT(&huart2, &Rx_data, 1);
	}
}

uint16_t sendTick = 0;
void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) {
	if (huart->Instance == huart1.Instance) {

	}
	if (huart->Instance == huart2.Instance) {
		if (gsmStatus == 0) {
			DEBUG_PRINT("Send...\r\n");
			gsmStatus = 1;
			sendTick = HAL_GetTick();
		}
	}
}

void sendAT(char command[], char answer[], int waitForAnswer) {
	char ATcommand[200];
	uint8_t commandBuffer[200] = { 0 };
	uint8_t buffer[200] = { 0 };
	uint8_t ATisOK = 0;

	HAL_UART_Receive_IT(&huart2, &Rx_data, 1);

	snprintf(ATcommand, sizeof(ATcommand), "AT%s\r\n", command);

	memcpy(commandBuffer, (uint8_t*) ATcommand, strlen(ATcommand) + 1);

	DEBUG_PRINT("Sending AT Command: \r\n");
	DEBUG_PRINT(ATcommand);

	while (!ATisOK) {
		if (gsmStatus == 0)
			HAL_UART_Transmit_IT(&huart2, commandBuffer, sizeof(commandBuffer));

		if (gsmStatus == 3) {
			rx_answer[sizeof(rx_answer) - 1] = '\0';

			ATisOK = !waitForAnswer;

			if (strstr((char*) rx_answer, "OK")) {
				ATisOK = 1;
			}

			DEBUG_PRINT("GSM answer: \r\n");
			char ATanswer[200];
			sprintf(ATanswer, "%s\r\n", (char* ) rx_answer);

			DEBUG_PRINT(ATanswer);
			memset(rx_answer, 0, sizeof(rx_answer));
			gsmStatus = 0;
		}

		if (gsmStatus >= 1) {

			if(gsmStatus == 2){
				if (HAL_GetTick() >= lastRxTick + 40) {
					memcpy(rx_answer, Rx_buffer, sizeof(Rx_buffer));

					rx_index = 0;
					memset(Rx_buffer, 0, sizeof(Rx_buffer));
					gsmStatus = 3;
				}
			}
			if(gsmStatus != 3){
				if (HAL_GetTick() >= sendTick + 6000) {
					DEBUG_PRINT("TimeOut\r\n");
					rx_index = 0;
					memset(rx_answer, 0, sizeof(rx_answer));
					memset(Rx_buffer, 0, sizeof(Rx_buffer));
					gsmStatus = 0;
				}
			}
		}
	}
}

void modemStart(char *apn, char *user, char *pwd) {
	sendAT("", "OK", 1);

	sendAT("+CPIN?", "OK", 1);

	sendAT("+CREG?", "OK", 1);

	sendAT("+CSQ", "OK", 1);

	char command[200];

	snprintf(command, sizeof(command), "+CGAUTH=1,1,\"%s\",\"%s\"", user, pwd);
	sendAT(command, "OK", 1);
	memset(command, 0, sizeof(command));

	snprintf(command, sizeof(command), "+CGDCONT=1,\"IP\",\"%s\"", apn);
	sendAT(command, "OK", 1);
	memset(command, 0, sizeof(command));

	sendAT("+CGACT=1,1", "OK", 0);

	sendAT("+CGATT?", "OK", 1);
} //A7670X Init
BarryWhit
Senior III

In the OP you claimed the UART data is being corrupted. Instead, you were getting an error because you were sending an invalid command and that red herring sent everyone trying to help you down the wrong path.

 

In the future, keep this mind and try to be sure that you're sure about what you're sure of. I hope your project goes smoothly from here on.

- If a post has answered your question, please acknowledge the help you received by clicking "Accept as Solution".
- Once you've solved your issue, please consider posting a summary of any additional details you've learned. Your new knowledge may help others in the future.