Protocols and Data Flow
From the “Configuration Guide” chapter, we know that serial port 0 on LQ 10 series products supports SBUS input and output. The earlier chapter describes SBUS to SBUS operation.…
2 min read · English documentationProtocols and Data Flow
Converting Serial Data to the SBUS Protocol
From the “Configuration Guide” chapter, we know that serial port 0 on LQ-10 series products supports SBUS input and output. The earlier chapter describes SBUS-to-SBUS operation. This chapter describes how to convert a serial protocol to SBUS.
-
First make sure that the LQ-10 device has established a network connection.
-
Assuming that data is sent from the device at 192.168.1.2, use the following configuration:
- Click to enable serial port UART0
- Select Standard as the function mode
- Add a forwarding rule. Select UDP as the transmission protocol, Unicast as the operating mode, Remote as the endpoint, and Transmit as the data direction. Set the target peer to 192.168.1.3 and the network port to 8080, as shown below:

- Enable serial port UART0 on the STA
- Select SBUS as the function
- Add a forwarding rule. Select UDP as the transmission protocol, Unicast as the operating mode, Local as the endpoint, and Receive as the data direction. Set the local listening IP to 192.168.1.3 and the network port to 8080, as shown below:

Conversion Example
We provide a code example that converts data frames from a common remote-controller serial protocol into standard SBUS frames. Customers only need to pass a remote-control signal containing serial-frame data in the format shown below to the provided sbus_encoder function. This produces an SBUS data frame recognized by the LQ module. The LQ-10 SBUS conversion interface then provides SBUS data suitable for the flight controller.
| Byte No. | Data | Field | Data Type | Detailed Description |
|---|---|---|---|---|
| 1 | 0x0F | Frame header | uint16_t | Start bit |
| 2-33 | ~ | Main data section | uint16_t | As detailed in the figure below |
| 34 | 0x0C | Reserved | uint16_t | Reserved; fixed at 0x0C |
| 35 | 0x33 | Checksum | uint16_t | XOR checksum of the remaining 33 bits, excluding the frame header |
/*----------Required header files----------*/
#include <stdio.h>
#include <stdint.h>
/*----------Protocol conversion functions----------*/
/**
* @brief Calculates the BCC checksum (XOR checksum) of the data
* @param data Pointer to the data to be checked
* @param length Length of the data to be checked
* @return uint8_t Calculated BCC checksum
*/
static uint8_t getBcc(uint8_t *data, uint16_t length)
{
uint8_t i;
uint8_t bcc = 0; // Initial value
while (length--)
{
bcc ^= *data++;
}
return bcc;
}
/**
* @brief Decodes a 25-byte SBUS packet into 35 bytes of raw channel data
* @param indata Pointer to the input SBUS packet (25 bytes)
* @param inlen Input data length (must be 25)
* @param outdata Pointer to the decoded output data (35 bytes)
* @param outlen Pointer to the output data length
* @return void
*
* @note Input data format: 25-byte SBUS packet
* Output data format: 35 bytes of decoded data (including the start byte, 16 channel values, end byte, and BCC checksum)
*/
static void sbus_decoder(uint8_t* indata, uint16_t inlen, uint8_t* outdata, uint8_t* outlen)
{
if ((inlen != 25) || (indata[0] != 0x0f) || (indata[inlen - 1] != 0x00)) return ;
uint8_t n = 0;
uint16_t val = 0;
outdata[n++] = 0x0f;
val = ((indata[1] | indata[2] << 8) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[2] >> 3 | indata[3] << 5) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[3] >> 6 | indata[4] << 2 | indata[5] << 10) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[5] >> 1 | indata[6] << 7) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[6] >> 4 | indata[7] << 4) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[7] >> 7 | indata[8] << 1 | indata[9] << 9) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[9] >> 2 | indata[10] << 6) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
val = ((indata[10] >> 5 | indata[11] << 3) & 0x07FF);
outdata[n++] = val >> 8; outdata[n++] = val & 0x00ff;
outdata[n++] = 0x0c;
uint8_t xorr = getBcc(&outdata[1], n - 1);
outdata[n++] = xorr;
*outlen = n;
}
/**
* @brief Encodes 35 bytes of raw channel data into a 25-byte SBUS packet
* @param indata Pointer to the input raw data (35 bytes)
* @param inlen Input data length (must be 35)
* @param packet Pointer to the output SBUS packet (25 bytes)
* @param outlen Pointer to the output data length
* @return void
*
* @note Input data format: 35 bytes of raw data (including the start byte, 16 channel values, end byte, and BCC checksum)
* Output data format: 25-byte SBUS packet
* Channel data range: 880-2160 maps to 0-2047 (11 bits)
*/
static void sbus_encoder(uint8_t* indata, uint16_t inlen, uint8_t* packet, uint8_t* outlen)
{
if ((inlen != 35) || (indata[0] != 0x0f) || (indata[inlen - 2] != 0x0c)) return ;
uint8_t xorr = getBcc(&indata[1], inlen - 2);
if (xorr != indata[inlen - 1]) return ;
uint16_t channels[16];
uint8_t* data = &indata[1];
for (int i = 0; i < 16; i++)
{
channels[i] = ((uint16_t)data[i * 2] << 8) | ((uint16_t)data[i * 2 + 1]);
channels[i] = (uint16_t)((float)(channels[i] - 880) / 0.625f);
}
packet[0] = 0x0F;
packet[1] = (unsigned char)((channels[0] & 0x07FF));
packet[2] = (unsigned char)((channels[0] & 0x07FF) >> 8 | (channels[1] & 0x07FF) << 3);
packet[3] = (unsigned char)((channels[1] & 0x07FF) >> 5 | (channels[2] & 0x07FF) << 6);
packet[4] = (unsigned char)((channels[2] & 0x07FF) >> 2);
packet[5] = (unsigned char)((channels[2] & 0x07FF) >> 10 | (channels[3] & 0x07FF) << 1);
packet[6] = (unsigned char)((channels[3] & 0x07FF) >> 7 | (channels[4] & 0x07FF) << 4);
packet[7] = (unsigned char)((channels[4] & 0x07FF) >> 4 | (channels[5] & 0x07FF) << 7);
packet[8] = (unsigned char)((channels[5] & 0x07FF) >> 1);
packet[9] = (unsigned char)((channels[5] & 0x07FF) >> 9 | (channels[6] & 0x07FF) << 2);
packet[10] = (unsigned char)((channels[6] & 0x07FF) >> 6 | (channels[7] & 0x07FF) << 5);
packet[11] = (unsigned char)((channels[7] & 0x07FF) >> 3);
packet[12] = (unsigned char)((channels[8] & 0x07FF));
packet[13] = (unsigned char)((channels[8] & 0x07FF) >> 8 | (channels[9] & 0x07FF) << 3);
packet[14] = (unsigned char)((channels[9] & 0x07FF) >> 5 | (channels[10] & 0x07FF) << 6);
packet[15] = (unsigned char)((channels[10] & 0x07FF) >> 2);
packet[16] = (unsigned char)((channels[10] & 0x07FF) >> 10 | (channels[11] & 0x07FF) << 1);
packet[17] = (unsigned char)((channels[11] & 0x07FF) >> 7 | (channels[12] & 0x07FF) << 4);
packet[18] = (unsigned char)((channels[12] & 0x07FF) >> 4 | (channels[13] & 0x07FF) << 7);
packet[19] = (unsigned char)((channels[13] & 0x07FF) >> 1);
packet[20] = (unsigned char)((channels[13] & 0x07FF) >> 9 | (channels[14] & 0x07FF) << 2);
packet[21] = (unsigned char)((channels[14] & 0x07FF) >> 6 | (channels[15] & 0x07FF) << 5);
packet[22] = (unsigned char)((channels[15] & 0x07FF) >> 3);
packet[23] = 0x03;
packet[24] = 0X00;
*outlen = 25;
}
