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

fgetc() buffer issues

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



Joined: 18 Apr 2011
Posts: 2

View user's profile Send private message

fgetc() buffer issues
PostPosted: Mon Apr 18, 2011 10:33 pm     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 19, 2011 8:54 am     Reply with quote

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

View user's profile Send private message

PostPosted: Tue Apr 19, 2011 10:36 am     Reply with quote

To suggest an explanation, your hardware may possibly loop back the send out data.
temtronic



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

View user's profile Send private message

PostPosted: Tue Apr 19, 2011 11:03 am     Reply with quote

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

View user's profile Send private message

PostPosted: Thu Apr 21, 2011 11:47 am     Reply with quote

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

View user's profile Send private message AIM Address

i think this is the code you seek
PostPosted: Thu Apr 21, 2011 3:02 pm     Reply with quote

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

View user's profile Send private message AIM Address

btw:
PostPosted: Thu Apr 21, 2011 3:04 pm     Reply with quote

"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
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