RS-485 Library
RS-485 is a multipoint communication which allows multiple devices to be connected to a single bus. mikroPascal PRO for ARM provides a set of library routines for comfortable work with RS485 system using Master/Slave architecture. Master and Slave devices interchange packets of information. Each of these packets contains synchronization bytes, CRC byte, address byte and the data. Each Slave has unique address and receives only packets addressed to it. The Slave can never initiate communication.
It is the user’s responsibility to ensure that only one device transmits via 485 bus at a time.
The RS-485 routines require the UART module. Pins of UART need to be attached to RS-485 interface transceiver, such as LTC485 or similar (see schematic at the bottom of this page).
- START byte value =
150
- STOP byte value =
169
- Address
50
is the broadcast address for all Slaves (packets containing address50
will be received by all Slaves except the Slaves with addresses150
and169
).
- The library uses the UART module for communication. The user must initialize the appropriate UART module before using the RS-485 Library.
- For MCUs with multiple UART modules it is possible to initialize them and then switch by using the UART_Set_Active routine.
Library Dependency Tree
External dependencies of RS-485 Library
Stellaris
The following variable must be defined in all projects using RS-485 Library: | Description : | Example : |
---|---|---|
var RS485_rxtx_pin : sbit; sfr; external; |
Control RS-485 Transmit/Receive operation mode | var RS485_rxtx_pin : sbit at GPIO_PORTA_DATA2_bit; |
var RS485_rxtx_pin_direction : sbit; sfr; external; |
Direction of the RS-485 Transmit/Receive pin | var RS485_rxtx_pin_direction : sbit at GPIO_PORTA_DIR2_bit; |
MSP432
The following variable must be defined in all projects using RS-485 Library: | Description : | Example : |
---|---|---|
var RS485_rxtx_pin : sbit; sfr; external; |
Control RS-485 Transmit/Receive operation mode | var RS485_rxtx_pin : sbit at DIO_P6OUT.B0; |
var RS485_rxtx_pin_direction : sbit; sfr; external; |
Direction of the RS-485 Transmit/Receive pin | var RS485_rxtx_pin_direction : sbit at DIO_P6DIR.B0; |
STM32
The following variable must be defined in all projects using RS-485 Library: | Description : | Example : |
---|---|---|
var RS485_rxtx_pin : sbit; sfr; external; |
Control RS-485 Transmit/Receive operation mode | var RS485_rxtx_pin : sbit at GPIOA_ODR.B6; |
CEC1x02
The following variable must be defined in all projects using RS-485 Library: | Description : | Example : |
---|---|---|
var RS485_rxtx_pin : sbit; sfr; external; |
Control RS-485 Transmit/Receive operation mode | var RS485_rxtx_pin : sbit at GPIO_OUTPUT_PIN_133_bit; |
Library Routines
- RS485Master_Init
- RS485Master_Receive
- RS485Master_Send
- RS485Slave_Init
- RS485Slave_Receive
- RS485Slave_Send
RS485Master_Init
Prototype |
procedure RS485Master_Init(); |
---|---|
Description |
Initializes MCU as a Master for RS-485 communication. |
Parameters |
None. |
Returns |
Nothing. |
Requires |
External dependencies of the library from the top of the page must be defined before using this function.
|
Example |
Stellaris// RS485 module pinout var rs485_rxtx_pin : sbit at GPIO_PORTA_DATA2_bit; // set transcieve pin rs485_rxtx_pin_direction : sbit at GPIO_PORTA_DIR2_bit; // set transcieve pin direction // End of RS485 module pinout ... UART1_Init(9600); // initialize UART1 module RS485Master_Init(); // intialize MCU as a Master for RS-485 communication Stellaris// RS485 module pinout var rs485_rxtx_pin : sbit at DIO_P6OUT.B0; // set transcieve pin rs485_rxtx_pin_direction : sbit at DIO_P6DIR.B0; // set transcieve pin direction // End of RS485 module pinout ... UART1_Init(9600); // initialize UART1 module RS485Master_Init(); // intialize MCU as a Master for RS-485 communication STM32// RS485 module pinout var rs485_rxtx_pin : sbit at GPIOA_ODR.B6; // set transcieve pin // End of RS485 module pinout ... UART1_Init(19200); // initialize UART1 module RS485Master_Init(); // intialize MCU as a Master for RS-485 communication CEC1x02// RS485 module pinout var rs485_rxtx_pin : sbit at GPIO_OUTPUT_PIN_133_bit; // set transcieve pin // End of RS485 module pinout ... UART1_Init(19200); // initialize UART1 module RS485Master_Init(); |
Notes |
None. |
RS485Master_Receive
Prototype |
procedure RS485Master_Receive(var data : array[10] of byte); |
---|---|
Description |
Receives messages from Slaves. Messages are multi-byte, so this routine must be called for each byte received. |
Parameters |
The routine automatically adjusts |
Returns |
Nothing. |
Requires |
MCU must be initialized as a Master for RS-485 communication. See RS485Master_Init. |
Example |
var msg : array[8] of byte; ... RS485Master_Receive(msg); |
Notes |
None. |
RS485Master_Send
Prototype |
procedure RS485Master_Send(var buffer : array[20] of byte; datalen : byte; slave_address : byte); |
---|---|
Description |
Sends message to Slave(s). Message format can be found at the bottom of this page. |
Parameters |
|
Returns |
Nothing. |
Requires |
MCU must be initialized as a Master for RS-485 communication. See RS485Master_Init. It is the user’s responsibility to ensure (by protocol) that only one device sends data via 485 bus at a time. |
Example |
var msg : array[8] of byte; ... // send 3 bytes of data to Slave with address 0x12 RS485Master_Send(msg, 3, 0x12); |
Notes |
None. |
RS485Slave_Init
Prototype |
procedure RS485Slave_Init(slave_address : byte); |
---|---|
Description |
Initializes MCU as a Slave for RS-485 communication. |
Parameters |
|
Returns |
Nothing. |
Requires |
External dependencies of the library from the top of the page must be defined before using this function.
|
Example |
Stellaris// RS485 module pinout var rs485_rxtx_pin : sbit at DIO_P6OUT.B0; // set transcieve pin rs485_rxtx_pin_direction : sbit at DIO_P6DIR.B0; // set transcieve pin direction // End of RS485 module pinout ... UART1_Init(9600); // initialize UART1 module RS485Slave_Init(160); // intialize MCU as a Slave for RS-485 communication with address 160 MSP432// RS485 module pinout var rs485_rxtx_pin : sbit at GPIO_PORTA_DATA2_bit; // set transcieve pin rs485_rxtx_pin_direction : sbit at GPIO_PORTA_DIR2_bit; // set transcieve pin direction // End of RS485 module pinout ... UART1_Init(9600); // initialize UART1 module RS485Slave_Init(160); // intialize MCU as a Slave for RS-485 communication with address 160 STM32// RS485 module pinout var rs485_rxtx_pin : sbit at GPIOA_ODR.B6; // set transcieve pin // End of RS485 module pinout ... UART1_Init(19200); // initialize UART1 module RS485Slave_Init(160); // intialize MCU as a Slave for RS-485 communication with address 160 CEC1x02// RS485 module pinout sbit RS485_rxtx_pin at GPIO_OUTPUT_PIN_133_bit; // set transcieve pin // end RS485 module pinout ... UART1_Init(9600); // initialize UART1 module RS485Slave_Init(160); // intialize MCU as a Slave for RS-485 communication with address 160 |
Notes |
None. |
RS485Slave_Receive
Prototype |
procedure RS485Slave_Receive(var data_buffer : array[20] of byte); |
---|---|
Description |
Receives messages from Master. If Slave address and Message address field don't match then the message will be discarded. Messages are multi-byte, so this routine must be called for each byte received. |
Parameters |
The routine automatically adjusts |
Returns |
Nothing. |
Requires |
MCU must be initialized as a Slave for RS-485 communication. See RS485Slave_Init. |
Example |
var msg : array[8] of byte; ... RS485Slave_Read(msg); |
Notes |
None. |
RS485Slave_Send
Prototype |
procedure RS485Slave_Send(var data : array[20] of byte; datalen : byte); |
---|---|
Description |
Sends message to Master. Message format can be found at the bottom of this page. |
Parameters |
|
Returns |
Nothing. |
Requires |
MCU must be initialized as a Slave for RS-485 communication. See RS485Slave_Init. It is the user’s responsibility to ensure (by protocol) that only one device sends data via 485 bus at a time. |
Example |
var msg : array[8] of byte; ... // send 2 bytes of data to the Master RS485Slave_Send(msg, 2); |
Notes |
None. |
Message format and CRC calculations
Q: How is CRC checksum calculated on RS485 master side?
const START_BYTE : byte = 0x96; // 10010110 const STOP_BYTE : byte = 0xA9; // 10101001 PACKAGE: -------- START_BYTE 0x96 ADDRESS DATALEN [DATA1] // if exists [DATA2] // if exists [DATA3] // if exists CRC STOP_BYTE 0xA9 DATALEN bits ------------ bit7 = 1 MASTER SENDS 0 SLAVE SENDS bit6 = 1 ADDRESS WAS XORed with 1, IT WAS EQUAL TO START_BYTE or STOP_BYTE 0 ADDRESS UNCHANGED bit5 = 0 FIXED bit4 = 1 DATA3 (if exists) WAS XORed with 1, IT WAS EQUAL TO START_BYTE or STOP_BYTE 0 DATA3 (if exists) UNCHANGED bit3 = 1 DATA2 (if exists) WAS XORed with 1, IT WAS EQUAL TO START_BYTE or STOP_BYTE 0 DATA2 (if exists) UNCHANGED bit2 = 1 DATA1 (if exists) WAS XORed with 1, IT WAS EQUAL TO START_BYTE or STOP_BYTE 0 DATA1 (if exists) UNCHANGED bit1bit0 = 0 to 3 NUMBER OF DATA BYTES SEND CRC generation : ---------------- crc_send := datalen xor address; crc_send := crc_send xor data[0]; // if exists crc_send := crc_send xor data[1]; // if exists crc_send := crc_send xor data[2]; // if exists crc_send := crc_send not crc_send; if ((crc_send = START_BYTE) or (crc_send = STOP_BYTE)) then crc_send := crc_send + 1; NOTE: DATALEN<4..0> can not take the START_BYTE<4..0> or STOP_BYTE<4..0> values.