1. Functional description of RS485 basic communication routine
The development board realizes communication with the computer serial port debugging assistant through UART1 interface + SP485EEN chip. And realize the following two sending and receiving example functions:
If the PC sends 5 bytes of data to the development board through 485, and the 5 bytes of data are 06 07 08 09 0A, the yellow LED1 flashes once
The development board sends 5 bytes of data to the PC through 485 every 1 second, 01 02 03 04 05
2. The purpose of this experimental teaching is to
master the following based on ShineBlink:
UART communication (occupying RX1, TX1)
GPIO controls the direction of the 485 conversion chip (D2 pin controls the direction of the 485 chip, high level)
-GPIO controls the on and off of LED1 (D8 connects to yellow LED1)
3.
The location of the module 485 interface involved in this experiment on the development board is as follows:
Note that in order to use the 485 interface, the P7 and P8 jumper caps must be shorted to connect the TX1 pin, RX1 pin and the 485 conversion chip.
4. Complete source code
The following code implements the following functions:
If the PC sends 5 bytes of data to the development board through 485, and the 5 bytes of data are 06 07 08 09 0A, the yellow LED1 flashes once.
The development board sends 5 bytes of data to the PC through 485 every 1 second, 01 02 03 04 05
- LIB_GpioOutputConfig("D8","STANDARD") --Initialize GPIO to control yellow LED1
- LIB_GpioOutputConfig("D2","STANDARD") -- Initialize GPIO control Max485 RE DE transceiver control
- --Configure the baud rate of Uart1 serial port to 19200 for 485 communication
- LIB_Uart1Config("BAUDRATE_19200")
- -- Enable MAX485 to send
- function SendEn()
- LIB_GpioWrite("D2",1)
- end
- --Enable MAX485 receiving
- function RecvEn()
- LIB_GpioWrite("D2",0)
- end
- -- Enable the 10 millisecond timer to start working
- LIB_10msTimerConfig("ENABLE")
- cnt_10ms = 0
- --Define the interrupt function of the 10 millisecond timer
- function LIB_10msTimerCallback()
- cnt_10ms = cnt_10ms + 1
- end
- --Start the big cycle
- while(GC(1) == true)
- do
- --Send 5 bytes of data to the PC every 1 second
- if cnt_10ms >= 100 then --1000ms
- cnt_10ms = 0
- send_data = {1,2,3,4,5}
- SendEn()
- LIB_Uart1BlockSend(send_data)
- RecvEn()
- end
- --Check whether the 5-byte data sent from the PC is received and verify
- recv_flag,recv_data = LIB_Uart1Recv()
- if recv_flag == 1 and #recv_data == 5 then
- if recv_data[1] == 6 and recv_data[2] == 7 and recv_data[3] == 8 and recv_data[4] == 9 and recv_data[5] == 10 then
- LIB_GpioToggle("D8") -- Toggle LED status
- end
- end
- end
Copy code
5. Experimental phenomenon
After connecting the 485 interface of the development board to the PC through the 485 to USB tool, copy the above code to the virtual TF card of the development board and start running. After that, the 5-byte data (01 02 03 04 05) sent by the development board can be received by the PC serial port debugging assistant every second, and when the debugging assistant sends it to the development board (06 07 08 09 0a), the yellow LED light of the development board will flash as shown below:
EEWORLDIMGTK1
EEWORLDIMGTK2
Note: The software needs to check "HEX display" and "HEX send".
Implementation of communication between device and host computer (Modbus host)
Introduction:
The following describes how to use ShineBlink as a device (Modbus slave) to communicate with a host computer (Modbus master), and implements the program code for function code 0x03 (read multiple holding registers) and function code 0x05 (write a single coil) on the ShineBlink device side.
1. Implementation Environment
The device acts as a Modbus slave and communicates with the host computer through the RS485 bus. We run the well-known Modbus Poll debugging software on the computer as the host computer to simulate the Modbus host. The Modbus Poll software can be downloaded from its official website.
2. Equipment Introduction
As one of the nodes in the Modbus network, the device has the following characteristics:Serial port attributes: 19200, N, 8, 1Device address: 21 (0x15)Modbus function codes supported by the device: 0x05 write a single coil 0x03 read multiple holding registersFunction introduction: 0x05, the host computer sends the 0x05 function code to the device, and when the value 0xFF00 is written to the coil with the coil address of 0x0000, the device starts running, and when the value 0x0000 is written to the coil with the coil address of 0x0000, the device stops running. 0x03, the host computer sends the 0x03 function code to the device, and reads 9 holding registers with the starting address of 0x0000 (each holding register value is 16-bit unsigned data). The data corresponding to each register is as follows:
EEWORLDIMGTK3
3. Modbus communication implementation code example
The following code not only implements function codes 03 and 05, but also responds to various abnormal situations to the Modbus host.
- --Definition of global variables used in the program
- Pm25Percent = 0
- HchoPercent = 0
- TvocPercent = 0
- MeshPercent = 0.0
- Temprature1 = 0.00
- Temprature2 = 0.00
- Wind485DisSpeed = 0
- DevIsRunning = 0 --Control device running or stopping
- FaultCode = 0 -- Fault code
- --ModBus communication function definition
- function ModbusProcess()
- local sdata = {}
-
- --Check whether the message sent by the Modbus host is received
- flag, data = LIB_Uart1Recv()
- if flag == 1 then
- --Determine whether the message is sent to the local machine, and only take care of it if it is sent to the local machine
- if data[1] == PI[2] then --PI[2], Modbus local address (1-247)
- --Judge Modbus function code
- if data[2] == 0x05 then -- 0x05 write a single coil
- --Here, the coil address 0x0000 is defined as the power on/off control signal
- if data[3] == 0x00 and data[4] == 0x00 then
- if data[5] == 0xff and data[6] == 0x00 then --ON
- DevIsRunning = 1 -- Set the global variable at startup
- elseif data[5] == 0x00 and data[6] == 0x00 then --OFF
- DevIsRunning = 0 -- Set the global variable to 0 at startup
- else
- --Here you need to reply to the illegal data 03 exception message (illegal data value), readers can complete it by themselves
- end
- --Reply OK and send back the received data intact
- LIB_GpioWrite("D2",1) -- Enable 485 module to send
- LIB_Uart1BlockSend(data)
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- else
- --Reply to abnormal message (illegal data address)
- sdata[1] = data[1] -- local address
- sdata[2] = data[2]+0x80 --When an exception occurs, the function code is increased by 0x80
- sdata[3] = 0x02 --Exception code 0x02 means the device does not support this data address
- CRC = LIB_CrcCalculate("CRC16_MODBUS", sdata)
- sdata[4] = CRC & 0x00ff -- low byte first
- sdata[5] = CRC >> 8 -- high digit at the end
- LIB_GpioWrite("D2",1) -- Enable 485 module to send
- LIB_Uart1BlockSend(sdata)
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- end
- --Here we use 0x03 instead of 0x04 because many hosts only support 03 06 16 instructions, so we just follow the crowd
- elseif data[2] == 0x03 then --0x03 Read multiple holding registers
- --Here, define the registers with the starting address of 0x0000 to store sensor data, and the number of registers to be read must be 9
- if data[3] == 0x00 and data[4] == 0x00 and data[5] == 0x00 and data[6] == 0x09 then
- sdata[1] = data[1] -- local address
- sdata[2] = data[2] -- function code
- sdata[3] = 18 --Number of bytes in the data field: 9 registers, a total of 18 bytes
- sdata[4] = Pm25Percent >> 8
- sdata[5] = Pm25Percent & 0x00ff
- sdata[6] = HchoPercent >> 8
- sdata[7] = HchoPercent & 0x00ff
- sdata[8] = TvocPercent >> 8
- sdata[9] = TvocPercent & 0x00ff
- sdata[10] = math.floor(MeshPercent) >> 8
- sdata[11] = math.floor(MeshPercent) & 0x00ff
- sdata[12] = math.floor(Temprature1) >> 8
- sdata[13] = math.floor(Temprature1) & 0x00ff
- sdata[14] = math.floor(Temprature2) >> 8
- sdata[15] = math.floor(Temprature2) & 0x00ff
- sdata[16] = Wind485DisSpeed >> 8
- sdata[17] = Wind485DisSpeed & 0x00ff
- sdata[18] = DevIsRunning >> 8
- sdata[19] = DevIsRunning & 0x00ff
- sdata[20] = FaultCode >> 8
- sdata[21] = FaultCode & 0x00ff
- CRC = LIB_CrcCalculate("CRC16_MODBUS", sdata)
- sdata[22] = CRC & 0x00ff -- low byte first
- sdata[23] = CRC >> 8 -- high digit at the end
- --Reply sensor data
- LIB_GpioWrite("D2",1) -- Enable 485 module to send
- LIB_Uart1BlockSend(sdata)
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- else
- --Reply to abnormal message (illegal data address)
- sdata[1] = data[1] -- local address
- sdata[2] = data[2]+0x80 --When an exception occurs, the function code is increased by 0x80
- sdata[3] = 0x02 --Exception code 0x02 means the device does not support this data address
- CRC = LIB_CrcCalculate("CRC16_MODBUS", sdata)
- sdata[4] = CRC & 0x00ff -- low byte first
- sdata[5] = CRC >> 8 -- high digit at the end
- LIB_GpioWrite("D2",1) -- Enable 485 module to send
- LIB_Uart1BlockSend(sdata)
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- end
- else
- --Reply to abnormal message (illegal function code)
- sdata[1] = data[1] -- local address
- sdata[2] = data[2]+0x80 --When an exception occurs, the function code is increased by 0x80
- sdata[3] = 0x01 --Exception code 0x01 means the device does not support this function code
- CRC = LIB_CrcCalculate("CRC16_MODBUS", sdata)
- sdata[4] = CRC & 0x00ff -- low byte first
- sdata[5] = CRC >> 8 -- high digit at the end
- LIB_GpioWrite("D2",1) -- Enable 485 module to send
- LIB_Uart1BlockSend(sdata)
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- end
- end
- end
- end
- --Start initializing ShineBlink
- --Configure the baud rate of Uart1 serial port to 19200 and connect to 485 module
- LIB_Uart1Config("BAUDRATE_19200")
- --485 send and receive control pins
- LIB_GpioOutputConfig("D2","STANDARD")
- LIB_GpioWrite("D2",0) -- Enable 485 module to receive
- --Start the big cycle
- while(GC(1) == true)
- do
- --Modbus communication processing
- ModbusProcess()
- end
Copy code
4. Modbus Poll Host Computer Experiment Process
(1) Configure 0x03 Read Holding Register Function (Setup)
(2) Establishing a Modbus serial communication connection (Connectiong)
(3) Data communication after establishing a connection
1. The host computer automatically sends a 0x03 command every second to read the values of the 9 holding registers of the device with the starting address of 0x0000
Communication data log:
The 23 bytes of data replied by the device above are given as an example:
For example: 15 03 12 00 06 00 00 00 01 00 00 00 16 00 16 00 00 00 00 00 00 D5 16
The CRC algorithm at the end of the data uses Modbus CRC16
- Local address: 0x15
- Function code: 0x03
- Number of bytes: 18 bytes (9 16-bit unsigned registers)
- Register 1: 0x0006 means pm25=6
- Register 2: 0x0000 means hch0=0
- Register 3: 0x0001 means tvoc=1
- Register 4: 0x0000 means mesh=6
- Register 5: 0x0016 indicates temprature1 = 21 degrees
- Register 6: 0x0016 indicates temprature2 = 21 degrees
- Register 7: 0x0000 means windspeed = 0
- Register 8: 0x0000 means running = 0
- Register 9: 0x0000 means faultcode=0
- CRC_L:0xD5
- CRC_H:0x16
Copy code
2. The host computer sends a power-on command (function code 0x05, write a single coil value 0xFF00 to the coil address 0x0000)
Communication data log:
3. The host computer sends a stop command (function code 0x05, write a single coil value 0x0000 to the coil address 0x0000)
The host computer sends: 15 05 00 00 00 00 CE DE The device should reply: 15 05 00 00 00 00 CE DE
|