CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Strange behavior while receiving serial port

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

Strange behavior while receiving serial port
PostPosted: Fri Oct 17, 2008 3:29 pm     Reply with quote

Hi,

I'm trying to detect a string over my serial port.
My serial port is connected to a Siemens modem.

The strange think is that I can detect the OK, but I can't detect the confirmation of a sent SMS.

If I send a 'fprintf(pc, "at%c", 0xD);'
and get the response from the serial port to an array, if I print the array everything is ok.
The modem answers an 'at' with <CR><LF>OK<LF><CR>.

So this is my code :
Code:

#include <18F452.h>
#include <stdlib.h>
#include <string.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=pc)

#define led PIN_B7

int32 timeout;

void setup_pic(){
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
}

void envia (char e){
   fputc(e,pc);
}

char recebe (){
   timeout=0;
   // This is an exagerating time ... 5s ...
   while(!kbhit(pc) && (++timeout<500000))
      delay_us(10);
   if(kbhit())
      return fgetc(pc);
   else return 0;
}

void main() {

   int i;
   char teste[80];

   setup_pic();

   output_low(led);

   fprintf(pc,"at%c", 0x0D);

   teste[i]=recebe();
   while(i<5) {
      i++;
      teste[i]=recebe();
   }

   // To know when to change the DB9 to the PC, so i can see the array...
   output_high(led);

   delay_ms(6000);

   for(i=0;i<20;i++)
      fprintf(pc, "  %c  ", teste[i]);
   
   while(TRUE){
      ;
   }
}


To see the output from the array, I had to change manually the RS232 interface from the modem to my PC, when the led goes on.
This is not the best solution for this but it was the hardware that I had Sad
In this case, I could see the OK in the array Very Happy

Now the problem Crying or Very sad
Code:
#include <18F452.h>
#include <stdlib.h>
#include <string.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, stream=pc)

#define led PIN_B7

int32 timeout;

void setup_pic(){
   // 0-output   1-input
   //set_tris_a(0x00);
   //set_tris_c(0x20);
   
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
}

void envia (char e){
   fputc(e,pc);
}

char recebe (){
   timeout=0;
   while(!kbhit(pc) && (++timeout<500000))
      delay_us(10);
   if(kbhit())
      return fgetc(pc);
   else return 0;
}

void main() {

   int i;
   char envia[80][6], teste[80];
   int32 data[80];

   setup_pic();

   output_low(led);
   
   // Initialize with a 'strange' value ...
   for(i=0;i<20;i++) data[i]=i+10;

   // So the output array is not empty ...
   for(i=0;i<20;i++) teste[i]='A';

   // Convert to base64 ... just to save space...
   for(i=0;i<20;i++) itoa(data[i], 64, envia[i]);

   fprintf(pc,"at+cmgf=1%c", 0xD);
   delay_ms(100);

   fprintf(pc,"at+cmgs=123456789%c",0xD);
   delay_ms(100);
   
   fprintf(pc,"1003");
   delay_ms(100);
   
   for(i=0;i<19;i++){
      fprintf(pc,"%s", envia[i]);      
   }
   // Just a way to send ^Z in the end of the message
   fprintf(pc,"%s%c", envia[19], 0x1A);

   i=0;

   // After send the SMS, waits for the response of the modem ...
   // With 'at' works ... with SMS doesn't !!!???
   teste[i]=recebe();   
   while(i<8){
      i++;
      teste[i]=recebe();
   }

   // To know when to change the serial to the PC
   output_high(led);
   
   delay_ms(6000);
   
   for(i=0;i<20;i++)
      fprintf(pc, "  %c  ", teste[i]);
   
   while(TRUE){
      ;
   }
}


I receive the SMS in my mobile, but the output array appears with the first 8 elements empty and the rest is the 'A'.

After the ^Z is send to the modem, the modem response is :
<CR><LF>+CMGS: 123<CR><LF>OK<CR><LF> (so the datasheet says...)
I know that with the condition i<8, i can't get all this ... but i don't get nothing !!! ?????
Is this because of ^Z ?? Does anybody experience something like this before.
I only want to know the answer of the modem to my commands ...
With 'at' works ... but with this doesn't ...
Can anybody help ??

Thank you
Jacob
RayJones



Joined: 20 Aug 2008
Posts: 30
Location: Melbourne, Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 17, 2008 4:17 pm     Reply with quote

Doesn't help with your problem, but why do you use

Code:
  fprintf(pc,"at+cmgf=1%c", 0xD);


When
Code:
  fprintf(pc,"at+cmgf=1\r");

is far easier to read, and less error prone and does exactly the same?

Likewise to send other "oddball" characters, the octal escape sequence is also a better choice.
ie to send a ^Z:
Code:
  fprintf(pc,"\032");


As for your problem, I presume it is taking > 40 seconds to see your LED light up?

Ray
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Fri Oct 17, 2008 5:14 pm     Reply with quote

Hi Ray.

I've tried with '\n' and it doesn't work... but i must confess that i didn't tried with '\r'. '\n' is equals to <CR> and '\r' is equals to <LF>, so i tried with '\n'. I will try what you've said and must agree with you that is far easier to read and to write like you've suggested Smile

Answering your question ... YES ... it takes about 40 seconds to the led go up Crying or Very sad
Then, it prints the array ... but with the first 8 positions empty ...

The strange thing is that with 'at' it works.
I really don't understand ... something is missing ... i think ...

Help me ...

Thank you
Jacob
RayJones



Joined: 20 Aug 2008
Posts: 30
Location: Melbourne, Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 17, 2008 5:56 pm     Reply with quote

No,

\r = CR
\n = LF

r = Return
n = NewLine

These hark back from the days when a carriage Return did exactly that, it returned the carriage holding the type keys on teleprinters to the left of the platten.
The Newline advanced the platten by one line.

As an aside, if you open a file in text mode, especially under DOS (yes I'm old!), the \n typically is expanded to CR\LF pairs.
This can cause great angst when you are dealing with binary data and you get extra characters :-(

Cheers, Ray
RayJones



Joined: 20 Aug 2008
Posts: 30
Location: Melbourne, Australia

View user's profile Send private message Visit poster's website

PostPosted: Fri Oct 17, 2008 6:03 pm     Reply with quote

If you chat with the modem using the PC, I presume you get the correct responses?

Next thing I'd be trying is to add the ERRORS directive to your #use RS232, especially since you are not reading responses from your prior AT commands, you will most definately have receiver overruns, which will cause the port to shutdown. You can read about this in the #use RS232 help.

Quote:
Warning:
The PIC UART will shut down on overflow (3 characters received by the hardware with a GETC() call). The "ERRORS" option prevents the shutdown by detecting the condition and resetting the UART.

Ray
ckielstra



Joined: 18 Mar 2004
Posts: 3680
Location: The Netherlands

View user's profile Send private message

PostPosted: Fri Oct 17, 2008 6:28 pm     Reply with quote

Try to simplify your test, now there are too many things that can go wrong.

Try using simple and fixed test texts. itoa() with base64 is not common. The CCS implementation will generate characters like '<', '>' and '@' with possible strange side effects on the modem's handling of the data.
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Oct 18, 2008 3:08 am     Reply with quote

Hi.

Yes Ray, with the PC everything works and i can see the answer of the modem...

One thing... if i activate the ERRORS options in '#use rs232', how can i 'catch' (printf) the ERRORS from the serial port ? I don't know how to do that Sad ... and i think that is very important for debugging Smile

Ckielstra,

i get the SMS correct in my mobile... and i think that itoa with base 64, just send ascii values that the modem understands ... so i say ...
But ... when i send an SMS using the PC ... i never have send strange chars ...I will try your suggestion ... i will put a fixed message and send it.

I'll wait for more feedback about the ERRORS.
Thank you for your attention
Jacob
jjacob



Joined: 08 Mar 2008
Posts: 54
Location: PORTUGAL (PORTO)

View user's profile Send private message

PostPosted: Sat Oct 18, 2008 10:46 am     Reply with quote

Hi all ...

After a few hours of experience, this code works !!!
And ... i changed the hardware, so i wouldn't have to change the DB9 manually Very Happy

Code:

#include <18F452.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>

#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600, BITS=8, PARITY=N, STOP=1, xmit=PIN_A2, rcv=PIN_A3, stream=modem)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS, stream=pc)

#define led PIN_B7

int32 timeout;

void envia (char e){
   fputc(e,modem);
}

char recebe (){
   timeout=0;
   while(!kbhit(modem) && (++timeout<50000))
      delay_us(10);
   if(kbhit())
      return fgetc(modem);
   else return 0;
}

int detect_at(){
   int i;
   char teste[10];
   
   recebe();
   recebe();
   
   teste[i]=recebe();   
   while(i<2){
      i++;
      teste[i]=recebe();
   }
   recebe();
   recebe();
   
   if(teste[0]=='O' && teste[1]=='K') return 1;
   else return 0;   
}

int detect_sms_send(){
   int i;
   char teste[30];
   
   for(i=0;i<5;i++)
         recebe();

   i=0;

   teste[i]=recebe();   
   while(i<6){
      i++;
      teste[i]=recebe();
   }

   if(teste[0]=='+' && teste[1]=='C' && teste[2]=='M') return 1;
   else return 0;
}

void setup_pic(){
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
}

void main() {

   int i;
   char envia[80][6], mobile[20], station_id[20], teste[80];
   int32 data[80];

   setup_pic();

   fprintf(pc,"\n\r TEST 123 !!!!!!\n\r");

   output_high(led);
   delay_ms(500);
   output_low(led);
   delay_ms(500);
   
   for(i=0;i<20;i++) data[i]=i+10;
   for(i=0;i<30;i++) teste[i]='A';

   for(i=0;i<20;i++) itoa(data[i], 64, envia[i]);

   i=0;

   fprintf(modem,"at+cmgf=1\r");
   if(detect_at()){
      output_high(led);
      delay_ms(500);
      output_low(led);
      delay_ms(500);
      
      output_high(led);
      delay_ms(500);
      output_low(led);
   } else {
      output_high(led);
      delay_ms(300);
      output_low(led);
      delay_ms(300);

      output_high(led);
      delay_ms(1300);
      output_low(led);
   }
   
   fprintf(modem,"at+cmgs=919455818\r");
   delay_ms(100);

   fprintf(modem,"TESTE 123");
   fprintf(modem,"\032");

   if(detect_sms_send()){
      output_high(led);
      delay_ms(500);
      output_low(led);
      delay_ms(500);
      
      output_high(led);
      delay_ms(500);
      output_low(led);
      delay_ms(500);
      
      output_high(led);
      delay_ms(500);
      output_low(led);      
   }else output_high(led);

   while(TRUE){
      ;
   }
}


This code detects the 'OK' after send 'at' and '+CM' after SMS send.
This is very simple and not optimized code. To test the char that are received by the serial port from the modem, the two functions could be optimized or even be one Very Happy

I've tried to use 'ERRORS' but i couldn't ... It always give 'Undefined identifier perror' a compiler error !!
Why ? I would like to use this.
Can anybody explain ?

Thank you.
Jacob
RayJones



Joined: 20 Aug 2008
Posts: 30
Location: Melbourne, Australia

View user's profile Send private message Visit poster's website

PostPosted: Sat Oct 18, 2008 3:22 pm     Reply with quote

Hello Jacob.

I am somewhat confused. You have ERRORS in the code you have pasted, and you say it works OK???

HOWEVER, you have totally refactored the way you talk to the modem.

You are now using a software emulation serial port, and ERRORS is not relevant in that mode.

My suggestion is you look at the assembly code generated in the listing file for the proper hardware serial port with ERRORS enabled and disabled. You will see that the compiler adds code to read the status register to force the overrun errors clear, and mirrors the hardware value into a variable you can pick up in your own code.
If you do not clear the UART errors, the UART will shutdown. By reading the status, the complier avoids this situation.

Because you are using the software serial port to the modem, overruns will not cause a shutdown of the serial port. In fact, unless you go seeking a returned response, the rx data will not even be read!
Usually you setup the SW Rx to use a pin that generates an IRQ on the falling edge of the start bit, then call getch in the IRQ to read the incoming word. Or if you know when data should be coming in, call getch, but it will otherwise hang if no data does actually arrive - not desirable.

Ray
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group