|
|
View previous topic :: View next topic |
Author |
Message |
Emre
Joined: 25 Sep 2017 Posts: 5 Location: Türkiye
|
Serial communication |
Posted: Mon Sep 25, 2017 8:52 am |
|
|
Hi,
I have a problem.
I want to communicate with RS485 with CCS C.
1 master and 2 slaves.
Can you share sample code? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Mon Sep 25, 2017 9:11 am |
|
|
You already have code for this in the examples with the compiler.....
Understand that for anything involving more than one slave there has to be an 'address' involved, and a protocol to handle whatever data you intend to send.
In the examples folder there are examples for ModBus (a common protocol). Change the slave address on the second device.
If you don't want this much complexity, and assuming you only need to send limited mounts of data, then a simpler protocol can be used. However this is totally down to what you need to do. We can't guess this...
A search here will find dozens (hundreds) or threads showing some basic RS485 comms.
Critical things though are:
1) Bus termination and biasing.
2) Biasing on the undriven RX line of the PIC.
3) Designing the protocol to fail safe and handle errors.
Start simple. Get your devices able to switch the buffers, listen to the bus, and transmit. |
|
|
Emre
Joined: 25 Sep 2017 Posts: 5 Location: Türkiye
|
|
Posted: Mon Sep 25, 2017 11:26 pm |
|
|
@Ttelmah thank you
But Can you answer these questions?
1.How is addressing done?
2.Where are my mistakes and places where I need to attach?
Master Code
Code: | #include <master.h>
#include <lcd.c>
#include <rs485.c>
//////////////////////////////////////////////////LCD pin connect//////////////////////////////////////////////////////////////
#define LCD_ENABLE PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
/////////////////////////////////////////// RS-485 SETTINGS ////////////////////////////////////////////////////////////////////
#define RS485_USE_EXT_INT_FALSE
#use rs232(baud=9600,xmit=RS485_TX_PIN,rcv=RS485_RX_PIN,enable=RS485_ENABLE_PIN,bits=9,long_data,errors,stream=slave_1)
#use rs232(baud=9600,xmit=RS485_TX_PIN,rcv=RS485_RX_PIN,enable=RS485_ENABLE_PIN,bits=9,long_data,errors,stream=slave_2)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void main()
{
set_tris_b(0x00); output_b(0x00);
set_tris_c(0x80); output_c(0x00);
set_tris_d(0x00); output_d(0x00);
lcd_init(); delay_us(20);
rs485_init(); delay_us(20);
while(TRUE)
{
printf(lcd_putc,"\f Veri Gonderme");
delay_ms(500);
output_high(RS485_ENABLE_PIN);
fprintf(slave_1,"\f Veri1=%s","Elma"); delay_us(20);
fprintf(slave_2,"\f Veri2=%s","Armut"); delay_us(20);
}
}
|
This is master code.
Now, Slave1 code.
Slave1 Code
Code: |
#include <slave_1.h>
#include <lcd.c>
#include <rs485.c>
//////////////////////////////////////////////////LCD pin connect//////////////////////////////////////////////////////////////
#define LCD_ENABLE PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
/////////////////////////////////////////// RS-485 SETTINGS ////////////////////////////////////////////////////////////////////
#define RS485_USE_EXT_INT_FALSE
#use rs232(baud=9600,xmit=RS485_TX_PIN,rcv=RS485_RX_PIN,enable=RS485_ENABLE_PIN,bits=9,long_data,errors,stream=slave_1)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char x,y;
void main()
{
set_tris_b(0x00); output_b(0x00);
set_tris_c(0x80); output_c(0x00);
set_tris_d(0x00); output_d(0x00);
lcd_init(); delay_us(20);
rs485_init(); delay_us(20);
while(TRUE)
{
printf(lcd_putc,"\f Haberlesme");
delay_ms(500);
output_low(RS485_ENABLE_PIN);
x=fgets(y,slave_1);
printf(lcd_putc,"\f Veri Alindi %s",x);
delay_ms(500);
}
}
|
and finally
Slave2 Code
Code: | #include <slave2.h>
#include <lcd.c>
#include <rs485.c>
//////////////////////////////////////////////////LCD pin connect//////////////////////////////////////////////////////////////
#define LCD_ENABLE PIN PIN_D0
#define LCD_RS_PIN PIN_D1
#define LCD_RW_PIN PIN_D2
#define LCD_DATA4 PIN_D4
#define LCD_DATA5 PIN_D5
#define LCD_DATA6 PIN_D6
#define LCD_DATA7 PIN_D7
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#use fast_io(b)
#use fast_io(c)
#use fast_io(d)
/////////////////////////////////////////// RS-485 SETTINGS ////////////////////////////////////////////////////////////////////
#define RS485_USE_EXT_INT_FALSE
#use rs232(baud=9600,xmit=RS485_TX_PIN,rcv=RS485_RX_PIN,enable=RS485_ENABLE_PIN,bits=9,long_data,errors,stream=slave_2)
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
char y;
void main()
{
set_tris_b(0x00); output_b(0x00);
set_tris_c(0x80); output_c(0x00);
set_tris_d(0x00); output_d(0x00);
lcd_init(); delay_us(20);
rs485_init(); delay_us(20);
while(TRUE)
{
printf(lcd_putc,"\f Communication");
delay_ms(500);
output_low(RS485_ENABLE_PIN);
fgets(y,slave_2);
delay_us(50);
output_high(RS485_ENABLE_PIN);
printf(lcd_putc,"\f Veri Alindi \n%c",y);
delay_ms(500);
}
} |
|
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Sep 26, 2017 1:35 am |
|
|
The rs485.c driver, just gives a basic 'send messages' communication.
You have to setup things for the driver, and telling it what you are going to use as hardware _before_ loading it, and the device addresses you want (RS485_ID).
What chips are you using?.
What do you actually want to send?.
What pins have you connected the RS485 driver chip to?.
(You only actually need one control connection).
What baud rate?.
Assuming hardware UART, the basic wiring on the transceiver chip should be:
Single connection to the DE and /RE pin. Wire these together to one pin on the PIC. (1)
RO pin on the driver with a pull up resistor to the +ve supply (4K7R), to the RX pin of the PIC. (2)
DI pin on the driver to the TX pin of the PIC. (3)
Then +5v and 0v to the driver chip.
A pins on all the drivers connected together via the bus.
B pins of all the drivers connected together via the bus.
Terminator at each end of the bus. At the master end, have a 556R resistor from the 'A' line to +5v, A 133R resistor between A and B, and a 556R resistor from B to 0v. At the other end, a simple 120R resistor.
This ensures 'A' is held above 'B', when the line is undriven.
Then:
Code: |
#include <slave_1.h>
#include <lcd.c>
#define RS485_ID 10 //perhaps 10, 11 & 12 for the 3 boards
#define RS485_USE_EXT_INT FALSE
#define RS485_RX_ENABLE //leave blank
#define RS485_ENABLE_PIN PIN_XX //PIN (1)
#define RS485_RX_PIN PIN_YY //PIN (2)
#define RS485_TX_PIN PIN_ZZ //PIN (3)
#include <rs485.c>
//Then get rid of your RS232 setup, and of the fast_io settings
//If you feel you must leave the fast_io, then read your chips data
//sheet, and ensure that the TRIS is set correctly for the UART, and
//to output for the pin used as the enable pin....
void RS485send(char* s, int8 id) //routine to send a string message
{
int8 size;
for(size=0; s[size]!='\0'; ++size);
rs485_wait_for_bus(FALSE);
while(!rs485_send_message(id, size, s))
delay_ms(RS485_ID);
//This ensures the delays are different in different devices
}
//Then assuming this is board 10,
//To send messages to boards 11 & 12
void main(void)
{
char message[] = "Test Message 1\n";
char message2[] = "Test Message 2\n";
delay_ms(100); //almost everything requires a short delay
lcd_init();
rs485_init();
while (TRUE)
{
rs485Send(message,11); //send the first string to board 11
rs485Send(message2,12); //and the second to board 12
delay_ms(1000);
}
}
|
The other devices need similar setups, but then then will call rs485_get_message to see if a message is available.
This is used like:
Code: |
char buffer[64];
while (TRUE)
{
if (rs485_get_message(buffer, FALSE) == TRUE)
{
//here a message has arrived and is now in the buffer
//Do what you want with it
}
else
{
//You can do whatever else you want when a message is not
//available
}
}
|
Since you can call 'get_message' with a 'FALSE' as I show, all the devices can do this when they are not sending, in case anything arrives from another unit. |
|
|
Emre
Joined: 25 Sep 2017 Posts: 5 Location: Türkiye
|
|
|
Emre
Joined: 25 Sep 2017 Posts: 5 Location: Türkiye
|
|
Posted: Tue Sep 26, 2017 2:14 am |
|
|
@Ttelmah
If I ask you to write me a program for 1 master 2 slave?
I want to review it.
If it's not a running program, it's not understood. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Sep 26, 2017 2:26 am |
|
|
1) Proteus....
Read the 'sticky' at the top of the forum. Proteus is full of bugs on the PIC....
2) You 'bus' between the Max487 chips does not want resistors at each chip, and the value needed is much lower than the 10K you show. A typical bus will have 120ohm impedance wiring, and this needs to be matched at the ends if you are not to get signal problems - this won't cause a problem with Proteus but will in the real world.
3) _Bias_. A RS485 bus needs to be biased off when idle. You are not doing this. There are transceivers that will do this for you and even terminators that do. Or the resistors as I describe. Required.
3) _Bias_. The line from the RO output of the RS485 driver needs to have a pull up resistor to bias it high. This line goes 'undriven' when the chip is transmitting, and leaving it floating, will give indeterminate behaviour.
I've posted a lot of the code for you, showing 90% of a device sending to two other units. |
|
|
Emre
Joined: 25 Sep 2017 Posts: 5 Location: Türkiye
|
|
Posted: Tue Sep 26, 2017 2:44 am |
|
|
I'm testing your code
1.
is the first code you sent for master?
2. Is the second send code you want to retrieve data from?For slaves? |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19513
|
|
Posted: Tue Sep 26, 2017 3:23 am |
|
|
The simple driver here, is not master/slave. It's device to device.
The bus sits idle.
Any device can send a 'message' to another numbered device.
It's like a 'field telephone'. You check that nobody else is sending, and then press the button to talk. 'Calling number 10, this is a message for you'. The devices just listen to the bus, and when they hear a message for their number, 'pick up' the message. |
|
|
|
|
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
|