|
|
View previous topic :: View next topic |
Author |
Message |
david_va
Joined: 18 Apr 2011 Posts: 2
|
fgetc() buffer issues |
Posted: Mon Apr 18, 2011 10:33 pm |
|
|
Hello,
I am working with a group on a project using the CCS PCWH compiler (Ver 4.097) in MPLab with a PICLF2620 microcontroller. We have run into an issue we have not been able to solve, and I am hoping someone here can provide some direction.
Our hardware setup is currently a host PC connected to the PIC using an FTDI as a USB->RS232 connector. The PIC is on a breadboard. We are using Port C on the PIC as a TX / RX combination to send AT commands and other bytes to an external device, and also read back. We have the tri-state on Port C set correctly.
We currently have the PIC set up so the TX and RX are connected, just to verify we can correctly send and receive bytes. When using fgetc(radio), where radio is the RS232 stream, we can transmit a byte from TX and receive it on RX. However, the receive buffer does not clear after the fgetc() call, and subsequent calls of fgetc() return the same byte as before, regardless of if we send a multi-byte string or another individual byte (through use of keyboard presses through a terminal.) What we would expect is for fgetc() to "hold" until a new byte is received on RX, instead of repeatedly returning the same character.
We've tried a variety of things, from adjusting baud rate and clock frequency, to reading and writing the RCREG manually in an attempt to clear it, to implementing a timed_fgetc() function, but we've been unsuccessful in solving the issue. The relevant code snippets are below:
Code: | #include <18F2620.H>
#include <main.h>
#include <stdlib.h>
#use delay(clock = 8000000) //PIC internal
//#device ICD = TRUE
#use rs232(baud=9600,parity=N,xmit=PIN_C6,rcv=PIN_C7,bits=8,stream=radio,ERRORS)
...
void main() {
char next;
char APIret;
int j = 0;
int i;
char ftest;
char ftest2;
SPBRG = 0x33;
SPBRGH = 0x00;
BAUDCOM = 0x40;
RCSTA = 0x90;
TXSTA = 0xA0;
// begin device setup
setup_adc_ports(AN0_TO_AN2);
setup_adc(ADC_CLOCK_INTERNAL);
// set tristates
set_tris_a(PA_TRIS);
set_tris_b(PB_TRIS);
set_tris_c(PC_TRIS);
port_b_pullups(TRUE);
setup_wdt(WDT_OFF); // keep off until done with preliminary stuff
set_rtcc(0);
setup_timer_0(RTCC_INTERNAL | RTCC_DIV_256 | RTCC_8_BIT);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED, 0, 1);
setup_timer_3(T3_DISABLED | T3_DIV_BY_1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
setup_low_volt_detect(FALSE);
setup_oscillator(OSC_8MHZ);
// end device setup
enable_interrupts(GLOBAL);
// output to RB to verify setup is complete
output_b(0xFF);
delay_ms(2000);
output_b(0x00);
delay_ms(1000);
// begin TX / RX test
while(true){
if(RCIF == 1)
{
ftest =fgetc(radio);
RCREG = 0;
RCIF = 0;
fprintf(radio, "%i\n\r",ftest);
}
//ftest = fgetc(radio);
if(rs232_errors != 0){
CREN = 0;
CREN = 1;
}
// flash RB
output_b(0xFF);
delay_ms(500);
output_b(0x00);
delay_ms(100);
fprintf(radio," RCSTA = 0x%x",RCSTA);
fprintf(radio," TXSTA = 0x%x",TXSTA);
fprintf(radio," Error = 0x%x",rs232_errors);
//ftest2 = kbhit(radio); // removed but was used to test if the buffer had data
//fprintf(radio," KBhit = %x\n\r",ftest2);
fprintf(radio," CON = %x\n\r",BAUDCOM);
fprintf(radio," BRGH = %x\n\r",SPBRG);
wait_for_RS232_to_complete();
}
...
}
|
The while loop in main waits until a byte is sent via RS232, then executes the rest, and we expect it to hold again at fgetc(radio). Instead, fgetc(radio) gets the same character over and over, and the return from kbhit() remains high, and any further bytes sent via RS232 are ignored.
It should be noted that we do not encounter this problem when the PIC is used with the MPLab Picdem Plus 2 board, only in its current breadboarded state.
Sorry for the long post, but any suggestions on fixing the code so we don't receive the same character repeatedly would be much appreciated. Please let me know if any further information is needed. |
|
|
rnielsen
Joined: 23 Sep 2003 Posts: 852 Location: Utah
|
|
Posted: Tue Apr 19, 2011 8:54 am |
|
|
First of all, if you are fairly new to CCS then I would strongly suggest that you allow the compiler to control the TRIS settings unless you absolutely need to control them in a special way. TRIS is an advanced function and can cause problems if you don't really know what you're doing.
You have global interrupts enabled but no interrupts declared. If you are going to be receiving data via the rs232 port then you really should use the ISR to receive the data (#INT_RDA). This will allow the hardware, that is built into the PIC, to do the work for you. Receive one byte at a time in the ISR. Some people try to receive an entire string but it's made to capture one byte.
If your code has a lot going on and you don't use an ISR then you could miss a lot of data that's coming in through your rs232. Just remember to keep your ISR short and sweet without delays or printing inside.
Ronald |
|
|
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Tue Apr 19, 2011 10:36 am |
|
|
To suggest an explanation, your hardware may possibly loop back the send out data. |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9246 Location: Greensville,Ontario
|
|
Posted: Tue Apr 19, 2011 11:03 am |
|
|
While in MPLAB, have you set the build configuration to 'release' instead of 'debug' , then recompiled, then burn the PIC ? |
|
|
david_va
Joined: 18 Apr 2011 Posts: 2
|
|
Posted: Thu Apr 21, 2011 11:47 am |
|
|
temtronic wrote: | While in MPLAB, have you set the build configuration to 'release' instead of 'debug' , then recompiled, then burn the PIC ? |
Just wanted to follow up and say thanks for suggesting this. We are new to MPLab and didn't realize there were different build modes. Switching to 'release' solved the problem (and some other ones we were having.) It's always something simple... |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
i think this is the code you seek |
Posted: Thu Apr 21, 2011 3:02 pm |
|
|
circular buffer method, dont forget to declare your correct
#user232
then try this:
Code: |
// simple serial ISR handler
BYTE RISR_out; // global background newchar from ISR BACKGND buffer
BYTE buffer[BUFFER_SIZE];
BYTE next_in = 0;
BYTE next_out = 0;
#define bkbhit (next_in!=next_out) // tells if serial chars are ready
// DO NOT CALL THIS receiver FUNCTION
// UNLESS bkbhit is true
// as you will get a null char back instead
// pass any new charcter received by int
byte bgetc(void) {
if (bkbhit) {
RISR_out=buffer[next_out];
next_out=(next_out+1) % BUFFER_SIZE;
return(RISR_out); // RISR_out is also a handy 'last cahr recived global
}
else return (0);
}
void mtbuf(void){ // clear all recived chars in buffer
while ( bkbhit) { bgetc();};
}
void DISR_INIT(void){ // set up the interrupt
clear_interrupt( int_rda );
enable_interrupts(int_rda);
enable_interrupts(global);
}
#int_rda // handle received chars in INT
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 !!
}
|
use with care - caveats explained in line |
|
|
asmboy
Joined: 20 Nov 2007 Posts: 2128 Location: albany ny
|
btw: |
Posted: Thu Apr 21, 2011 3:04 pm |
|
|
"buffer_size"
depends on your resources in ram
but a value of 128 should be plenty for normally encountered bauds
unless you NEVER check for new chars
i typically use 48 bytes or less even at 115200 and above |
|
|
|
|
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
|