|
|
View previous topic :: View next topic |
Author |
Message |
bsack
Joined: 21 Feb 2006 Posts: 2 Location: Buffalo NY
|
problem reading-to/writing-from buffer |
Posted: Wed Feb 22, 2006 2:25 pm |
|
|
hello all,
i'm trying to figure out how to write a program that collects some data over rs232, writes it to a buffer, reads the buffer, performs an action based on that data over a period of time, and then reads the data that may have come into the buffer during the time the action was being performed [and then does the action... etc.].
my first attempt used getc() et al to get data from rs232, and this worked well as long as the execution loop (running a stepper motor in this case) finished before more data was sent. if the data was sent while the loop was running, the program would hang after the loop was completed.
i tried to fix this by emulating the example in CCS's ex_sisr.c file. i created a small buffer that could be filled (i hoped) while the output loop was running. allow me to bore you with my code:
Code: |
#include <16f876a.h>
#fuses HS,NOWDT,NOPROTECT,NOPUT,NOLVP,BROWNOUT
#use DELAY(CLOCK=20000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, BRGH1OK)
#use FAST_IO(B)
#include <stdlib.h>
// the following from ccs ex_sisr.c
#define BUFFER_SIZE 4
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);
}
// my code
void main()
{
char ip[BUFFER_SIZE];//string input buffer
int32 bn = 0;//big number
int p;//position number
int16 time;//
int j;//index used in buffer
int1 flag = 0;
enable_interrupts(global);
enable_interrupts(int_rda);
printf("Hello .. \r\n");//greeting
while (1){
if (flag == 1){
bn=atol(ip);//make it a number
p=bn/1000;//strip off the top digit
time=bn-(p*1000);//get the bottom 3 digits
printf("bn: %lu p: %u time: %lu\r\n", bn, p, time);
flag = 0;//reset flag
}
// below is where output stuff would happen, just a simple
//countdown in this case
if (p != 0){
while (p != 0){
printf("countdown: %u\r\n", p);
p = (p - 1);
delay_ms(500);
}
}
while(bkbhit){
for(j=0;j<=(BUFFER_SIZE - 1);++j){
ip[j] = bgetc();//get input string one char at a time
printf("buf: %S %u\r\n", ip, j);// watch the buffer fill (or not)
if(j==(BUFFER_SIZE - 1))
flag = 1;//set flag
}
}
}
}
|
in this case, the last index in the buffer is not filled (or read?) until the output loop ends. this is what the terminal shows - the buffer-filling stuff doesn't display until after the loop has finished whether the data came in during or after its run:
Code: |
buf: 8 0
buf: 83 1
buf: 837 2
buf: 8372 3
bn: 8372 p: 8 time: 372
countdown: 8
countdown: 7
countdown: 6
countdown: 5
countdown: 4
countdown: 3
countdown: 2
countdown: 1
buf: 9372. 0
buf: 9972. 1
buf: 9992. 2
buf: 9991. 3
bn: 9991 p: 9 time: 991
countdown: 9
countdown: 8
countdown: 7
countdown: 6
countdown: 5
countdown: 4
countdown: 3
countdown: 2
countdown: 1
|
i seem to be misunderstanding something fairly basic here - is it clear what i want to do? it seems fairly universal, i just haven't been able to find any other examples out there.
many thanks,
bill |
|
|
Ttelmah Guest
|
|
Posted: Wed Feb 22, 2006 3:49 pm |
|
|
Start with your buffer being nowhere near large enough. You delay for 500mSec. In this time, if 9600bps communication runs flat out, you could receive 480 characters...
Don't count through the buffer 'size' in the output. Basically, if bkbhit is set, there are characters waiting. Remember characters can still be arriving while you are printing. Potentially your printout, could take about 15 character times, and another fifteen characters could have been received while you do this. This is why your code stays in the handler, since the output, is taking so long, that when it executes the first time, four characters have already been received, and the routine will loop four times, without a exiting.
Technically, your ip string, needs to be five characters long, with a null terminator in ip[4], otherwise garbage may get printed. That this hasn't happened so far, has been luck...
Best Wishes |
|
|
bsack
Joined: 21 Feb 2006 Posts: 2 Location: Buffalo NY
|
|
Posted: Fri Feb 24, 2006 9:04 pm |
|
|
thank you for the clue. i added a null terminator and this made the code do pretty much what i wanted - though it's very ugly looking and i won't be sharing it anytime soon! - but if i continue to read postings here and read some more c texts i may get more of a handle on how to cope with these problems on my own.
thanks again,
bill |
|
|
|
|
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
|