I have to make this project for my school but i can't make it run. I've problems with message extraction and with the interrupt. Please help. This is my code
#include <reg51.h> #include <string.h> sbit Water=P2^0; sbit Window=P2^1; //declarations void clear(void); void tx0(unsigned char); void delay_sms (unsigned int); void SMSString(char*text) ; void init(); void read_text(unsigned char * , unsigned char * , unsigned char *); unsigned char j,abc; unsigned char idata msg1[150]; unsigned char rec_no[20]; unsigned char time_date[20]; unsigned char choice=0; unsigned char idata tmp10[16]; void serial () interrupt 4 { msg1[abc]=SBUF; abc++; RI=0; } void main (void) { clear(); init(); Window=0; Water=0; SMSString("AT\r"); // AT commands to initialize gsm modem delay_sms(1000); SMSString( "ATe0\r"); // turn off echo delay_sms(1000); SMSString( "AT&W\r"); // save settings delay_sms(1000); SMSString( "AT+CMGF=1\r"); // select text mode for sms delay_sms(1000); SMSString( "AT+CNMI=2,1,0,0,0\r"); // notification of new sms delay_sms(1000); SMSString( "AT+CMGR=1\r"); // AT command to read sms delay_sms(1000); do { IE=0X90; // Enable serial interrupt delay_sms(1000); // i get a response like this // +CMGR: "REC UNREAD","+3069********",,"11/04/09,11:26:48+12" // Window on // OK // I think that's the format the 8051 get +CMTI: "SM",1\r+CMGR: "REC UNREAD","+306982037789",,"11/04/09,11:26:48+12"\rStatus\n\rOK\r // read sms and store in buffer msg1 read_text(msg1,rec_no,time_date); if(strncmp("Water on",msg1,8)==0) { Water=1; strncpy(tmp10,"Water Window ",16); tmp10[6]=Water; tmp10[15]=Window; SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } else if(strncmp("Water off",msg1,9)==0) { Water=0; strncpy(tmp10,"Water Window ",16); tmp10[6]=Water; tmp10[15]=Window; SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } else if(strncmp("Window on",msg1,9)==0) { Window=1; strncpy(tmp10,"Water Window ",16); tmp10[6]=Water; tmp10[15]=Window; SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } else if(strncmp("Window off",msg1,10)==0) { Window=0; strncpy(tmp10,"Water Window ",16); tmp10[6]=Water; tmp10[15]=Window; SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } else if(strncmp("Status",msg1,6)==0) { strncpy(tmp10,"Water Window ",16); tmp10[6]=Water; tmp10[15]=Window; SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } else { SMSString("AT+CMGS=\""); SMSString(rec_no); SMSString("\"+<CR>\r"); delay_sms(1000); SMSString("Wrong Command"); SMSString("\n\r"); delay_sms(1000); SMSString(rec_no); delay_sms(1000); SMSString(msg1); delay_sms(1000); } SMSString("AT+CMGD=1\r"); delay_sms(1000); IE=0X00; // Disable serial interrupt delay_sms(1000); } while(1); } void init(void) { j=0; abc=0; TL1=0XFD; //9600 @ 11.0592 TH1=0xFD; TMOD=0x20; SCON=0x50; TR1=1; } void SMSString(unsigned char* text) //function to send SMS using GSM modem { while (*text) { tx0(*text++); } } void tx0(unsigned char x) //send data to serial port 0 { EA=0; SBUF=x; while(TI==0); TI=0; EA=1; } void delay_sms (unsigned int count) { unsigned int i; while(count) { i = 115; while(i>0) i--; count--; } } void read_text( unsigned char *msg,unsigned char *no ,unsigned char *time) { unsigned char *temp; temp=msg; do msg++; while(*msg!='+'); do msg++; while(*msg!='+'); do msg++; while(*msg!='+'); // reaching number do *no++=*msg++; while(*msg!='"'); // reaching time *no++='\0'; msg++; msg++; msg++; do *time++=*msg++; while(*msg!='"'); // reaching message *time='\0'; do msg++; while(*msg!='\r'); msg++; do *temp++=*msg++; while(*msg!='\n'); // reaching the end of message *temp='\0'; } void clear(void) { unsigned char a; for(a=0;a<100;a++) msg1[a]=0x00; }
The delay_sms() creates a delay in ms, e.x. delay_sms(1000) creates 1sec delay. maybe today, maybe tomorrow, maybe not next week
NOBODY knows what a compiler will do to a delay routine, delays MUST be done in assemble or with timers
Also, why is there no indentions in your code, it is very tough to read
Erik
I fix some of the errors you indicated me but still the code is not running properly. I can receive whatever i sent with the SMSString() but i can't receive the sms to the microcontroller and of course i can't get the phone number and the message from it. This is my fixed code
#include <reg51.h> #include <string.h> sbit Water=P2^0; sbit Window=P2^1; //declarations void clear(void); void tx0(unsigned char); void delay_sms (unsigned int); void SMSString(char*text) ; void init(); void Status(); void init_modem(); void process_modem_character(unsigned char *); unsigned char idata phone[15]; // Store received phone number unsigned char idata msg1[100]; // Store received message unsigned char j,abc; //unsigned char idata tmp10[27]; void serial () interrupt 4 using 1 { if(RI) //receive mode { RI=0; abc=SBUF; if(abc<100) { msg1[abc++]=SBUF; } else { RI=1; } } } void main (void) { clear(); init(); init_modem(); do { IE=0X90; // Enable serial interrupt delay_sms(1000); // i get a response like this // +CMGR: "REC UNREAD","+3069********",,"11/04/09,11:26:48+12" // Window on // OK // I think that's the format the 8051 get // \+CMTI\: \"SM\",1\r+CMGR: \"REC UNREAD\"\,\"+306982037789\"\,\,\"11\/04\/09\,11\:26\:48\+12\"\rStatus\n\rOK\r process_modem_character(msg1); // read sms and store it if(strncmp("Water on",msg1,8)==0) { Water=1; Status(); } else if(strncmp("Water off",msg1,9)==0) { Water=0; Status(); } else if(strncmp("Window on",msg1,9)==0) { Window=1; Status(); } else if(strncmp("Window off",msg1,10)==0) { Window=0; Status(); } else if(strncmp("Status",msg1,6)==0) { Status(); } else { SMSString("AT+CMGS=\""); SMSString(phone); SMSString("\"+<CR>\r"); delay_sms(1000); SMSString("Wrong Command"); SMSString("\n\r"); delay_sms(1000); SMSString(phone); delay_sms(1000); SMSString(msg1); delay_sms(1000); } SMSString("AT+CMGD=1\r"); delay_sms(1000); IE=0X00; // Disable serial interrupt delay_sms(1000); } while(1); } void init(void) { j=0; abc=0; TL1=0XFD; //9600 @ 11.0592 TH1=0xFD; TMOD=0x20; SCON=0x50; TR1=1; } void SMSString(unsigned char* text) //function to send SMS using GSM modem { while (*text) { tx0(*text++); } } void tx0(unsigned char x) //send data to serial port 0 { EA=0; SBUF=x; while(TI==0); TI=0; EA=1; } void delay_sms (unsigned int count) { unsigned int i; while(count) { i = 115; while(i>0) i--; count--; } } void init_modem(void) { Window=0; Water=0; SMSString("AT\r"); // AT commands to initialize gsm modem delay_sms(1000); SMSString( "ATe0\r"); // turn off echo delay_sms(1000); SMSString( "AT&W\r"); // save settings delay_sms(1000); SMSString( "AT+CMGF=1\r"); // select text mode for sms delay_sms(1000); SMSString( "AT+CNMI=2,1,0,0,0\r"); // notification of new sms delay_sms(1000); SMSString( "AT+CMGR=1\r"); // AT command to read sms delay_sms(1000); } void Status(void) { //tmp10 = sprintf( SBUF, "Water is %s and Window is %s\n" , Water, Window); SMSString("AT+CMGS=\""); SMSString(phone); SMSString("\"+<CR>"); delay_sms(1000); //SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } enum States { STATE_IDLE, STATE_FIND_CMT, STATE_CMT_GET_NUMBER, STATE_CMT_GET_COMMA, STATE_CMT_GET_MSG_START, STATE_CMT_GET_MSG, } state = STATE_IDLE; const char* pattern; int ch; void process_modem_character(unsigned char*msg) { switch (state) { case STATE_IDLE: if (msg == '+') { state = STATE_FIND_CMT; pattern = "\+CMTI\: \"SM\",1\r+CMGR: \"REC UNREAD\"\,\""; } break; case STATE_FIND_CMT: if (*pattern != msg) { state = STATE_IDLE; } else { pattern++; if (*pattern == '\0') { state = STATE_CMT_GET_NUMBER; ch = 0; } } break; case STATE_CMT_GET_NUMBER: if (msg == '\"') { state = STATE_CMT_GET_COMMA; } else if (ch >= sizeof(phone)) { // Too long phone number :( state = STATE_IDLE; } else { ch++; phone[ch] = *msg; phone[ch] = '\0'; } break; case STATE_CMT_GET_COMMA: if (msg == ' ') { ; // Ignore white space } else if (msg == ',') { state = STATE_CMT_GET_MSG_START; } else { // Invalid character received state = STATE_IDLE; } break; default: // Invalid state. state = STATE_IDLE; } // switch } // process_modem_character void clear(void) { unsigned char a; for(a=0;a<100;a++) msg1[a]=0x00; }
Please help
This is not how to receive data:
void serial () interrupt 4 using 1 { if (RI) { //receive mode RI=0; abc=SBUF; if(abc<100) { msg1[abc++]=SBUF; } else { RI=1; } } }
Seems more like random changes.
Look at standard example code for receiving serial data in interrupt handler. But abc (which you haven't still renamed to something meaningful) should not be assigned from SBUF - for every character received on the UART you may only read one (1) time from SBUF.
And you call process_modem_character(msg1) without caring if msg1 contains any characters. And your state machine doesn't consume any characters. And you have code like:
if (*pattern != msg) ...
but pattern is a pointer to char and msg is a pointer to unsigned char. Besides mixing char and unsigned char - what does the star do? *pattern would be the character pointed to by pattern. But msg is not a character but a pointer - comparing a character and a pointer isn't meaningful.
Try to implement a ring buffer or incomming data, and have your processing check if the ring buffer have data available. Then eat data and switch states depending on what you find. And keep track of pauses where you have no data or line endings to synchronize your state machine.
You don't get anything to work for the simple reason that you have neither tried to debug this code by running it and comparing what happens with what you expected, nor have you tried to just in your head evaluate these lines and figure out what values the different variables might have and what would happen if you step the code in your head. The major part of writing code is actually stepping the code in the head - we can't run a debugger until we have code, but we must be able to read and understand without debugger to be able to write the code in the first place.
void serial () interrupt 4 using 1 { if (RI) { //receive mode RI=0; abc=SBUF; if(abc<100) { msg1[abc++]=SBUF; } else { RI=1; /////////// this will get you right back into the ISR } } }
I had to reformat your code to verufy this, what is wrong with lining the braces up???, look at the comment above.
abc=SBUF; .... msg1[abc++]=SBUF;
storing in a buffer indexed by the hex value of the character received?????
It looks to me as if you do not believe in the adage "think before you do"
Brace positioning is very much a matter of strongly-held personal preference.
Many people like their braces on the end of the "controlling" line:
if( test ) { // stuff } else { // alternative stuff }
Some people (like me) like their braces alone on a line, aligned with the "controlling" line
Some people (quite inexplicably, IMO) like their braces alone on a line, aligned with the "controlled" line(s)
To name but three.
The important thing is, whatever you choose, to be consistent
plenty more here: en.wikipedia.org/.../Indent_style
I modified my braces and changed the serial interrupt but there is still a lot work to be done.
#include <reg51.h> #include <string.h> #include <stdio.h> sbit Water=P2^0; sbit Window=P2^1; //declarations void clear(void); void tx0(unsigned char); void delay_sms (unsigned int); void SMSString(char*text) ; void init(); void Status(); void init_modem(); void process_modem_character(unsigned char *); unsigned char idata phone[15]; // Store received phone number unsigned char idata msg1[100]; // Store received message unsigned char j,bufcounter; void serial () interrupt 4 using 1 { if (RI) { while(!RI) { RI=0; if(bufcounter<100) { msg1[bufcounter++]=SBUF; } } } } void main (void) { clear(); init(); init_modem(); do { IE=0X90; // Enable serial interrupt delay_sms(1000); // i get a response like this // +CMGR: "REC UNREAD","+3069********",,"11/04/09,11:26:48+12" // Window on // OK // I think that's the format the 8051 get // \+CMTI\: \"SM\",1\r+CMGR: \"REC UNREAD\"\,\"+3069********\"\,\,\"11\/04\/09\,11\:26\:48\+12\"\rStatus\n\rOK\r process_modem_character(msg1); // read sms and store it if(strncmp("Water on",msg1,8)==0) { Water=1; Status(); } else if(strncmp("Water off",msg1,9)==0) { Water=0; Status(); } else if(strncmp("Window on",msg1,9)==0) { Window=1; Status(); } else if(strncmp("Window off",msg1,10)==0) { Window=0; Status(); } else if(strncmp("Status",msg1,6)==0) { Status(); } else { SMSString("AT+CMGS=\""); SMSString(phone); SMSString("\"\n\r"); delay_sms(1000); SMSString("Wrong Command"); SMSString("\n\r"); delay_sms(1000); } SMSString("AT+CMGD=1\r"); delay_sms(1000); IE=0X00; // Disable serial interrupt delay_sms(1000); } while(1); } void init(void) { j=0; bufcounter=0; TL1=0XFD; //9600 @ 11.0592 TH1=0xFD; TMOD=0x20; SCON=0x50; TR1=1; } void SMSString(unsigned char* text) //function to send SMS using GSM modem { while (*text) { tx0(*text++); } } void tx0(unsigned char x) //send data to serial port 0 { EA=0; SBUF=x; while(TI==0); TI=0; EA=1; } void delay_sms (unsigned int count) { unsigned int i; while(count) { i = 115; while(i>0) i--; count--; } } void init_modem(void) { Window=0; Water=0; SMSString("AT\r"); // AT commands to initialize gsm modem delay_sms(1000); SMSString( "ATe0\r"); // turn off echo delay_sms(1000); SMSString( "AT&W\r"); // save settings delay_sms(1000); SMSString( "AT+CMGF=1\r"); // select text mode for sms delay_sms(1000); SMSString( "AT+CNMI=2,1,0,0,0\r"); // notification of new sms delay_sms(1000); SMSString( "AT+CMGR=1\r"); // AT command to read sms delay_sms(1000); } void Status(void) { unsigned char tmp10 = sprintf(msg1 ,"Water is %s and Window is %s\n" , Water, Window); SMSString("AT+CMGS=\""); SMSString(phone); SMSString("\"\n"); delay_sms(1000); //SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); } enum States { STATE_IDLE, STATE_FIND_CMT, STATE_CMT_GET_NUMBER, STATE_CMT_GET_COMMA, STATE_CMT_GET_MSG_START, STATE_CMT_GET_MSG, } state = STATE_IDLE; const unsigned char* pattern; int ch; void process_modem_character(unsigned char*msg) { switch (state) { case STATE_IDLE: if (msg == '+') { state = STATE_FIND_CMT; pattern = "\+CMTI\: \"SM\",1\r+CMGR: \"REC UNREAD\"\,\""; } break; case STATE_FIND_CMT: if (*pattern != msg) { state = STATE_IDLE; } else { pattern++; if (*pattern == '\0') { state = STATE_CMT_GET_NUMBER; ch = 0; } } break; case STATE_CMT_GET_NUMBER: if (msg == '\"') { state = STATE_CMT_GET_COMMA; } else if (ch >= sizeof(phone)) { // Too long phone number :( state = STATE_IDLE; } else { ch++; phone[ch] = *msg; phone[ch] = '\0'; } break; case STATE_CMT_GET_COMMA: if (msg == ' ') { ; // Ignore white space } else if (msg == ',') { state = STATE_CMT_GET_MSG_START; } else { // Invalid character received state = STATE_IDLE; } break; default: // Invalid state. state = STATE_IDLE; } // switch } // process_modem_character void clear(void) { unsigned char a; for(a=0;a<100;a++) msg1[a]=0x00; }
Also i get error C214: illegal pointer conversion
void Status(void) { unsigned char tmp10 = sprintf(msg1 ,"Water is %s and Window is %s\n" , Water, Window); SMSString("AT+CMGS=\""); SMSString(phone); SMSString("\"\n"); delay_sms(1000); SMSString(tmp10); SMSString("\n\r"); delay_sms(1000); }
and i don't really understand why.
Stop writing random noise and try to think about everything you write.
tmp10 is a character. Do SMSString expect a character? Doesn't it expect a pointer to one or more characters?
Water and Window are bits. So why do you think %s is good formatting parameters for the sprintf() call? Don't you think bits have some form of integer values? %s is used to print strings, not integers.
Don't post questions as soon as you get stuck. Read the manual. Make sure you have understood the relevant sections in it. Post questions if you can't understand a specific part of the manual or you think you have fulfilled the requirements given in the manual but still get errors. But do not post questions for every compilation error you get or you will never get done with this assignment.