| 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: 1660
 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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  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: 9587
 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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  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: 19964
 
 
 
			    
 
 | 
			
				|  |  
				|  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?
 |  | 
	
		|  | 
	
		|  |