Welcome to 2.4G 10-channel Controller repository
STM32 basic routines
STM32 basic routines
STM32 basic routinesHardware PreparationExperiment ObjectiveHT-10A Remote ControllerSBUS ReceiverSTM32 ProjectPin ConfigurationROS Control Board SchematicProject Pin ConfigurationImplementation PrincipleCore CodeSerial Port FunctionsSBUS DataMain FunctionHardware ConnectionDownload ProgramExperiment Results
Hardware Preparation
- HT-10A Remote Controller
- SBUS Receiver
- ROS Control Board
Experiment Objective
Parse the SBUS protocol data received by the HT-10A remote controller's receiver through the ROS control board, and print the values of each channel via the serial port.
Users need to set up the STM32CubeIDE environment themselves!The project source code for this tutorial is SBUS.zip in the [Software Materials] folder.
HT-10A Remote Controller
Install 4 AA batteries in advance to power the HT-10A remote controller:

| HT-10A Remote Controller | Default Channels: No channel mapping on the remote |
|---|---|
| CH1 | Right Joystick: Left/Right |
| CH2 | Right Joystick: Up/Down |
| CH3 | Left Joystick: Up/Down |
| CH4 | Left Joystick: Left/Right |
| CH5 | SWA Channel |
| CH6 | SWB Channel |
| CH7 | SWC Channel |
| CH8 | SWD Channel |
| CH9 | VRA Channel |
| CH10 | VRB Channel |
SBUS Receiver
Diagram showing the hardware connection between the SBUS receiver and the ROS control board:
| SBUS Receiver | ROS Control Board |
|---|---|
| S | S |
| + | V |
| - | G |

STM32 Project
This tutorial only demonstrates the main code and functionality: Refer to the [Software Materials] folder for the detailed project code.
Pin Configuration
ROS Control Board Schematic
The SBUS interface is connected to the PA3 pin (USART2 RX pin) of the ROS control board:

Project Pin Configuration
- USART2
Mode: Asynchronous
Basic Parameters:
Baud Rate: 100000
Word Length: 9
Parity: Even
Stop Bits: 2
Data Direction: Receive and Transmit
Enable NVIC: USART2 global interrupt


Implementation Principle
USART2 receives the channel data sent by the SBUS receiver and parses it. The parsed data is printed through USART1.
Core Code
Serial Port Functions
- Serial Port Initialization
x// Initialize USARTvoid USART_Init(void){HAL_UART_Receive_IT(&huart1, (uint8_t *)&RxTemp, 1);HAL_UART_Receive_IT(&huart2, (uint8_t *)&RxTemp_2, 1);printf("start serial\n");}
- Serial Port Interrupt for Data Reception
xxxxxxxxxx// The serial port receiving is interrupted.void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){if (huart == &huart1){// Test sending data. In practice, data should not be sent during interruptsUSART1_Send_U8(RxTemp);// Continue receiving dataHAL_UART_Receive_IT(&huart1, (uint8_t *)&RxTemp, 1);}if (huart == &huart2){SBUS_Reveive(RxTemp_2);// printf("a:%d\n", RxTemp_2);HAL_UART_Receive_IT(&huart2, (uint8_t *)&RxTemp_2, 1);}}
SBUS Data
- Receiving SBUS Data
xxxxxxxxxx// Receives SBUS cache datavoid SBUS_Reveive(uint8_t data){// If the protocol start flag is met, data is receivedif (sbus_start == 0 && data == SBUS_START){sbus_start = 1;sbus_new_cmd = 0;sbus_buf_index = 0;inBuffer[sbus_buf_index] = data;inBuffer[SBUS_RECV_MAX - 1] = 0xff;}else if (sbus_start){sbus_buf_index++;inBuffer[sbus_buf_index] = data;}// Finish receiving a frame of dataif (sbus_start & (sbus_buf_index >= (SBUS_RECV_MAX - 1))){sbus_start = 0;if (inBuffer[SBUS_RECV_MAX - 1] == SBUS_END){memcpy(sbus_data, inBuffer, SBUS_RECV_MAX);sbus_new_cmd = 1;}}}
- Parsing SBUS Data
xxxxxxxxxx// Parses SBUS data into channel valuesstatic int SBUS_Parse_Data(void){g_sbus_channels[0] = ((sbus_data[1] | sbus_data[2] << 8) & 0x07FF);g_sbus_channels[1] = ((sbus_data[2] >> 3 | sbus_data[3] << 5) & 0x07FF);g_sbus_channels[2] = ((sbus_data[3] >> 6 | sbus_data[4] << 2 | sbus_data[5] << 10) & 0x07FF);g_sbus_channels[3] = ((sbus_data[5] >> 1 | sbus_data[6] << 7) & 0x07FF);g_sbus_channels[4] = ((sbus_data[6] >> 4 | sbus_data[7] << 4) & 0x07FF);g_sbus_channels[5] = ((sbus_data[7] >> 7 | sbus_data[8] << 1 | sbus_data[9] << 9) & 0x07FF);g_sbus_channels[6] = ((sbus_data[9] >> 2 | sbus_data[10] << 6) & 0x07FF);g_sbus_channels[7] = ((sbus_data[10] >> 5 | sbus_data[11] << 3) & 0x07FF);g_sbus_channels[8] = ((sbus_data[12] | sbus_data[13] << 8) & 0x07FF);g_sbus_channels[9] = ((sbus_data[13] >> 3 | sbus_data[14] << 5) & 0x07FF);#ifdef ALL_CHANNELSg_sbus_channels[10] = ((sbus_data[14] >> 6 | sbus_data[15] << 2 | sbus_data[16] << 10) & 0x07FF);g_sbus_channels[11] = ((sbus_data[16] >> 1 | sbus_data[17] << 7) & 0x07FF);g_sbus_channels[12] = ((sbus_data[17] >> 4 | sbus_data[18] << 4) & 0x07FF);g_sbus_channels[13] = ((sbus_data[18] >> 7 | sbus_data[19] << 1 | sbus_data[20] << 9) & 0x07FF);g_sbus_channels[14] = ((sbus_data[20] >> 2 | sbus_data[21] << 6) & 0x07FF);g_sbus_channels[15] = ((sbus_data[21] >> 5 | sbus_data[22] << 3) & 0x07FF);#endif// Security detection to check for lost connections or data errorsfailsafe_status = SBUS_SIGNAL_OK;if (sbus_data[23] & (1 << 2)){failsafe_status = SBUS_SIGNAL_LOST;printf("SBUS_SIGNAL_LOST\n");// lost contact errors}else if (sbus_data[23] & (1 << 3)){failsafe_status = SBUS_SIGNAL_FAILSAFE;printf("SBUS_SIGNAL_FAILSAFE\n");// data loss error}return failsafe_status;}
- Printing SBUS Data
xxxxxxxxxxvoid SBUS_Handle(void){if (sbus_new_cmd){int res = SBUS_Parse_Data();sbus_new_cmd = 0;if (res) return;#if SBUS_ALL_CHANNELSprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",g_sbus_channels[0], g_sbus_channels[1], g_sbus_channels[2],g_sbus_channels[3], g_sbus_channels[4], g_sbus_channels[5],g_sbus_channels[6], g_sbus_channels[7], g_sbus_channels[8],g_sbus_channels[9], g_sbus_channels[10], g_sbus_channels[11],g_sbus_channels[12], g_sbus_channels[13], g_sbus_channels[14],g_sbus_channels[15]);#elseprintf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d\r\n",g_sbus_channels[0], g_sbus_channels[1], g_sbus_channels[2],g_sbus_channels[3], g_sbus_channels[4],g_sbus_channels[5],g_sbus_channels[6], g_sbus_channels[7],g_sbus_channels[8],g_sbus_channels[9]);#endif}}
Main Function
xxxxxxxxxxvoid Bsp_Loop(void){// Detect button down eventsif (Key1_State(KEY_MODE_ONE_TIME)){Beep_On_Time(50);static int press = 0;press++;printf("press:%d\n", press);}SBUS_Handle();Bsp_Led_Show_State_Handle();// The buzzer automatically shuts down when times outBeep_Timeout_Close_Handle();HAL_Delay(10);}
Hardware Connection
| SBUS Receiver | ROS Control Board |
|---|---|
| S | S |
| + | V |
| - | G |

Download Program
Use the FlyMcu program to download the program: Different development boards have different methods for entering download mode. For the ROS control board, press the BOOT button before powering on, and release it after connecting to the computer.
①: COM Port and Baud Rate Settings → COM port can be checked in the system device manager, baud rate select 115200
②: Program File → Select the .hex file of the SBUS project: Located in the Debug folder of the SBUS project
③④: Select according to the options in the image
⑤: Confirm all options are set correctly, then click the burn button

Experiment Results
After downloading the SBUS project file to the ROS control board, the LED will flash every 200 milliseconds. You can connect the ROS control board to a computer via the MicroUSB interface and view the data of each channel of the HT-10A remote controller through the serial port.
Note: Configure the serial port settings according to the image below!
xxxxxxxxxxFor pairing the SBUS receiver with the HT-10A remote controller, refer to the [2. SBUS Receiver Pairing] tutorial, which explains the button functions corresponding to each channel of the HT-10A remote controller.
