|
|
View previous topic :: View next topic |
Author |
Message |
arloedx
Joined: 21 Aug 2009 Posts: 15 Location: Texas
|
Help with RS485_get_message |
Posted: Fri Aug 21, 2009 4:16 pm |
|
|
Hi,
I am trying to set up a simple communication between two PIC18f252 using two MAX487. I was able to transmit data but I am unable to receive it using the RS485_get_message function from the RS485.c library (If I use getc() I can see the data I was transmitting). I'm sure its a matter of how I'm setting it up. Any help is appreciated. Also I am using Proteus ISUS to simulate the PIC to PIC communication. My receiver code is as follows.
Thanks
Code: |
#include <18f252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=PC)
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#include <lcd2.h>
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x09
#define RS485_ENABLE_PIN PIN_C5
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7
#include <rs485.c>
#include <stdlib.h>
void LCD_CHECK();
int8 msg[32];
void main()
{
set_tris_b(0x00);
set_tris_c(0x80);
output_low(RS485_ENABLE_PIN);
rs485_init();
lcd_init();
LCD_CHECK();
while(true)
{
rs485_get_message(msg, TRUE);
printf(lcd_putc, "%d ", msg);
}
}
void LCD_CHECK()
{
lcd_gotoxy(1,1);
printf(lcd_putc, "System Ready");
delay_ms(500);
printf(lcd_putc,"\f");
}
|
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Aug 21, 2009 4:23 pm |
|
|
Quote: | #use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=PC) |
The #use rs232() library code has an "ENABLE=pin #" feature, where
you can specify the enable pin, in the same way as the xmit and rcv pins.
See this CCS driver file for an example:
Quote: | c:\program files\picc\drivers\rs485.c |
|
|
|
arloedx
Joined: 21 Aug 2009 Posts: 15 Location: Texas
|
|
Posted: Mon Aug 24, 2009 10:37 am |
|
|
I added the "enable = pin_c5" PCM programmer suggested but still I have problems. I will provide my transmitter source code, the reciever source code and the schematics to show the entire picture...
Master Transmitter Code:
Code: |
#include <18f252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7)
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#include <lcd2.h>
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x01
#define RS485_DEST_ID 0x09
#define RS485_ENABLE_PIN PIN_C5
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7
#include <rs485.c>
#include <stdlib.h>
void LCD_CHECK();
void state(unsigned char s);
void frequency(unsigned char frc);
void LCD_CHECK()
{
lcd_gotoxy(1,1);
printf(lcd_putc, "System Ready");
delay_ms(500);
printf(lcd_putc,"\f");
}
int8 size=1;
int i, max = 5 ;
int8 bufsend[5] = {'A','B','C','D','E'};
int *pointer;
void main()
{
set_tris_b(0x00);
set_tris_c(0x80);
output_high(RS485_ENABLE_PIN);
rs485_init();
lcd_init();
LCD_CHECK();
while(true)
{
for(i=0; i<max; i++)
{
pointer = &bufsend[i];
rs485_wait_for_bus(TRUE);
rs485_send_message(RS485_DEST_ID, size, pointer);
printf(lcd_putc,"\fSent: %c", bufsend[i]);
delay_ms(400);
}
delay_ms(1000);
}
}
|
Slave Receiver Code:
Code: |
#include <18f252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=10000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, enable = PIN_C5, stream=PC)
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#include <lcd2.h>
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x09
#define RS485_ENABLE_PIN PIN_C5
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7
#include <rs485.c>
#include <stdlib.h>
void LCD_CHECK();
int8 msg[32];
void main()
{
set_tris_b(0x00);
set_tris_c(0x80);
output_low(RS485_ENABLE_PIN);
rs485_init();
lcd_init();
LCD_CHECK();
while(true)
{
rs485_get_message(msg, FALSE);
printf(lcd_putc, "%d ", msg[1]);
delay_ms(400);
}
}
void LCD_CHECK()
{
lcd_gotoxy(1,1);
printf(lcd_putc, "System Ready");
delay_ms(500);
printf(lcd_putc,"\f");
}
|
This outputs the following in the simulation:
There are a couple of things wrong with this...the first being for some reason the Master is transmitting "AH" instead of just "A" I dont know why this is happening but that is not important right now. The focus of this post in on the receivers side. As we can see a 0 is being received.
If I use
Code: |
i = getc();
printf(lcd_putc, "%d ", i);
|
We get "9 1 72" on the receiver LCD as shown in the second picture, where 9 is the slave_id, 1 is the size of tranmission, and 72 is the ascii value for "H"
To my understanding rs485_get_message is supposed to be able to interpret the incomming data but It has not worked for me so far. Any help would be awesome. Thanks in advance. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 24, 2009 11:43 am |
|
|
I made a mistake on that. The enable is handled in the #use rs232()
statement inside rs485.c and it's set by the line in bold:
Quote: |
#define RS485_ID 0x01
#define RS485_DEST_ID 0x09
#define RS485_ENABLE_PIN PIN_C5
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7 |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 24, 2009 1:36 pm |
|
|
I just looked at your schematic. I'm not sure why you need the PC
stream at all. You have LCDs for status messages. You don't
use the "PC" stream. You can delete these two lines:
Quote: |
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, stream=PC)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, enable = PIN_C5, stream=PC) |
Quote: | void main()
{
set_tris_b(0x00);
set_tris_c(0x80);
|
You're using Standard i/o mode. (It's the default mode of the compiler,
if no mode is defined). In that mode, the compiler sets the TRIS for you.
The library code sets the TRIS, and the output_high() and output_low()
functions (etc.) set the TRIS. You don't have to do it. I suggest that
you delete both of those lines (in both the Master and Slave code). |
|
|
arloedx
Joined: 21 Aug 2009 Posts: 15 Location: Texas
|
|
Posted: Mon Aug 24, 2009 2:26 pm |
|
|
PCM Programmer,
Thank you for responding. I tried your suggestions but that still does not solve the problem. I don't understand if my problem is with the way i'm transmitting, the way the HW is set up, or the way i'm using the rs485_get_message function. Personally I think its rs485_get_message function and I have looked at the examples provided by PICC and implemented the function as shown in the examples but I never receive data properly. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Mon Aug 24, 2009 2:41 pm |
|
|
Quote: |
while(true)
{
rs485_get_message(msg, FALSE);
printf(lcd_putc, "%d ", msg[1]);
delay_ms(400);
} |
I think there is a problem in the way you are calling that routine.
Here is the description of the routine, within the rs485.c file:
Quote: |
// 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) |
You're not checking to see if a message was actually received. You're
immediately jumping into printf with the contents of the 2nd byte in the
msg array, regardless of whether a message has been received or not.
I think it would be better to test the return value of the routine, and
only call printf() if it returns 'TRUE'). Example:
Code: |
while(true)
{
if(rs485_get_message(msg, FALSE))
printf(lcd_putc, "%d ", msg[1]);
}
|
I didn't look at your transmit code yet. I just looked at your receive code. |
|
|
arloedx
Joined: 21 Aug 2009 Posts: 15 Location: Texas
|
|
Posted: Tue Aug 25, 2009 8:09 am |
|
|
Quote: |
Code: |
while(true)
{
if(rs485_get_message(msg, FALSE))
printf(lcd_putc, "%d ", msg[1]);
}
|
|
When I try this It would appear I never receive a message. I don't understand why though. Thanks again for any help and future help. |
|
|
arloedx
Joined: 21 Aug 2009 Posts: 15 Location: Texas
|
|
Posted: Tue Aug 25, 2009 9:33 am |
|
|
I think i have isolated the problem.
From the RS485.c file I am calling two routines: rs485_init() and rs485_get_message(). When simulating my code I have discovered that it is getting stuck at the part in the rs485_get_message routine where:
Code: |
if(rs485_ni == rs485_no)
return FALSE;
|
rs485_ni and rs485_no are both initialized to equal 0 in the rs485_init() routine and are never updated before getting to the get_message function. Is this a flaw in the rs485.c file, am I supposed to modify it or am I missing something? I am sure I am receiving data as I can see it on an oscilloscope. Please help. Thanks. |
|
|
shashank27187
Joined: 28 Jul 2009 Posts: 13
|
|
Posted: Tue Sep 01, 2009 3:55 am |
|
|
As said above to check whether data is received or not using the code:
Code: |
while(true)
{
if(rs485_get_message(msg, FALSE))
printf(lcd_putc, "%d ", msg[1]);
}
|
I wish to say that I have tried this thing out and made a change in the program. Actually it is like this:
Code: |
void main(){
rs485_init();
rs485_no=1; /// change made as per the definition in driver file to update the value
lcd_init();
output_low(LCD_RW);
output_high(PIN_B1);
delay_ms(1000);
output_low(PIN_B1);
while(1){
lcd_putc('\f');
printf(lcd_putc, "abv gt msg");
delay_ms(500);
//
if(rs485_get_message(data, FALSE))
{
lcd_putc('\f');
printf(lcd_putc, "a=%d ", data[0]);
delay_ms(1000);
|
I found that the slave node receives something. It prints the value of "a"
which should be data[0] but the value printed does not equals the value sent.
My sample code is here:
http://www.ccsinfo.com/forum/viewtopic.php?t=40022&highlight=rs485
When I am sending a data of length say 3 then I receive the data but what is displayed in LCD is not what is being sent.... some numerical garbage.
Any help will be appreciated....Thanx... |
|
|
duongnc
Joined: 30 Nov 2010 Posts: 1
|
cs stand for checksum |
Posted: Tue Nov 30, 2010 9:15 pm |
|
|
The problem you face is the check sum byte of the Protocol. You can look down into rs485_send_message function
Code: | for(i=0, cs=rs485_id^to^len; i<len; ++i) {
cs ^= *data;
fputc(*data, RS485_CD);
++data;
} |
cs stand for checksum and it is 1 byte. |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Mon Aug 18, 2014 4:01 pm |
|
|
Dear All,
tried the code listed above, and during debugging, it is clear that the micro is looping in the:
Code: | rs485_wait_for_bus(TRUE); |
the receiver is showing "0 0 0 0 0"
I tried the same code to have an easy starting. On the transmitter side, the LCD is displaying nothing. The code I am using is:
Code: | #include <18f252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#include <lcd.c>
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x01
#define RS485_DEST_ID 0x09
#define RS485_ENABLE_PIN PIN_C2
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7
#include <rs485.c>
#include <stdlib.h>
void LCD_CHECK();
void LCD_CHECK()
{
lcd_gotoxy(1,1);
printf(lcd_putc, "System Ready");
delay_ms(500);
printf(lcd_putc,"\f");
}
int8 size=1;
int i, max = 5 ;
int8 bufsend[5] = {'A','B','C','D','E'};
int *pointer;
void main()
{
rs485_init();
lcd_init();
LCD_CHECK();
while(true)
{
for(i=0; i<max; i++)
{
pointer = &bufsend[i];
rs485_wait_for_bus(TRUE);
rs485_send_message(RS485_DEST_ID, size, pointer);
printf(lcd_putc,"\fSent: %c", bufsend[i]);
delay_ms(1000);
}
delay_ms(1000);
}
} |
and receiver side:
Code: | #include <18f252.h>
#fuses HS,NOWDT,NOPROTECT,NOLVP
#use delay(clock=20000000)
#use rs232(baud=9600,xmit=PIN_C6, rcv=PIN_C7, enable = PIN_C5, stream=PC)
#define LCD_RS_PIN PIN_B0
#define LCD_RW_PIN PIN_B1
#define LCD_ENABLE_PIN PIN_B2
#define LCD_DATA0 PIN_B4
#define LCD_DATA1 PIN_B5
#define LCD_DATA2 PIN_B6
#define LCD_DATA3 PIN_B7
#include <lcd.c>
#define RS485_RX_BUFFER_SIZE 64
#define RS485_USE_EXT_INT FALSE
#define RS485_ID 0x09
#define RS485_ENABLE_PIN PIN_C2
#define RS485_TX_PIN PIN_C6
#define RS485_RX_PIN PIN_C7
#include <rs485.c>
#include <stdlib.h>
void LCD_CHECK();
int8 msg[32];
void main()
{
output_low(RS485_ENABLE_PIN);
rs485_init();
rs485_no=1;
lcd_init();
LCD_CHECK();
while(true)
{
//! if(rs485_get_message(msg, FALSE));
//! printf(lcd_putc, "%d ", msg[1]);
//! delay_ms(400);
}
}
void LCD_CHECK()
{
lcd_gotoxy(1,1);
printf(lcd_putc, "System Ready");
delay_ms(500);
printf(lcd_putc,"\f");
} |
the setup I am using is here:
http://postimg.org/image/8z1fcokwj/ |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9225 Location: Greensville,Ontario
|
|
Posted: Mon Aug 18, 2014 4:14 pm |
|
|
Are you using real PICs wired as in the schematic then it can't work!
Several errors in configureation...
Also always add 'errors' to USE RS232(...options...) when using the hardware UART peripheral...This is mandatory...
jay |
|
|
aaronik19
Joined: 25 Apr 2011 Posts: 297
|
|
Posted: Tue Aug 19, 2014 2:24 am |
|
|
I just ordered the parts and will be delivered next week. I am making a simulation to finish the program and when the parts arrive , i built the circuit immediately. But during debugging i noticed that the master is looping in the wait_bus function. When i disable it, thr master starts to send the mesages and display on the lcd. Is there so,ething wrong in the circuit? |
|
|
|
|
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
|