View previous topic :: View next topic |
Author |
Message |
Requan
Joined: 11 May 2008 Posts: 74
|
UART buffer strange behavior |
Posted: Fri Oct 19, 2012 6:35 am |
|
|
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
|
|
Posted: Fri Oct 19, 2012 6:38 am |
|
|
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
|
|
Posted: Fri Oct 19, 2012 6:48 am |
|
|
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: 19553
|
|
Posted: Fri Oct 19, 2012 8:14 am |
|
|
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: 9246 Location: Greensville,Ontario
|
|
Posted: Fri Oct 19, 2012 11:42 am |
|
|
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
|
|
Posted: Fri Oct 19, 2012 12:29 pm |
|
|
Thanks for answers.
Ttelmah
What do You advice to for me to do?
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
|
|
Posted: Fri Oct 19, 2012 2:30 pm |
|
|
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: 19553
|
|
Posted: Fri Oct 19, 2012 2:34 pm |
|
|
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
|
|
Posted: Fri Oct 19, 2012 2:37 pm |
|
|
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: 19553
|
|
Posted: Fri Oct 19, 2012 2:40 pm |
|
|
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
|
|
Posted: Fri Oct 19, 2012 6:27 pm |
|
|
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.
|
|
|
Requan
Joined: 11 May 2008 Posts: 74
|
|
Posted: Sun Oct 21, 2012 4:51 am |
|
|
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: 19553
|
|
Posted: Sun Oct 21, 2012 7:57 am |
|
|
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
|
|
Posted: Sun Oct 21, 2012 10:30 am |
|
|
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? |
|
|
|