Skip to content

UART / RS485 Bus Servo SDK Development Manual (STM32F103)

版本 GitHub 开发资源包
v1.2026.0305 GitHub 点击下载

This SDK wraps the low-level C API based on the bus servo UART / RS485 Communication Protocol, helping developers quickly implement precise control, status readback, and multi-axis synchronous control for all supported bus servo models on the STM32F103 platform.

Quick Start

After the basic development environment and hardware wiring are ready, use the entries below to jump directly to the corresponding function examples.

Each example provides complete code that can be copied, compiled, and run directly for quick verification and debugging.

=== Part 1: Environment Setup ===


1. Resource Preparation

Before writing code, make sure the following software and hardware development resources are ready:

1.1 Development Tools and Driver Software

Tip

Click the Development Resource Package at the top of this page to download all resources in one package.

1.2 Hardware Preparation

Use the STM32 all-in-one controller board (PTC-32). This controller integrates the functions of STM32F103C8T6 and the servo adapter board UC-01 at the hardware level. It removes complex wiring, works out of the box, and greatly reduces early-stage hardware troubleshooting time.

Option 2 (Advanced Expansion)

Core board + UC-01 adapter board combination Suitable for developers who already have a controller board or need to integrate servo into a more complex robot system. This option provides high flexibility.

2. Hardware Wiring Instructions

2.1 Serial Port Resource Allocation Convention

In the provided SDK examples, the hardware serial port (UART) resources of STM32F103 are assigned as follows:

  • UART1: Control communication channel. Connects to the Bus Servo adapter board, used to send control commands and receive Servo feedback.
  • UART2: Log output channel (optional). Connects to a USB-to-TTL module, used to print printf Configuration information to the PC.
  • UART3: Reserved and not used by default.

2.2 Physical Wiring Topology

Used to flash the compiled firmware.

ST-Link V2 Pin STM32 Core Board Pin
SWDIO SWIO / IO
SWCLK SWCLK / CLK
GND GND
3.3V 3V3

Control Communication Wiring (STM32 UART1 <-> Servo Adapter Board)

Tip

If you use the STM32 all-in-one controller board (PTC-32), skip this step. This step applies only to Option 2: core board + UC-01 adapter board.

STM32F103 GPIO Bus Servo Adapter Board UC01 Wiring Description
PA_9 (UART1 Tx) Rx MCU sends control commands
PA_10 (UART1 Rx) Tx MCU receives servo feedback data
5V 5V Logic-level reference, depending on adapter board power supply
GND GND Common ground, required
Hardware Wiring Diagram

Log Configuration Wiring (STM32 UART2 <-> USB-to-TTL) - Optional

STM32F103 GPIO USB-to-TTL Module (External) Wiring Description
PA_2 (UART2 Tx) Rx MCU outputs printf logs
PA_3 (UART2 Rx) Tx Receives PC-side configuration commands, reserved
GND GND Common ground, required

Overall Topology Diagram

Firmware Download Wiring Diagram

3. Project Configuration and Build Structure

3.1 Project Import and Keil5 Configuration

After extracting the downloaded SDK source package fashionstar-uart-servo-stm32f103-master, enter the corresponding example directory. The steps below use the communication check example as the reference:

  • 1. Open the project: double-click /FashionStarUartServo/Project/FashionStarUartServo.uvprojx to launch Keil5.
Keil Project Interface
Keil Project Configuration Interface
  • 2. Configure the compiler: make sure the project uses Use default compiler version 5 (ARM Compiler 5) for compatibility.
Compiler Configuration Interface
Compiler Version Configuration
  • 3. Configure the downloader: in the Options for Target -> Debug tab, select the Debugger you are using. The standard configuration in this manual is ST-Link Debugger.
Downloader Configuration Interface

3.2 Build and Firmware Download

  • 1. Click the Build button at the top of Keil to build the project. Check the Build Output window below and confirm that it shows 0 Error(s), 0 Warning(s).
Build Output Window
Build Success Message
  • 2. Plug ST-Link into a USB port on the computer, then click Download to flash the firmware to the STM32 chip.
Firmware Download Button
  • 3. After flashing is complete, press the Reset button on the STM32 core board. The program will start running.

3.3 SDK Project Directory Tree

For easier secondary development, review the module structure under the SDK User folder:

├── fashion_star_uart_servo    // 核心:FashionStar 舵机通信协议封装层 API
│   ├── fashion_star_uart_servo.c
│   └── fashion_star_uart_servo.h
├── main.c                     // 业务层:用户主程序入口
├── ring_buffer                // 底层组件:C语言实现的环形缓冲队列(处理串口字节流)
│   ├── README.md
│   ├── ring_buffer.c
│   └── ring_buffer.h
├── stm32f10x_conf.h
├── sys_tick                   // 底层组件:系统时间管理(封装延时与倒计时函数)
│   ├── sys_tick.c
│   └── sys_tick.h
└── usart                      // 底层组件:串口通信驱动(提供宏定义快捷开关 UART1/2/3)
    ├── README.md
    ├── usart.c
    └── usart.h

=== Part 2: servo Function APIs and Core Examples ===


4. Communication Check (Ping)

Before performing complex motion control, verify that the physical link and communication protocol are working properly. Sending a Ping command checks whether the servo with a specific ID on the bus is online. If the servo is online, it immediately returns a response packet containing its basic status.

Function Prototype

FSUS_STATUS FSUS_Ping(
    Usart_DataTypeDef *usart,
    uint8_t servo_id
);

Parameter Description

  • usart: pointer to the Serial Port data object corresponding to Servo control, such as &usart1.
  • servo_id: ID of the Servo to check.

Return Value

  • Returns the status code FSUS_STATUS.
  • Returns 0 (FSUS_STATUS_SUCCESS) if the request succeeds. A non-zero value indicates communication failure.
  • For the complete error codes, refer to fashion_star_uart_servo.h.

Function Call Example

statusCode = FSUS_Ping(servoUsart, servoId);

▶️ Check Whether the Servo Is Online

Logic Description:

  • Continuously sends communication check commands to servo ID 0.
  • Prints the online status of the servo in the UART2 log serial port according to the response status code.

Complete Example Code

/********************************************************
 * 测试通信检测指令,测试舵机是否在线
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
// <注意事项>
// 使用前确保已设置usart.h里面的USART2_ENABLE为1
Usart_DataTypeDef* loggingUsart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((loggingUsart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(loggingUsart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}

// 连接在转接板上的总线伺服舵机ID号
uint8_t servoId = 0; 
// 发送Ping请求的状态码
FSUS_STATUS statusCode; 

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1)
    {   
        printf("\r\n");
        // Ping一下舵机
        printf("[INFO]ping servo %d \r\n", servoId);
        statusCode = FSUS_Ping(servoUsart, servoId);
        printf("[INFO]status code %d \r\n", statusCode);

        // 根据状态码做不同的处理
        if (statusCode == FSUS_STATUS_SUCCESS){
            printf("[INFO]ping success, servo %d echo \r\n", servoId);
        }else{
            printf("[ERROR]ping fail, servo %d not online \r\n", servoId);
        }
        // 等待1000ms
        SysTick_DelayMs(1000);
    }
}

5. Single-Turn Angle Control

Note

  • Command overwrite: servo follows the latest-command-first rule. When angle control commands are sent continuously, a new command immediately overwrites the previous one. Add a delay between consecutive motions, or poll the current angle to determine whether the motion has completed.
  • bus protection: when sending commands continuously to the same servo, keep the command interval above 10 ms.
  • Power holding: if power = 0 or the configured value is greater than the system power holding value, the servo uses the configured power holding value by default. This can be modified through PC configuration software.
  • Physical limits: the actual time required to reach the target position depends on the maximum physical speed of the servo model and the current external load.

Simple Single-Turn Angle Control

This is the most basic point-to-point control method. It moves the servo to the specified angle within the specified cycle time.

Basic Control Mode Diagram

Function Prototype

FSUS_STATUS FSUS_SetServoAngle(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    uint16_t interval,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_id: target Servo ID.
  • angle: target absolute angle. The minimum unit is 0.1°, and the valid range is [-180.0, 180.0].
  • interval: expected motion run time (ms).
  • power: maximum power limit (mV) for this motion. The default is 0.
  • wait: API blocking mode. 0 means non-blocking, where the API returns after the command is sent. 1 means blocking wait, where the API blocks until the Servo rotates into position.

Function Call Example

// 舵机控制相关的参数
uint8_t servoId = 0;  // 舵机的ID号
float angle = 0;// 舵机的目标角度  舵机角度在-180度到180度之间, 最小单位0.1°
uint16_t interval = 2000; // 运行时间ms  可以尝试修改设置更小的运行时间,例如500ms
uint16_t power = 0; // 舵机执行功率 单位mV 默认为0   
uint8_t wait = 0; //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 

FSUS_SetServoAngle(servoUsart, servoId, angle, interval, power, wait);

Advanced Single-Turn Angle Control (Time-Based)

This mode adds trapezoidal speed planning to the basic control method. By specifying the acceleration time and deceleration time, it effectively reduces mechanical jitter and current impact during start and stop.

Trapezoidal Speed Planning Diagram

Function Prototype

FSUS_STATUS FSUS_SetServoAngleByInterval(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    uint16_t interval,
    uint16_t t_acc,
    uint16_t t_dec,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • interval: total run time (ms), which must satisfy interval > t_acc + t_dec.
  • t_acc: time required to accelerate from rest to the constant-speed stage (ms), with a minimum value of > 20.
  • t_dec: time required to decelerate from constant speed to stop (ms), with a minimum value of > 20. (Other parameters are the same as above.)

Function Call Example

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servoId = 0;  
// 舵机的目标角度
// 舵机角度在-180度到180度之间, 最小单位0.1°
float angle = 0; 
// 运行时间ms  
// 可以尝试修改设置更小的运行时间,例如500ms
uint16_t interval = 2000; 
// 加速时间
uint16_t t_acc = 100;
// 减速时间
uint16_t t_dec = 150;
// 舵机执行功率 单位mV 默认为0   
uint16_t power = 0;
 //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 0; 

FSUS_SetServoAngleByInterval(servo_usart, servo_id, angle, interval, t_acc, t_dec, power, wait);

Advanced Single-Turn Angle Control (Speed-Based)

This mode is suitable for applications that need the servo to move to the target point at a specific constant physical speed.

Constant Speed Control Diagram

Function Prototype

FSUS_STATUS FSUS_SetServoAngleByVelocity(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    float velocity,
    uint16_t t_acc,
    uint16_t t_dec,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • velocity: target cruising speed in °/s. The valid range is [1, 750]. (Other parameters are the same as above.)

Function Call Example

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servoId = 0;  
// 舵机的目标角度
// 舵机角度在-180度到180度之间, 最小单位0.1°
float angle = 0; 
// 目标转速
float velocity;
// 加速时间
uint16_t t_acc = 100;
// 减速时间
uint16_t t_dec = 150;
// 舵机执行功率 单位mV 默认为0   
uint16_t power = 0;
 //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 0; 

FSUS_SetServoAngleByVelocity(servo_usart, servo_id, angle, velocity, t_acc, t_dec, power, wait);

Read Current Single-Turn Angle

Reads the absolute angle of the current physical position of the servo.

Function Prototype

// 查询单个舵机的角度信息 angle 单位度
FSUS_STATUS FSUS_QueryServoAngle(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float *angle
);

Function Call Example

uint8_t servoId = 0;    // 舵机的ID号
float curAngle = 0;     // 舵机当前所在的角度
FSUS_QueryServoAngle(servoUsart, servoId, &curAngle); // 读取一下舵机的角度
//curAngle = 当前单圈角度

▶️ Control a Single Servo for Complex Motion

Logic Description:

  • Demonstrates the three single-turn control APIs above.
  • The servo moves back and forth in different control modes. After each motion completes, the callback query API prints the reached angle in real time, making it easier to compare the behavior of different speed planning modes.

Complete Example Code:

/********************************************************
 * 测试控制舵机的角度, 让舵机在两个角度之间做周期性旋转
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
Usart_DataTypeDef* servo_usart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
Usart_DataTypeDef* logging_usart = &usart2;



// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((logging_usart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(logging_usart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}



//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servo_id = 0;  
// 舵机的目标角度
// 舵机角度在-180度到180度之间, 最小单位0.1°
float angle = 0; 
// 运行时间ms  
// 可以尝试修改设置更小的运行时间,例如500ms
uint16_t interval;
// 目标转速
float velocity;
// 加速时间
uint16_t t_acc;
// 减速时间
uint16_t t_dec;
// 舵机执行功率 单位mV 默认为0   
uint16_t power = 0;
// 设置舵机角度的时候, 是否为阻塞式 
// 0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 1; 
// 读取的角度
float angle_read;

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){
        printf("GOTO: 135.0f\r\n");
        // 简易角度控制 + 当前角度查询
        angle = 135.0;
        interval = 2000;
        FSUS_SetServoAngle(servo_usart, servo_id, angle, interval, power, wait);
        FSUS_QueryServoAngle(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);

        // 带加减速的角度控制(指定周期) + 当前角度查询
        printf("GOTO+Interval: 0.0f\r\n");
        angle = 0.0f;
        interval = 1000;
        t_acc = 100;
        t_dec = 150;
        FSUS_SetServoAngleByInterval(servo_usart, servo_id, angle, interval, t_acc, t_dec, power, wait);
        FSUS_QueryServoAngle(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);

        // 带加减速的角度控制(指定转速) + 当前角度查询
        printf("GOTO+Velocity: -135.0f\r\n");
        angle = -135.0f;
        velocity = 200.0f;
        t_acc = 100;
        t_dec = 150;
        FSUS_SetServoAngleByVelocity(servo_usart, servo_id, angle, velocity, t_acc, t_dec, power, wait);
        FSUS_QueryServoAngle(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);
  }
}

Reference Terminal Output Log: a small steady-state error can be observed in the actual reached angle

GOTO: 135.0f
Cur Angle: 134.7
GOTO+Interval: 0.0f
Cur Angle: 0.3
GOTO+Velocity: -135.0f
Cur Angle: -134.6

▶️ Control Multiple Servo with Serial Commands

Logic Description:

  • Uses non-blocking mode (wait=0) to continuously send control commands to the bus.
  • Works with delays in the MCU main loop to implement basic coordination between servo ID 0 and ID 1.

Tip

If strict synchronization is required for multiple servo, use synchronous commands.

Complete Example Code:

#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

//// 舵机控制相关的参数
// 运行时间ms  
// 可以尝试修改设置更小的运行时间,例如500ms
uint16_t interval = 2000; 
// 舵机执行功率 单位mV 默认为0   
uint16_t power = 0;
// 设置舵机角度的时候, 是否为阻塞式 
// 0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 0; 

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1)
    {   
        // 简易角度控制指令,控制0和1号舵机
        FSUS_SetServoAngle(servoUsart, 0, 135.0, interval, power, wait);
        FSUS_SetServoAngle(servoUsart, 1, 45.0, interval, power, wait);
        // 等待动作完成
        SysTick_DelayMs(interval);

        // 等待2s
        SysTick_DelayMs(2000);

        // 简易角度控制指令,控制0和1号舵机
        FSUS_SetServoAngle(servoUsart, 0, -135.0, interval, power, wait);
        FSUS_SetServoAngle(servoUsart, 1, -45.0, interval, power, wait);
        // 等待动作完成
        SysTick_DelayMs(interval);

        // 等待2s
        SysTick_DelayMs(2000);
    }
}

▶️ Deadband Evaluation and Autonomous Motion Closed Loop

Logic Description:

  • In robot kinematics development, the MCU often needs to know precisely whether a joint has physically reached its target.
  • This example shows how to automatically calculate the estimated execution time based on the target deviation, then use high-frequency polling of the current angle with servoDeadBlock deadband tolerance to implement a high-intensity software-level position closed-loop verification.

Complete Example Code:

#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
// <注意事项>
// 使用前确保已设置usart.h里面的USART2_ENABLE为1
Usart_DataTypeDef* loggingUsart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((loggingUsart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(loggingUsart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}

// 舵机控制相关的参数
uint8_t servoId = 0;    // 舵机的ID
float curAngle = 0;     // 舵机当前所在的角度
float nextAngle = 0;    // 舵机的目标角度
uint16_t speed = 200;   // 舵机的转速 单位 °/s
uint16_t interval = 0;  // 舵机旋转的周期
uint16_t power = 0;     // 舵机执行功率 单位mV 默认为0
uint8_t wait = 0;       // 0:不等待 1:等待舵机旋转到特定的位置;
// 舵机角度死区, 如果舵机当前角度跟
// 目标角度相差小于死区则代表舵机到达目标角度, 舵机不再旋转
// <注意事项>
//      死区跟舵机的型号有关系, 取决于舵机固件的设置, 不同型号的舵机会有差别
float servoDeadBlock = 1.0; 

// 查询舵机的角度
uint16_t calcIntervalMs(uint8_t servoId, float nextAngle, float speed){
    // 读取一下舵机的角度
    FSUS_QueryServoAngle(servoUsart, servoId, &curAngle);
    // 计算角度误差
    float dAngle =  (nextAngle > curAngle) ? (nextAngle - curAngle) : (curAngle - nextAngle);
    // 计算所需的时间
    return (uint16_t)((dAngle / speed) * 1000.0);
}

// 等待舵机进入空闲状态IDLE, 即舵机到达目标角度
void waitUntilServoIDLE(uint8_t servoId, float nextAngle){

    while(1){
        // 读取一下舵机的角度
        FSUS_QueryServoAngle(servoUsart, servoId, &curAngle);

        // 判断舵机是否达到目标角度
        float dAngle =  (nextAngle > curAngle) ? (nextAngle - curAngle) : (curAngle - nextAngle);

        // 打印一下当前的舵机角度
        printf("curAngle: %f dAngle: %f\r\n", curAngle, dAngle);

        // 判断是否小于死区
        if (dAngle <= servoDeadBlock){
            break;
        }
        // 等待一小段时间
        SysTick_DelayMs(5);
    }
}


int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1)
    {   
        // 设置舵机的目标角度
        nextAngle = 120.0;
        // 根据转速还有角度误差计算周期
        interval = calcIntervalMs(servoId, nextAngle, speed);
        printf("Set Servo %f-> %f", curAngle, nextAngle);
        // 控制舵机角度
        FSUS_SetServoAngle(servoUsart, servoId, nextAngle, interval, power, wait);
        // SysTick_DelayMs(interval);
        SysTick_DelayMs(5);
        waitUntilServoIDLE(servoId, nextAngle);

        // 等待1s 看舵机死区范围
        SysTick_DelayMs(1000);
        // 读取一下舵机的角度
        FSUS_QueryServoAngle(servoUsart, servoId, &curAngle);
        printf("Final Angle: %f", curAngle);
        SysTick_DelayMs(1000);

        // 设置舵机的目标角度
        nextAngle = -120;
        // 根据转速还有角度误差计算周期
        interval = calcIntervalMs(servoId, nextAngle, speed);
        // 控制舵机角度
        FSUS_SetServoAngle(servoUsart, servoId, nextAngle, interval, power, wait);
        // 需要延时一会儿,确保舵机接收并开始执行舵机控制指令
        // 如果马上发送舵机角度查询信息,新发送的这条指令可能会覆盖舵机角度控制信息
        SysTick_DelayMs(5);
        waitUntilServoIDLE(servoId, nextAngle);

        // 等待1s 看舵机死区范围
        SysTick_DelayMs(1000);
        // 读取一下舵机的角度
        FSUS_QueryServoAngle(servoUsart, servoId, &curAngle);
        printf("Final Angle: %f", curAngle);
        SysTick_DelayMs(1000);
    }
}

6. Multi-Turn Angle Control

Note

  • Command overwrite: servo follows the latest-command-first rule. When angle control commands are sent continuously, a new command immediately overwrites the previous one. Add a delay between consecutive motions, or poll the current angle to determine whether the motion has completed.
  • bus protection: when sending commands continuously to the same servo, keep the command interval above 10 ms.
  • Power holding: if power = 0 or the configured value is greater than the system power holding value, the servo uses the configured power holding value by default. This can be modified through PC configuration software.
  • Physical limits: the actual time required to reach the target position depends on the maximum physical speed of the servo model and the current external load.
  • Multi-turn control breaks through the physical dead zone limit of traditional single-turn [-180°, +180°], making it especially suitable for continuous cable winding, slide rail drive, continuous turntables, and similar applications.
  • The control parameter logic and constraints are basically the same as single-turn mode, but the valid range of the target angle angle is greatly expanded.

Simple Multi-Turn Angle Control

Simple Multi-Turn Control Curve

Function Prototype

FSUS_STATUS FSUS_SetServoAngleMTurn(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    uint32_t interval,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_id: target Servo ID.
  • angle: multi-turn target absolute angle. The minimum unit is 0.1°, and the value range expands to [-368640.0°, 368640.0°] (about ±1024 turns).
  • interval: expected motion run time (ms).
  • power: maximum power limit (mV) for this motion. The default is 0.
  • wait: API blocking mode. 0 means non-blocking, where the API returns after the command is sent. 1 means blocking wait, where the API blocks until the Servo rotates into position.

Function Call Example

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servo_id = 0;  
// 舵机的目标角度
float angle= 720.0f; 
uint32_t interval = 2000;   // 运行时间ms  
// 舵机执行功率,单位mV,默认为0 
uint16_t power = 0;
 //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 0; 

FSUS_SetServoAngleMTurn(servo_usart, servo_id, angle, interval, power, wait);

Advanced Multi-Turn Angle Control (Time-Based)

Advanced Multi-Turn Angle Control Curve (Time-Based)

Function Prototype

FSUS_STATUS FSUS_SetServoAngleMTurnByInterval(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    uint32_t interval,
    uint16_t t_acc,
    uint16_t t_dec,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • interval: total run time (ms), which must satisfy interval > t_acc + t_dec.
  • t_acc: time required to accelerate from rest to the constant-speed stage (ms), with a minimum value of > 20.
  • t_dec: time required to decelerate from constant speed to stop (ms), with a minimum value of > 20. (Other parameters are the same as above.)

Function Call Example

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servo_id = 0;  
// 舵机的目标角度
float angle= 720.0f; 
uint32_t interval = 2000;   // 运行时间ms  
// 舵机执行功率,单位mV,默认为0 
uint16_t power = 0;
 //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 1; 
// 加速时间(单位ms)
uint16_t t_acc = 100;
// 减速时间
uint16_t t_dec = 200;

FSUS_SetServoAngleMTurnByInterval(servo_usart, servo_id, angle, interval, t_acc, t_dec, power, wait);

Advanced Multi-Turn Angle Control (Speed-Based)

Advanced Multi-Turn Angle Control Curve (Speed-Based)

Function Prototype

FSUS_STATUS FSUS_SetServoAngleMTurnByVelocity(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float angle,
    float velocity,
    uint16_t t_acc,
    uint16_t t_dec,
    uint16_t power,
    uint8_t wait
);

Parameter Description

  • velocity: target cruising speed in °/s. The valid range is [1, 750]. (Other parameters are the same as above.)

Function Call Example

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servo_id = 0;  
// 舵机的目标角度
float angle= 720.0f; 
float velocity = 100.0f;    // 电机转速, 单位dps,°/s 
// 舵机执行功率,单位mV,默认为0 
uint16_t power = 0;
 //  API是否为阻塞式,0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 1; 
// 加速时间(单位ms)
uint16_t t_acc = 100;
// 减速时间
uint16_t t_dec = 200;

FSUS_SetServoAngleMTurnByVelocity(servo_usart, servo_id, angle, velocity, t_acc, t_dec, power, wait);

Read Current Multi-Turn Angle

Function Prototype

FSUS_STATUS FSUS_QueryServoAngleMTurn(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    float *angle
);

Function Call Example

uint8_t servoId = 0;    // 舵机的ID号
float curAngle = 0;     // 舵机当前所在的角度
FSUS_QueryServoAngleMTurn(servoUsart, servoId, &curAngle); // 读取一下舵机的角度
//curAngle = 当前单圈角度

Reset Turn Count

Note

Before resetting the turn count, send the stop command - release torque and unlock command first to make sure the servo is in a free state.

This command resets the turn count information of the servo and records the current absolute position angle as the current angle. The angle range is [-180.0, 180.0].

Function Prototype

FSUS_STATUS FSUS_ServoAngleReset(
    Usart_DataTypeDef *usart,
    uint8_t servo_id
);

Function Call Example

uint8_t servoId = 0;    // 舵机的ID号
FSUS_ServoAngleReset(servoUsart, servoId); // 清除多圈圈数

▶️ Multi-Turn Large-Angle Motion Control

Logic Description:

  • Demonstrates rotating the servo by 720 degrees (two turns), then reversing it back to 0 degrees while printing the multi-turn angle in real time during control.
  • This example demonstrates the three multi-turn angle control methods above and the API usage for querying the real-time multi-turn angle.

Complete Example Code:

/********************************************************
 * 舵机多圈控制模式演示
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servo_usart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
// <注意事项>
// 使用前确保已设置usart.h里面的USART2_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* loggingUsart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((loggingUsart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(loggingUsart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}


// 使用串口3作为舵机控制的端口
// <接线说明>
// STM32F103 PB10(Tx)   <----> 总线伺服舵机转接板 Rx
// STM32F103 PB11(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
// Usart_DataTypeDef* servo_usart = &usart3; 

//// 舵机控制相关的参数
// 舵机的ID号
uint8_t servo_id = 0;  
// 舵机的目标角度
// 舵机角度在-135度到135度之间, 精确到小数点后一位
float angle; 
uint32_t interval;  // 运行时间ms  
float velocity;         // 电机转速, 单位dps,°/s
// 舵机执行功率 单位mV,默认为0 
uint16_t power = 0;
// 设置舵机角度的时候, 是否为阻塞式 
// 0:不等待 1:等待舵机旋转到特定的位置; 
uint8_t wait = 1; 
// 加速时间(单位ms)
uint16_t t_acc;
// 减速时间
uint16_t t_dec;

// 读取的角度
float angle_read;
int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){  
        printf("MTurn GOTO: 720.0f\r\n");
        //简易多圈角度控制 + 当前多圈角度查询
        angle = 720.0f;
        interval = 2000;
        FSUS_SetServoAngleMTurn(servo_usart, servo_id, angle, interval, power, wait);
        FSUS_QueryServoAngleMTurn(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);


        printf("MTurn GOTO: 0.0f\r\n");
        angle = 0.0;
        FSUS_SetServoAngleMTurn(servo_usart, servo_id, angle, interval, power, wait);
        FSUS_QueryServoAngleMTurn(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);


        //带加减速的多圈角度控制(指定周期) + 当前多圈角度查询
        printf("MTurn+Interval GOTO: -180.0f\r\n");
        angle = 180.0f; 
        interval = 1000;
        t_acc = 100;
        t_dec = 200;
        FSUS_SetServoAngleMTurnByInterval(servo_usart, servo_id, angle, interval, t_acc, t_dec, power, wait);
        FSUS_QueryServoAngleMTurn(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);

        //带加减速的多圈角度控制(指定转速) + 当前多圈角度查询
        printf("MTurn+Velocity GOTO: -180.0f\r\n");
        angle = -180.0f;
        velocity = 100.0f;
        t_acc = 100;
        t_dec = 200;
        FSUS_SetServoAngleMTurnByVelocity(servo_usart, servo_id, angle, velocity, t_acc, t_dec, power, wait);
        FSUS_QueryServoAngleMTurn(servo_usart, servo_id, &angle_read);
        printf("Cur Angle: %.1f\r\n", angle_read);

        // 等待2s
        SysTick_DelayMs(2000);

  }
}

Reference Terminal Output Log

MTurn GOTO: 720.0f
Cur Angle: 719.7
MTurn GOTO: 0.0f
Cur Angle: 0.4
MTurn+Interval GOTO: -180.0f
Cur Angle: 179.7
MTurn+Velocity GOTO: -180.0f
Cur Angle: -179.5
MTurn GOTO: 720.0f
Cur Angle: 719.5
MTurn GOTO: 0.0f
Cur Angle: 0.4
MTurn+Interval GOTO: -180.0f
Cur Angle: 179.7
MTurn+Velocity GOTO: -180.0f
Cur Angle: -179.5

▶️ Continuous Rotation of the Servo

Complete Example Code:

#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

FSUS_STATUS statusCode; // 请求包的状态码
uint8_t servoId = 0;    // 连接在转接板上的总线伺服舵机ID号
uint16_t speed = 20;    // 舵机的旋转速度 20°/s
uint8_t is_cw = 0;      // 舵机的旋转方向
int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){
        // 舵机轮式模式定速控制 顺时针旋转3s
        is_cw = 1;
        FSUS_WheelKeepMove(servoUsart, servoId, is_cw, speed);
        SysTick_DelayMs(3000);

        // 舵机刹车 停顿2s 
        FSUS_WheelStop(servoUsart, servoId);
        SysTick_DelayMs(1000);

        // 舵机轮式模式定速控制 逆时针旋转3s
        is_cw = 0;
        FSUS_WheelKeepMove(servoUsart, servoId, is_cw, speed);
        SysTick_DelayMs(3000);

        // 舵机刹车 停顿2s 
        FSUS_WheelStop(servoUsart, servoId);
        SysTick_DelayMs(1000);
    }
}

▶️ Timed Rotation of the Servo

Complete Example Code:

/***************************************************
 * 轮式控制模式 定时旋转
 * <注意事项>
 * 在测试本例程时, 请确保舵机没有机械结构/接线的约束, 
 * 舵机可以360度旋转
 ***************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

FSUS_STATUS statusCode; // 请求包的状态码
uint8_t servoId = 0;    // 连接在转接板上的总线伺服舵机ID号
uint16_t speed = 20;    // 舵机的旋转速度 20°/s
uint8_t is_cw = 0;      // 舵机的旋转方向
uint16_t nTime = 3000;  // 延时时间
int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){
        // 舵机轮式模式定速控制 顺时针旋转3s
        is_cw = 1;
        FSUS_WheelMoveTime(servoUsart, servoId, is_cw, speed, nTime);
        // FSUS_WheelMoveTime是非阻塞的,因为有时候需要控制多个舵机同时旋转
        // 所以在后面要手动加延迟
        SysTick_DelayMs(nTime);

        // 停顿1s 
        SysTick_DelayMs(1000);

        // 舵机轮式模式定速控制 逆时针旋转3s
        is_cw = 0;
        FSUS_WheelMoveTime(servoUsart, servoId, is_cw, speed, nTime);
        SysTick_DelayMs(nTime);

        // 停顿1s 
        SysTick_DelayMs(1000);
    }
}

▶️ Fixed-Turn Rotation of the Servo

Complete Example Code:

/***************************************************
 * 轮式模式 定圈旋转
 * <注意事项>
 * 在测试本例程时, 请确保舵机没有机械结构/接线的约束, 
 * 舵机可以360度旋转
 ***************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

FSUS_STATUS statusCode; // 请求包的状态码
uint8_t servoId = 0;    // 连接在转接板上的总线伺服舵机ID号
uint16_t speed = 200;   // 舵机的旋转速度 单位°/s
uint8_t is_cw = 0;      // 舵机的旋转方向
uint16_t nCircle = 1;   // 舵机旋转的圈数

// 估计旋转圈数所需要花费的时间
uint16_t estimateTimeMs(uint16_t nCircle, uint16_t speed){
    return (uint16_t)((float)nCircle * 360.0 / (float)speed * 1000);
}

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){
        // 舵机轮转模式定速控制 顺时针旋转1圈
        is_cw = 1;
        FSUS_WheelMoveNCircle(servoUsart, servoId, is_cw, speed, nCircle);
        // FSUS_WheelMoveNCircle是非阻塞的,因为有时候需要控制多个舵机同时旋转
        // 延时估算所需时间
        SysTick_DelayMs(estimateTimeMs(nCircle, speed));

        // 停顿1s 
        SysTick_DelayMs(1000);

        // 舵机轮转模式定速控制 逆时针旋转1圈
        is_cw = 0;
        FSUS_WheelMoveNCircle(servoUsart, servoId, is_cw, speed, nCircle);
        // 注意: FSUS_WheelMoveNCircle是非阻塞的,因为有时候需要控制多个舵机同时旋转
        // 延时估算所需时间
        SysTick_DelayMs(estimateTimeMs(nCircle, speed));

        // 停顿1s 
        SysTick_DelayMs(1000);
    }
}

7. Damping Mode

By adjusting the electromagnetic damping coefficient of the motor, the servo can provide a smooth resistance to external force, similar to being immersed in a viscous fluid, when it is no longer absolutely rigidly locked. This is well suited for passive teaching of robotic arms, gravity-drop buffering, and similar applications.

Function Prototype

// 舵机阻尼模式
FSUS_STATUS FSUS_DampingMode(
    Usart_DataTypeDef *usart,
    uint8_t servoId,
    uint16_t power
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servoId: target Servo ID.
  • power: response power for this damping mode, in mW. The higher the configured power, the stronger the hysteresis resistance felt when external force tries to rotate the Servo.

Function Call Example

// 连接在转接板上的总线伺服舵机ID号
uint8_t servoId = 0; 
// 阻尼模式下的功率,功率越大阻力越大
uint16_t power = 500;
// 设置舵机为阻尼模式
FSUS_DampingMode(servoUsart, servoId, power);

▶️ Experience Damping Feel

Logic Description:

  • After damping mode is enabled, the system idles and waits.
  • You can directly rotate the output shaft of the servo by hand to feel the specific flexible resistance produced by power = 500.

Complete Example Code:

/***************************************************
 * 总线伺服舵机阻尼模式
 ***************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

// 连接在转接板上的总线伺服舵机ID号
uint8_t servoId = 0; 
// 阻尼模式下的功率,功率越大阻力越大
uint16_t power = 500;
int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();
    // 设置舵机为阻尼模式
    FSUS_DampingMode(servoUsart, servoId, power);
    while (1)
    {   
        //主循环什么也不做
        // 等待1000ms
        SysTick_DelayMs(1000);
    }
}

▶️ Damping Mode and Motion Trajectory Capture

Logic Description:

  • Combines damping mode with position query to create an effect similar to robotic-arm motion teaching. The MCU captures and prints the drag trajectory created when you manually rotate the servo in real time.

Complete Example Code:

#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 
// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
// <注意事项>
// 使用前确保已设置usart.h里面的USART2_ENABLE为1
Usart_DataTypeDef* loggingUsart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((loggingUsart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(loggingUsart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}

FSUS_STATUS statusCode; // 请求包的状态码
uint8_t servoId = 0;    // 连接在转接板上的总线伺服舵机ID号
uint16_t power = 500;   // 阻尼模式下的功率,功率越大阻力越大
float angle = 0;        // 舵机的角度

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();
    // 设置舵机为阻尼模式
    FSUS_DampingMode(servoUsart, servoId, power);
    while (1)
    {   
        // 读取一下舵机的角度
        statusCode = FSUS_QueryServoAngle(servoUsart, servoId, &angle);

        if (statusCode ==FSUS_STATUS_SUCCESS){
            // 成功的读取到了舵机的角度
            printf("[INFO] servo id= %d ; angle = %f\r\n", servoId, angle);
        }else{
            // 没有正确的读取到舵机的角度
            printf("\r\n[INFO] read servo %d angle, status code: %d \r\n", servoId, statusCode);
            printf("[ERROR]failed to read servo angle\r\n");
        }
        // 等待1000ms
        SysTick_DelayMs(500);
    }
}

8. Stop Command

Three stop modes are provided: stop and release torque, hold the current position with torque, and enter damping mode.

Tip

This command can also be used to enable servo torque. When the servo servo is unlocked, sending the hold torque command makes it rebuild holding torque from its current position.

Function Prototype

FSUS_STATUS FSUS_StopOnControlMode(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    uint8_t mode,
    uint16_t power
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_id: target Servo ID.
  • mode: stop mode number.
  • 0 - fully release torque and unlock, so the shaft can be moved freely.
  • 1 - hold absolute position with torque, locking the current position.
  • 2 - enter electromagnetic damping mode with flexible hysteresis.
  • power: if 2 (damping) is selected, this parameter sets the effective power limit after entering damping mode (mW).

Function Call Example

/* 舵机控制模式停止指令*/
//mode 指令停止形式
//0-停止后卸力(失锁)
//1-停止后保持锁力
//2-停止后进入阻尼状态
uint8_t stopcolmode=0;
uint8_t servo_id = 0;   // 连接在转接板上的总线伺服舵机ID号
uint16_t power = 500;  //功率
FSUS_StopOnControlMode(servoUsart, servo_id, stopcolmode, power);

▶️ Automatically Switch to Damping After Motion Completes

Logic Description:

  • Demonstrates a typical workflow: command the servo motion -> wait until its motion cycle completes -> immediately switch the internal electric control mode to stopcolmode=2 to enter damping mode.

Complete Example Code:

/********************************************************
* 控制舵机执行完指令进入阻尼状态
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
Usart_DataTypeDef* servo_usart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
Usart_DataTypeDef* logging_usart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((logging_usart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(logging_usart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}


//0-停止后卸力(失锁)
//1-停止后保持锁力
//2-停止后进入阻尼状态
uint8_t stopcolmode=2;

float   angle = 135.0;// 舵机的目标角度
uint16_t interval = 1000;// 时间间隔ms
uint16_t    power = 500;// 舵机执行功率
uint8_t servo_id=0;// 舵机的ID号

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    FSUS_SetServoAngle(servo_usart, servo_id, angle, interval, power);
    SysTick_DelayMs(2000);

    //停止后进入对应状态
    FSUS_StopOnControlMode(servo_usart, servo_id, stopcolmode, power);
    SysTick_DelayMs(1000);
    while (1){

  }
}

9. Synchronous Commands

When developing multi-axis linkage equipment such as robotic arms and humanoid robots, ordinary polling-style serial communication can introduce small timing differences as each joint receives commands, causing the motion posture to deform.

FSUS_SyncCommand allows the host to package the target parameters of all joints into one long command and send it to the bus at once. All online servo are triggered almost simultaneously at the hardware level, helping reproduce the kinematic algorithm accurately.

Function Prototype

FSUS_STATUS FSUS_SyncCommand(
    Usart_DataTypeDef *usart,
    uint8_t servo_count,
    uint8_t ServoMode,
    FSUS_sync_servo servoSync[]
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_count: number of Servo participating in this synchronous control operation.
  • ServoMode: declares the specific purpose of this group-control command batch.
  • 1: simple angle control
  • 2: angle control with acceleration and deceleration (specified cycle)
  • 3: angle control with acceleration and deceleration (specified speed)
  • 4: simple multi-turn angle control
  • 5: multi-turn angle control with acceleration and deceleration (specified cycle)
  • 6: multi-turn angle control with acceleration and deceleration (specified speed)
  • 7: data monitoring
  • servoSync[]: core structure array used to store the control parameters to be sent to each node.

Function Call Example

/*同步指令模式选择
* 1:设置舵机的角度
* 2:设置舵机的角度(指定周期)
* 3:设置舵机的角度(指定转速)
* 4:设置舵机的角度(多圈模式)
* 5:设置舵机的角度(多圈模式, 指定周期) 
* 6:设置舵机的角度(多圈模式, 指定转速)
* 7:读取舵机的数据*/
uint8_t sync_mode=1;//同步指令模式

uint8_t sync_count=5;//舵机数量

//数组定义在#include "fashion_star_uart_servo.c" 
FSUS_sync_servo SyncArray[20]; // 假设您要控制20个伺服同步
ServoData servodata[20];//假设您要读取20个伺服舵机的数据

//如需更改舵机数量在#include "fashion_star_uart_servo.h"对应修改extern
extern FSUS_sync_servo SyncArray[20]; // 假设您要控制20个伺服同步
extern ServoData servodata[20];//假设您要读取20个伺服舵机的数据

servoSyncArray[0].angle=90;/*角度*/
servoSyncArray[0].id=0;/*舵机ID号*/
servoSyncArray[0].velocity=100;/*速度*/                servoSyncArray[0].interval_single=1000;/*单圈时间*/    servoSyncArray[0].interval_multi=1000; /*多圈时间*/     servoSyncArray[0].t_acc=100;/*加速时间*/    
servoSyncArray[0].t_dec=100;/*减速时间*/                servoSyncArray[0].power=100;/*功率*/
/*********************************以此类推赋值剩下舵机参数 灵活性高**************************************/

FSUS_SyncCommand(servo_usart, servo_count, servomode, servoSyncArray);

▶️ System-Level Millisecond Synchronous Coordination

Logic Description:

  • Demonstrates how to fill the SyncArray structure, package the control parameters of five servo (ID: 0-4), and broadcast them to the bus so that all axes can start synchronously with high real-time performance and reach the target pose.
  • Immediately broadcasts mode 7 afterward to read the latest system status.

Complete Example Code:

#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef* servoUsart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
Usart_DataTypeDef* logging_usart = &usart2;



// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((logging_usart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(logging_usart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}

/*同步指令模式选择
* 1:设置舵机的角度
* 2:设置舵机的角度(指定周期)
* 3:设置舵机的角度(指定转速)
* 4:设置舵机的角度(多圈模式)
* 5:设置舵机的角度(多圈模式, 指定周期) 
* 6:设置舵机的角度(多圈模式, 指定转速)
* 7:读取舵机的数据*/
uint8_t servomode=1;//自行更改数值设置模式

//舵机数量,如果id不是从0开始,请把参数设置为最大舵机id号
uint8_t servo_count=5;

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){

    SyncArray[0].angle=90;
        SyncArray[0].id=0;SyncArray[0].interval_single=100;SyncArray[0].interval_multi=1000;SyncArray[0].velocity=100;SyncArray[0].t_acc=20;SyncArray[0].t_dec=20;
        SyncArray[1].angle=-90;
        SyncArray[1].id=1;SyncArray[1].interval_single=100;SyncArray[1].interval_multi=1000;SyncArray[1].velocity=100;SyncArray[1].t_acc=20;SyncArray[1].t_dec=20;
        SyncArray[2].angle=90;
        SyncArray[2].id=2;SyncArray[2].interval_single=100;SyncArray[2].interval_multi=1000;SyncArray[2].velocity=100;SyncArray[2].t_acc=20;SyncArray[2].t_dec=20;
        SyncArray[3].angle=-90;
        SyncArray[3].id=3;SyncArray[3].interval_single=100;SyncArray[3].interval_multi=1000;SyncArray[3].velocity=100;SyncArray[3].t_acc=20;SyncArray[3].t_dec=20;
        SyncArray[4].angle=-90;
        SyncArray[4].id=4;SyncArray[4].interval_single=100;SyncArray[4].interval_multi=1000;SyncArray[4].velocity=100;SyncArray[4].t_acc=20;SyncArray[4].t_dec=20;
        //发送同步指令控制
        FSUS_SyncCommand(servo_usart,sync_count,servomode,SyncArray);
        SysTick_DelayMs(1000);
        //发送同步指令读取
        FSUS_SyncCommand(servo_usart,sync_count,7,SyncArray);
        SysTick_DelayMs(200);

        SyncArray[0].angle=45;SyncArray[0].interval_single=0;SyncArray[0].velocity=20;
        SyncArray[1].angle=-45;SyncArray[1].interval_single=0;SyncArray[1].velocity=20;
        SyncArray[2].angle=45;SyncArray[2].interval_single=0;SyncArray[2].velocity=20;
        SyncArray[3].angle=-45;SyncArray[3].interval_single=0;SyncArray[3].velocity=20;
        SyncArray[4].angle=-45;SyncArray[4].interval_single=0;SyncArray[4].velocity=20;
        //发送同步指令控制
        FSUS_SyncCommand(servo_usart,sync_count,servomode,SyncArray);
        SysTick_DelayMs(1000);
        //发送同步指令读取
        FSUS_SyncCommand(servo_usart,sync_count,7,SyncArray);
        SysTick_DelayMs(200);
  }
}

10. Asynchronous Commands (Temporary Storage and Delayed Trigger)

Asynchronous commands allow the host to write motion commands into the internal register cache of the servo in advance, like a memo. At this stage, the servo does not execute them.

Only when the host determines that the time is right and sends an asynchronous execution enable command to the bus does the servo immediately start executing the stored motion. This is especially suitable for building complex distributed trigger networks.

Asynchronous Write (Enable Asynchronous Command Storage Mode)

Function Prototype

FSUS_STATUS FSUS_BeginAsync(
    Usart_DataTypeDef *usart
);
  • Parameter Description
  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.

Function Call Example

FSUS_BeginAsync(servo_usart); // 通知底层:后续指令不要立刻跑,先缓存起来

Asynchronous Execution (End Asynchronous Mode and Execute/Discard)

Function Prototype

FSUS_STATUS FSUS_EndAsync(
    Usart_DataTypeDef *usart,
    uint8_t mode
);

Parameter Description * mode: terminal logic trigger flag. 0 approves execution of the stored motion, while 1 discards and clears the stored motion.

Function Call Example

uint8_t async_mode=0; //0:执行存储的命令  1:取消存储的命令
FSUS_EndAsync(servo_usart,async_mode);

▶️ Delayed Trigger for Asynchronous Commands

Logic Description:

  • Demonstrates sending an angle command after enabling the system asynchronous switch. At this moment, the device remains still.
  • After the MCU actively sleeps and blocks for a 5-second delay, it sends the End command to confirm execution and wake the underlying hardware.

Complete Example Code:

/********************************************************
 * 存储一次命令,在下次发送命令的时候才执行 
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
Usart_DataTypeDef* servo_usart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
Usart_DataTypeDef* logging_usart = &usart2;



// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((logging_usart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(logging_usart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}


#define ID 0 // 舵机的ID号
float angle;           //舵机角度设置
float angle_read;            // 读取的角度
uint16_t power = 1000; // 舵机执行功率 单位mV 默认为0
uint16_t interval = 0; // 舵机旋转的周期

uint8_t async_mode=0; //0:执行存储的命令  1:取消存储的命令

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    while (1){

    //异步写入
        FSUS_BeginAsync(servo_usart);

        printf("GOTO: 135.0f\r\n");
    // 简易角度控制 + 当前角度查询
    angle = 135.0;
    interval = 2000;
    FSUS_SetServoAngle(servo_usart, ID, angle, interval, power);
    FSUS_QueryServoAngle(servo_usart, ID, &angle_read);
    printf("Cur Angle: %.1f\r\n", angle_read);

        printf("*******************\n");

    //第一次发送上面的命令是不会动的,只是存储了命令
    //等待5秒
        SysTick_DelayMs(5000);

        //异步执行
        FSUS_EndAsync(servo_usart,async_mode);
  }
}

11. Data Monitoring (Batch Read)

Compared with reading each physical parameter one by one, the system provides the FSUS_ServoMonitor function, which loads the complete status data of the servo into one structure at once and greatly reduces bus communication occupancy time.

Function Prototype

FSUS_STATUS FSUS_ServoMonitor(
    Usart_DataTypeDef *usart,
    uint8_t servo_id,
    ServoData servodata[]
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servoId: target Servo ID.

  • servodata[]: pointer to the receive structure object used to store the complete status data of the Servo.

packet includes:

Function Call Example

//要读取的舵机id号
uint8_t servoId = 0; 
//舵机的存储数据结构体
ServoData servodata_single[1];
// 读取舵机数据函数
FSUS_ServoMonitor(servo_usart,servo_id,servodata_single);

▶️ Full Monitoring of Servo Sensor Data

Logic Description:

  • After initializing the servo, periodically sends Monitor requests to the lower layer. It then accesses member variables of servodata_single, such as voltage, current, power, temperature, and angle, to format and output real-time hardware status to the UART2 configuration port.

Complete Example Code:

/********************************************************
 * 测试舵机的数据回读,并通过串口打印全部数据
 ********************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)    <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx)   <----> 总线伺服舵机转接板 Tx
// STM32F103 GND        <----> 总线伺服舵机转接板 GND
// STM32F103 V5         <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
Usart_DataTypeDef* servo_usart = &usart1; 

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
Usart_DataTypeDef* logging_usart = &usart2;



// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while((logging_usart->pUSARTx->SR&0X40)==0){}
    /* 发送一个字节数据到串口 */
    USART_SendData(logging_usart->pUSARTx, (uint8_t) ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);       
    return (ch);
}

/*数据监控的数据
* id:舵机的id号
* voltage:舵机的电压
* current:舵机的电流
* power:舵机的执行功率
* temperature:舵机的温度 
* status:舵机的状态
* angle:舵机的角度
* circle_count:舵机的转动圈数
*/
ServoData servodata_single[1];//读取一个舵机数据的结构体

//要读取的舵机id号
uint8_t servo_id=0;

int main (void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();
    while (1){
            //每1秒读取一次
            FSUS_DampingMode(servo_usart,servo_id,500);
            FSUS_ServoMonitor(servo_usart,servo_id,servodata_single);
            printf("read ID: %d\r\n", servodata_single[0].id);
            printf("read sucess, voltage: %d mV\r\n", servodata_single[0].voltage);
            printf("read sucess, current: %d mA\r\n", servodata_single[0].current);
            printf("read sucess, power: %d mW\r\n", servodata_single[0].power);
            printf("read sucess, temperature: %d \r\n", servodata_single[0].temperature);
            if ((servodata_single[0].status >> 3) & 0x01)
            printf("read sucess, voltage too high\r\n");
            if ((servodata_single[0].status >> 4) & 0x01)
            printf("read sucess, voltage too low\r\n");
            printf("read sucess, angle: %f\r\n", servodata_single[0].angle);
            printf("read sucess, circle_count: %d\r\n",servodata_single[0].circle_count);
            SysTick_DelayMs(1000);

  }
}

12. Origin Setting

Note

Before triggering origin reset, send the stop command - release torque and unlock command first to make sure the servo is in a free state.

Function Prototype

FSUS_STATUS FSUS_SetOriginPoint(
    Usart_DataTypeDef *usart,
    uint8_t servo_id
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_id: target Servo ID.

Function Call Example

uint8_t servoId = 0;    // 舵机的ID号
FSUS_SetOriginPoint(servoUsart, servoId); // 将当前物理结构位置重新映射为固件级 0 度

13. Read and Write Servo Custom Configuration Parameters

In some cases, you may only need to read or modify one specific hardware register address in the servo memory table, such as voltage or protection values.

Function Prototype

// 读取数据
FSUS_STATUS FSUS_ReadData(
    Usart_DataTypeDef *usart,
    uint8_t servoId,
    uint8_t address,
    uint8_t *value,
    uint8_t *size
);

Parameter Description

  • usart: Serial Port data object Usart_DataTypeDef corresponding to Servo control.
  • servo_id: target Servo ID.

  • address: start address number of the queried parameter in the internal memory table of the Servo. See the appendix table for details.

  • value: receive buffer pointer used to store the readback data.
  • size: returns the actual byte length of valid data at this address (1, 2, or 4 bytes).

Function Call Example

uint8_t servoId = 0;        // 连接在转接板上的总线伺服舵机ID号
uint8_t value;
uint8_t dataSize;

statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_SERVO_STATUS, (uint8_t *)&value, &dataSize);

if (statusCode == FSUS_STATUS_SUCCESS)
{
    // 舵机工作状态标志位
    // BIT[0] - 执行指令置1,执行完成后清零。
    // BIT[1] - 执行指令错误置1,在下次正确执行后清零。
    // BIT[2] - 堵转错误置1,解除堵转后清零。
    // BIT[3] - 电压过高置1,电压恢复正常后清零。
    // BIT[4] - 电压过低置1,电压恢复正常后清零。
    // BIT[5] - 电流错误置1,电流恢复正常后清零。
    // BIT[6] - 功率错误置1,功率恢复正常后清零。
    // BIT[7] - 温度错误置1,温度恢复正常后清零。

    if ((value >> 3) & 0x01)
        printf("read sucess, voltage too high\r\n");
    if ((value >> 4) & 0x01)
        printf("read sucess, voltage too low\r\n");
}

Parameter Write

Warning

  • For key non-volatile parameters such as ID and baud rate, we strongly recommend using the Windows PC configuration software visual software.
  • Use this API for runtime code-level modification only when necessary. Incorrect modification may cause abnormal device behavior.

Function Prototype

// 写入数据
FSUS_STATUS FSUS_WriteData(
    Usart_DataTypeDef *usart,
    uint8_t servoId,
    uint8_t address,
    uint8_t *value,
    uint8_t size
);

Function Call Example

uint8_t servoId = 0;        // 连接在转接板上的总线伺服舵机ID号
float angleLimitLow = -90.0;    // 舵机角度下限设定值
value = (int16_t)(angleLimitLow*10); // 舵机角度下限 转换单位为0.1度
statusCode = FSUS_WriteData(servoUsart, servoId, FSUS_PARAM_ANGLE_LIMIT_LOW, (uint8_t *)&value, 2);

▶️ Read Servo Parameters

Logic Description:

  • Shows how to use the low-level communication layer FSUS_ReadData function.
  • The code demonstrates reading voltage, current, power, and temperature ADC values. It also shows the underlying mathematical formula for converting the temperature ADC value to Celsius, and uses bit operations to parse the 8-bit status status register flags.

    // servo operating status flag bits // BIT[0] - set to 1 while a command is executing, cleared after execution is complete. // BIT[1] - set to 1 when command execution fails, cleared after the next correct execution. // BIT[2] - set to 1 for stall protection, cleared after the stall is resolved. // BIT[3] - set to 1 for overvoltage, cleared after voltage returns to normal. // BIT[4] - set to 1 for undervoltage, cleared after voltage returns to normal. // BIT[5] - set to 1 for current protection, cleared after current returns to normal. // BIT[6] - set to 1 for power protection, cleared after power returns to normal. // BIT[7] - set to 1 for temperature protection, cleared after temperature returns to normal.

Complete Example Code:

/***************************************************
* 读取舵机参数
 ***************************************************/
#include "stm32f10x.h"
#include "usart.h"
#include "sys_tick.h"
#include "fashion_star_uart_servo.h"
#include "math.h"

// 使用串口1作为舵机控制的端口
// <接线说明>
// STM32F103 PA9(Tx)  <----> 总线伺服舵机转接板 Rx
// STM32F103 PA10(Rx) <----> 总线伺服舵机转接板 Tx
// STM32F103 GND      <----> 总线伺服舵机转接板 GND
// STM32F103 V5       <----> 总线伺服舵机转接板 5V
// <注意事项>
// 使用前确保已设置usart.h里面的USART1_ENABLE为1
// 设置完成之后, 将下行取消注释
Usart_DataTypeDef *servoUsart = &usart1;

// 使用串口2作为日志输出的端口
// <接线说明>
// STM32F103 PA2(Tx) <----> USB转TTL Rx
// STM32F103 PA3(Rx) <----> USB转TTL Tx
// STM32F103 GND     <----> USB转TTL GND
// STM32F103 V5      <----> USB转TTL 5V (可选)
// <注意事项>
// 使用前确保已设置usart.h里面的USART2_ENABLE为1
Usart_DataTypeDef *loggingUsart = &usart2;

// 重定向c库函数printf到串口,重定向后可使用printf函数
int fputc(int ch, FILE *f)
{
    while ((loggingUsart->pUSARTx->SR & 0X40) == 0)
    {
    }
    /* 发送一个字节数据到串口 */
    USART_SendData(loggingUsart->pUSARTx, (uint8_t)ch);
    /* 等待发送完毕 */
    // while (USART_GetFlagStatus(USART1, USART_FLAG_TC) != SET);
    return (ch);
}

uint8_t servoId = 0;    // 连接在转接板上的总线伺服舵机ID号
FSUS_STATUS statusCode; // 状态码

int main(void)
{
    // 嘀嗒定时器初始化
    SysTick_Init();
    // 串口初始化
    Usart_Init();

    // 读取用户自定义数据
    // 数据表里面的数据字节长度一般为1个字节/2个字节/4个字节
    // 查阅通信协议可知,舵机角度上限的数据类型是有符号短整型(UShort, 对应STM32里面的int16_t),长度为2个字节
    // 所以这里设置value的数据类型为int16_t
    int16_t value;
    uint8_t dataSize;
    // 传参数的时候, 要将value的指针强行转换为uint8_t

    // 读取电压
    statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_VOLTAGE, (uint8_t *)&value, &dataSize);

    printf("read ID: %d\r\n", servoId);

    if (statusCode == FSUS_STATUS_SUCCESS)
    {
        printf("read sucess, voltage: %d mV\r\n", value);
    }
    else
    {
        printf("fail\r\n");
    }

    // 读取电流
    statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_CURRENT, (uint8_t *)&value, &dataSize);
    if (statusCode == FSUS_STATUS_SUCCESS)
    {
        printf("read sucess, current: %d mA\r\n", value);
    }
    else
    {
        printf("fail\r\n");
    }

    // 读取功率
    statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_POWER, (uint8_t *)&value, &dataSize);
    if (statusCode == FSUS_STATUS_SUCCESS)
    {
        printf("read sucess, power: %d mW\r\n", value);
    }
    else
    {
        printf("fail\r\n");
    }
    // 读取温度
    statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_TEMPRATURE, (uint8_t *)&value, &dataSize);
    if (statusCode == FSUS_STATUS_SUCCESS)
    {
        double temperature, temp;
        temp = (double)value;
        temperature = 1 / (log(temp / (4096.0f - temp)) / 3435.0f + 1 / (273.15 + 25)) - 273.15;
        printf("read sucess, temperature: %f\r\n", temperature);
    }
    else
    {
        printf("fail\r\n");
    }   
    // 读取工作状态
    statusCode = FSUS_ReadData(servoUsart, servoId, FSUS_PARAM_SERVO_STATUS, (uint8_t *)&value, &dataSize);
    if (statusCode == FSUS_STATUS_SUCCESS)
    {
        // 舵机工作状态标志位
        // BIT[0] - 执行指令置1,执行完成后清零。
        // BIT[1] - 执行指令错误置1,在下次正确执行后清零。
        // BIT[2] - 堵转保护置1,解除堵转后清零。
        // BIT[3] - 电压过高置1,电压恢复正常后清零。
        // BIT[4] - 电压过低置1,电压恢复正常后清零。
        // BIT[5] - 电流保护置1,电流恢复正常后清零。
        // BIT[6] - 功率保护置1,功率恢复正常后清零。
        // BIT[7] - 温度保护置1,温度恢复正常后清零。

        if ((value >> 3) & 0x01)
            printf("read sucess, voltage too high\r\n");
        if ((value >> 4) & 0x01)
            printf("read sucess, voltage too low\r\n");
    }
    else
    {
        printf("fail\r\n");
    }
    printf("================================= \r\n");
    // 死循环
    while (1)
        ;
}

Reference Terminal Output Log

read ID: 0                                      //舵机id
read success, voltage: 8905 mv                 //当前电压
read success, current: 0 ma                    //当前电流
read success, power: 0 mw                      //当前功率
read success, temperature: 32.240993           //当前温度
read success, voltage too high                 //如果当前电压超过舵机参数设置的舵机高压保护值,可以读到标志位
=================================

=== Part 3: Appendix Quick Reference Tables ===


Appendix Table 1: Read-Only Parameter Table

Use this table with the address parameter of the FSUS_ReadData function.

Address Parameter Name Data Type Unit Remarks
1 Voltage uint16_t mV
2 Current uint16_t mA
3 Power uint16_t mW
4 Temperature uint16_t ADC Refer to the [ADC-Temperature Mapping Table]
5 Status Flags uint8_t BIT[0] - set to 1 while command execution is in progress, cleared after execution completes
BIT[1] - set to 1 when command execution fails, cleared after the next correct execution
BIT[2] - set to 1 for stall protection, cleared after stall is resolved
BIT[3] - set to 1 for overvoltage protection, cleared after voltage returns to normal
BIT[4] - set to 1 for undervoltage protection, cleared after voltage returns to normal
BIT[5] - set to 1 for overcurrent protection, cleared after current returns to normal
BIT[6] - set to 1 for power protection, cleared after power returns to normal
BIT[7] - set to 1 for temperature protection, cleared after temperature returns to normal

Appendix Table 2: Custom Parameter Table

Use this table with FSUS_WriteData and FSUS_ReadData.

Address Parameter Name Data Type Unit Remarks
33 Command Response Switch uint8_t 0x00: do not send response packets (default)
0x01: send response packets
34 servo ID uint8_t Range: 0-254
36 Baud Rate Configuration uint8_t 0x01 - 9,600
0x02 - 19,200
0x03 - 38,400
0x04 - 57,600
0x05 - 115,200 (default)
0x06 - 250,000
0x07 - 500,000
0x08 - 1,000,000
37 Stall Protection Switch uint8_t When the servo runs for longer than 功率保护值
0x00: stall protection off, run at the reduced power protection value (default)
0x01: stall protection on, the servo releases torque
38 Stall Power Limit uint16_t mW
39 Voltage Protection Lower Limit uint16_t mV
40 Voltage Protection Upper Limit uint16_t mV
41 Temperature Protection Value uint16_t ADC
42 Power Protection Value uint16_t mW
43 Current Protection Value uint16_t mA
46 servo Power-On Torque Switch uint8_t 0x00: release torque (default) 0x01: maintain torque
48 Angle Limit Switch uint8_t 0x00: disabled (default) 0x01: enabled
49 Power-On Soft Start Switch uint8_t 0x00: disabled (default) 0x01: enabled
50 Power-On Soft Start Time uint16_t ms
51 servo Angle Upper Limit int16_t 0.1°
52 servo Angle Lower Limit int16_t 0.1°

Appendix Table 3: NTC Thermistor ADC Temperature Mapping Conversion Table

The raw data read through address=4 is an ADC digital value. It must be substituted into a logarithmic function to convert it to Celsius. The table below provides common lookup values in the core operating range.

ADC Temperature Reference Table

(The following is a quick lookup mapping table for frequently used 50°C-79°C temperatures and ADC return values.)

Actual Temperature (°C) Raw ADC Actual Temperature (°C) Raw ADC Actual Temperature (°C) Raw ADC
50 1191 60 941 70 741
51 1164 61 918 71 723
52 1137 62 897 72 706
53 1110 63 876 73 689
54 1085 64 855 74 673
55 1059 65 835 75 657
56 1034 66 815 76 642
57 1010 67 796 77 627
58 986 68 777 78 612
59 963 69 759 79 598