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

RS232 for a PIC16F1947

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



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

RS232 for a PIC16F1947
PostPosted: Wed Jul 20, 2011 2:54 pm     Reply with quote

Hi Everyone -

I am high fan of the mantra "R.T.F.M." and if I missed it in the manual, please do let me know where it is so that a record of this is kept in the forums for the next newbie that comes along.

SerialCom.C provided by CCS is near and dear to me since it was the code I used to understand the TX and RX methods of the CCS compiler. I was able to get it up and running for a PIC16F876. Made a few minor modifications and added comments for my understanding. I have since used variations of it in other projects

Recently, I have fired up the 16F1947. It a newer PIC, containing 2 EUSARTS.

I made a few modifications to the SerialCom code in effort to get it up and running, but I do not believe that the PIC is processing it. I can see with an O-scope that the data being sent is getting through the transceiver to Pin 32 of the PIC (64 pin TQFP). I have also used LEDs on my board to help me determine if I'm getting to specific locations in the code. It currently looks like it is getting hung up on the printf statement on line 173 (or so it seems)

I tend to believe that:

1. I may be missing a fuse...
2. I may be missing an option in the #USE rs232 -OR-
3. I may have an incorrect option since I am working with 2 UARTs
4. I may be missing another function that was okay for the 16F876, but not okay for the 16F1947

Your help and recommendations are truly appreciated. I promise to post the final SerialCom for 16F1947 when I get it up and running.

Regards -

RckRllRfg

Code:

/*****************************************************************************/
/*                                                                           */
/*                            From CCS's SerialCom.C                         */
/*                                                                           */
/* This program received and loops back serial bytes using inter-            */
/* rupts in and out.                                                         */
/*                                                                           */
/*****************************************************************************/

/*****************************************************************************/

/* Notes

Worked like a champ for 16F876.  Reminants of this code were left in
for the purposes of comparison.

*/

#include <16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay( clock=20000000 )

/*****************************************************************************/

#define R_BUFFER_SIZE 32

BYTE r_buffer[ R_BUFFER_SIZE ];
BYTE r_next_in = 0;
BYTE r_next_out = 0;

/*****************************************************************************/

#define T_BUFFER_SIZE 64
byte t_buffer[ T_BUFFER_SIZE ];
byte t_next_in = 0;
byte t_next_out = 0;

/*****************************************************************************/

#int_rda
void r_serial_isr() { // This is the serial Rx Interrupt Service Routine
   int temp;

   // PIC - Port 12 of RealTerm - Peripheral to PIC
#use rs232( UART1, baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, errors)

   r_buffer[ r_next_in ] = getc();    // Get a charater from ??? and stuff it in the buffer
   temp = r_next_in;                  // Remember the curent Rx in index location in the buffer
   r_next_in = (r_next_in + 1) % R_BUFFER_SIZE; // point to the next location in the buffer
   if (r_next_in == r_next_out)       // if the input now points to the output the buffer is full
     r_next_in = temp;                // if so, go back to where you were pointing at first
} // void r_serial_isr()

/*****************************************************************************/

#int_tbe
void t_serial_isr() { // This is the serial Tx Interrupt Service Routine

   if (t_next_in != t_next_out) // If Tx Buffer is not empty
   {

      // PIC - Port 10 of RealTerm - From PIC to peripheral
//#use rs232( baud=9600, parity=N, xmit=PIN_C5, rcv=PIN_C4, bits=8, errors) // for 16F876
  #use rs232( UART2, baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, errors) // for 16F1947

      putc( t_buffer[ t_next_out ] ); // output the next byte from the Tx Buffer to the USART
      t_next_out = (t_next_out + 1) % T_BUFFER_SIZE; // Point to the next unsent charater to be sent later
   }
   else  // Tx buffer has now become empty
      disable_interrupts( int_tbe ); // so turn off any further interrupts from it
} // end void t_serial_isr()

/*****************************************************************************/

BYTE bgetc() { // This routine is called by programs to fetch one byte out of the serial Rx queue
   BYTE c;

//   while (r_next_in == r_next_out);                // This line says: Wait if the buffer is full... Let's not!
   if (r_next_in != r_next_out)                      // If the Rx buffer is not empty,
   {
      c = r_buffer[ r_next_out ];                    // Fetch the next byte out of it
      r_next_out = (r_next_out + 1) % R_BUFFER_SIZE; // Increment the index to point to the next byte in the queue


     output_low(PIN_D5);                             // Light an LED to tell me you are there
   }
   return( c ); // Return it to the calling program
} // end BYTE bgetc()

/*****************************************************************************/
   
void bputc(BYTE c) { // This routine is called by programs to put a byte into the serial Tx output queue
   short restart;
   int ni;

   restart = (t_next_in == t_next_out);  // If the Tx buffer is empty,
                                         // we will need to restart it at the end of this routine
   t_buffer[ t_next_in ] = c;            // Stuff the character in the next position in the Tx buffer
   ni = (t_next_in + 1) % T_BUFFER_SIZE; // Figure out and remember where the next character after
                                         // this on will need to be put
   while (ni == t_next_out);             // Apparently this next location is already taken
                                         // (i.e. the buffer is full), so wait as long as the buffer remains full
   t_next_in = ni;                       // Now you are free to point to the next location
                                         // for the next byte (which will come along sometime later) to use
   if (restart)                          // If we detected that the Tx Buffer had gone empty,
                                         // then the Tx interrupts may be shut off, so
      enable_interrupts( int_tbe );      // we need to restart them
} // end void bputc(BYTE c)

// SIDE NOTE: We will need add a routing to tell us how many free bytes exist in the Tx Buffer and
// check it before putting anything in here so that we do not get hung up waiting - ever!

void init( void ) { // This routine is called by program to initialize the registers necessary

/* This code has been added to define the ports and to establish necessary registers */
 
/* Initialization of the port */

/* - Note - the Port A information does not exactly match what was found on the schematics; however,
     However, this code seems to work with the Sony camera example from which it came; therefore,
     we will leave the settings "as is".  Note that the schematic provided is not the exact same.
*/

   //Start the RS-485 on receive mode
   //output_low(PIN_A2);  // for 16F876

   // For the 16F1947 Transceiver on my board I have to establish a few signals:
   // using Linear LTC1387.

   //RX Transceiver

   // Activate the Transciever (IN-ON)
   output_high(PIN_E1);
   // Establish protocol mode on Pin RE2:  RS-232 is low
   output_low(PIN_E2);
   // Ensure the TX mode is disabled (DXEN)
   output_low(PIN_E3);
   // Enable the RX mode (RXEN)
   output_high(PIN_E0);
   
   //TX  Transceiver
 
   //Activate the Transciever (OUT-ON)
   output_high(PIN_E5);
   // Establish protocol mode on Pin RE6:  RS-232 is low
   output_low(PIN_E6);
   // Ensure the RX mode is disabled (RXEN)
   output_low(PIN_E4);
   // Enable the TX mode (DXEN)
   output_high(PIN_E7);

 } // end void init( void )


/*****************************************************************************/
   
void main() { // The main entry point for the C-level code (jumped to after the hidden bootup code)
   
   //Initialize
   init();  //Initialize the ports
   // As part of starting up we need to enable both specific and global interrupts
   enable_interrupts( int_rda ); // Enable interrupts for receiving serial data
   enable_interrupts( global );  // Enable global interrupts

   
   printf( bputc, "\r\n\Running...\r\n" );  // Say hello to the new world!
   
      // Light an led to tell me you are there
     output_low(PIN_D7);
   
   delay_ms( 2000 );  // Wait 2 seconds
   printf( bputc, "This is buffered data #1 of 3\r\n" ); // Send some more data out the serial port

   output_low(PIN_D6);                                   // Light an LED to tell me you are there
   delay_ms( 2000 );  // Wait 2 seconds
   printf( bputc, "This is buffered data #2 of 3\r\n" ); // Send some more data out the serial port
   delay_ms( 2000 );  // Wait 2 seconds
   printf( bputc, "This is buffered data #3 of 3\r\n" ); // Send some more data out the serial port

   do { // forever
     if (r_next_in != r_next_out) bputc( bgetc() );

   } while (TRUE); // Armageddon
} // end Main()

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Wed Jul 20, 2011 4:29 pm     Reply with quote

Quote:
SerialCom.C provided by CCS

I don't think CCS supplies a serialcom.c file. There is no such file in
the CCS directories, as least for the PCM and PCH compilers.
The following Google search comes up with nothing:
Quote:

site:ccsinfo.com +serialcom.c

But anyway, try making a simple getc, putc program for UART2. You can
do that with only a few lines of code. See if that works first.

Also post your compiler version. It's possible that there are bugs with
UART2 in your version.
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

PostPosted: Wed Jul 20, 2011 6:43 pm     Reply with quote

Humm... You are probably right... It may have come from microchipc.com...

Anyway, I wrote the following code and I think that it is working. I am sending an RX signal using RealTerm and getting a TX signal, though the integrity of the TX signal is rather poor. I am viewing the TX signal via O-scope (since the RealTerm isn't detecting it) This is on the other side of the transceiver, so it isn't a PIC issue at this point.

BTW, here the code that I used based on PCM Programmer's recommendation and the code from another posting similar to this topic. This one fills in some of the blanks for the newbies:

For the newbies - Please note that other than the pins called out in the #USE rs232 commands, the pins that I am calling out are based on my custom board. When playing with the UARTS and LEDs, you will need to deal with the transceivers on your board accordingly.

Note, I am not flashing the LEDs. I simply want them to turn on as a sanity check.


Code:

#include <16F1947.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay( clock=20000000 )

 
//====================================
void main()
{
int8 c;

   // For the 16F1947 Transceiver on my board I have to establish a few signals:
   // using Linear LTC1387.

   //RX Transceiver

   // Activate the Transceiver (IN-ON)
   output_high(PIN_E1);
   // Establish protocol mode on Pin RE2:  RS-232 is low
   output_low(PIN_E2);
   // Ensure the TX mode is disabled (DXEN)
   output_low(PIN_E3);
   // Enable the RX mode (RXEN)
   output_high(PIN_E0);
   
   //TX  Transceiver
 
   //Activate the Transciever (OUT-ON)
   output_high(PIN_E5);
   // Establish protocol mode on Pin RE6:  RS-232 is low
   output_low(PIN_E6);
   // Ensure the RX mode is disabled (RXEN)
   output_low(PIN_E4);
   // Enable the TX mode (DXEN)
   output_high(PIN_E7);

    output_low(PIN_D7);   // Light an led to tell me you are there

#use rs232( baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, UART2, errors)
printf("Start \n\r");

while(1)
  {
//light a light
    output_low(PIN_D6);   // Light an led to tell me you are there

#use rs232( baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, UART1, errors)

   c = getc();


#use rs232( baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, UART2, errors)
   putc(c);
  }
 
}

ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Wed Jul 20, 2011 9:07 pm     Reply with quote

Hi,

You should look into using serial 'streams' to help clean up your code, and make it more easy to read.

John
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

PostPosted: Wed Jul 20, 2011 10:01 pm     Reply with quote

Hi John -

I'm certainly interested; however, I'm short for time on this project. I notice a brief explanation in the manual; however, not enough to get my head wrapped around it. If you have any links or sample code, please point me to it.


Regards -

RckrllRfg
ezflyr



Joined: 25 Oct 2010
Posts: 1019
Location: Tewksbury, MA

View user's profile Send private message

PostPosted: Thu Jul 21, 2011 8:17 am     Reply with quote

Hi,

There is nothing to really wrap your head around, it's really quite simple.

Instead of using a unique '#use rs232' prior to each usage of 'getc' and 'putc', you place two '#use rs232' statements at the top of your program with a unique 'stream' for each serial port, and then select which stream you wish to use in your code with 'fgetc' and 'fputc'.

Code:


#use rs232( baud=9600, parity=N, xmit=PIN_C6, rcv=PIN_C7, bits=8, UART2, errors, stream=COM1)
#use rs232( baud=9600, parity=N, xmit=PIN_G1, rcv=PIN_G2, bits=8, UART2, errors, stream=COM2)

c = fgetc(COM1);

putc(c, COM2);




John
RckRllRfg



Joined: 20 Jul 2011
Posts: 60

View user's profile Send private message

PostPosted: Thu Jul 21, 2011 5:54 pm     Reply with quote

Wow... Excellent. Thank you for pointing it out.
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