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 support@ccsinfo.com

Garbage in on Software RS232

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



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

Garbage in on Software RS232
PostPosted: Tue Jul 04, 2006 8:10 am     Reply with quote

I'm using two PIC18F452 with 40Mhz clocks (crystal).

They both have wireless radio links connected to the hardware UART that use a serial protocol.

I can communicate between them fine. The problem comes when I set up a software UART to connect one of the boards to a PC.
Due to the fast clock speed, the only speed I could get satisfactory reception was 115,200 baud.

I can transmit data from the PIC to the PC fine, however any character I send from the PC to the PIC is garbage.

It is definitely a problem with the software UART/PC as the radio transmission link works fine (this has been tested by setting the PIC to transmit a character across the radio and for the receiving PIC to echo a string when that particular character is received).

Code is posted below - can anyone see any possible reasons why?

PIC connected to PC
Code:


      
//******************************************************************************
// INCLUDE FILES
#define Fosc 40000000              // I'm using a 40 MHz crystal
#include <18F452.h>
#device *=16 ADC=8
//-------------------------------------------------------------------------------------
// DEFINES
#define WireTX PIN_B0
#define WireRX PIN_B1
//-------------------------------------------------------------------------------------
// COMPILER DIRECTIVES and HARDWARE CONFIGURATION
#use delay(clock = Fosc)

#fuses EC_IO      // EC Oscillator with RA6 configured as DIO
#fuses NOOSCSEN      // Oscillator System Clock Switch Disabled
#fuses NODEBUG      // No Background Debugger
#fuses NOLVP      // Low Voltage ICSP Disabled
#fuses NOPROTECT    // No Code Protect
#fuses NOWDT      // No onboard watchdog
#fuses PUT         // Power Up Timer Enabled
#fuses BROWNOUT      // Brown Out Reset enabled
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS, STREAM=Wireless)
#use rs232(baud=115200, xmit=WireTX, rcv=WireRX, ERRORS, STREAM=Computer)
#byte RCREG = 0x1A

//-------------------------------------------------------------------------------------
// GLOBALS
static char  *c;
int term=0;
//-------------------------------------------------------------------------------------


//Code to add a timeout facility to getc, taken from CCS helpfile
short timeout_error;

char timed_getc() {
long timeout;
timeout_error=FALSE;
timeout=0;
 while(!kbhit(Wireless)&&(++timeout<50000))   // 1/2 second
     delay_us(10);

   if(kbhit())
     return(fgetc(Wireless));
   else {
     timeout_error=TRUE;
     return(0);

   }

}


void clear_usart_receiver(void) {

char d;

d = RCREG;
d = RCREG;
d = RCREG;
}


// MAIN PROGRAM & SETUP
void main()
{
fprintf(Computer,"Receiver online\n\r\n\r");
while(TRUE) {


while(kbhit(Computer)==0)
{
delay_us(1);
output_high(PIN_E2);
}
c = fgetc(Computer);
// delay_ms(50); //Introduced a 50ms delay in case the half duplex requirement of the software UART was the problem - this made no difference
fputc(c,Wireless);


output_low(PIN_E2);



while(1)
{

                  output_low(PIN_E2);
                  
                  c = timed_getc();
                  if(c==0)
                  {
                  fprintf(Computer,"Time out.\n\r\n\r");
                  break;
                  output_high(PIN_E2);
                  }
                  fputc(c,Computer);
                  

} //end of while1

         c=0;
         } //end of while TRUE



} //End of main 


PIC only connected to wireless:

Code:


//******************************************************************************
// INCLUDE FILES
#define Fosc 40000000              // I'm using a 40 MHz crystal
#include <18F452.h>
#device *=16 ADC=8
//-------------------------------------------------------------------------------------
// DEFINES
#define WireTX PIN_B0
#define WireRX PIN_B1
//-------------------------------------------------------------------------------------
// COMPILER DIRECTIVES and HARDWARE CONFIGURATION
#use delay(clock = Fosc)

#fuses EC_IO      // EC Oscillator with RA6 configured as DIO
#fuses NOOSCSEN      // Oscillator System Clock Switch Disabled
#fuses NODEBUG      // No Background Debugger
#fuses NOLVP      // Low Voltage ICSP Disabled
#fuses NOPROTECT    // No Code Protect
#fuses NOWDT      // No onboard watchdog
#fuses PUT         // Power Up Timer Enabled
#fuses BROWNOUT      // Brown Out Reset enabled
#use rs232(baud=19200, xmit=PIN_C6, rcv=PIN_C7, ERRORS, STREAM=Wireless)
#byte RCREG = 0x1A
//-------------------------------------------------------------------------------------
// GLOBALS
static char  *c;
int count=0;

short timeout_error;

char timed_getc() {
long timeout;
timeout_error=FALSE;
timeout=0;
 while(!kbhit(Wireless)&&(++timeout<50000))   // 1/2 second
     delay_us(10);

   if(kbhit())
     return(fgetc(Wireless));
   else {
     timeout_error=TRUE;
     return(0);

   }

}



void clear_usart_receiver(void)

{

char d;
d = RCREG;
d = RCREG;
d = RCREG;
}




//-------------------------------------------------------------------------------------
// MAIN PROGRAM & SETUP
void main()
{

   while(1)
   {

if(kbhit(Wireless))
               {
                  c = getc();
delay_ms(500); //Introduced a delay between character reception and re-transmission just in case of the software UART on the receiving PIC causing a problem.
ascii(c);
                  fprintf(Wireless, "%c key pressed (COUNT = %d)\n\r",c, count);
                  output_high(PIN_E2);
                  delay_ms(100);
                  output_low(PIN_E2);
                  clear_usart_receiver();
                  count++;



               }
   } //End of while(1)


} //End of main


Any help would be great...

Thanks.
Mark



Joined: 07 Sep 2003
Posts: 2838
Location: Atlanta, GA

View user's profile Send private message Send e-mail

PostPosted: Tue Jul 04, 2006 8:57 am     Reply with quote

Do you have an RS232 transceiver between the PIC and the PC? Something like a MAX232.
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

PostPosted: Tue Jul 04, 2006 9:12 am     Reply with quote

Yes. Receiving data from the PIC works fine, its just sending thats the problem.
Ttelmah
Guest







PostPosted: Tue Jul 04, 2006 9:19 am     Reply with quote

The problem is that you cannot use the 'timed getc', at this high rate, with the code as shown. For software serial, the code basically has to be waiting for the first bit to arrive, or no more than a fraction of a bit time 'late', in reaching this point. Each loop in the timed getc, is over 10uSec in length (10usec in the delay, plus the time needed to check the input, and update/check the counter). The bit time of the 115200bps communication, is only 8.68uSec, so you will completely miss the start bit most of the time...
You need to drop the loop time to only a couple of uSec (delay_us(1)), and then it should work.
Realistically, for a timed_getc, with the software serial, at such a high rate, you might be 'better off', using a hardware timer, setting a flag when this triggers, and just waiting while this flag is untrue and no serial is seen.

Best Wishes
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

PostPosted: Wed Jul 05, 2006 2:44 am     Reply with quote

Thanks for the info. That definitely seemed to be it.. however I still have this problem.

I changed the code to launch straight into getc()

Code:

....
fprintf(Computer,"Receiver online\n\r\n\r");
while(TRUE) {
c = fgetc(Computer);
fputc(c,Wireless);

while(1)
c = timed_getc();

....


but I still get garbage...?

I've never had anything successfully transmitted from PC to PIC using software.
How would I go about using a hardware timer?

Doing an echo of the character read in from PIC shows garbage too:

Code:


c = fgetc(Computer);
fprintf(Computer,"Character read in: %c\n\r\n\r", c);



This is really stumping me...
Ttelmah
Guest







PostPosted: Wed Jul 05, 2006 3:17 am     Reply with quote

You will.
It is the delay in the _timed_getc_ function, that will still cause the problem. You must be waiting for _each_ character (not just the first), and the time delay in the timed_getc function, is just too long. As written, it is aimed at data rates like 9600bps, where a few uSec error will not matter, not for use at 115200bps.
something like this ought to work:
Code:

//in the global stuff at the head of the program
#byte INTCON=0xFF2
#bit TMR0IF=INTCON.2

char timed_getc(void) {
   timeout_error=FALSE;
   disable_interrups(GLOBAL);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
   //This sets timer0, to overflow in about 0.8 seconds. Change the
   //prescaler to get different times.
   set_timer0(0);
   clear_interrupt(INT_TIMER0);
   while (!kbhit(Wireless)) {
       //If timer0 overflows, this flag will become set, aborting the wait
       if (TMR0IF) {
           timeout_error=TRUE;
           return(0);
       }
   }
   //If you get this far, kbhit has been seen. Save time, and read.
   return(fgetc(Wireless));
}


Best Wishes
bwgames



Joined: 21 Jul 2005
Posts: 36

View user's profile Send private message

PostPosted: Wed Jul 05, 2006 4:02 am     Reply with quote

There was a typo in "
disable_interrups(GLOBAL); " which I've fixed, however clear_interrupt doesn't appear to be recognised.

I'm guessing you could use

TMR0IF = 0; instead? Tried that and it compiles fine.


However, I seem to have misled everyone.

I'm having no problems reading from/to the wireless.

The problem comes when I'm waiting for input from the PC.

I've adapted your timed_getc to work with the computer input as follows:

Code:

char timed_getc_computer(void) {
   timeout_error=FALSE;
   disable_interrupts(GLOBAL);
   setup_wdt(WDT_OFF);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_128);
   //This sets timer0, to overflow in about 0.8 seconds. Change the
   //prescaler to get different times.
   set_timer0(0);
   TMR0IF = 0; // Clear Timer 0 interrupt flag
   while (!kbhit(Computer)) {
       //If timer0 overflows, this flag will become set, aborting the wait
       if (TMR0IF) {
           timeout_error=TRUE;
           return(0);
       }
   }
   //If you get this far, kbhit has been seen. Save time, and read.
   return(fgetc(Computer));
}


and similarly for wireless, but I still get garbage, even when I do a simple test such as what I pasted earlier:

Code:

do
{
c = timed_getc_computer();
} while(c == 0);

fprintf(Computer,"Character read in: %c\n\r\n\r", c);
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