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

Problem in receiving a string through UART/RS-485

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



Joined: 10 Jan 2013
Posts: 68

View user's profile Send private message

Problem in receiving a string through UART/RS-485
PostPosted: Tue Sep 24, 2013 7:19 am     Reply with quote

Hi
I’m trying to read some registers from a modbus slave and store it in a string.(Communication Format is: ASCII 7,N,2 9600)
The normal query looks like this:
Code:

TX=":010321000006D5\r\n"
RX=":01030C0000052A0CC200000000172AB2\r\n"

But I receive two extra null chars at the beginning of the response. (I check using a USB-485 converter on my PC.)
Here's the hex representation of message bytes:
Code:

00003A30313033304330303030303532413043433230303030303030303137324142320D0A

The function get_string is a modified version of the one from the file input.c.
What do you guys think is the problem?
Code:

#include <16F873A.h> //CCS v4.130
#device adc=10
#FUSES NOWDT, HS, PUT, NOBROWNOUT, NOLVP

#use delay(clock=16000000)
#use rs232(BAUD=9600,UART1,ERRORS)

#bit TRMT         = getenv("BIT:TRMT")
#define RE_DE   PIN_C5

int8 cmd[40];
int8 i;
int1 timeout_error=FALSE;

void putc7n2(int8 chr);
int8 getc7n2();
void get_string(char* s, int8 max);
//*********************************************************
void main()
{
  setup_adc_ports(NO_ANALOGS);

  while(1)
  {
    delay_ms(500);
    strcpy(cmd,"dummy fill.");
    output_high(RE_DE);
    printf(putc7n2,":010321000006D5\r\n");    //read registers 2100-2105 (6)
    while(TRMT==0);                           //wait untill sending is done
    output_low(RE_DE);

    get_string(cmd, 40);                      //store the response in cmd

    output_high(RE_DE);
    if (timeout_error)
      printf(putc7n2, "Timeout\r\n");
    else
    {
      for (i=0; i<40; ++i)
      {
        printf(putc7n2, "%X", cmd[i]);
      }
      printf(putc7n2, "\r\n");
    }
    while(TRMT==0);                           //wait untill sending is done
    output_low(RE_DE);
  }
}
//*********************************************************
void get_string(char* s, int8 max)
{
  int16 timeout=10000;                  // 10000 * 10us = 100ms. The response has to be 'finished' in 100ms
  int8 len=0;
  char c;

  timeout_error=FALSE;
  --max;
  do
  {
    while(!kbhit()&&(--timeout))      //wait for new charachter and decrease timeout.
      delay_us(10);

    if(kbhit())                       // if it's kbhit, getc. if not, then timeout has reached.
      c=getc7n2();
    else
    {
      timeout_error=TRUE;
      break;
    }

    if(len<=max)
      s[len++]=c;
    else
      break;

  } while(c!=0x0A);
  s[len]=0;
}
//*********************************************************
void putc7n2(int8 chr)
{
  bit_set(chr,7);      // Simulate an extra stop bit by setting the MSB
  putc(chr);
}
//*********************************************************
int8 getc7n2()
{
  int8 chr;
  chr=getc();
  bit_clear(chr,7);    // clear extra stop bit
  return(chr);
}
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Sep 24, 2013 8:41 am     Reply with quote

Possibly termination.

When the bus turns round, for a little while the 485, is undriven, while the other end decides it is going to reply. If the bus is not physically biased to the 'off' state, when undriven, and you are not using 485 chips that guarantee to see an undriven bus as 'idle', then you will see extra characters like this.
Choices to avoid this, are to either design a little bus biasing into the termination, or chose RS485 drivers than see an undriven bus as idle.

Other thing, do you have a pull up on the RX line of the PIC?.

When the receiver is disabled, when you are sending, this line needs to be pulled high, otherwise extra characters can be seen.

Best Wishes
notbad



Joined: 10 Jan 2013
Posts: 68

View user's profile Send private message

PostPosted: Tue Sep 24, 2013 1:57 pm     Reply with quote

Thank you very much Ttelmah!
I already had 620 ohm idle biasing resistors, but the pull-up on RX solved the problem!
What exactly causes this? The crosstalk from TX Line?
It's weird because there were always exactly two nulls and nothing else!

As this issue is not discussed in the datasheet, how should I have known this? Embarassed
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Tue Sep 24, 2013 2:55 pm     Reply with quote

If you think about it the PIC pin is an input. When you turn off the transceiver, nothing is driving it. What is going to keep it high?.

Since you are not using interrupt driven RX, there are just two characters of buffering in the hardware. These are received when you once again start listening. A line going low, will give a zero character.

Best Wishes
notbad



Joined: 10 Jan 2013
Posts: 68

View user's profile Send private message

PostPosted: Wed Sep 25, 2013 2:08 pm     Reply with quote

Thank you Ttelmah!

I added a button and a piece of code at the end of the while(1) to write a register in the slave.
The slave responds to command but I don’t need this response. This overruns the hardware buffer.
How can I safely clear the buffer and overrun errors?
I used two getc()s but the pic gets stuck if there is occasionally no response.

Another question:
Is checking TRMT bit enough to make sure a printf is 'done'?
Doesn't TRMT go high for a moment after the second last byte is sent and the last byte is being moved to the TSR?
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 1:38 am     Reply with quote

The 'ERRORS' in the #use RS232 adds code to clear the overrun error, or framing error when a character is read.
However you can (of course) only read the character, when there is one to read.
So:
Code:

   if (kbhit())
       getc();
   if (kbhit())
       getc();

Makes calling the getc's become dependant on there being a character there.
Or:
Code:

    while(kbhit())
       getc();

Will just read anything that is waiting, then immediately return.

Honestly though I have to say consider interrupt driven receive.

Best Wishes
notbad



Joined: 10 Jan 2013
Posts: 68

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 3:13 am     Reply with quote

Code:

    while(kbhit())
       getc();


This works. Thanks.
Can you please answer my other question.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 3:37 am     Reply with quote

No. This is down to the phase in the instruction cycle, when things happen. The PIC does the transfer to the output register from the holding register _before_ status bits are tested in the instruction cycle.
Hence you can just test TRMT.

Best Wishes
RF_Developer



Joined: 07 Feb 2011
Posts: 839

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 4:10 am     Reply with quote

Ttelmah wrote:
A line going low, will give a zero character.


Hmm, a line going low should give a framing error as there's no stop bit. That suggests that some necessary error handling is not going on, or is giving unexpected or un-thought-about results. I've not looked into precisely what does happen with various error conditions, but it's plausible that when using "errors" in the #use rs232 as the default error handling will do something simple like resetting the UART after the error but may then pass a character, a null seems the most likely default, to the user's code. I'd expect only one however as there wouldn't be a start bit to start reception of any more (spurious) characters.
Ttelmah



Joined: 11 Mar 2010
Posts: 19515

View user's profile Send private message

PostPosted: Thu Sep 26, 2013 7:37 am     Reply with quote

It'll give a zero, and the framing error bit set in RS232_ERRORS.
He is not testing this bit, so as far as his code is concerned, it'll just give zero.

Best Wishes
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