|
|
View previous topic :: View next topic |
Author |
Message |
friedrich Guest
|
sending message with RS485.C |
Posted: Fri Nov 21, 2008 1:36 am |
|
|
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
|
|
Posted: Fri Nov 21, 2008 1:55 am |
|
|
I believe the "CD" stands for "collision detect". |
|
|
friedrich Guest
|
|
Posted: Fri Nov 21, 2008 2:09 pm |
|
|
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
|
|
Posted: Fri Nov 21, 2008 2:32 pm |
|
|
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
|
|
Posted: Sun Nov 23, 2008 5:40 am |
|
|
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
|
|
Posted: Mon Nov 24, 2008 1:36 am |
|
|
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
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
|
|
Posted: Mon Nov 24, 2008 3:41 am |
|
|
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
|
|
Posted: Mon Nov 24, 2008 1:16 pm |
|
|
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
|
|
Posted: Mon Nov 24, 2008 3:52 pm |
|
|
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.
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
|
|
Posted: Mon Nov 24, 2008 4:06 pm |
|
|
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
|
|
Posted: Thu Jul 23, 2009 11:17 am |
|
|
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
|
|
Posted: Thu Jul 23, 2009 11:32 am |
|
|
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
|
|
Posted: Thu Jul 23, 2009 2:11 pm |
|
|
It worked, it was just that!!!!! But do not understand because it worked ... .. heheeh
I review my concepts. . rsrr.
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. |
|
|
|
|
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
|