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!
View all questions in Keil forum