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

Receiving buffer

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



Joined: 15 Dec 2011
Posts: 20

View user's profile Send private message

Receiving buffer
PostPosted: Thu Dec 29, 2011 2:34 pm     Reply with quote

Hope somebody can help.

I using a 16f690 pic with a max232 chip.

Receiving and sending data works fine, but according to the data sheet the pic only got a 2 byte buffer.

Problem is I want to add a string of about 20-30 characters before sending it to the pic, not sending character for character. The pic now only accepts the first two bytes then ignores the rest. Does anybody know if there are chips available that got a bigger buffer or is my understanding wrong? Or should I change my program (using a plc to send data) to send only two characters at a time ? And then store it as an array ?

Regards,
Labjac
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Thu Dec 29, 2011 2:42 pm     Reply with quote

You need to look at two of the examples that come with the compiler.
EX_SISR.c, shows how to implement an interrupt driven circular buffer for serial receive. The EX_STISR.c, shows how to implement an interrupt driven transmit buffer.
Such buffers are common in everything. If you look at your PC, the UART hardware buffer is typically only about 8 characters in size, yet you can send/ receive hundreds of bytes without problems. The reason, is that Windows implements exactly such interrupt driven buffers for you.
I'd suggest if you have enough RAM, make your buffers 32bytes in size (the sample code only works efficiently with 'binary' buffer sizes - 2,4,8,16,32 bytes etc..). If space is really tight, odd sizes can be used, and a search here will find the code tweaks needed to make these work well.

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Thu Dec 29, 2011 4:14 pm     Reply with quote

To add to Ttelmahs excellent comments - if you ditch the inefficient
modulo % operator and use an if-then statement for buffer wrap ..
then - there is NO Loss of efficiency for ANY sized buffer your pic can handle.
w/o segmentation
Labjac



Joined: 15 Dec 2011
Posts: 20

View user's profile Send private message

PostPosted: Fri Dec 30, 2011 5:29 am     Reply with quote

Hallo

Thanks again for the always quick response, I used the example code and it works perfect, but there is a line in the code I still don't understand, can somebody please try an explain this to me.

Code:

#define BUFFER_SIZE 32
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;


#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   next_in=(next_in+1) % BUFFER_SIZE;
   if(next_in==next_out);
   next_in=t;           // Buffer full !!
}

#define bkbhit (next_in!=next_out)

BYTE bgetc() {
   BYTE c;

   while(!bkbhit) ;
   c=buffer[next_out];
   next_out=(next_out+1) % BUFFER_SIZE;
   return(c);
}



void main() {

   enable_interrupts(global);
   enable_interrupts(int_rda);

   printf("\r\n\Running...\r\n");

               // The program will delay for 10 seconds and then display
               // any data that came in during the 10 second delay

   do {
      delay_ms(10000);
      printf("\r\nBuffered data => ");
      while(bkbhit)
        putc( bgetc() );
   } while (TRUE);



The two part I highlighted in Bold, what does that % part do?

Quote:

next_in=(next_in+1) % BUFFER_SIZE;
if(next_in==next_out);


And also at what point will next_in=Next_out.

Still new with the C language, only part I can see that got anything to do with the % sign is Modus, but sure this is not what it's been used for here.

Then Asmboy you also mentioned the % if ineffecient, can you send me an example of how you would have done it.

Regards,
Labjac
temtronic



Joined: 01 Jul 2010
Posts: 9243
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Dec 30, 2011 8:54 am     Reply with quote

With your project open, press F11 to gain access to the onscreen help files ! Mine's always open as an instant reference to CCS Compiler information.
% refers to a type of math, please look it up....I'm older and forget things....
but KNOW where the info is located !!

As for the next_in=next_out you have to visualize that this is a circular buffer and the 'pointer' has to point to the next available array element.it loops from 1,2,3,... to 32 to 1,2,3....etc.
Ttelmah



Joined: 11 Mar 2010
Posts: 19538

View user's profile Send private message

PostPosted: Fri Dec 30, 2011 9:55 am     Reply with quote

You code has a fault with a full buffer - you have an extra ';' that should not be there.

On '%', the thing is you want a number that can go through a range, from '0' to the 'buffer size-1', so (for example), with a buffer size of 5, would go:

0 1 2 3 4 0 1 2 3 4....

Now the '%' operator returns the remainder from a division, so if you had a number going 0 1 2 3 4 5 6 7 8.... and then divided this by 5, the _remainder_ would be:

0 1 2 3 4 0 1 2 3 4

Exactly what is wanted. _but_ the problem is that it is an appallingly slow operator when used with a size like '5'. To get the remainder, the processor performs a division by 5, then takes the integer that results, multiplies this by 5, and subtracts this from the original number. On a PIC16, even with an 8bit value, this takes about 170 instructions!. On the PIC18, it is faster, but still takes about 117 instructions. Even worse, since this involves using the integer division code inside an interrupt, interrupts _will_ be disabled wherever the same code is used outside the interrupt....

The alternative to using '%', is to use the 'if' test. All you do is:

if (++counter == buffer_size) counter=0;

Here counter goes:

0 1 2 3 4, then on the next increment, it == 5, so jumps back to 0, exactly as needed. This takes only half a dozen instructions.

So you want either:

next_in=(++next_in) % BUFFER_SIZE;

or

if(++next_in==BUFFER_SIZE) next_in=0;

The latter is the better solution.

The former does work OK, if a binary buffer size is selected, since the compiler then replaces the '%' operator, with a binary and, which is almost as good. It is a case of a bit of 'careless' programming by CCS, which doesn't cause any problems as done, but does if you change the buffer size without being aware of the limitations.

So:
Code:

#int_rda
void serial_isr() {
   int t;

   buffer[next_in]=getc();
   t=next_in;
   if(++next_in==BUFFER_SIZE)
      next_in=0;
   if(next_in==next_out) //get rid of the ';' here - wrong.....
      next_in=t;    // Buffer full !!
}


Is the faster and better version that works with different buffer sizes.

Best Wishes
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