I am doing a project on SMS sending through GSM using SIM 900 module and 8051.

My code is:

unsigned char *command = "AT";
unsigned char *echo = "ATE0";
unsigned char *msgConfig = "AT+CMGF=1";
unsigned char *number = "AT+CMGS=\"8283******\"";
unsigned char *message = "hello";
unsigned char *CTRLZ = 0x1A;
void serial_init(void); 
void serial(unsigned char);
void puts(unsigned char *p );
void delay(void);

void main()
delay(); // delay of approx 1 sec

void serial_init(void)

TMOD=0x20; //timer 1, mode 2(8-bit autoreload) to set baud rate 
TH1=0xFD; //-3 to TH1 for 9600 baud rate
SCON=0x50; // 8 bit txion, 1 start 1 stop bit, REN enable for both txfr and rxve
TR1=1; // start timer

void puts(char *p)
char *temp = p; /*temp pointer so that the actual pointer is not displaced */
while(*temp != 0x00)

void serial(unsigned char x)


void delay(void) // delay for approx 1 sec
int i;
TMOD=0x01; // timer 0 in mode 1
TL0=0x00; // starting value from 0 
TR0=1; // sart timer
while(TF0==0); // polling TF flag for high
TR0=0; // stop timer
TF0=0; // clear flag TF0


The problem here is that the SMS has not been not sent by the GSM module.

When I use the calling function by replacing the AT commands, then calling works but SMS does not. I think I am wrong in sending AT commands for SMS.

  • 1
    \$\begingroup\$ unsigned char *CTRLZ = 0x1A; is incorrect, should be unsigned char CTRLZ = 0x1A; (without the *) since it is not a string. Then use putc instead of puts. (Or make it a string with a proper trailing '\0') \$\endgroup\$ – tcrosley Apr 29 '15 at 10:53
  • \$\begingroup\$ Also the delays may be problematic. You might have to poll the module to see when it is ready to receive your message, or acknowledges a command. \$\endgroup\$ – rdtsc Apr 29 '15 at 12:37
  • \$\begingroup\$ puts() here is a user defined function... How it may b problematic?? \$\endgroup\$ – Bob Parihar Apr 29 '15 at 17:57
  • \$\begingroup\$ Or define your Ctrl+Z string as "\x1a". \$\endgroup\$ – MarkU Apr 30 '15 at 8:07

(While this answer perhaps might seem rude it is not meant to be. It is just a b) style answer).

You should never, never, never, ever use delay, sleep or similar to wait for the respose from the modem! In the same way you hopefully never would think of writing a web browser that ignores all responses the web server sends back to you, you should never think of writing a modem communication program that ignores all responses the modem sends back to you.

You MUST change your algorithm to the following:

do {
    line = read_full_line();
} while (!is_final_result_code(line));

where read_full_line reads characher by character until it receives \n and the previous character was \r (assuming V1 format1).

You can look at the code for atinout for an example for the is_final_result_code function (you can also compare to isFinalResponseError and isFinalResponseSuccess in ST-Ericsson's U300 RIL, although note that CONNECT is not a final result code, it is an intermediate result code, so the name isFinalResponseSuccess is not 100% correct).

Also, specifically for AT+CMGS, you MUST wait for the \r\n> response from the modem before you start sending the payload. See the first part of this answer for more details.

1 See 6.2.6 DCE response format in V.250. You should not change this to V0, even if it might seem tempting to only having to check for a single character at the end of final result codes, but because information text have always \r\n as EOL, and you are just way better of treating all lines in the same way.

| improve this answer | |

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.