# How to interface GSM with 8051 microcontroller to send SMS?

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

My code is:

#include<reg51.h>
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()
{
serial_init();
puts(command);
delay(); // delay of approx 1 sec
puts(echo);
delay();
puts(msgConfig);
delay();
puts(number);
delay();
puts(message);
delay();
puts(CTRLZ);
while(1);

}
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)
{
serial(*temp);
temp++;
}
}

void serial(unsigned char x)
{

SBUF=x;
while(TI==0);
TI=0;

}
void delay(void) // delay for approx 1 sec
{
int i;
TMOD=0x01; // timer 0 in mode 1
for(i=0;i<142;i++)
{
TL0=0x00; // starting value from 0
TH0=0x00;
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.

• 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') – tcrosley Apr 29 '15 at 10:53
• 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. – rdtsc Apr 29 '15 at 12:37
• puts() here is a user defined function... How it may b problematic?? – Bob Parihar Apr 29 '15 at 17:57
• Or define your Ctrl+Z string as "\x1a". – 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:

send_at_command("AT+WHATEVER\r");
do {

where read_full_line reads characher by character until it receives \n and the previous character was \r (assuming V1 format1).
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.