2
votes

I am trying to read from a sensor with PIC 18f4550 at baud rate=38400. With a FIFO Circular buffer, I am able to store data from the sensor to an array.

The sensor will respond to a request command and return a measurement of 15 bytes (the same as the circular buffer I created). I have to grab all 15 bytes and put \r\n at the end to separate each measurement since there is no deliminator.

So I used two pointers, inputpointer and outputpointer to store bytes and transmit byte out. Because 18f4550 only has one hard UART, I use it to read data and send commands to sensor and at the same time use a software UART to output to a laptop via RS232.

I request a new measurement when the buffer is read and sent to serial port.

It works well but I just want to know if there is a better way to avoid FIFO overrun when the head pointer overruns tail pointer, ie when there is a lot of data getting buffered but they cannot get output in time.

Here is the code: 16MHZ PIC 18f4550 mikroC compiler

char dataRx[15];
char unsigned inputpointer=0;
char unsigned outputpointer=0;
        // initialize pointers and buffer.
void main() {
      ADCON1=0x0F;  //turn analog off

      UART1_Init(115200);  //initialize hardware UART @baudrate=115200, the same setting for the sensor
      Soft_UART_Init(&PORTD,7,6,38400,0); //Initialize soft UART to commnuicate with a laptop
      Delay_ms(100); //let them stablize



      PIE1.RCIE = 1;                //enable interrupt source
      INTCON.PEIE = 1;
      INTCON.GIE = 1;


      UART1_Write(0x00);            //request a measurement.
      UART1_Write(0xE1);            //each request is 2 bytes

      while(1){

        Soft_UART_Write(dataRx[outputpointer]);  //output one byte from the buffer to laptop
        outputpointer++;                        //increment output pointer
        if(outputpointer==0x0F)                 //reset pointer if it's at the end of the array
        {
            outputpointer=0x00;
            Soft_UART_Write(0x0D);              //if it's at the end, that means the buffer is filled with exactly one measurement and it has been output to the laptop. So I can request another measurement.
            Soft_UART_Write(0x0A);              //add \r\n
            UART1_Write(0x00);                  //request another measurement
            UART1_Write(0xE1);
        }



}
void interrupt(void){ //interrupt routine when a byte arrives
      dataRx[inputpointer]=UART1_Read();            //put a byte to a buffer
      inputpointer++;
      if (inputpointer==0x0F){inputpointer=0;}      //reset pointer.

}

1
FIFO Overrun? You have a FIFO underrun bug in your code: You don't check whether there is actually data in before sending the first byte. It probably only sort of works because you soft uart is slow.Turbo J
@TurboJ I am getting dsPIC30f4011 with 2 UART modules and it's on the way. But I don't think it solves the problem. There are more codes for sending data then receiving data and receiving has high priority(interrupt driven) so eventually there will be an overrun unless I stop requesting until all bytes have been sent out.Timtianyang
is there any reason why not to use separate buffers for transmit and receive? technically they should be separate buffers.pm101

1 Answers

0
votes

Maybe you could DISABLE the interrupt WHILE you are transferring the sensor reading OUT and then RE-ENABLE it after completion of transferring the data out?

It may not make a significant difference but it may stop the FIFO overrun you mentioned?