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

RF Module Message Corruption

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
michaelb[logged out]
Guest







RF Module Message Corruption
PostPosted: Sun Jan 29, 2006 4:51 pm     Reply with quote

Hi,

I'm sending data between an RF Solutions AM-RT4-433 transmitter and a AM-RR3-433. I am sending data between two PIC16F877A's over the UART's using 300 baud. Viewing the incoming singal directly from the receiver it is fine, however once gone through the PIC it is corrupted. Using 4MHz crystal and PCWH 3.212 if that is of any use. Thanks in advance for any help.
Kind Regards,

Michael

Data Sent:
Code:
      printf("%c", 0xBA); // LAM - something for the RX's USART to "lock onto"
      printf("%c", 0xBE); // LAM - something for the RX's USART to "lock onto"
      printf("%c", 0xFA); // LAM - something for the RX's USART to "lock onto"
      printf("%c", 0xCE); // LAM - something for the RX's USART to "lock onto"
      printf("UUUUDUaUtUaU UHUeUrUeU\rU\n");

Lot's of preamble just to make sure Smile

Data Received:
Code:

UUUWU]U=UUoU5U5UU@

or

UUUWU]U=UUoU5U5UU

Something like that


My code is
Code:
#include <16F877.h>                                     //PIC16F877A Device
#device *=16                                            //Use 16 Bit Pointers
#fuses HS,NOWDT,NOPROTECT,NOLVP                         //Set Fuses
#use delay(clock=4000000)                              //20MHz Clock
#use rs232(baud=300, xmit=PIN_C6, rcv=PIN_C7, ERRORS)  //Configure RS232 Comms




#define  esc 0x1B //Terminal Escape Character
#byte RCREG = 0x1A


//Function Prototypes
void cls();                                  //Clear Terminal Screen



//Global Variables
int line_complete = 0;

#INT_RDA //Serial RX Interrupt
RDA_isr()
{
   char real;
   real = getc();
   printf("%c", real);

}

void main()
{
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);

   cls();

   printf("Listening\r\n");
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);
 
   while(1)
   {
      while(!line_complete) //Wait for sentence to be completed
      {
         #asm
            NOP
         #endasm
      }
   }
}

void cls(void) //Send clear command to terminal
{
   printf("%c[2J",esc);
}
libor



Joined: 14 Dec 2004
Posts: 288
Location: Hungary

View user's profile Send private message

PostPosted: Sun Jan 29, 2006 7:54 pm     Reply with quote

Don't use printf() in the interrupt handler routines. Just quickly store the incoming data in an array and print them in a not timing-sensitive function. Printf() takes a long time to execute, you are missing some action on the RX line during its execution.
ak6dn



Joined: 08 Jan 2006
Posts: 23
Location: Saratoga, CA USA

View user's profile Send private message

re: RF module message corruption
PostPosted: Sun Jan 29, 2006 11:14 pm     Reply with quote

Attached is a little section of test code that I use on the transmit side where I'm sending data from a PIC16F877A to a PC serial port. The link is thru a Laipac TLP315A/RLP315A pair of wireless modules. The below code works just fine.

A key point to note is that most of these direct digital RF modules have not only maximum data rates (4800baud for this module) BUT also minimum data rates (400baud for this module). The transmit code below will send characters from the buffer if there are any, and if none it will send a sync/idle character of 0xF0.

I chose 0xF0 as the idle character specifically because it has EXACTLY one falling edge per character, so syncing up the receiver is totally unambiguous (including the odd parity which I use, but this is optional).

On the receive side I just discard all 0xF0 characters as 'filler' (and I know my transmit state machine will never send 0xF0 accidentally).

The issue of NOT using printf in your receive intr routine is a key point. I would also check to see if the '300baud' rate is supported as a data rate thru your modules. This seems to be somewhat on the low side to me, and you could easily be violating the min data rate of your modules.

Code:
#include <16F877A.h>
#fuses XT,WDT,PUT,NOPROTECT,NOCPD,NOWRT,NOLVP,NOBROWNOUT,NODEBUG

#use delay (clock=3686400)
#use rs232 (baud=4800, bits=8, parity=O, errors, xmit=PIN_C6, rcv=PIN_C7)

// global data

#define TX_BUFFER_SIZE 16
char tx_buffer[TX_BUFFER_SIZE];
int8 tx_buffer_in = 0; // index of last char placed in buffer
int8 tx_buffer_out = 0; // index of last char transmitted

// transmit interrupt service

#int_tbe
void serialtx_isr (void)
{
    // check for presence of char to transmit
    if (tx_buffer_in == tx_buffer_out) {
        // nope, send idle flag
        putc(0xF0);
    } else {
        // transmit char at current buffer position
        putc(tx_buffer[tx_buffer_out]);
        // put seen flag at just transmitted character (debug/sanity)
        tx_buffer[tx_buffer_out] = '!';
        // bump index to next slot, modulo buffer size
        tx_buffer_out = (tx_buffer_out+1) % TX_BUFFER_SIZE;
        // and done
    }
    return;
}

// add a character to the transmit buffer

void bputc (char c)
{
    int8 index;

    // bump buffer position pointer
    index = (tx_buffer_in+1) % TX_BUFFER_SIZE;
    // if in/out indices collide, buffer is full, must wait
    while (index == tx_buffer_out) delay_us(100);
    // put current char in buffer
    tx_buffer[tx_buffer_in] = c;
    // bump input index for real
    tx_buffer_in = index;
    // and done
    restart_wdt();
    return;
}

// Main program

void main (void)
{
    int8 i;

    // configure I/O pins
    set_tris_a(0x00);
    set_tris_b(0x00);
    set_tris_c(0x00);
    set_tris_d(0x00);
    set_tris_e(0x00);

    // watchdog
    setup_wdt(WDT_2304MS);

    // allow interrupts
    enable_interrupts(int_tbe);
    enable_interrupts(global);

    // loop forever
    for (;;) {

        // do something
        for (i = 0; i < 56; i++) {
            switch (i % 8) {
                case 0:  printf(bputc, "\r\n"); break;
                case 1:  printf(bputc, "a"); break;
                case 2:  printf(bputc, "bcd"); break;
                case 3:  printf(bputc, "efghijklmnopqrstuvwxyz"); break;
                case 4:  printf(bputc, "0123456789"); break;
                case 5:  printf(bputc, "(        )"); break;
               default:  break;
            }
            delay_ms(40);
        }

        // wait until all char transmitted
        while (tx_buffer_in != tx_buffer_out) { delay_ms(5); restart_wdt(); }

    } // for (;;)

    // should never get here...
    reset_cpu();

}
michaelb



Joined: 28 Nov 2005
Posts: 17

View user's profile Send private message

PostPosted: Mon Jan 30, 2006 3:44 am     Reply with quote

Thanks for the suggestions. I've tried them out, but still to no avail I'm afraid.
The min/ max data rate is 50 - 2000 Hz, I thought 1 baud may be higher than 1 Hz as it involves transitions so kept the baudrate low. I've now increased it to 1200. I should mention that the supposed TTL/CMOS output of the RF module did not seem to trigger the PIC's UART, so i've looped it back on itself through a MAX233 (i.e. TTL-RS232 back to RS232 - TTL), as this seems to work. Below is the code I've now changed it to. Any help is extremely welcome.
Code:

#include <16F877.h>                                     //PIC16F877A Device
#device *=16                                            //Use 16 Bit Pointers
#fuses HS,NOWDT,NOPROTECT,NOLVP                         //Set Fuses
#use delay(clock=4000000)                              //20MHz Clock
#use rs232(baud=1200, xmit=PIN_C6, rcv=PIN_C7, ERRORS)  //Configure RS232 Comms


#define  esc 0x1B //Terminal Escape Character

#byte RCREG = 0x1A
#byte RCSTA=0x18
#define SPEN_BIT 7
#define OERR_BIT 1
#define FERR_BIT 2
#define CREN_BIT 4


//Function Prototypes
void cls();                                  //Clear Terminal Screen
void clear_usart_receiver(void);             //Clear USART Receiver RX Buffers
void reset_uart(void);                       //Reset hardware USART


//Global Variables
int line_complete = 0;
char buffer[30];
int buffer_pointer = 0;
int data_valid = 0;

#INT_RDA //Serial RX Interrupt
RDA_isr()
{

   char real;
   real = getc();

   if((real == 'U') && (data_valid == 0))
   {
      data_valid = 1;
   }
   else if((real == '\r') || (real == '\n'))
   {
      data_valid = 0;
      line_complete = 1;
   }

   if(data_valid)
   {
      buffer[buffer_pointer]  = real;
      buffer_pointer++;
   }

   if(buffer_pointer >= 29)
   {
      data_valid = 0;
      line_complete = 1;
   }

}

void main()
{
   int  i=0;
   setup_adc_ports(NO_ANALOGS);
   setup_adc(ADC_OFF);
   setup_psp(PSP_DISABLED);
   setup_spi(FALSE);
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
   setup_timer_1(T1_DISABLED);
   setup_timer_2(T2_DISABLED,0,1);

   cls();

   printf("Listening\r\n");
   enable_interrupts(GLOBAL);
   enable_interrupts(INT_RDA);

   while(1)
   {
      while(!line_complete) //Wait for sentence to be completed
      {
         #asm
            NOP
         #endasm
      }

      if(line_complete)
      {
         disable_interrupts(INT_RDA);
         printf("DONE\r\n");
         for(i=0;i < buffer_pointer;i++)
         {
            putc(buffer[i]);
         }
         clear_usart_receiver();
         reset_uart();
         line_complete = 0;
         buffer_pointer = 0;
         enable_interrupts(INT_RDA);
      }
   }
}

void cls(void) //Send clear command to terminal
{
   printf("%c[2J",esc);
}

void clear_usart_receiver(void) //Clear UART Receive Buffers
{
   char c;
   c = RCREG;
   c = RCREG;
   c = RCREG;
}


void reset_uart(void) //Reset the USART
{
   bit_clear(RCSTA, SPEN_BIT); // Reset the serial port
   bit_clear(RCSTA, OERR_BIT);
   bit_clear(RCSTA, FERR_BIT);
   bit_clear(RCSTA, CREN_BIT);
   delay_ms(1);
   bit_set(RCSTA, SPEN_BIT);
   bit_set(RCSTA, CREN_BIT);
   delay_ms(1);

}

As the \r\n characters are never detected by the PIC, the ouput is only ever printed when the buffer reaches the limit. Terminal output looks like this:
Code:

UUUW=o5ՑUUUW=oDONE
or
UUUW=o5UUUW=oDONE

Usually the top line is received, but the fact that it does sometimes vary is concerning.
michaelb



Joined: 28 Nov 2005
Posts: 17

View user's profile Send private message

PostPosted: Mon Jan 30, 2006 4:28 am     Reply with quote

Fixed now. I've been very silly... got my MAX233 wiring messed up. Thanks for everyone's input.

Michael
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