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 support@ccsinfo.com

sending message with RS485.C

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







sending message with RS485.C
PostPosted: Fri Nov 21, 2008 1:36 am     Reply with quote

hi everybody,

would anyone explain me what does the RS485_CD mean and why do we use it in the sending routine below.

this is a code extracted from the RS485.C file

Code:
 #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=RS485)
   #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, multi_master, errors, stream=RS485_CD)




Code:

// Purpose:    Send a message over the RS485 bus
// Inputs:     1) The destination address
//             2) The number of bytes of data to send
//             3) A pointer to the data to send
// Outputs:    TRUE if successful
//             FALSE if failed
// Note:       Format:  source | destination | data-length | data | checksum
int1 rs485_send_message(int8 to, int8 len, int8* data) {
   int8 try, i, cs;
   int1 ret = FALSE;

   RCV_OFF();
   #if RS485_USE_EXT_INT
      disable_interrupts(GLOBAL);
   #endif

   for(try=0; try<5; ++try) {
      rs485_collision = 0;
      fputc((int16)0x100|rs485_id, RS485_CD);
      fputc((int16)0x100|to, RS485_CD);
      fputc(len, RS485_CD);

      for(i=0, cs=rs485_id^to^len; i<len; ++i) {
         cs ^= *data;
         fputc(*data, RS485_CD);
         ++data;
      }

      fputc(cs, RS485_CD);
      if(!rs485_collision) {
         ret = TRUE;
         break;
      }
      delay_ms(RS485_ID);
   }

   RCV_ON();
   #if RS485_USE_EXT_INT
      enable_interrupts(GLOBAL);
   #endif

   return(ret);
}




thanks in advance.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Nov 21, 2008 1:55 am     Reply with quote

I believe the "CD" stands for "collision detect".
friedrich
Guest







PostPosted: Fri Nov 21, 2008 2:09 pm     Reply with quote

PCM programmer wrote:
I believe the "CD" stands for "collision detect".

Hi PCM, thank you for your answer,

I noticed that when in receiving routine we use:

Code:
#use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, errors, stream=[b]RS485[/b])


while in sending we use:

Code:
 #use rs232(baud=9600, xmit=RS485_TX_PIN, rcv=RS485_RX_PIN, enable=RS485_ENABLE_PIN, bits=9, long_data, [b]force_sw[/b], [b]multi_master[/b], errors, stream=[b]RS485_CD[/b])



why do you use different #use rs232() with the same device ?


can anyone explain me those lines ?

Code:
  fputc((int16)0x100|rs485_id, RS485_CD);


Code:
 for(i=0, cs=rs485_id^to^len; i<len; ++i) {
         cs ^= *data;
         fputc(*data, RS485_CD);
         ++data;



any answer will be appreciated.

thanks.
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Fri Nov 21, 2008 2:32 pm     Reply with quote

Quote:
why do you use different #use rs232() with the same device ?

During transmission, they have to worry about detecting a collision.
Look in the section on "#use rs232()" in the CCS manual. Look at the
explanation for "Multi-Master". You had a question about why the use
of "FORCE_SW". The manual says "May not be used with the
[hardware] UART".
http://www.ccsinfo.com/downloads/ccs_c_manual.pdf


Quote:
fputc((int16)0x100|rs485_id, RS485_CD);

The difference between address and data is indicated by setting the
9th bit = 1 for an address.


Quote:
for(i=0, cs=rs485_id^to^len; i<len; ++i) {
cs ^= *data;
fputc(*data, RS485_CD);
++data;
}

"cs" stands for "checksum". They are sending the data and building
the checksum byte in that loop. Look at the comments above the
rs485_send_message() function. They explain the message format
and the bytes that are contained in it:
Quote:
// Format: source | destination | data-length | data | checksum
friedrich
Guest







PostPosted: Sun Nov 23, 2008 5:40 am     Reply with quote

Hi PCM Programmer,

thank you again for your attention to my topic,

PCM programmer wrote:
Quote:
why do you use different #use rs232() with the same device ?

During transmission, they have to worry about detecting a collision.
Look in the section on "#use rs232()" in the CCS manual. Look at the
explanation for "Multi-Master". You had a question about why the use
of "FORCE_SW". The manual says "May not be used with the
[hardware] UART".




thanks for this link, I had the 2007 manual.


PCM programmer wrote:

Quote:
fputc((int16)0x100|rs485_id, RS485_CD);

The difference between address and data is indicated by setting the
9th bit = 1 for an address.


ok.


PCM programmer wrote:

Quote:
for(i=0, cs=rs485_id^to^len; i<len; ++i) {
cs ^= *data;
fputc(*data, RS485_CD);
++data;
}

"cs" stands for "checksum". They are sending the data and building
the checksum byte in that loop. Look at the comments above the
rs485_send_message() function. They explain the message format
and the bytes that are contained in it:
Quote:
// Format: source | destination | data-length | data | checksum




ok, here, we use different streams for sending and receiving.


I'd like to know (this may be basic), if we use in a code the RS485.C routines (below), do we have to write the a new "#use rs232()" can there be a conflict between them and those of the RS485.C ?.

- int1 rs485_get_message(int* data_ptr, int wait)
- nt1 rs485_send_message(int to, int len, int* data)
- void rs485_wait_for_bus(int1 clrwdt)



thanks in advance
friedrich
Guest







PostPosted: Mon Nov 24, 2008 1:36 am     Reply with quote

friedrich wrote:

I'd like to know (this may be basic), if we use in a code the RS485.C routines (below), do we have to write the a new "#use rs232()" can there be a conflict between them and those of the RS485.C ?.

- int1 rs485_get_message(int* data_ptr, int wait)
- nt1 rs485_send_message(int to, int len, int* data)
- void rs485_wait_for_bus(int1 clrwdt)


thanks in advance


Probably I wasn't enough clear,

I mean if we use

Code:
#include <rs485.c>



do we have to add a new #use rs232 in my code or modify the #use rs232 of rs485.c (I have one master talking to 3 slaves)

thanks
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Nov 24, 2008 3:41 am     Reply with quote

I may have missed something, but the technique used in rs485.c driver, utilizing two instances of #use rs232 with apparently the same UART pins is explained neither in the manual nor the driver source. It must be regarded as undocumented feature so far. I noticed, that in the driver source, a force_sw is included with the TX stream, while it has been removed in your post. The difference should be expected to matter.

You can use the driver as is, or design your own one, if complete information on the double #use rs232 isn't available. Personally, I prefer to supress Rx during Tx in the RS485 driver hardware connection, in this case no collision detection feature is present but no issue of processing echo characters, too.
friedrich
Guest







PostPosted: Mon Nov 24, 2008 1:16 pm     Reply with quote

Hi Fvm,

thanks for answering,

FvM wrote:
I may have missed something, but the technique used in rs485.c driver, utilizing two instances of #use rs232 with apparently the same UART pins is explained neither in the manual nor the driver source. It must be regarded as undocumented feature so far. I noticed, that in the driver source, a force_sw is included with the TX stream, while it has been removed in your post. The difference should be expected to matter.


yes, you're right and that's what I did not completely understand,that's what PCM Programmer tried to explain it to me, the use of a software UART with "hardware"pins

FvM wrote:

You can use the driver as is, or design your own one, if complete information on the double #use rs232 isn't available. Personally, I prefer to supress Rx during Tx in the RS485 driver hardware connection, in this case no collision detection feature is present but no issue of processing echo characters, too.


how do you process for that (in code I mean)?


thanks in advance.
friedrich
Guest







PostPosted: Mon Nov 24, 2008 3:52 pm     Reply with quote

Hi again,

I have a question regarding the RS485.C that popped into my mind when I read it, in fact, I noticed that there is no obvious link between rs485_get_message() and the other routines that handle incoming data : rs485_add_to_temp() and incomming_rs485().

could any helpful spirit explain this for me ?

excuse me for asking too much questions. Confused




Code:
// Purpose:    Get a message from the RS485 bus and store it in a buffer
// Inputs:     1) A pointer to a buffer to store a message
//             2) TRUE  - wait for a message
//                FALSE - only check if a message is available
// Outputs:    TRUE if a message was received
//             FALSE if wait is FALSE and no message is available
// Note:       Data will be filled in at the pointer as follows:
//             FROM_ID  DATALENGTH  DATA...
int1 rs485_get_message(int* data_ptr, int1 wait)
{
   while(wait && (rs485_ni == rs485_no)) {}

   if(rs485_ni == rs485_no)
      return FALSE;
   else {
      int n;
      n = rs485_buffer[(rs485_no+1)%sizeof(rs485_buffer)] + 2;

      for(; n>0; --n)
      {
         *data_ptr = rs485_buffer[rs485_no];
         if(++rs485_no >= sizeof(rs485_buffer))
         {
            rs485_no = 0;
         }
         ++data_ptr;
      }
      return TRUE;
   }
}

#endif




Code:
// The index for the temporary receive buffer
int8 temp_ni;

// Purpose:    Add a byte of data to the temporary receive buffer
// Inputs:     The byte of data
// Outputs:    None
void rs485_add_to_temp(int8 b)
{....




Code:
// Purpose:    Interrupt service routine for handling incoming RS485 data
#if (RS485_USE_EXT_INT==FALSE)
#int_rda
#else
#int_ext
#endif
void incomming_rs485()
{.....

PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Mon Nov 24, 2008 4:06 pm     Reply with quote

Quote:
rs485_add_to_temp()

This function is called by the #int_rda routine in 3 places.


Quote:
rs485_buffer[temp_ni] = b;

The rs485_add_to_temp() function writes the incoming character into the buffer with this line of code.

Quote:
n = rs485_buffer[(rs485_no+1)%sizeof(rs485_buffer)] + 2;
*data_ptr = rs485_buffer[rs485_no];

The rs485_get_message() reads the rs485_buffer[] array in 2 places
inside that routine, as shown in the lines above.
monttec



Joined: 30 Mar 2009
Posts: 5
Location: São Paulo, Brasil

View user's profile Send private message

PostPosted: Thu Jul 23, 2009 11:17 am     Reply with quote

I will take the topic.

Please someone help me!

I'm trying to make a communication using the RS485 driver rs485.c
But I am not getting.

When you call the function "rs485_send_message (id, size, pointer)"
she returns the value 0 "false"

This function by which I understand should return 1 "true" and not 0 "false. ?

I am doing something wrong?

Thank you!


Google traslate.

---------------------------------------------------------------
Vou aproveitar o tópico.

Por favor, alguém me ajude !!!

Estou tentando fazer uma comunicação rs485 utilizando o driver rs485.c
Mas não estou conseguindo.

Quando chamo a função “rs485_send_message(id, size, pointer)”
ela me retorna o valor 0 “false”

Essa função pelo que eu entendi deveria retornar 1”true” e não o 0”false. ?

Estou fazendo alguma coisa errada ?

Obrigado !

Code:

#include <16F628A.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, stream=PC)

#define  RS485_RX_BUFFER_SIZE 64
#define  RS485_USE_EXT_INT    TRUE

int8 RS485_IDd = 5;
#define RS485_IDd RS485_ID

#include <rs485.c>
#include <stdlib.h>

int id = 12;
int size = 3;
int8 bufsend[4] = {01,12,03};
int8 *pointer;


void main()
{
     
   rs485_init();
   
   while(true)
   {
               
    pointer = &bufsend[0];
       
   do{
   
      rs485_send_message(id, size, pointer);
     
     }while(!rs485_send_message(id, size, pointer));
           
    //Returns TRUE if successful, FALSE if failed 
           
    fprintf(pc,"send successful");
    fprintf(pc,"\n\r");
    fprintf(pc,"\n\r");                       
         
   }
}
PCM programmer



Joined: 06 Sep 2003
Posts: 21708

View user's profile Send private message

PostPosted: Thu Jul 23, 2009 11:32 am     Reply with quote

Quote:
#define RS485_USE_EXT_INT TRUE

This is a mistake. The External interrupt code should only be
used if you are using a software UART, with the Rx pin on pin B0. But
you are using the Hardware UART. Change the #define to FALSE,
as shown below:
Quote:
#include <16F628A.h>
#device *=16
#fuses HS, NOWDT, NOLVP, NOBROWNOUT, NOPROTECT, PUT
#use delay(clock=20000000)
#use rs232(baud=9600, xmit=PIN_B2, rcv=PIN_B1, stream=PC)

#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE // Change to FALSE
int8 RS485_IDd = 5;
#define RS485_IDd RS485_ID

#define RS485_TX_PIN PIN_B2 // Add this line
#define RS485_RX_PIN PIN_B1 // Add this line


#include <rs485.c>
#include <stdlib.h>

Also, the rs485.c file normally uses pins C6 and C7 for the hardware
UART. But your PIC uses B2 and B1, so you must add the two #define
statements shown above in bold.

Also, the rs485.c file uses pins B4 and B5 to control the enable lines
on the RS-485 transceiver chip. You need to look at your hardware
design and if the enable pins are different, then add #define statements
for the those pins also.
transceiver chip
monttec



Joined: 30 Mar 2009
Posts: 5
Location: São Paulo, Brasil

View user's profile Send private message

PostPosted: Thu Jul 23, 2009 2:11 pm     Reply with quote

It worked, it was just that!!!!! But do not understand because it worked ... .. Very Happy heheeh

I review my concepts. . rsrr. Embarassed

I tried for two days and can not.

My Hardware PIC

B0 - RO Max485 chip
B1 - RX Hyper Terminal is Debug
B2 - TX Hyper Terminal is Debug
B3 - DI chip Max485
B4 - DE Max485 chip
B5 - RE Max485 chip


Thank you, PCM. Wink
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