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

UART buffer strange behavior

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



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

UART buffer strange behavior
PostPosted: Fri Oct 19, 2012 6:35 am     Reply with quote

Dear CCS Member,
I wrote program on Host to communicate via modbus RTU, rs485 with sensors(PIC 18F67J60, CCS 4.134).
When during communication i disconnect and connect again sensor, sometimes ( i think when i connect during data transmission and host receive incomplete data) host receive data in wrong sequence from this moment up to forever, please look at:

Correct data:
Code:

01 03 1D 00 09 54 82 73 33 33 85 46 CC CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 AA 55 6B

Receive by Host:
eg.1
Code:

6B 01 03 1D 00 09 54 82 73 33 33 85 46 CC CD 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 02 AA 55

eg.2
Code:

00 00 00 00 00 00 00 00 00 00 00 00 00 02 AA 55 6B 00 01 03 1D 00 09 54 82 73 33 33 85 46 CC CD 00 00


The data are shifted.
my code:
Code:

int8 ModbusReceiveData(int8 SlaveID, int16 BytesQuantity, int32 TimeOutValue)
{
   int8 FunctionCode = 1;
   int8 index=0;
   BYTE temp_chr;
   int32 TimeOutCounter = 0;
   for(int i = 0; i < BytesQuantity; i++)
   {
   Modbus.Buffer[i] = 0;
   }
         while (TimeOutCounter < TimeOutValue)
         {
            if (bkbhit)
            {         
               //Now have a character
               temp_chr = bgetc(); //get the character
               TimeOutCounter = 0;               
               Modbus.Buffer[index]=temp_chr; //store the character
               if (index < BytesQuantity) ++index; //and update the counter
               
               if (index == BytesQuantity) //if i receive all data
               {
                 //Modbus.Buffer[index] = '\0'; // end buffer
                  ModbusCalcCrc(BytesQuantity - 2);
                  if((Modbus.Buffer[index - 1] == Modbus.CRC_Hi) && (Modbus.Buffer[index - 2] == Modbus.CRC_Lo ))
                  {
                     index=0;
                     if((Modbus.Buffer[0]==SlaveID))// sprawdzam odebrany kod funkcji
                     {
                      FunctionCode =  Modbus.Buffer[1];
                     }
                     else
                     {
                        FunctionCode =  0;
                     }
                  }
                  else
                  {
                     FunctionCode = 0;
                  }
                  break;
               }
            }
            TimeOutCounter++;
         }
   clear_usart();
 
   return FunctionCode;             
}

clear_usart:
Code:

void clear_usart(void)
{
   char c;
   while (kbhit()) c=getc();     
}

UART:
Code:

#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7,bits=8,parity=N,stop=1,stream = UART1)
#define BUFFER_SIZE 64

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;
   if(++next_in==BUFFER_SIZE)
      next_in=0;
   if(next_in==next_out) //get rid of the ';' here - wrong.....
      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);
}

It seems that buffer is not clear, i add clear function but it didn't help.

What else i have to do to clear buffer?

Best Regards,
Martin


Last edited by Requan on Fri Oct 19, 2012 6:45 am; edited 1 time in total
asmallri



Joined: 12 Aug 2004
Posts: 1635
Location: Perth, Australia

View user's profile Send private message Send e-mail Visit poster's website

PostPosted: Fri Oct 19, 2012 6:38 am     Reply with quote

I am guessing your RS485 bus is not correctly terminated.
_________________
Regards, Andrew

http://www.brushelectronics.com/software
Home of Ethernet, SD card and Encrypted Serial Bootloaders for PICs!!
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 6:48 am     Reply with quote

Arrow asmallri

Thanks for reply.
I have resistor 120 Ohm on both side.
I tested on very short cable and behaviour is the same.
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 8:14 am     Reply with quote

You have to be careful with RS485. Depending on the buffer chips you use, some are certified to give a 'idle' (high) output, when the bus is undriven. Others _require_ you to apply a tiny bias voltage to the bus as part of your termination, to ensure that when the bus is not driven, devices see this output. Without this, an undriven bus can float to the active state, and what you then receive is dependant on luck....

Best Wishes
temtronic



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

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 11:42 am     Reply with quote

You should always add 'errors' to the use rs232(......) options as well when using the hardware UART.

hth
jay
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 12:29 pm     Reply with quote

Thanks for answers.
Arrow Ttelmah
What do You advice to for me to do?
Arrow temtronic
You right i forget about it, but i have to admit that i don't understand how it works.
I have to add this option only or something else?
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Oct 19, 2012 2:30 pm     Reply with quote

Code:

 while(!bkbhit) ;


should be EXTERNAL to the Bgetc function
NOT inside it !!!!

then use it like this :


Code:

    if (bkbhit) yourBYTE_var=bgetc();
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 2:34 pm     Reply with quote

On bias, search the web. Texas do a very good note about it.
Search for "RS485 bus bias".


Best Wishes
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 2:37 pm     Reply with quote

Quote:
should be EXTERNAL

That code is right out of Ex_sisr.c:
c:\program files\picc\examples\ex_sisr.c
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Fri Oct 19, 2012 2:40 pm     Reply with quote

It is one of those 'understand what you and CCS are doing' things.
The bkbhit test needs to be inside bgetc, _in case_ somebody calls it _without_ first checking if data is available. It should be there, _but_ if you don't want to hang if data is not available, the programmer should also test before calling....

Best Wishes
asmboy



Joined: 20 Nov 2007
Posts: 2128
Location: albany ny

View user's profile Send private message AIM Address

PostPosted: Fri Oct 19, 2012 6:27 pm     Reply with quote

OH i get it - this was done for consistency -
to make bgetc() work logically the same as getc() right ??

I never knew getc() had an included kbhit inside it before.

i learn something useful every day on this forum.


Very Happy Very Happy Very Happy
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Sun Oct 21, 2012 4:51 am     Reply with quote

Quote:

You have to be careful with RS485. Depending on the buffer chips you use, some are certified to give a 'idle' (high) output, when the bus is undriven. Others _require_ you to apply a tiny bias voltage to the bus as part of your termination, to ensure that when the bus is not driven, devices see this output. Without this, an undriven bus can float to the active state, and what you then receive is dependant on luck....


I wonder one thing. When i had problem with data i connected PC via rs485/rs232 interface to the 485 bus. Data on bus were ok but PIC received in wrong seguence.

2 years ago i wrote similar program in "Proton PIC Basic" and it was ok.
Ttelmah



Joined: 11 Mar 2010
Posts: 19550

View user's profile Send private message

PostPosted: Sun Oct 21, 2012 7:57 am     Reply with quote

That was something wrong with your code/hardware I'm afraid. The compiler does nothing to the byte order....
When you 'connected the PC to the bus', what you see, is dependant on the behaviour of the buffers used in the PC interface, so if they happen tobe ones that do accept an undriven bus as giving an 'idle' output, the result may well differ from what the PIC sees.
Also, unless the bus buffers used on yor PIC basic example, were the same as the ones you are now using, the sane applies here.

Best Wishes
Requan



Joined: 11 May 2008
Posts: 74

View user's profile Send private message

PostPosted: Sun Oct 21, 2012 10:30 am     Reply with quote

There is something strange more (maybe it helps to find solution):
during "wrong transmission" when is change 485 address in receiver (I have dip-switch on board) and host send query with no reply and next I return to proper address - from now all work fine.

I tried to manually reset many things: buffer, index, variables but nothing helps.

Could you tell me how to reset transmission, maybe reset interrupt?
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