cancel
Showing results for 
Search instead for 
Did you mean: 

STM32F030C8 Interface with Quectel M95

HARI krishna
Associate II
Posted on December 07, 2016 at 12:59

Hi all,

I am working for a project which is having 5 interfacing modules out of this one module needs to interface quectel M95 GSM modem to stm32f030C8. From PCB side and Hardware all was done working fine modem Responding to AT Commands.USART1 is used for interfacing M95 module. STM32 cube MX tool is used for generate code for TrueStudio.

Here is my problem,when i sent AT command modem responding with OK and reading messages also.For that i am using USART2 to display received message on PC terminal using MAX3232 converter.

If i want read the message which is received , in that received message some part of message is missing.i tried to increase the buffer size & receive length in the HAL_UART_Receive_IT  function but not worked out.

I am using usart1 receive interrupt .Receiving uart message are not exact what we need to receive some of sending characters also received.

uint8_t  uart1_aRxBuffer[150],

send_Buf[100];

HAL_UART_Transmit(&huart1,(uint8_t *)send_Buf,len,1000);

HAL_UART_Receive_IT(&huart1,(uint8_t *)uart1_aRxBuffer,len1);

please help on this it is need to submit to the client ASAP.

#no-hablo-hal
1 ACCEPTED SOLUTION

Accepted Solutions
Posted on December 15, 2016 at 20:05

The response you are seeing makes perfect sense because your logic is completely confused.

Regardless of the command, this is the way your logic is currently working:

1. You transmit a string (command) to the M95 like AT+GSM.....

2. You delay 2 seconds, during which time the M95 sends a response

3. you THEN enable the UART to receive data, using interrupts (and I still don't see your interrupt handling code)

4. the result of (2) above is that the response from the M95 happens while you are sitting in a 2 second delay.  As a result you get whatever was received by the hardware before it overflowed because you are not emptying the Rx buffer as characters are coming in.  So you get the first 2 characters '+C' which is the beginning of '+CPMS....' but since nobody is looking at the receiver, after the first two characters are buffered in the hardware peripheral (in the Rx register and the CPU interface register) it drops all subsequent characters on the floor.  The whole message was sent back by the M95 while you are sitting in a delay loop and ignoring what is coming back for 2 seconds.  So when you finally enable the Receiver with your HAL call it gives you the two characters it had stuck in the peripheral's registers.

What you need to do is enable the Receiver BEFORE you send a command so that you get back anything that the M95 sends you.  Including the command you sent if you have Echo enabled.  YOU need to figure out what to expect back based on whether echo is on or not, etc etc etc, and throw out any extraneous information and extract the useful response.  You can't use delays to hope that the bad stiff gets ignored and you'll get the good stuff because you don't know how long it will be before the M95 responds.

By waiting 2 seconds to look at the receiver after sending a command, you are ignoring the response from the M95.

And as a side note, setting a receive buffer 5 characters bigger than the size of the buffer you were passed is dangerous at best.  (assuming this will even know what the size is since what is passed to the function is pointer to an arbitrary array)

If you would like me to write the code for you, let me know.

View solution in original post

14 REPLIES 14
Posted on December 07, 2016 at 20:11

It's a little hard to understand what your problem is.  It sound like you are receiving some of the characters you sent out, which causes you a problem?  You show that you are using the Rx channel in Interrupt mode but you do not talk about or show the code you use to respond to the received character interrupt.  I will assume you have the capability to correctly buffer what is being received back from your external device.

The first thing I would suspect is that the device you are communicating with is in ECHO mode, so that every character you send to it, is sent back to you on your Rx line.  This is useful when you are using a terminal emulator program on a PC to talk to the device, not necessarily helpful when you are connecting with your microcontroller.  If you have an AT command to turn off ECHO , like ATE=0, you might send this first.  And then clear your receive buffers.

Next, by using the non-interrupt call to Txmit your message, the program will block until all of the characters are transferred to the UART before moving on to the next statement that starts the Rx channel.  With that the case, and if echo is on, what I would expect is the following:

  1. The Rx channel of the uart actually receives the first character echoed by your external device and is held in a register in the UART, but not transferred since the interrupt Rx has not yet been enabled. 
  2. Not sure but a second character might be received and held due to the double-buffer nature of the UART.
  3. All other characters sent out will be dropped because the UART is 'full:
  4. Last character sent may get received because the HAL_UART_Transmit() call returns when the last character is sent to the buffer but this happens before the last (and maybe the next to last) character has been sent out of the UART.  Depending on the timing and how fast your ISR empties the Rx buffer, it may get one or two of the last echoed characters before it starts receiving the actual response from the peripheral.

There are a number of ways to deal with the situation.  One is to run the Tx in interrupt mode, which will let you immediately enable the receiver and get back all of the echoed characters and throw out what you know to expect.  Also you could just enable the receiver before you send the message and it will have the same effect.  Alternately you can turn off echo on the peripheral as mentioned above.

In any case, you need to make sure you flush the receiver in some controlled way to ensure you only return meaning ful outputs from the device.

Posted on December 07, 2016 at 21:11

You'll need to manage or suppress the echo back from the modem, and resync depending on the OK, ERROR, NO CARRIER, etc responses the modem might provide. Arbitrary delays should also be avoided, network interaction may take several minutes to complete, and sending characters before completion might result in a command being aborted.

Turn Echo Off

ATE0

Turn Echo On

ATE1

With the HAL stuff make sure you are not creating some blocking code within a call-back (via IRQ Handler). Review how much data was received or transmitted, and if the request timed-out.

#no%20hablo%20hal

>>

please help on this it is need to submit to the client ASAP.

Nobody here cares, your client isn't paying us.

http://www.catb.org/~esr/faqs/smart-questions.html#urgent

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 10, 2016 at 18:19

If the second UART is only for debug, try to program the baudrate of the debug uart to be higher than the one going to the Quectel device. Then do not use buffer. When a byte is received from Quectel, directly write the DR of the debug UART TX. Good luck!

HARI krishna
Associate II
Posted on December 15, 2016 at 13:53

This is the source code what is running for GSM COM,

UART1 for Quectel M95,UART2 is for Hyper terminal.UART not receiving full reply message.

uint8_t test_commands()

{

send_cmnd((char *)''AT\r'',''OK'');

send_cmnd((char *)''ATE0\r'',''OK'');

send_cmnd((char *)''AT+CPMS=\''SM\'',\''SM\'',\''SM\''\r'',(''+CPMS: SM,0,50,SM,0,50,SM,0,50''));

send_cmnd((char *)''AT+CMGF=1\r'',''OK'');

send_cmnd((char *)''AT+CNMI=2,0,0,0,0\r'',''OK'');

send_cmnd((char *)''AT+CMEE=1\r'',''OK'');

send_cmnd((char *)''AT+CSCS=\''GSM\''\r'',''OK'');

return 0;

}

void send_cmnd(char *AT_cmd_string,char *response_string)

{

char send_Buf[50]={0};//added

sprintf(send_Buf,AT_cmd_string);

uint8_t len = strlen(AT_cmd_string);

printf(''\r\nGSM Tx: %s\r\n'',(int8_t*)AT_cmd_string);

if(len)

{

HAL_UART_Transmit_IT(&huart1,(uint8_t *)send_Buf,len);

}

HAL_Delay(2000);

reponse_read(response_string);

}

void reponse_read(char *response_string)

{

uint8_t len1;

len1=sizeof(response_string);

HAL_UART_Receive_IT(&huart1,(uint8_t *)uart1_aRxBuffer,(len1+5));

HAL_Delay(500);

printf(''\r\n UART1 Rx:%s\r'',uart1_aRxBuffer);

len1=0;

}

And the hyper terminal  Displays below :

0690X00000603KzQAI.jpg

At the red mark we are expecting  result : 

''+CPMS: SM,0,50,SM,0,50,SM,0,50'' but not sucesses

Is UART1 & UART2 use the same buffer for writing & reading?

HARI krishna
Associate II
Posted on December 15, 2016 at 14:06

For the Above code is there any changes needed for receiving uart data from quectel M95.

Is there any problem with receiving data on uart2 and printing it on uart1 with ms delay?

By using these responses i need to check weather modem initialized correctly or not. 

please help me on this issue.

Seb
ST Employee
Posted on December 15, 2016 at 14:27

I'm guessing how long does it take to send 'UART1 RX:' and how many bytes I may received in this time?

Try this: inside the interrupt of receiving a byte from Quectel, directly send and write the debug UART the same byte, and make sure the debug UART baud rate is higher (so you don't need extra buffering). When you write your 'GSM....' string, 

send_cmnd((char *)'AT+CPMS=\'SM\',\'SM\',\'SM\'\r',('+CPMS: SM,0,50,SM,0,50,SM,0,50')); anticipate and add immediately the UART1 Rx: string before sending. Then it might work better. Let us know.

Posted on December 15, 2016 at 20:05

The response you are seeing makes perfect sense because your logic is completely confused.

Regardless of the command, this is the way your logic is currently working:

1. You transmit a string (command) to the M95 like AT+GSM.....

2. You delay 2 seconds, during which time the M95 sends a response

3. you THEN enable the UART to receive data, using interrupts (and I still don't see your interrupt handling code)

4. the result of (2) above is that the response from the M95 happens while you are sitting in a 2 second delay.  As a result you get whatever was received by the hardware before it overflowed because you are not emptying the Rx buffer as characters are coming in.  So you get the first 2 characters '+C' which is the beginning of '+CPMS....' but since nobody is looking at the receiver, after the first two characters are buffered in the hardware peripheral (in the Rx register and the CPU interface register) it drops all subsequent characters on the floor.  The whole message was sent back by the M95 while you are sitting in a delay loop and ignoring what is coming back for 2 seconds.  So when you finally enable the Receiver with your HAL call it gives you the two characters it had stuck in the peripheral's registers.

What you need to do is enable the Receiver BEFORE you send a command so that you get back anything that the M95 sends you.  Including the command you sent if you have Echo enabled.  YOU need to figure out what to expect back based on whether echo is on or not, etc etc etc, and throw out any extraneous information and extract the useful response.  You can't use delays to hope that the bad stiff gets ignored and you'll get the good stuff because you don't know how long it will be before the M95 responds.

By waiting 2 seconds to look at the receiver after sending a command, you are ignoring the response from the M95.

And as a side note, setting a receive buffer 5 characters bigger than the size of the buffer you were passed is dangerous at best.  (assuming this will even know what the size is since what is passed to the function is pointer to an arbitrary array)

If you would like me to write the code for you, let me know.

Posted on December 16, 2016 at 07:28

Thanks for your helpful reply,below is the interrupt handle code for UART receiving ,even after removing increment buffer size same result was seen from the device.

/**

* @brief Receive an amount of data in interrupt mode.

* @param huart: UART handle.

* @param pData: pointer to data buffer.

* @param Size: amount of data to be received.

* @retval HAL status

*/

HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)

{

if((huart->State == HAL_UART_STATE_READY) || (huart->State == HAL_UART_STATE_BUSY_TX))

{

if((pData == NULL ) || (Size == 0))

{

return HAL_ERROR;

}

/* Process Locked */

__HAL_LOCK(huart);

huart->pRxBuffPtr = pData;

huart->RxXferSize = Size;

huart->RxXferCount = Size;

/* Computation of UART mask to apply to RDR register */

UART_MASK_COMPUTATION(huart);

huart->ErrorCode = HAL_UART_ERROR_NONE;

/* Check if a transmit process is ongoing or not */

if(huart->State == HAL_UART_STATE_BUSY_TX)

{

huart->State = HAL_UART_STATE_BUSY_TX_RX;

}

else

{

huart->State = HAL_UART_STATE_BUSY_RX;

}

/* Enable the UART Parity Error Interrupt */

__HAL_UART_ENABLE_IT(huart, UART_IT_PE);

/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */

__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);

/* Process Unlocked */

__HAL_UNLOCK(huart);

/* Enable the UART Data Register not empty Interrupt */

__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);

return HAL_OK;

}

else

{

return HAL_BUSY;

}

}

if possible please send me the code for this interface.

HARI krishna
Associate II
Posted on December 16, 2016 at 11:51

Using the Above application stm32 need to read the text messages which are stored in the SIM card.

In these messages are some are lengthy(120 characters) for this how to define a receive buffer?

what is the maximum byte buffer size that uart can receive ?

Can i use 

HAL_UART_Receive_IT(&huart1,(uint8_t *)uart1_aRxBuffer,150);?

is there any problem for using lengthy receive buffer?