16f84 and RS232 [edit: now 16f876]

For questions and comments on programming in general. And for any items that don't fit into the forums below.

Moderators: Benj, Mods

Post Reply
stratsal
Posts: 5
Joined: Mon Feb 19, 2007 3:24 pm

16f84 and RS232 [edit: now 16f876]

Post by stratsal »

Hello people,

Is it possible for someone to post an example code, that is sending a character from the pic through rs232, using the USART?

Thank you!

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello Stratsal

the PICmicro 16F84 does not have UART hardware.

You have two options to send / receive the RS232 protocol

1) Use a PICmicro with an onboard UART
2) Use a Bit Banging software approach

There are plenty of examples available online on how to program these protocols.

stratsal
Posts: 5
Joined: Mon Feb 19, 2007 3:24 pm

Post by stratsal »

Hi Benj

I just realized that I wrote 16f84 when I actually meant 16f876 :shock: :oops: .... sorry.
Can I change the title?
I found some examples which confused me even more. If it is possible I need a very simple example just to get started...

Thank you!

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello Stratsal

Which programming language are you using? Maybe I can dig you something out.

stratsal
Posts: 5
Joined: Mon Feb 19, 2007 3:24 pm

Post by stratsal »

I am using C language and C2C compiler with sourceboost IDE. I have built a max232 circuit and I want to test it by sending a character from the pic to a pc and read that character using hyperterminal. I understand that i have to use a function like putchar but I don't know how exactly to implement it.

Thank you

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello Stratsel

This code is written in BoostC which is also made by Sourceboost so it should be fairly easy to change the commands to C2C.

The baud rate may need changing for your configuration. The current code is configured for a baud rate of 9600 when the osscilator is 19.6608MHz. There are a few lines in the main code that will allow you to alter the baud rate. See the PICmicro datasheet for more info. If you cant get it working then post your ideal baud rate and your oscillator speed and I will calculate the values for you.

Send Char

Code: Select all

void SendRS232Char(char Char)
{
	//GetSendRS232CharCode
	#define fc_rsSTATUS_LOOP      0
	#define fc_rsSTATUS_TIMEOUT   1
	#define fc_rsSTATUS_RXBYTE    2
	set_bit(txsta, TXEN);
	while ((pir1 & (1<< TXIF)) == 0);
	txreg = Char;	    
}
Receive Char
A lot of this code is regarding error checking and finding bugs. You should be able to remove a lot of it if you wish.

Code: Select all

char ReceiveRS232Char(char timeout)
{
	 //GetReceiveRS232CharCode
	#define fc_rsSTATUS_LOOP      0
	#define fc_rsSTATUS_TIMEOUT   1
	#define fc_rsSTATUS_RXBYTE    2
	   char delay1 = 0;
	   char delay2 = 0;
	   char dummy = 0;
	   char retVal = 255;
	   char bWaitForever = 0;
	   char rxStatus = fc_rsSTATUS_LOOP;
	   if (timeout == 255)
	   {
	       bWaitForever = 1;
	   }
	   set_bit(rcsta, CREN);
	   while (rxStatus == fc_rsSTATUS_LOOP)
	   {
	       if ((pir1 & (1 << RCIF)) != 0)
	       {
	           //received a Char
	           rxStatus = fc_rsSTATUS_RXBYTE;
	       } else {
	           if (bWaitForever == 0)
	           {
	               //don't wait forever, so do timeout thing...
	               if (timeout == 0)
	               {
	                   rxStatus = fc_rsSTATUS_TIMEOUT;
	                   #ifdef fc_rs232_debug
	                       //FCD_RS2320_SendRS232Char('<');
	                       //FCD_RS2320_SendRS232Char('t');
	                       //FCD_RS2320_SendRS232Char('i');
	                       //FCD_RS2320_SendRS232Char('m');
	                       //FCD_RS2320_SendRS232Char('e');
	                       //FCD_RS2320_SendRS232Char('o');
	                       //FCD_RS2320_SendRS232Char('u');
	                       //FCD_RS2320_SendRS232Char('t');
	                       //FCD_RS2320_SendRS232Char('>');
	                   #endif
	               } else {
	                   //decrement timeout
	                   delay1--;
	                   if (delay1 == 0)
	                   {
	                           timeout--;
	                   }
	               }
	           }
	       }
	   }
	   if (rxStatus == fc_rsSTATUS_RXBYTE)
	   {
	       if ((rcsta & (1 <<FERR)) != 0)
	       {
	           dummy = rcreg;      //need to read the rcreg to clear FERR
	           #ifdef fc_rs232_debug
	               FCD_RS2320_SendRS232Char('<');
	               FCD_RS2320_SendRS232Char('F');
	               FCD_RS2320_SendRS232Char('E');
	               FCD_RS2320_SendRS232Char('R');
	               FCD_RS2320_SendRS232Char('R');
	               FCD_RS2320_SendRS232Char('>');
	           #endif
	       } else {
	       if ((rcsta & (1 << OERR)) != 0)
	           {
	               //need to read the rcreg to clear error
	               clear_bit(rcsta, CREN);
	               set_bit(rcsta, CREN);
	               #ifdef fc_rs232_debug
	                   FCD_RS2320_SendRS232Char('<');
	                   FCD_RS2320_SendRS232Char('O');
	                   FCD_RS2320_SendRS232Char('E');
	                   FCD_RS2320_SendRS232Char('R');
	                   FCD_RS2320_SendRS232Char('R');
	                   FCD_RS2320_SendRS232Char('>');
	               #endif
	           } else {
	               retVal = rcreg; //no error, so rx byte is valid
	               #ifdef fc_rs232_echo
	                   FCD_RS2320_SendRS232Char(retVal);
	               #endif
	           }
	       }
	   }
	   return (retVal);
}
Main Example

Code: Select all

	#define fc_rsSTATUS_LOOP      0
	#define fc_rsSTATUS_TIMEOUT   1
	#define fc_rsSTATUS_RXBYTE    2

	   txsta = 4; // 8-bit, async, low speed, off
	   spbrg = 127; // set the baud rate
	   rcsta = 0;              // 8-bit, disabled
	   set_bit(rcsta, SPEN);   // turn on serial interface

	//Call Component Macro
	//Call Component Macro: RS232(0)::SendRS232Char(0xFF)
	FCD_RS2320_SendRS232Char(0XFF);


	//Call Component Macro
	//Call Component Macro: retval=RS232(0)::ReceiveRS232Char(255)
	FCV_RETVAL = FCD_RS2320_ReceiveRS232Char(255);

stratsal
Posts: 5
Joined: Mon Feb 19, 2007 3:24 pm

Post by stratsal »

Hi again,
Thank you for the code. I managed to come up with this code but it doesn't work.

Code: Select all

#include <p16f876.h>
#include "send.h"

#pragma CLOCK_FREQ 4000000

#define TRMT_MASK 2


// Port address
char PORTC@0x07;
char TRISC@0x87;
char PIE1@0x8c;
char PIR1@0x0c;
#define PortCConfig 0x98 
// USART Registers
char TXREG@0x19;
char RCREG@0x1a;
char TXSTA@0x98;
char RCSTA@0x18;
char SPBRG@0x99;
//functions
void SendChar(char);    
void ConfigureComms(void);
void SendString(const char *); // Send a string

void ConfigureComms(void)
{
 INTCON = 0x00;

    set_bit( RCSTA, SPEN );    // Enable Serial port
    clear_bit( RCSTA, RX9 );   // 8 bit receive mode
    clear_bit( TXSTA, TX9 );   // 8 bit transmit mode

   // Values for a clock frequency of 3.579545Mhz
   // for other clock frequency values see the microchip data.

      SPBRG = 22;              // SPBRG = 22 ( Set Baud rate 9,600 )

    set_bit( TXSTA, BRGH );    // BRGH = 1   ( High speed mode )
   //clear_bit( TXSTA, BRGH );    // BRGH = 0   ( Low speed mode )

    clear_bit( TXSTA, SYNC );  // Asyncronous mode;
    set_bit( TXSTA, TXEN );    // Enable Transmitter
    set_bit( PIE1, RCIE );     // Enable Receive Interrupt
    set_bit( RCSTA, CREN );    // Enable continuous receive
    clear_bit( PIR1, RCIF );   // Clear Receive Interrupt flag
    set_bit( INTCON, PEIE );   // Enable all Peripheral Interrupts
    set_bit( INTCON, GIE );    // Enable Global Interrupts

}

void SendChar(char k)
{

   set_bit(txsta, TXEN); 
   while ((pir1 & (1<< TXIF)) == 0); 
   txreg = k; 
}

void SendString(const char *p)
{

 char s = 0;

                // Check for end of string

    while( p[s] != 0 )
         {
            SendChar( p[s++] );

         }

}

void main()
{
ConfigureComms();
SendChar('k');
//SendString(const char*p);
}
I am probably doing something horribly wrong, since I am a newbie with pic programming. Any comments?Thanks!

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Hello Stratsal

you should find that if you modify your functions to match the code below. The trasmission routines should now work. If not then let me know what is happening. You may want to change your Osc frequency as you get a 1.32% error rate when using a baud of 9600 at your current frequency. However this should not affect the communication unless you are sending a heavy load of data or you are sending the signal a large distance.

Another point is to look in the PIC include file you are using. This file will already define all of the registers inside the PICmicro so you dont have to repeat the defines in your program. You may have to change all of the register names to lowercase to get the program to compile correctly after doing this.

Code: Select all

void ConfigureComms(void) 
{ 
      set_bit( RCSTA, SPEN );    // Enable Serial port 
      // Values for a clock frequency of 3.579545Mhz 
      // for other clock frequency values see the microchip data. 
      SPBRG = 22;              // SPBRG = 22 ( Set Baud rate 9,600 ) 
      TXSTA = 4;
      set_bit( RCSTA, CREN );    // Enable continuous receive 
} 


void SendChar(char k) 
{ 
   set_bit(TXSTA, TXEN); 
   while ((PIR1 & (1<< TXIF)) == 0); 
   TXREG = k; 
} 


void SendString(const char *p) 
{ 
   char idx = 0; 
   // Check for end of string 
    while( p[idx] != 0 ) 
    { 
            SendChar( p[idx] );
            idx++;
    } 
} 

Lastly if your clock is actually 4MHz then you need to change the following lines to this.

Code: Select all

// Values for a clock frequency of 4Mhz 
SPBRG = 25;              // SPBRG = 25 ( Set Baud rate 9,600 )

stratsal
Posts: 5
Joined: Mon Feb 19, 2007 3:24 pm

Post by stratsal »

Hi Benj,

I run the program with this settings: 4Mhz clock and baud=25. I receive a lot of gibberish on hyperterminal. The settings I use on HT are (BPS=9600, data bits=8, parity=none, stop bits=1, flow control=none). I also used 3.579535Mhz clock with baud=22 but I get same result. Also I can;t get the send string function to work :( Any Ideas?

Thank you

User avatar
Benj
Matrix Staff
Posts: 15312
Joined: Mon Oct 16, 2006 10:48 am
Location: Matrix TS Ltd
Has thanked: 4803 times
Been thanked: 4314 times
Contact:

Post by Benj »

Strasel

I have emailed you with some sample code to hopefully get you up and running with this.

Post Reply