Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Help!! Give me a subroutine to read the response from a GSM phone thoorug USART.

Status
Not open for further replies.

ROCKET SCIENTIST

Member level 3
Joined
Feb 25, 2012
Messages
61
Helped
5
Reputation
10
Reaction score
5
Trophy points
1,288
Activity points
1,728
Help!! Give me a subroutine to read the response from a GSM phone through USART.

Hello all,
I'm trying to communicate with my SE k300i phone with an atmega8 running on 8MHz crystal.
I wrote a C code for it which says "AT" from MCU. The phone should say "OK" back to MCU. I want to read this response. Someone told me that the phone response format is" LF CR OK LF CR " SOMETHING LIKE THIS. In this format "CR" is appearing twice.Last one is the string end marker so first one is to be ignored. So, I wrote this code,

Code:
void read(void) {
int mark=0; i=0; 
do {
data[i]=USARTReadChar(); 
if(data[i]=='\r' && mark==0) mark=1; 
if(data[i]=='\r' && mark==1) mark=3; 
i++;}
while(data[i-1]!='\r' && mark!=3); }

the character read function is:

Code:
char USARTReadChar() {
//Wait untill a data is available 
while(!(UCSRA & (1<<RXC))) {/*Do nothing*/}
/*Now USART has data IN BUFFER*/   return UDR;}

Now the problem is it isn't working!! You may ask for the data send routine
Code:
char at[6]={'A','T','\r','\n','\0'};

void attention(void)
{int j=0;
do {USARTWriteChar(at[j]); j++; }
while(at[j-1]!='\0'); }

This routine is working. I've tested it by connecting MCU Tx+phone RX and
phone TX+PC RX through max232 and I got "OK" in the terminal...

To show the received data string from phone I used LCD. I wanted to see individual characters received.
codes are:
Code:
LCDClear();
for(int dis=0;dis<=5;dis++)
{
LCDGotoXY(0,1);
LCDWriteChar(data[dis]);
_delay_ms(300);
}
_delay_ms(300);
LCDGotoXY(0,1);
LCDWriteChar('\r');

I know LF and CR are unprintable. But I sdould at least see O and K. why MCU isn't working then? I don't understand. Is the phone response format is wrong???
Please help me guys.:roll:

Thanks in advance,
RS..
 

ROCKET SCIENTIST said:
Code:
LCDClear();
for(int dis=0;dis<=5;dis++)
{
LCDGotoXY(0,1);
LCDWriteChar(data[dis]);
_delay_ms(300);
}
_delay_ms(300);
LCDGotoXY(0,1);
LCDWriteChar('\r');
LCDGotoXY(0,1) sets cursor at a specific position right?
But in this way the cursor is always set in the same position. The result would be only one character to be visible, the last one, in our case '\r' which is not printable.
So you may have a correct rx function, but a wrong result on LCD.
Try replacing with LCDGotoXY(dis,1) (assuming that the first argument is about columns).

Hope that helped,
Alexandros
 

I don't think it is needed to move the cursor each time to write a character, just use the LCDGotoXY once out of the loop and then send all the characters that you want using LCDWriteChar to print characters is contiguous positions

Alex
 

Thanx. Actually I wanted to display the characters at the same position each time. That's why in each iteration I set the position.
 

Thanx. Actually I wanted to display the characters at the same position each time. That's why in each iteration I set the position.
It would be helpful if you posted the complete code. UART not beeing interrupt driven is dangerous because if you do not poll at the correct moment, you may loose incoming bytes.
 

originally posted by:alexxx
LCDGotoXY(0,1) sets cursor at a specific position right?
Yes you are right. column 0 row 1. Umm, well, I tried your modification but It's not working this time too.
Are you sure my "read" function is right? Because, I placed a LCDClear function in between the "read" and "display" function.
But LCDClear isn't executing. When I turn on the circuit, Cursor is at position(0,2) and it remains there. I'm confused.
I think may be the problem is in Read function.. Because to test LCD hardware I just replaced "data" array by a fixed array dt[]="hello".
And the LCD is displaying it nicely.

Moreover in USART comm. I used the sequence:

attention(); read(); LCDClear(); then the display routine...
So I guess During receiving data, read() is getting stuck somewhere and following codes are not being executed. Please suggest what to do.

---------- Post added at 17:10 ---------- Previous post was at 16:57 ----------

Here is the full code. Sorry for a lot of commented sections as I was testing many things. My project is actually to control a remote load by sending sms. For this thing I have to send command to phone , receive response, compare it with prefixed value and then take necessary actions..

Hope this will help you to help me out..........



Code:
//**********remote load control by USART driver************

#define F_CPU 8000000UL

#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include "lcd.h"

uint8_t i=0, k=0, m=0;int comp; 
char dta[16]; char da[]="hello";
char tst[7]={'\n','\r','O','K','\n','\r'}; // the test string to compare with
char at[6]={'A','T','\r','\n','\0'};
char ecoff[10]={'A','T','E','0','\r','\n','\0'};
char call[24]={'A','T','D','+','8','8','0','1','7','2','2','5','0','2','3','7','0',';','\r','\n','\0'};
char mem[16]={'A','T','+','C','P','M','S','=','"','M','E','"','\r','\n','\0'};
char regi[12]={'A','T','+','C','R','E','G','?','\r','\n','\0'};


//*************************TIMER SECTION*********************************************

void init_timer1(void)  {
TCCR1A = 0x00;/*normal operate*/ TCCR1B = 0b00000011;/*prescale /64 */ 
TIMSK |= (1<<TOIE1);/*ovf. int. en*/     }

void timer1_off(void) {TCCR1B = 0x00; }

ISR(TIMER1_OVF_vect)		// happens after .5 sec from starting timer
{  UCSRB &= (~(1<<RXEN)); i=10;  }

//************************USART  SECTION*********************************************

void USARTInit(uint16_t ubrr_value) {
UBRRL = ubrr_value; UBRRH = (ubrr_value>>8); //Set Baud rate
/*Set Frame Format >>Async mode >>No Parity >>1 StopBit >>charsize 8*/
UCSRC=(1<<URSEL)|(3<<UCSZ0);
/*Enable The RX and TX UCSRB=(1<<RXEN)|(1<<TXEN);  */  }
//-----------------------------------------------------------------
char USARTReadChar() {
//Wait untill a data is available 
while(!(UCSRA & (1<<RXC))) {/*Do nothing*/}
/*Now USART has data IN BUFFER*/   return UDR;}
//-----------------------------------------------------------------
void USARTWriteChar(char data) {
//Wait untill the transmitter is ready
while(!(UCSRA & (1<<UDRE))) {/*Do nothing*/}
UDR=data;/*Now write the data to USART buffer*/  }
//***********************************************************************************


void delay3s(void)     // a delay of 3.6 seconds
{
_delay_ms(400); _delay_ms(400); _delay_ms(400);
_delay_ms(400); _delay_ms(400); _delay_ms(400);
_delay_ms(400); _delay_ms(400); _delay_ms(400); }

void call_phone(void)
{int cl=0;
do {USARTWriteChar(call[cl]); cl++; }
while(call[cl-1]!='\0');
delay3s();  }

void echo_off(void)
{int z=0;
do {USARTWriteChar(ecoff[z]); z++; }
while(ecoff[z-1]!='\0');
delay3s(); }

void attention(void)
{int j=0;
do {USARTWriteChar(at[j]); j++; }
while(at[j-1]!='\0');
delay3s(); }

void memory_select(void)
{int ms=0;
do {USARTWriteChar(mem[ms]); ms++; }
while(mem[ms-1]!='\0');
delay3s(); }

void check_reg(void)
{int rg=0;
do {USARTWriteChar(regi[rg]); rg++; }
while(regi[rg-1]!='\0');
delay3s(); }
//----------------------------------------------------------------------------
// THE READ FUNCTION 
//----------------------------------------------------------------------------

/* old read function**************************************
void read(void) {int mark=0;i=0; do {dta[i]=USARTReadChar(); 
if(dta[i]=='\r' && mark==0) mark=1; if(dta[i]=='\r' && mark==1) mark=3; i++;}
while(dta[i-1]!='\r' && mark!=3); }
----------------------------------------------------------*/
/*new one*/
void read(void) {int mark=0;i=0;
for(i=0;i<=10;i++)
{dta[i]=USARTReadChar();} 
}
//****************************************************************************
void compare(void)
{
int l=0; int mk=0;
while(l<=10)
{
if(dta[l] != tst[l]) {LCDGotoXY(0,1);LCDWriteString("nm");comp=0;break;}
if(dta[l]=='\r' && tst[l]=='\r' && mk==0) mk=1;
if(dta[l]=='\r' && tst[l]=='\r' && mk==1) mk=3;
if(dta[l] == tst[l] && mk!=3) {PORTC|=(1<<5);_delay_ms(300);PORTC&=~(1<<5);l++;}
if(dta[l]=='\r' && tst[l]=='\r' && mk==3) {LCDGotoXY(0,1);LCDWriteString("mat");comp=3;break;}
}
_delay_ms(800);
}

}    

//--------------------------------------------------\\
//              THE MAIN FUNCTION                   \\
//--------------------------------------------------\\


int main(void)
{
sei();			//ENABLE GLOBAL INTRPT
USARTInit(207); 	//UBRR = 207 baud 2400
InitLCD(LS_BLINK);	//INITIALIZE THE LCD

//LCDGotoXY(0,0);
//LCDWriteString("hello testing");

/*****************************************************************
//while(1)


UCSRB |= (1<<TXEN);UCSRB |= (1<<RXEN);_delay_ms(100);

//init_timer1();
//for(j=0;str[j]!='\0';j++)
//{USARTWriteChar(str[j]);}

UCSRB &= ~(1<<TXEN); UCSRB &= ~(1<<RXEN);
LCDClear(); i=0; j=0; delay3s(); 
****************************************************************/


UCSRB |= (1<<TXEN);UCSRB |= (1<<RXEN);  //enable tx & rx
echo_off();   // turn off the echo first for low traffic

while(1){

//call_phone();delay3s();delay3s();delay3s();

attention(); read(); 
//compare();
LCDClear();
for(int dis=0;dis<=5;dis++)
{
LCDGotoXY(dis,1);
LCDWriteChar(da[dis]);
_delay_ms(300);
}
_delay_ms(300);
LCDGotoXY(0,1);
LCDWriteChar('\r');
//------------------------
//memory_select(); memory_select(); //no need to take response
//------------------------
//check_reg(); check_reg();

// delay3s();
}

return 0;
}

I am not an expert in C programming. So, I could not use interrupts at correct positions.

RS.
 
Last edited:

Code:
void ISR_sc(void) interrupt 4
{
	unsigned char a;
	if(TI==1)
	{
		TI = 0;
	}
	else
	{
		a=SBUF;
	if(setting==0)
	{
		if(a=='!')
		{
			f9=1;
		}
		if(a=='+')
		{
		F1=1;
		}
		if(a=='\n')
		{
		f2=1;
		}
		if(a=='!')
		{
		F3=1;
		}
		if(a=='\r' && count>4)
		{
			f5=1;
		}
	
	count++;
	if(count>=75 && count<86 )
	{
		stringa[count-75]=a;
	}
	}
	else
	{
		if(a=='\r')
		{
			f8=1;
		}
		if(a=='+')
		{
		f4=1;
		}
		if(a==',')
		{
		f6=1;
		}
		if(a=='\r' && count>4)
		{
		f7=1;
		}
		string[count]=a;
		count++;
	}
	/*	if(a=='!');
		{
			f6=1;
		}*/
	RI=0;
	}
}
this is the routine in 8051 which i used to compare gsm response hope you will understand..
 
Last edited by a moderator:

ROCKET SCIENTIST said:
Code:
char dta[16]; char da[]="hello";
......................
......................
/*new one*/
void read(void) {int mark=0;i=0;
for(i=0;i<=10;i++)
{dta[i]=USARTReadChar();} 
}
......................
......................
for(int dis=0;dis<=5;dis++)
{
LCDGotoXY(dis,1);
LCDWriteChar(da[dis]);
_delay_ms(300);
}

According to this code, you are storing incoming data in dta[], but you are printing data from da[].
Furthermore, you could take alex's advice under consideration.

alexan_e said:
I don't think it is needed to move the cursor each time to write a character, just use the LCDGotoXY once out of the loop and then send all the characters that you want using LCDWriteChar to print characters is contiguous positions

In addition:
Can you debug the code, or you are using a programer for downloading the hex file?
 

Dear alexxx,

Sorry I forgot to tell that da[] was only for test purpose.I used it to check any hardware problem in lcd connection. actually I was reading dta[]. The receiving string storage. See my comment no #6 if u have time. I've explained there. I've done a few more test in the meantime. And surprisingly I've found that dta[] is storing only the last received character in our case "CR"[carriage return]. I don't know why. I've read usart immediately after sending command. in the last test I've omitted displaying characters in lcd and used a compare routine with this array

Code:
char tst[4]={'O','K','\r'};  int comp;
void compare(void)
{
int l=0;
while(l<=10)
{
if(dta[l] != tst[l]) {LCDGotoXY(0,0);LCDWriteString("nomatch");_delay_ms(100);comp=0;break;}
if(dta[l]==tst[l] && dta[l]!='\r') l++;
if(dta[l]=='\r' && tst[l]=='\r')  // '\r' is the last character
	{LCDGotoXY(0,0);LCDWriteString("match");_delay_ms(100);comp=3;break;}
}
_delay_ms(800);
}

comp is just a flag to do something later. Pls, find me the mistake. Is there any critical timing criteria in usart reading?? you were talking about driving by interrupt...

thanx,
RS.
 

ROCKET SCIENTIST said:
da[] was only for test purpose.
Can you please post the exact same code you try to run? Please remove all unnecessary stuff like test flags or text that are not beeing used, in order to make the code easilly readable.
You didn't answer, are you using a debugger or a programmer?
 

Thanks, alexxx,
here is the final code.. I'm writing on winAVR's notepad.. I don't know how to debug this type of code, because gsm phone can't be found in a simulator..


Code:
//**********remote load control by USART driver************

#define F_CPU 8000000UL

#include <avr/io.h>
#include <inttypes.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#include <math.h>
#include "lcd.h"

uint8_t i=0, k=0, m=0;int comp; 
char dta[16];                     // data storage
char tst[16]={'O','K','\n','\r','\0'}; // the test string to compare with
char at[6]={'A','T','\n','\r','\0'};   // at command


//************************USART  SECTION************************************

void USARTInit(uint16_t ubrr_value) {
UBRRL = ubrr_value; UBRRH = (ubrr_value>>8); //Set Baud rate
/*Set Frame Format >>Async mode >>No Parity >>1 StopBit >>charsize 8*/
UCSRC=(1<<URSEL)|(3<<UCSZ0);  }
//-----------------------------------------------------------------
char USARTReadChar() {
//Wait untill a data is available 
while(!(UCSRA & (1<<RXC))) {/*Do nothing*/}
return UDR;}
//-----------------------------------------------------------------
void USARTWriteChar(char data) {
//Wait untill the tx is ready
while(!(UCSRA & (1<<UDRE))) {/*Do nothing*/}
UDR=data;/*Now write the data to USART buffer*/  }
//*************************************************************************


void delay3s(void)     // a delay of 3.6 seconds
{
_delay_ms(400); _delay_ms(400); _delay_ms(400);
_delay_ms(400); _delay_ms(400); _delay_ms(400);
_delay_ms(400); _delay_ms(400); _delay_ms(400); }


void attention(void)
{int j=0;
do {USARTWriteChar(at[j]); j++; }
while(at[j-1]!='\0');
delay3s(); }


// THE READ FUNCTION 

void read(void) {int mark=0;i=0; 
do {dta[i]=USARTReadChar(); 
if(dta[i]=='\r' && mark==0) mark=1; 
if(dta[i]=='\r' && mark==1) mark=3; 
i++;}
while((dta[i-1]!='\r') && (mark!=3)); }

//--------------------------------------------------
//              THE MAIN FUNCTION                   
//--------------------------------------------------


int main(void)
{
_delay_ms(50); sei();	//ENABLE GLOBAL INTRPT
USARTInit(207); 	//UBRR = 207 baud 2400
InitLCD(LS_BLINK);  LCDGotoXY(0,0);	//INITIALIZE THE LCD
UCSRB |= (1<<TXEN);UCSRB |= (1<<RXEN); // enable tx and rx
attention(); 

while(1){

attention();  

read(); //UCSRB &= (~(1<<RXEN));UCSRB &= (~(1<<TXEN));
_delay_ms(400);LCDClear();_delay_ms(400);

for(int dis=0;dis<=5;dis++)
{
LCDGotoXY((2*dis),1);
LCDWriteInt(dta[dis], 2);
_delay_ms(400);_delay_ms(400);
}
delay3s();

}

return 0;
}

tell me if u need anything more...

you can see that, I've used attention() function once before the while() loop because i don't know why but for the 1st time the phone was giving junk data and from the 2nd time it was giving OK in the terminal.(I've bypassed a single line to terminal to see what's happening between mcu and phone)...
 
Last edited:

I checked the UART code and it seems OK. The only thing I've noticed is that you are using 2400 baudrate. Does the modem have autobaud capability? Or 2400 is the default baudrate? Because the provided code does not set modem's baudrate.

ROCKET SCIENTIST said:
Someone told me that the phone response format is" LF CR OK LF CR "
The modem I use responds as follows:
CR LF OK CR LF

If this is the case with your modem as well, all CR and LF must change position with each other inside your code.
 

Thanx a lot alexxx for helping me out this far. I'll be so thankful to you.
I'm using sony ericsson k300i phone. It has autobaud function but I made a mistake . I set the baud as 2400. Now I don't know the command that returns the phone to it's autobaud function... :(
so u think I should interchange CR and LF. Well, when tested with LCD, I used int value to show on display because LF and CR are non printable. On display I got something like this [10 13 00 00 00 00] 10<=> LF and 13<=>CR so seems like my modem sends LF first. Okay, but I'll try your idea.

RS.
 
  • Like
Reactions: alexxx

    alexxx

    Points: 2
    Helpful Answer Positive Rating
ROCKET SCIENTIST said:
Okay, but I'll try your idea.
It would be better if you found a datasheet of the modem included in this phone, rather than trying ideas! :)


ROCKET SCIENTIST said:
Now I don't know the command that returns the phone to it's autobaud function
There must be a "restore factory settings command". AT&F0 is for my modem.

---------- Post added at 21:17 ---------- Previous post was at 21:09 ----------

Here is the modem's datasheet.
**broken link removed**

I failed to notice any <LF><CR> sequence.
By the way it seems that the "restore factory settings" command is "AT&F".

Hope this helps,
Alexandros
 
Thanx alexxx,
I'm extremely sorry for giving u wrong info..My mistake... My LCD also shown CR LF sequence... and I modified the read function as
Code:
void read(void){ int mark=0;
for(int i=0; i<=50; i++)
{dta[i]=USARTReadChar(); 
if     ( (dta[i]=='\n') && (mark==0) ) mark=1; 
else if( (dta[i]=='\n') && (mark==1) ) mark=2;
else if( (dta[i]=='K') && (mark==2) ) {mark=3;break;}
} }

and now I'm getting all characters CR LF O K .... It's working !!!

Thanx for the datasheet and command line... You are a great helper..

RS
 
  • Like
Reactions: alexxx

    alexxx

    Points: 2
    Helpful Answer Positive Rating
Status
Not open for further replies.

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top