|
|
View previous topic :: View next topic |
Author |
Message |
Labjac
Joined: 15 Dec 2011 Posts: 20
|
Receiving buffer |
Posted: Thu Dec 29, 2011 2:34 pm |
|
|
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: 19568
|
|
Posted: Thu Dec 29, 2011 2:42 pm |
|
|
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
|
|
Posted: Thu Dec 29, 2011 4:14 pm |
|
|
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
|
|
Posted: Fri Dec 30, 2011 5:29 am |
|
|
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: 9255 Location: Greensville,Ontario
|
|
Posted: Fri Dec 30, 2011 8:54 am |
|
|
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: 19568
|
|
Posted: Fri Dec 30, 2011 9:55 am |
|
|
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 |
|
|
|
|
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
|