Hello all,
I am trying to send Command from 89S52 Controller to SIM900 GSM Modem
when i am sending command as
"AT" in response my Receive buffer is able to receive all bytes and code is working fine.
if request is "AT"Response is "AT 0X0D 0X0A 0X0D 0X0A OK " -> working fine
but if i send command as “AT+IPR=9600”
then expected response should be same "AT 0X0D 0X0A 0X0D 0X0A OK " but my buffer is not able to collect it.
it is receiving "AT " and after this it is receiving junk characters (in second attempt i tried to make buffer memory dynamically allocated but that is making program more dirty)
GSM is responding correctly (i verified it using hyperterminal), my code is not able to receive it correctly.
/*drivers.c*/ extern int buf_count; char Rec_buf[10] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; void serial_IT(void) interrupt 4 { if (RI == 1) { /* if reception occur */ RI = 0; /* clear reception flag for next reception */ Rec_buf[buf_count] = SBUF; /* Read receive data */ buf_count++; if(buf_count == 10) { buf_count = 0; } } } void Send_cmd(char *cmd) { while(*cmd != '\0') { Uart_send(*cmd); cmd++; } Uart_send(0x0D); Uart_send(0X0A); } void Uart_send(char data_snd) { TI = 0; SBUF = data_snd; while(TI==0); TI = 0; } /*application.c*/ int Check_rsponse_OK(void) { int ret_val = 0; if(Rec_buf[0] == 'A' && Rec_buf[1] == 'T' && Rec_buf[2] == 0x0D && Rec_buf[3] == 0X0A && Rec_buf[4] == 0x0D && Rec_buf[5] == 0x0A && Rec_buf[6] == 'O' && Rec_buf[7] == 'K') { port_0_0 = 1; port_0_1 = 0; ret_val = 1; } else { port_0_0 = 0; port_0_1 = 1; ret_val = 0; } return ret_val; } /*main.c*/ void main (void) { int ret_val = 0; init_app( ); Send_cmd(Check_cmd); do { ret_val = Check_rsponse_OK(); }while(ret_val != 1); Reset_receiver_Buffer(); while(1); }
Your assumptions are wrong, and you have a too small receive buffer.
You see an AT and a OK as response because you have echo on.
But echo on means that when you send the command "AT+IPR=9600" you will not just get an AT+OK back. You will first get the echo of the sent command (including cr+lf) then you will get an OK + cr+lf as response to the command.
So 10 characters of receive buffer is way too small, making the OK overwrite the start of the command echo.
It helps to experiment with the Hyperterminal or similar and look at exactly how the modem behaves.
Hello,
Thank you , so much for that information, i was thinking there is problem with my LED's or receiver buffer, but now problem got sort out. Thank you ones again
I have increased buffer size to 50 and implemented below given logic (which only searches 'OK' in buffer)
Hope so (next task)reading messages from Modem and replaying to it should be not complected,if you think i should know something more then suggestions are welcome.
for(j=0; j<50; j++) { if(Rec_buf[j] == 'O') { if(Rec_buf[j+1] == 'K') { port_0_0 = 1; port_0_1 = 0; return 1; } } else { port_0_0 = 0; port_0_1 = 1; } } }
1) Why scan 50 positions? you shouldn't scan more than you know you have filled.
2) You store data in a ring buffer. But that means that the start might not be at the start of the buffer. With a traditional ring buffer, there is an insert pointer and a readout pointer. And you can read until the readout pointer reaches the insert pointer. And the insert pointer must not continue until it collides with the insert pointer.
3) Your code can try to access the array one byte too far since your first loop scans the full lenght of the arary and the inner if checks one icon next.
4) You can inform the modem to disable echo if you want. Then you just get answers to queries, and the OK from commands.
Sorry, got a phone call yesterday so I forgot to finish my post.
Note that the strings from the modem normally comes as individual lines.
And you get an echo response to your command and then you get a modem response.
It's best when you parse the received data to try to see it as text lines. So don't look for just an OK somewhere in the buffer - that will falsely match the echo data in case you send a command that happens to include the substring "OK".
So never look for OK in a line that happens to start with AT.
Another thing - there can also be unsolicited text strings from the modem. Like if someone is calling the modem then the modem will inform about the ringing.
Thank you for your comment,
Things i am going to do is
1. Implement RING BUFFER 2. Try compare compete string
I switched off the ECHO , But now i am not able to send anything to MODEM Using Putty Prompt.
i am getting hard time for debugging so i am planning to join A Display to controller which can display what messages i am receiving.
If you are still trying to learn C, and communicate with a GSM modem via AT commands, they why don't you do so on a PC. Get a compiler, write a console based application to open the serial port, and learn to send and receive streams of characters, and how to parse responses. The PC has a big screen, supports printf(), etc , you can plug in serial ports and modems.
Learning to do this on an embedded system as your first real programming experience seems to be a bit overwhelming.
My Advice dear friend don’t use those standard C string function for GSM modems they just don’t fit the job they look for NULL at the end of string but there is no null in GSM modem responses domain and for many other reasons try to implement your send and receive functions
"they just don’t fit the job"
Nonsense!
They are perfectly usable!
"they look for NUL at the end of string"
Yes, of course that is true.
"there is no NUL in GSM modem responses"
So just add one, then!
Whatever you do, you're going to have to provide some way to mark the end of the response - so you might as well choose one which is going to allow you to use standard functions!
I think you need to rethink your use of the C string functions, since it doesn't seem like you have really considered how they can be used.
It's trivial to make sure that the full text mass has a terminating zero - if receiving 47 characters from the serial port driver, it isn't exactly hard to do buf[47] = '\0' to zero-terminate the buffer.
strchr() is great for locating a character in a buffer - like a \r or \n maybe. strpos() is great for looking for a subsstring. strncmp() is great for comparing just the initial part. ...
If you can't make do with the C string functions, then you haven't learned how to use the tools yet so it's an issue behind the keyboard.
Where is the forum edit when needed?
For some reason I had to write strpos() which is a non-standard function in C when intending to write strstr(). The disadvantage of doing too much PHP lately - in PHP strpos() gives the index of the hit while strstr() gives the remaining string.
Dear friend Andy Neil if you involve yourself to send some data over modem that my contain 0(NULL) and that’s not end of data you will face what I say for sure it's just take some time to face this for example for one transparent port project like RS232 or … that may send data that don't fit your expectations the you will face it ;) believe me man it is not that modem response that will get you it is what you send over media that will get you some day and that will be soon! And adding char substitute and ... won't be easy at all and it is unnecessary over head when you send data trough TCP link
" New! RE: don’t use those standard C string function for GSM modems "they just don’t fit the job"
Whatever you do, you're going to have to provide some way to mark the end of the response - so you might as well choose one which is going to allow you to use standard functions!"
Remember that there is a big difference between being in AT command mode, and having established a session where you send data though the modem to the other side.
AT command responses are only relevant when being in the AT command mode. That's also a reason why there exists multiplexer commands to create multiple serial interfaces to GSM modules - to allow AT commands to query signal strength etc on one virtual serial port, while another serial channel is sending/receiving data.
And by the way my dear friend as you say " it's an issue behind the keyboard" because when you don’t understand what is your tool for it is for standard functions like cout cin puts … not for Buffering using modem involve buffering data and in buffer may (and it will be for sure include 0 null if it is not you own data) and it is not use for C string it is just like that you want to cut metal with plastic knife when you just have a saw! And you have only one media to you modem and that’s probably you USART and that need a buffer not string!
How buffering of incoming data is performed is totally irrelevant to how the code processes AT commands and AT command responses.
In this specific case, the OP is doing AT+IPR to change baudrate - which obviously also requires the OP to care about the result of that baudrate change. Changing from strchr() to memchr() isn't going to make much of a difference if the UART is listening at the wrong speed...
Yes sending command to switch baud rate with out of fixing MCU baud rate to receive response is yet another problem but in first place I told him to don’t use string for modem communications as advice not as solution to his problem!(and it was just a Advice generally for modem communication )