RS485 CAN Shield
| ||
Introduction
RS485 CAN Shield Designed for NUCLEO/XNUCLEO.
More |
Feature
- Based on the standard Arduino interface design, it is compatible with development boards including UNO, Leonardo, NUCLEO, and XNUCLEO.
- Features RS485 function, and the transceiver is MAX3485 with a power supply of 3.3V.
- Features CAN function, and the transceiver is SN65HVD230 with a power supply of 3.3V.
Note: RS485 CAN Shield can only use a 3.3V power supply, UNO, Leonardo, and other Arduino cannot use the CAN function due to hardware limitations.
Hardware Description
MAX3485
The MAX3485 interface chip is an RS-485 driver chip from Maxim. Low power transceiver for RS-485 communication.
It works with a single power supply of +3.3 V and adopts half-duplex communication. The RO and DI terminals are the output of the receiver and the output of the driver respectively.
Input terminal; /RE and DE are the enable terminals for receiving and transmitting respectively. When /RE is logic 0, the device is in the receiving state; when DE is logic 0, the device is in the receiving state.
When the logic is 1, the device is in the sending state; the A and B terminals are the differential signal terminals for reception and transmission, respectively. When A-B>+0.2V, the RO output logic is 1; when A-B<-0.2V, the RO output logic is 0. A matching resistor is added between the A and B terminals, generally 100Ω resistance.
pin | Function |
RO | Receiver Output |
/RE | Receive output enable |
DE | Send Output Enable |
DI | Output Driver Input |
GND | Power Ground |
A | Differential signal positive terminal |
B | Differential signal reverse terminal |
VCC | Power (3.3V) |
SN65HVD230
SN65HVD230 is a 3.3V CAN transceiver produced by Texas Instruments, which is suitable for higher communication rates and good anti-interference capability, and high-reliability serial communication over the CAN bus. SN65HVD230 has 3 different working modes of high speed, slope, and wait.
Its working mode control can be achieved through the Rs control pin. The output pin Tx of the CAN controller is connected to the data of the SN65HVD230 Input D, the data sent by this CAN node can be transmitted to the CAN network; while the receive pins Rx and Rx of the CAN controller.
The data output terminal R of SN65HVD230 is connected to receive data.
Pin | Function |
D | Driver Input |
GND | Power Ground |
VCC | Power (3.3V) |
R | Receive Output |
Vref | Reference Output |
CANL | Low Bus Output |
CANH | High Bus Output |
RS | Working Mode Control Terminal |
How to use
Preparations
- Two RS485 CAN Shield.
- Two STM32 development board, we use Waveshare Xnucleo-F103RB board (with STM32F103R chip) in this manual.
- Some jumper wire.
Description of Jumper settings on Xnucleo
- D14 (PB_9) and D15 (PB_8) are CAN's sending and receiving ports respectively as default.
- Note: please remap PB_9 and PB_8 to the function of STM32 CAN1 by modifying the program: GPIO_PinRemapConfig(GPIO_Remap1_CAN1, ENABLE);
- D7(PA_8) is for RS485 sending or receiving enable. The high level is for sending, low level is for receiving.
- D8(PA_9), D2(PA_10) are the sending and receiving port of UART1. D0(PA_2), and D1(PA_3) are the sending and receiving ports of UART2. You can choose UART1 or UART2 for the RS485 transceiver port by setting jumper 485 RXD/TXD JMP.
- Note: PA_2 and PA_3 of Xnucleo are Serial to USB ports as default. If you want to use D0 and D1 as RS485 serial ports, the jumper JP4 should be set: connect pin 1 and pin 3, and connect pin 2 and pin 4.
- Communication between two boards: connect the CANH and CANL to another one’s CANH and CANL of the CAN port separately. Connect the A and B to another one’s A and B of the RS485 port separately.
Hardware Connection
Shield | STM32 | Function |
VCC | 3.3V | Power Input |
GND | GND | Ground |
D2 | PA10 | RS485 Receiving Terminal |
D8 | PA9 | RS485 Sending Terminal |
D7 | PA8 | RS485 Sending & Receiving Enable Terminal |
D14 | PB9 | CAN Sending Terminal |
D15 | PB8 | CAN Receiving Terminal |
D0 and D1 output the information to the serial port on the PC side.
Working principle
The demo program, divided into sending and receiving programs, is based on mbed frame + STM32 library.
CAN
The CAN driver is written based on STM32 library, packaged into the two file CAN.cpp and CAN.h.
At the beginning of the program, function CAN_Config() is called to initiate related registers.
At the side of sending program, the message to be sent will be saved into the Mailbox TxMessage, then it will be sent by calling CAN_Transmit(CAN1, &TxMessage).
At the side of receiving program, the message received will be saved into the Mailbox RxMessage by calling CAN_Receive(CAN1, CAN_FIFO0, &RxMessage).
RS485
The sending side program sets RS485_E to high level, which will make RS485 into sending status. Messages will be sent by function RS485.printf, through RS485 serial port.
The receiving side program enables reception interruption, and sets RS485_E to low level, which will set RS485 to receiving status. Then, RX interrupt handler will scan received message via RS485.scanf.
Connection:
- D14 and D15 are CAN's sending and receiving port respectively as default.
- D8(PA_9), D2(PA_10) are the sending and receiving port of RS485.
- D7(PA_8) is for RS485 sending or receiving enable. High level is for sending, low level is for receiving.
- Message is sent to serial port of PC through D0 and D1.
- The CANH and CNAL of one CAN port should be connected to another’s CANH and CANL port, and the A and B port of one RS485 should be connected to another’s A and B.
Sending side program description
CAN: After related registers are initiated. the message to be sent will be saved into the Mailbox, and then it will be sent by driver functions.
RS485: Set RS485_E to high level, which will make RS485 into sending status. Messages will be sent through RS485 serial port.
#include "mbed.h" #include "CAN.h" Serial pc(D1,D0); //serial print message Serial RS485(D8, D2); //RS485_TX RS485_RX DigitalOut RS485_E(D7); //RS485_E CanTxMsg TxMessage; uint8_t TransmitMailbox = 0; int i =0,j=0; int main() { CAN_Config(); //CAN initiation RS485_E = 1; //enable RS485 sending status /* TxMessage */ //Setting message of Txmessage TxMessage.StdId = 0x10; TxMessage.ExtId = 0x1234; TxMessage.RTR=CAN_RTR_DATA; TxMessage.IDE=CAN_ID_STD; TxMessage.DLC=8; TxMessage.Data[0] = 'C'; TxMessage.Data[1] = 'A'; TxMessage.Data[2] = 'N'; TxMessage.Data[3] = ' '; TxMessage.Data[4] = 'T'; TxMessage.Data[5] = 'e'; TxMessage.Data[6] = 's'; TxMessage.Data[7] = 't'; pc.printf( "**** This is a RS485_CAN_Shield Send test program ****\r\n"); while(1) { RS485.printf("ncounter=%d ",j); //RS485 sending wait(1); TransmitMailbox = CAN_Transmit(CAN1, &TxMessage); //CAN sending i = 0; while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFFF)){ i++; } if(i == 0xFFF){ pc.printf("\r\can send fail\r\n"); //Send Timeout, fail } else{ pc.printf("\r\nCAN send TxMessage successfully \r\n"); //Send successfully } pc.printf("\r\nRS485 send: counter=%d\r\n",j++); //Print message pc.printf("The CAN TxMsg: %s\r\n",TxMessage.Data); wait(1); } }
Receiving side program description
CAN: After related registers are initiated. The receiving side will check if FIFO data exist. If yes, the received message will be saved in the mailbox RxMessage and printed.
RS485: Enable RS485 reception interruption and set RS485_E to low for setting RS485 to receiving status. Then, the interrupt service demo will scan the received message via RS485.scanf.
#include "mbed.h" #include "CAN.h" Serial pc(D1,D0); //serial print message Serial RS485(D8, D2); //RS485_TX RS485_RX DigitalOut RS485_E(D7); //RS485_E CanRxMsg RxMessage; //RxMessage char s[1024]; void callback() //RS485 RX interrupt handler { //Note: you need to actually read from the serial to clear the RX interrupt RS485.scanf("%s",s); //Save received messages pc.printf("\r\nRS485 Receive:%s \r\n",s); //Print Received messages } int main() { CAN_Config(); //CAN initiation RS485.attach(&callback); //Open RS485 reception interruption RS485_E = 0; //Enable receiving status pc.printf( "**** This is a can receive test program ****\r\n"); while(1) { while(CAN_MessagePending(CAN1, CAN_FIFO0) < 1) // Message waiting { } CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //CAN data reception pc.printf("The CAN RxMsg: %s\r\n",RxMessage.Data); //Print received messages } }
Operating phenomenon
The serial port of sending side will print:
**** This is a RS485_CAN_Shield Send test program **** CAN send TxMessage successfully RS485 send: counter=0 The CAN TxMsg: CAN Test CAN send TxMessage successfully RS485 send: counter=1 The CAN TxMsg: CAN Test CAN send TxMessage successfully RS485 send: counter=2 The CAN TxMsg: CAN Test
The serial port of receiving side will print:
**** This is a can receive test program **** RS485 Receive:ncounter=0 The CAN RxMsg: CAN Test RS485 Receive:ncounter=1 The CAN RxMsg: CAN Test RS485 Receive:ncounter=2 The CAN RxMsg: CAN Test RS485 Receive:ncounter=3 The CAN RxMsg: CAN Test
Working principle
The demo program, divided into sending and receiving programs, is based on mbed frame + STM32 library.
CAN
The CAN driver is written based on STM32 library, packaged into the two file CAN.cpp and CAN.h.
At the beginning of the program, function CAN_Config() is called to initiate related registers.
At the side of sending program, the message to be sent will be saved into the Mailbox TxMessage, then it will be sent by calling CAN_Transmit(CAN1, &TxMessage).
At the side of receiving program, the message received will be saved into the Mailbox RxMessage by calling CAN_Receive(CAN1, CAN_FIFO0, &RxMessage).
RS485
The sending side program sets RS485_E to high level, which will make RS485 into sending status. Messages will be sent by function RS485.printf, through RS485 serial port.
The receiving side program enables reception interruption, and sets RS485_E to low level, which will set RS485 to receiving status. Then, RX interrupt handler will scan received message via RS485.scanf.
Connection:
- D14 and D15 are CAN's sending and receiving port respectively as default.
- D8(PA_9), D2(PA_10) are the sending and receiving port of RS485.
- D7(PA_8) is for RS485 sending or receiving enable. High level is for sending, low level is for receiving.
- Message is sent to serial port of PC through D0 and D1.
- The CANH and CNAL of one CAN port should be connected to another’s CANH and CANL port, and the A and B port of one RS485 should be connected to another’s A and B.
Sending side program description
CAN: After related registers are initiated. the message to be sent will be saved into the Mailbox, and then it will be sent by driver functions.
RS485: Set RS485_E to high level, which will make RS485 into sending status. Messages will be sent through RS485 serial port.
#include "mbed.h" #include "CAN.h" Serial pc(D1,D0); //serial print message Serial RS485(D8, D2); //RS485_TX RS485_RX DigitalOut RS485_E(D7); //RS485_E CanTxMsg TxMessage; uint8_t TransmitMailbox = 0; int i =0,j=0; int main() { CAN_Config(); //CAN initiation RS485_E = 1; //enable RS485 sending status /* TxMessage */ //Setting message of Txmessage TxMessage.StdId = 0x10; TxMessage.ExtId = 0x1234; TxMessage.RTR=CAN_RTR_DATA; TxMessage.IDE=CAN_ID_STD; TxMessage.DLC=8; TxMessage.Data[0] = 'C'; TxMessage.Data[1] = 'A'; TxMessage.Data[2] = 'N'; TxMessage.Data[3] = ' '; TxMessage.Data[4] = 'T'; TxMessage.Data[5] = 'e'; TxMessage.Data[6] = 's'; TxMessage.Data[7] = 't'; pc.printf( "**** This is a RS485_CAN_Shield Send test program ****\r\n"); while(1) { RS485.printf("ncounter=%d ",j); //RS485 sending wait(1); TransmitMailbox = CAN_Transmit(CAN1, &TxMessage); //CAN sending i = 0; while((CAN_TransmitStatus(CAN1, TransmitMailbox) != CANTXOK) && (i != 0xFFF)){ i++; } if(i == 0xFFF){ pc.printf("\r\can send fail\r\n"); //Send Timeout, fail } else{ pc.printf("\r\nCAN send TxMessage successfully \r\n"); //Send successfully } pc.printf("\r\nRS485 send: counter=%d\r\n",j++); //Print message pc.printf("The CAN TxMsg: %s\r\n",TxMessage.Data); wait(1); } }
Receiving side program description
CAN: After related registers are initiated. The receiving side will check if FIFO data exist. If yes, the received message will be saved in the mailbox RxMessage and printed.
RS485: Enable RS485 reception interruption and set RS485_E to low for setting RS485 to receving status. Then, interrupt service routine will scan received message via RS485.scanf.
#include "mbed.h" #include "CAN.h" Serial pc(D1,D0); //serial print message Serial RS485(D8, D2); //RS485_TX RS485_RX DigitalOut RS485_E(D7); //RS485_E CanRxMsg RxMessage; //RxMessage char s[1024]; void callback() //RS485 RX interrupt handler { //Note: you need to actually read from the serial to clear the RX interrupt RS485.scanf("%s",s); //Save received messages pc.printf("\r\nRS485 Receive:%s \r\n",s); //Print Received messages } int main() { CAN_Config(); //CAN initiation RS485.attach(&callback); //Open RS485 reception interruption RS485_E = 0; //Enable receiving status pc.printf( "**** This is a can receive test program ****\r\n"); while(1) { while(CAN_MessagePending(CAN1, CAN_FIFO0) < 1) // Message waiting { } CAN_Receive(CAN1, CAN_FIFO0, &RxMessage); //CAN data reception pc.printf("The CAN RxMsg: %s\r\n",RxMessage.Data); //Print received messages } }
Operating phenomenon
The serial port of sending side will print:
**** This is a RS485_CAN_Shield Send test program **** CAN send TxMessage successfully RS485 send: counter=0 The CAN TxMsg: CAN Test CAN send TxMessage successfully RS485 send: counter=1 The CAN TxMsg: CAN Test CAN send TxMessage successfully RS485 send: counter=2 The CAN TxMsg: CAN Test
The serial port of receiving side will print:
**** This is a can receive test program **** RS485 Receive:ncounter=0 The CAN RxMsg: CAN Test RS485 Receive:ncounter=1 The CAN RxMsg: CAN Test RS485 Receive:ncounter=2 The CAN RxMsg: CAN Test RS485 Receive:ncounter=3 The CAN RxMsg: CAN Test
Resources
FAQ
Support
Technical Support
If you need technical support or have any feedback/review, please click the Submit Now button to submit a ticket, Our support team will check and reply to you within 1 to 2 working days. Please be patient as we make every effort to help you to resolve the issue.
Working Time: 9 AM - 6 PM GMT+8 (Monday to Friday)