|
|
View previous topic :: View next topic |
Author |
Message |
sliders_alpha
Joined: 03 Mar 2008 Posts: 55
|
receiving a RS232 signal,should be easy but it's not working |
Posted: Sat Mar 21, 2009 6:20 am |
|
|
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
|
Re: receiving a RS232 signal,should be easy but it's not wor |
Posted: Sat Mar 21, 2009 2:12 pm |
|
|
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
|
|
Posted: Sat Mar 21, 2009 2:36 pm |
|
|
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
|
|
Posted: Sat Mar 21, 2009 3:48 pm |
|
|
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
|
|
Posted: Sat Mar 21, 2009 7:44 pm |
|
|
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
|
|
Posted: Sun Mar 22, 2009 5:36 am |
|
|
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
|
|
Posted: Sun Mar 22, 2009 7:57 am |
|
|
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
|
|
Posted: Sun Mar 22, 2009 11:57 am |
|
|
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
|
|
Posted: Sun Mar 22, 2009 6:45 pm |
|
|
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
|
|
Posted: Mon Mar 23, 2009 3:01 pm |
|
|
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
|
|
Posted: Wed Mar 25, 2009 1:22 pm |
|
|
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
|
|
Posted: Wed Mar 25, 2009 1:48 pm |
|
|
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
|
|
Posted: Thu Mar 26, 2009 1:35 am |
|
|
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
|
|
Posted: Sat Mar 28, 2009 1:46 am |
|
|
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
|
|
Posted: Tue Mar 31, 2009 12:02 pm |
|
|
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 |
|
|
|
|
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
|