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

16F88 and RS232

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



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

16F88 and RS232
PostPosted: Sat Feb 26, 2005 2:53 am     Reply with quote

I have question about 16F88, RS232 and PCH 3.217.

I write the following test program (To do short, I don't give the LCD routine).
Code:

#include <16F88.h>
#fuses NOWDT,INTRC_IO,  MCLR, BROWNOUT, NOLVP, PUT, NOPROTECT
#device *=16
#use delay(clock = 8000000)
#use rs232 (baud=4800,parity=N,xmit=PIN_B5,rcv=PIN_B2, errors  )

#define LINE_1          0x00
#define LINE_2          0x40
#define CLEAR_DISP      0x01

#define LCD_D0          PIN_A0   //DB4
#define LCD_D1          PIN_A1   //DB5
#define LCD_D2          PIN_A2   //DB6
#define LCD_D3          PIN_A3   //DB7
#define LCD_EN          PIN_A6   //enable
#define LCD_RS          PIN_A7   // rs


const char Title [] = "Title";
char cRS232;
char cString[12];


#separate void LCD_Init ( void );
#separate void LCD_SetPosition ( unsigned int cX );
#separate void LCD_PutChar ( unsigned int cX );
#separate void LCD_PutCmd ( unsigned int cX );
#separate void LCD_PulseEnable ( void );
#separate void LCD_SetData ( unsigned int cX );
#separate void Erase_SecondLine ( void );


#use fast_io ( A )
#use standard_io ( B )

/*****   Interrupts    ****/

#int_rda
   void SerialInterrupt (void)
      {
      cRS232=1;
      fgets (cString);
      }



void main()
   {
   port_b_pullups(TRUE);

   setup_adc_ports(NO_ANALOGS);
   set_tris_a ( 0x00 );
   delay_ms (100);
   cRS232 = 0;
 
   LCD_Init ( ) ;
   LCD_PutCmd ( CLEAR_DISP );
   LCD_SetPosition (LINE_1);
   printf(LCD_PutChar,"%s    ", Title);


   enable_interrupts (int_rda);
   enable_interrupts (global);

while(1)
   {
   if (cRS232 == 1)
      {
      disable_interrupts (int_rda);
      LCD_SetPosition (LINE_2);
      printf(LCD_PutChar,"%s    ", cString);
      cRS232 = 0;
      enable_interrupts (int_rda);
      }
   }

}



I read string within the interrupt and, in the main, I print it to the LCD. All work fine.

Now, the Pic don't send data and I wish use the pin B5 as output for Led control. I change the code in the use RS232 statement and nothing in hardware.
Code:
#use rs232 (baud=4800,parity=N,rcv=PIN_B2, errors  )

The manual say that is possible. But ....
- the string is not send to my LCD,
- when I compare both LST files, I see that the code for use RS232 statement without tx pin is bigger than in other case.

I think that the Pic don't work with interrupt communication but with software communication. I don't found this confirmation in the manual.
Could you confirm ? Is it normal or not ?
Have a nice week end.
Thanks and regard.
Ttelmah
Guest







PostPosted: Sat Feb 26, 2005 3:20 am     Reply with quote

When you change the RS232 definition, you automatically switch to using software RS232. Your original form is the 'correct' way to code to use the hardware UART. Understand, that if you code as originally written, and then never send anything to the transmit output, there is nothing to stop you using the pin for other things, and that no code is actually generated for the transmit pin, till it is used. By removing the reference to the transmit pin, you force the compiler to use the software RS232, so the code grows.
With the software RS232, 'int_rda', is never going to occur. Hence it will not work.
In the original code, I would change to buffering the serial, rather than using 'fgets'. The problem is that if garbage arrives at the RS232 input, that does not include a 'end of line' character, the code will remain hung inside the interrupt. Also if the string that arrives is larger than the string space you have allocated, the data will overrun, and overwrite other variables in memory, causing chaos. What you have will only work if the data is always 'right'....

Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Sat Feb 26, 2005 3:23 am     Reply with quote

Or to give a short answer, you can't split the hardware serial port.
It's all or nothing.

The 16F88 data sheet shows this in the section on the RCSTA register:
Code:
bit 7 SPEN: Serial Port Enable bit
1 = Serial port enabled (configures RB2/SDO/RX/DT and
                                    RB5/SS/TX/CK pins as serial port pins)
0 = Serial port disabled

Because of this, when you use the following line, the compiler creates a
software UART receiver:
Code:
#use rs232 (baud=4800,parity=N,rcv=PIN_B2, errors  )
GDetienne



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

Thanks
PostPosted: Sat Feb 26, 2005 4:52 am     Reply with quote

Thanks for your quick answer. That confirm what I think but with correct reasons.
Two questions :
- could you confirm that I can use the Tx port for Led control if I am sure not use it for transmit.
- I use fgets (cString) in my interrupt. Till now I try with caracters without garbage. I agree with you, it's better to change it for security. Do you think the best is a ring buffer or go out the interrupt after a fixed number of caracters ? What is your experience ? The length of my string is not constant but lower than 10 caracters.

Thanks a lot Ttelmah and PCM programmer (and others) for your advies.

Guy
Ttelmah
Guest







PostPosted: Sat Feb 26, 2005 7:45 am     Reply with quote

A ring buffer is a 'good' solution. However you might (assuming you want to always deal with a complete 'string' in the main code), consider a linear buffer. With this you just start adding characters to a string area in memory, and throw them away if the string gets too long (you lose data from the 'end', whereas with a ring buffer you normally lose it from the 'front' in the event of an overflow). When you see the terminator character, you set the flag to say you have a complete string, add a 'null' to the buffer, and it is just sitting there waiting in the buffer. With this you only need one counter. Effectively it'd behave exactly like the fgets, but with a limited size, and with the characters only added one at a time (to avoid sitting in the interrupt routine waiting for the string to arrive).
Yes, you can just use the output pin for another operation. Since the compiler does not actually generate the 'Tx' code, till you write something with putc, there is no problem. :-)
Code:

char cRS232;
char cString[12];
#define cEOS (13)

#int_rda
void SerialInterrupt (void) {
    static int8 ctr;
    int8 temp;
    temp=getc();
    if (temp=cEOS) {
        cString[ctr]='\0';
        cRS232=true;
        ctr=0;
        return;
    }
    cString[ctr]=temp;
    if (ctr<11) {
        ctr+=1;
    }
}

This should behave very like your existing program, except that if more than 11 characters arrive before the end of string character is seen, the trailing characters will just overwrite each other, and the routine will be called for each character in turn.

Best Wishes
GDetienne



Joined: 20 Sep 2003
Posts: 47
Location: Brussel - Belgium

View user's profile Send private message

Thanks
PostPosted: Sat Feb 26, 2005 8:34 am     Reply with quote

Thanks a lot. I have some directions to improve my self.

Thanks.
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