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

receiving a RS232 signal,should be easy but it's not working
Goto page 1, 2  Next
 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

receiving a RS232 signal,should be easy but it's not working
PostPosted: Sat Mar 21, 2009 6:20 am     Reply with quote

hi,

I must, for my graduation project, do a "mother-clock" which retrieve time from a GPS module (EM-406A) and then send it to a lot of "daughter-clock" and siren.

BUT

I can't manage to read the RS232 signal which come from the GPS module.

Here is a picture :


As you can see, it's a 4800baud, parity EVEN, 8 bits and with 2 stop bit signal.

But can CCS handle it? I can't set the amount of stop bit in the RS232 declaration.

My issue is : I'm waiting for the line to be ready (at least 1L for 100ms) and then I do a gets or a getc, but those to wait forever in 95%.

Here is more, I'm going to try to describe those :



As you can see, B2 is going low when the line is ready and then B3 is going HIGH when gets start (and will go LOW when gets stop)

and gets wait for ever

Another (a successful catch this time) : sometimes, it works, IF the first getc can read it then ALL the other getc will succeed (each time a getc is done output_toggle is done on b3).



Why are my gets and getc failing so much? do you have any ideas?

Here is my code :
Code:

#include <16F876A.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#USE RS232(BAUD=4800, XMIT=PIN_C6, RCV=PIN_C7, PARITY= E, bits = 8)
#include <Lcd_drivers.c>

int ok = 0;

int wait_for_line(void);
char timed_getc(void);

#INT_TIMER0
void timer0_isr(void)
   {
   ok++;
   }

void main(void)
   {
   char test[15];
   char ini[] = "en attente";
   char ok[] = "ok";              //init variable
   output_low(pin_b2);
   output_low(pin_b3);

    enable_interrupts(INT_TIMER0);//De-masquage de l'IT timer0
    enable_interrupts(GLOBAL);    //DM global
   
    setup_timer_0 (RTCC_DIV_256);
    delay_ms(100);
    output_low(PIN_A4);  //RW
    LCD_init();
    LCD_curseur_pos(1,1);
    LCD_send_string(ini);

   output_high(pin_b2);
   wait_for_line();
   output_low(pin_b2);

   output_high(pin_b3);
   //gets(test);
   test[0] = getc();
   output_toggle(pin_b3);
   test[1] = getc();
   output_toggle(pin_b3);
   test[2] = getc();
   output_toggle(pin_b3);
   test[3] = getc();
   output_toggle(pin_b3);
   test[4] = getc();
   output_toggle(pin_b3);
   test[5] = getc();
   output_toggle(pin_b3);
   test[6] = getc();
   output_toggle(pin_b3);
   test[7] = getc();
   output_toggle(pin_b3);
   test[8] = getc();
   output_toggle(pin_b3);
   test[9] = getc();
   output_toggle(pin_b3);
   test[10] = getc();
   output_toggle(pin_b3);
   test[11] = getc();
   output_toggle(pin_b3);
   test[12] = getc();
   output_toggle(pin_b3);
   test[13] = getc();
   output_toggle(pin_b3);
   test[14] = getc();
   output_toggle(pin_b3);


   LCD_curseur_pos(15,1);
   LCD_send_string(ok);
   LCD_curseur_pos(1,2);
   lcd_send_car(test[0]);lcd_send_car(test[1]);lcd_send_car(test[2]);
   lcd_send_car(test[3]);lcd_send_car(test[4]);lcd_send_car(test[5]);
   lcd_send_car(test[6]);lcd_send_car(test[7]);lcd_send_car(test[8]);
   lcd_send_car(test[9]);lcd_send_car(test[10]);lcd_send_car(test[11]);
   lcd_send_car(test[12]);lcd_send_car(test[13]);lcd_send_car(test[14]);


   }

int wait_for_line(void)
   {
   while(1)
      {
      while(!input(PIN_C7)){}
      ok = 0;
      set_timer0(0);
      while(ok!=5 && input(PIN_C7)){}
      if (ok == 5)
         {return(1);}
      }
   }

_________________
yup, i know, i don't speak english very well

CCS V4.057
RLScott



Joined: 10 Jul 2007
Posts: 465

View user's profile Send private message

Re: receiving a RS232 signal,should be easy but it's not wor
PostPosted: Sat Mar 21, 2009 2:12 pm     Reply with quote

sliders_alpha wrote:
hi,
...As you can see, it's a 4800baud, parity EVEN, 8 bits and with 2 stop bit signal.

But can CCS handle it? I can't set the amount of stop bit in the RS232 declaration...

That is not necessary for receiving. An extra stop bit looks exactly the same as a pause between characters when it is being received by a UART that is only expecting one stop bit. The receiving UART will happily wait until the next start pulse to start receiving the next character.
_________________
Robert Scott
Real-Time Specialties
Embedded Systems Consulting
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Mar 21, 2009 2:36 pm     Reply with quote

Some details of your code are hard to understand, e.g. the purpose of wait_for_line(). I simply want to doubt, if similar actions are necessary with signal sourced from a TX UART, that can be most effectively processed by a receiving UART rather than polling an input pin.

I also have difficulties with your description, cause gets() isn't used in the present code. Gets() actually would be one candidate for a piece of code that "waits forever" (if no <CR> comes along). I think, I never used it in any embedded software up to now. wait_for_line() is the other candidate.

An example of the expected data packet would be more helpful than waveforms, I think.
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Sat Mar 21, 2009 3:48 pm     Reply with quote

I see, thanks RLScott =D

wait_for_line() is waiting for a 1L of at least 100ms (i don't want to read in the middle of a data packet)

You don't see any gets because this is the getc version.

Just replace this :
Code:

   output_high(pin_b3);
   //gets(test);
   test[0] = getc();
   output_toggle(pin_b3);
   test[1] = getc();
   output_toggle(pin_b3);
   test[2] = getc();
   output_toggle(pin_b3);
   test[3] = getc();
   output_toggle(pin_b3);
   test[4] = getc();
   output_toggle(pin_b3);
   test[5] = getc();
   output_toggle(pin_b3);
   test[6] = getc();
   output_toggle(pin_b3);
   test[7] = getc();
   output_toggle(pin_b3);
   test[8] = getc();
   output_toggle(pin_b3);
   test[9] = getc();
   output_toggle(pin_b3);
   test[10] = getc();
   output_toggle(pin_b3);
   test[11] = getc();
   output_toggle(pin_b3);
   test[12] = getc();
   output_toggle(pin_b3);
   test[13] = getc();
   output_toggle(pin_b3);
   test[14] = getc();
   output_toggle(pin_b3);


by this :
Code:

output_high(pin_c3);
gets(data); //data is 80 char long
output_low(pin_c3);

Both versions are waiting forever, getc and gets.

I'm expecting a NMEA string which is enden by a <CR>

http://www.sparkfun.com/datasheets/GPS/EM-406A_User_Manual.PDF
page 5
_________________
yup, i know, i don't speak english very well

CCS V4.057
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Sat Mar 21, 2009 7:44 pm     Reply with quote

A gps chirps when it wants. Most will want to use an isr triggered on the receipt of a char. The isr places the received char into a circular buffer.
In this way no char from the gps is lost. The main routine reads the buffer with the captured gps sentence. CCS has examples of using a circular buffer to receive RS232. C'est pas facile au meme c'est pas si complique
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Sun Mar 22, 2009 5:36 am     Reply with quote

i've tried one time to read datapacket with isr but i wasn't able to read the fist packet, the first was trigering my isr and then my program was reading the rest (NOT with this, on a other project,)

so, i've done that : (in real life not in simulation)



and i put those two program inside those pic, 16f877A is sending "$G" each 800ms and the 16F876A is trying to catch them.

as you can see i've use the same parameters in both program :

emmiter program :

Code:

#include <16F877A.H>
#fuses XT, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 4000000)
#USE RS232(BAUD=4800, XMIT=PIN_C6, RCV=PIN_C7, PARITY= E, bits = 8)

void main(void)
   {
   char lol[] = "$GP";

   while(1)
      {
     
      puts(lol);
      delay_ms(800);
      }
   }   


no need to explain this one

receiver progam

Code:

#include <16F876A.H>
#fuses HS, NOWDT, NOPROTECT, BROWNOUT, PUT, NOLVP
#use delay(clock = 20000000)
#include <lcd_drivers.c>
#USE RS232(BAUD=4800, XMIT=PIN_C6, RCV=PIN_C7, PARITY= e, bits = 8)

int ok = 0;

#INT_TIMER0
void timer0_isr(void)
   {
   ok++; //each time timer0 is overloading, ok is incremented
   }

int wait_for_line(void);

void main(void)
   {
   char test[2];////////////////
   char ini[] = "en attente"; //var init
   char ok[] = "OK";          //
   /////////////////////////////
   
   /////////////////////////////////init IT
   enable_interrupts(INT_TIMER0); //De-masquage de l'IT rs232
   enable_interrupts(GLOBAL);     //DM global
   /////////////////////////////////
   
   ///////////////////////INIT LCD & control pin
   delay_ms(200);       //
   output_low(PIN_A4);  //RW low
   LCD_init();          //
   output_low(pin_b2);  //
   output_low(pin_b3);  //
   ///////////////////////
   
   ///////////////////////
   LCD_curseur_pos(1,1);//printing "waiting"
   LCD_send_string(ini);//         
   ///////////////////////
   
   //////////////////////
   output_high(pin_b2);//
   wait_for_line();    //waiting for the line to be ready
   output_low(pin_b2);///i don't want to sample in the middle
   //////////////////////of a data packet
   
   /////////////////retriving
   test[0]=getc();//$
   test[1]=getc();//G
   /////////////////
   
   ////////////////////////
   LCD_curseur_pos(15,1);//
   LCD_send_string(ok);  //printing ok
   LCD_curseur_pos(7,2); //and the 2 char retrivied before
   lcd_send_car(test[0]);//
   lcd_send_car(test[1]);//
   ////////////////////////

   }
   

int wait_for_line(void)
   {
   while(1)
      {
      while(!input(PIN_C7)){}//if RX == 0L wait for a 1L
      /////////////////
      ok = 0;        //set ok to 0
      set_timer0(0); //set time to 0
      /////////////////
      while(ok!=5 && input(PIN_C7)){}////while RX == 1L and ok !=5 do nothing
      ///////////////////////////////////
      if (ok == 5)                     //if when coming out from while(ok!=5 && input(PIN_C7))
         {return(1);}                  //ok = 5, then the line is ready, return then sent us back to the main program,
      }//////////////////////////////////if not, where in the middle of a data packet then we start again
   }


i've watched what is going on with an oscilloscope and it's the same, wait for line is waiting, then getc() is launched and then it wait for ever.

i think it's CCS fault, what about you?
should i write my own getc() fonction?

also, how do you call all those data packet? in french its called a "tramme"

thanks
_________________
yup, i know, i don't speak english very well

CCS V4.057
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sun Mar 22, 2009 7:57 am     Reply with quote

I guess, your problem is related to Microchip's UART behaviour.
Quote:
If the receive FIFO is overrun, no additional characters will be received until the overrun condition is cleared.

In your code, overruns are unfortunately forced by wait_for_line(), I think.

You can simply cause CCS C to reset any UART errors automaticly.
Code:
#USE RS232(BAUD=4800, XMIT=PIN_C6, RCV=PIN_C7, PARITY= e, bits = 8,errors)

Apart from this problem, the code is supposed to work. Also gets() is O.K. with NMEA-0183 packets, cause they have a terminating <CR>. Cause they also have an unique start character, there would be a simple and effective replacement for wait_for_line() to my opinion.
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Sun Mar 22, 2009 11:57 am     Reply with quote

this indeed worked, thanks a lot =D
_________________
yup, i know, i don't speak english very well

CCS V4.057
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Sun Mar 22, 2009 6:45 pm     Reply with quote

Those are nice scope images. Can you tell us what hardware & software you used to get them?
_________________
The search for better is endless. Instead simply find very good and get the job done.
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Mon Mar 23, 2009 3:01 pm     Reply with quote

i'll check that wednesday (i don't think its written this way =D) because i won't have access to our electronic labs before
_________________
yup, i know, i don't speak english very well

CCS V4.057
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Wed Mar 25, 2009 1:22 pm     Reply with quote

i did those reading with an MSO6034A from agilent technologies.

and i don't know if it's me or not but they are selled at 12000$, i mean, WOW we have more than then of them, i didn't know that my highschool was so rich
_________________
yup, i know, i don't speak english very well

CCS V4.057
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Wed Mar 25, 2009 1:48 pm     Reply with quote

All recent Agilent scopes, starting from economy 3000 series, can print a waveform hardcopy to an USB memory or show it on a web server, you don't need a 6xxx model. Other leading manufacturers as Tektronix or LeCroy have basically similiar features, also low cost Asian products most likely have.
Douglas Kennedy



Joined: 07 Sep 2003
Posts: 755
Location: Florida

View user's profile Send private message AIM Address

PostPosted: Thu Mar 26, 2009 1:35 am     Reply with quote

Here is some sample code if it helps
I always use an isr and a buffer when working with an external asynchronous device like a GPS

Code:

byte gps_buff[BUFFER_SIZE]; // implemented as a circular buffer
#int_rda
void gps_isr()
{
char c;

/// note this routine needs to as short as possible since it is called
/// for each char received from GPS

c=RCREG ; // get data from RCREG hardware clears RCIF

if (c=='$') { sentence=true;output_low(LED1);return;} // new sentence

if(sentence){
     
      gps_buff[next_gps_ptr]=c;
      if (++next_gps_ptr>sizeof(gps_buff)) next_gps_ptr=0; // circular  buffer
      if((c==10)||(c==13)) {sentence=false;output_high(LED1);}
     
            }

}

///////////////////////////////////////////////////////////////////
///////////////////////////// subs //////////////////////////////
//////////////////////////////////////////////////////////////////

int gps_getc()
{
/// this is blocking just as getc is blocking ( waits for char)
/// to unblock remove the wait loop and set a flag or default to
/// a special char EX @ to indicate circular buffer is waiting for GPS

char c;
int next_char_ptr;
next_char_ptr=last_read_ptr+1;
if (next_char_ptr>sizeof(gps_buff))next_char_ptr=0;


// there is data available if next_gps_ptr != next_char_ptr

wait:  // data from gps will allow isr to update gps_ptr

if (next_gps_ptr == next_char_ptr) goto wait; // let gps advance
else        {
             c=gps_buff[next_char_ptr];
             if(c=='*')PARSING=false; // PARSING is reset in main loop
             last_read_ptr=next_char_ptr;
             if (PARSING) GPS_CRC=GPS_CRC ^ c; // calc between $ and *
            }
return(c);
}

int get_gps_CRC()
{
// get hex CRC immediately after the *
char hh,hl;

hh=gps_getc();
if (hh-'0'<10) hh=hh-'0';else hh=hh-'A'+10;
hl=gps_getc();
if (hl-'0'<10) hl=hl-'0';else hl=hl-'A'+10;


return hh*16+hl;
}

int get_gps_str( char * s)
{
// extract the item up to the next ',' or '*'
char c;
int len;
len=0;
c=gps_getc();

while ((c!=',') && (c!='*') && (len<10))
       {
        if ( (c>' ') && (c<'~') ) s[len++]=c;
        c=gps_getc();
       
       }
s[len]=0; // null terminate
return(len);
}
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Sat Mar 28, 2009 1:46 am     Reply with quote

Code:
c=RCREG

Ao that how you retrieve a char that was store inside the buffer?

Because when I was trying to do it by interrupt, I was always missing the first one (which was triggering the interrupt).

thanks for your code

Quote:

Apart from this problem, the code is supposed to work. Also gets() is O.K. with NMEA-0183 packets, cause they have a terminating <CR>. Cause they also have an unique start character, there would be a simple and effective replacement for wait_for_line() to my opinion.


I don't think you can use gets without wait_for_line().

Because if gets() is launch in the middle of a data packet ans in the middle of a string, won't i miss the <CR> char?




Anyway, I've succeeded in receiving a datastring, looking for "$GPGAA," and then extracting time.

I'll try to do it with interruption when I'll have a fully working board (this part work, lets do the other, I've 15 week left)
_________________
yup, i know, i don't speak english very well

CCS V4.057
sliders_alpha



Joined: 03 Mar 2008
Posts: 55

View user's profile Send private message

PostPosted: Tue Mar 31, 2009 12:02 pm     Reply with quote

i, once again, require your help.

this board require 2 RS232 port, one for the GPS module and one for a computer (setting when alarm should be triggered, time zone, etc).

i've put the computer RS232 on C6 and C7, and the GPS RS232 on B4 and B5

would i be able to read data from the gps by interrupt?
_________________
yup, i know, i don't speak english very well

CCS V4.057
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Goto page 1, 2  Next
Page 1 of 2

 
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