STM32 + MODBUS RTU + RS485 实现方案

简介: STM32 + MODBUS RTU + RS485 实现方案

一、系统架构与硬件连接

1.1 硬件连接表

STM32F103C8T6 RS485模块 说明
PA9 (TX1) DI 发送数据
PA10 (RX1) RO 接收数据
PA8 DE/RE 收发控制(高电平发送,低电平接收)
3.3V VCC 电源
GND GND 共地

1.2 MODBUS RTU协议帧格式

[从机地址][功能码][数据起始地址][数据数量/数据值][CRC16校验]
  • 地址:1字节(1-247)
  • 功能码:1字节(03=读保持寄存器,06=写单个寄存器,16=写多个寄存器)
  • 数据:N字节
  • CRC16:2字节(低位在前)

二、代码实现

2.1 头文件(modbus_rtu.h)

#ifndef __MODBUS_RTU_H
#define __MODBUS_RTU_H

#include "stm32f10x.h"

// MODBUS配置
#define MODBUS_SLAVE_ADDR   0x01    // 从机地址
#define MODBUS_BAUDRATE    9600     // 波特率
#define MODBUS_REG_NUM      10      // 寄存器数量

// 功能码定义
#define FUNC_READ_REG      0x03    // 读保持寄存器
#define FUNC_WRITE_SINGLE  0x06    // 写单个寄存器
#define FUNC_WRITE_MULTI  0x10    // 写多个寄存器

// 错误码定义
#define ERR_NONE           0x00     // 无错误
#define ERR_FUNC_CODE     0x01     // 非法功能码
#define ERR_REG_ADDR      0x02     // 非法数据地址
#define ERR_REG_VALUE     0x03     // 非法数据值

// 全局变量
extern uint16_t modbus_regs[MODBUS_REG_NUM];  // MODBUS寄存器数组
extern uint8_t modbus_rx_buf[256];            // 接收缓冲区
extern uint8_t modbus_tx_buf[256];            // 发送缓冲区
extern uint8_t modbus_rx_len;                 // 接收长度
extern uint8_t modbus_frame_flag;              // 帧接收完成标志

// 函数声明
void MODBUS_Init(void);
void MODBUS_ProcessFrame(void);
void MODBUS_SendResponse(uint8_t *data, uint8_t len);
uint16_t CRC16_Calculate(uint8_t *data, uint16_t len);
void MODBUS_UpdateDisplay(void);

#endif /* __MODBUS_RTU_H */

2.2 主程序(main.c)

#include "stm32f10x.h"
#include "modbus_rtu.h"
#include "usart.h"
#include "delay.h"
#include "lcd.h"

// MODBUS寄存器数据
uint16_t modbus_regs[MODBUS_REG_NUM] = {
   
    0x1234, 0x5678, 0x9ABC, 0xDEF0, 0x1111,
    0x2222, 0x3333, 0x4444, 0x5555, 0x6666
};

// 通信缓冲区
uint8_t modbus_rx_buf[256];
uint8_t modbus_tx_buf[256];
uint8_t modbus_rx_len = 0;
uint8_t modbus_frame_flag = 0;

// 系统状态显示
typedef struct {
   
    uint32_t rx_count;       // 接收帧计数
    uint32_t tx_count;       // 发送帧计数
    uint16_t last_reg_addr;   // 最后操作的寄存器地址
    uint16_t last_reg_value;  // 最后操作的寄存器值
    uint8_t last_func_code;   // 最后功能码
} SystemStatus;

SystemStatus sys_status = {
   0};

int main(void)
{
   
    // 系统初始化
    SystemInit();
    Delay_Init();
    USART1_Init(9600);  // MODBUS通信串口
    USART2_Init(115200); // 调试输出串口
    LCD_Init();          // LCD显示屏

    printf("STM32 MODBUS RTU Slave Starting...\r\n");
    LCD_ShowString(0, 0, "MODBUS RTU Slave");
    LCD_ShowString(0, 20, "Addr: 0x01 Baud: 9600");

    // MODBUS初始化
    MODBUS_Init();

    uint32_t last_display_update = 0;

    while(1)
    {
   
        // 处理MODBUS帧
        if(modbus_frame_flag)
        {
   
            MODBUS_ProcessFrame();
            modbus_frame_flag = 0;
            modbus_rx_len = 0;
        }

        // 每秒更新显示
        if(millis() - last_display_update > 1000)
        {
   
            MODBUS_UpdateDisplay();
            last_display_update = millis();
        }

        Delay_ms(10);
    }
}

2.3 MODBUS核心实现(modbus_rtu.c)

#include "modbus_rtu.h"
#include "string.h"

// GPIO控制RS485收发
#define RS485_TX_EN()   GPIO_SetBits(GPIOA, GPIO_Pin_8)   // PA8高电平,发送模式
#define RS485_RX_EN()   GPIO_ResetBits(GPIOA, GPIO_Pin_8) // PA8低电平,接收模式

/**
  * @brief  MODBUS初始化
  */
void MODBUS_Init(void)
{
   
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    // 1. 使能时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    // 2. 配置RS485收发控制引脚(PA8)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    RS485_RX_EN();  // 默认接收模式

    // 3. 配置USART1引脚(PA9-TX, PA10-RX)
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    // 4. USART参数配置
    USART_InitStructure.USART_BaudRate = MODBUS_BAUDRATE;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART1, &USART_InitStructure);

    // 5. 使能接收中断
    USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);

    // 6. NVIC配置
    NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    // 7. 使能USART
    USART_Cmd(USART1, ENABLE);

    printf("MODBUS RTU Initialized: Addr=0x%02X, Baud=%d\r\n", 
           MODBUS_SLAVE_ADDR, MODBUS_BAUDRATE);
}

/**
  * @brief  CRC16计算
  * @param  data: 数据指针
  * @param  len: 数据长度
  * @retval CRC16校验值
  */
uint16_t CRC16_Calculate(uint8_t *data, uint16_t len)
{
   
    uint16_t crc = 0xFFFF;
    uint16_t i, j;

    for(i = 0; i < len; i++)
    {
   
        crc ^= data[i];
        for(j = 0; j < 8; j++)
        {
   
            if(crc & 0x0001)
            {
   
                crc >>= 1;
                crc ^= 0xA001;  // MODBUS CRC多项式
            }
            else
            {
   
                crc >>= 1;
            }
        }
    }
    return crc;
}

/**
  * @brief  发送MODBUS响应
  * @param  data: 发送数据指针
  * @param  len: 数据长度
  */
void MODBUS_SendResponse(uint8_t *data, uint8_t len)
{
   
    uint16_t crc;

    // 切换到发送模式
    RS485_TX_EN();
    Delay_us(10);

    // 发送数据
    for(uint8_t i = 0; i < len; i++)
    {
   
        USART_SendData(USART1, data[i]);
        while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET);
    }

    // 等待发送完成
    while(USART_GetFlagStatus(USART1, USART_FLAG_TC) == RESET);

    // 切换回接收模式
    Delay_us(10);
    RS485_RX_EN();

    sys_status.tx_count++;
}

/**
  * @brief  处理MODBUS帧
  */
void MODBUS_ProcessFrame(void)
{
   
    uint8_t slave_addr = modbus_rx_buf[0];
    uint8_t func_code = modbus_rx_buf[1];
    uint16_t crc_received, crc_calculated;

    // 检查从机地址
    if(slave_addr != MODBUS_SLAVE_ADDR && slave_addr != 0x00)
    {
   
        return;  // 不是发给本机的帧
    }

    // 检查CRC
    crc_received = (modbus_rx_buf[modbus_rx_len-1] << 8) | modbus_rx_buf[modbus_rx_len-2];
    crc_calculated = CRC16_Calculate(modbus_rx_buf, modbus_rx_len-2);

    if(crc_received != crc_calculated)
    {
   
        printf("CRC Error: Received=0x%04X, Calculated=0x%04X\r\n", 
               crc_received, crc_calculated);
        return;
    }

    sys_status.last_func_code = func_code;
    sys_status.rx_count++;

    printf("RX Frame: ");
    for(uint8_t i = 0; i < modbus_rx_len; i++)
    {
   
        printf("%02X ", modbus_rx_buf[i]);
    }
    printf("\r\n");

    // 处理不同功能码
    switch(func_code)
    {
   
        case FUNC_READ_REG:  // 读保持寄存器
            Handle_ReadRegisters();
            break;

        case FUNC_WRITE_SINGLE:  // 写单个寄存器
            Handle_WriteSingleRegister();
            break;

        case FUNC_WRITE_MULTI:  // 写多个寄存器
            Handle_WriteMultipleRegisters();
            break;

        default:  // 非法功能码
            Send_ExceptionResponse(ERR_FUNC_CODE);
            break;
    }
}

/**
  * @brief  处理读寄存器请求
  */
void Handle_ReadRegisters(void)
{
   
    uint16_t start_addr = (modbus_rx_buf[2] << 8) | modbus_rx_buf[3];
    uint16_t reg_count = (modbus_rx_buf[4] << 8) | modbus_rx_buf[5];
    uint8_t resp_len = 0;
    uint16_t crc;

    // 检查地址合法性
    if(start_addr >= MODBUS_REG_NUM || 
       start_addr + reg_count > MODBUS_REG_NUM)
    {
   
        Send_ExceptionResponse(ERR_REG_ADDR);
        return;
    }

    // 构建响应帧
    modbus_tx_buf[resp_len++] = MODBUS_SLAVE_ADDR;
    modbus_tx_buf[resp_len++] = FUNC_READ_REG;
    modbus_tx_buf[resp_len++] = reg_count * 2;  // 字节数

    // 添加寄存器数据
    for(uint16_t i = 0; i < reg_count; i++)
    {
   
        modbus_tx_buf[resp_len++] = (modbus_regs[start_addr + i] >> 8) & 0xFF;
        modbus_tx_buf[resp_len++] = modbus_regs[start_addr + i] & 0xFF;
    }

    // 计算CRC
    crc = CRC16_Calculate(modbus_tx_buf, resp_len);
    modbus_tx_buf[resp_len++] = crc & 0xFF;
    modbus_tx_buf[resp_len++] = (crc >> 8) & 0xFF;

    // 发送响应
    MODBUS_SendResponse(modbus_tx_buf, resp_len);

    sys_status.last_reg_addr = start_addr;
    sys_status.last_reg_value = modbus_regs[start_addr];

    printf("Read Registers: Addr=%d, Count=%d\r\n", start_addr, reg_count);
}

/**
  * @brief  处理写单个寄存器请求
  */
void Handle_WriteSingleRegister(void)
{
   
    uint16_t reg_addr = (modbus_rx_buf[2] << 8) | modbus_rx_buf[3];
    uint16_t reg_value = (modbus_rx_buf[4] << 8) | modbus_rx_buf[5];
    uint8_t resp_len = 0;
    uint16_t crc;

    // 检查地址合法性
    if(reg_addr >= MODBUS_REG_NUM)
    {
   
        Send_ExceptionResponse(ERR_REG_ADDR);
        return;
    }

    // 写入寄存器
    modbus_regs[reg_addr] = reg_value;

    // 回显相同的数据作为响应
    memcpy(modbus_tx_buf, modbus_rx_buf, 6);
    resp_len = 6;

    // 计算CRC
    crc = CRC16_Calculate(modbus_tx_buf, resp_len);
    modbus_tx_buf[resp_len++] = crc & 0xFF;
    modbus_tx_buf[resp_len++] = (crc >> 8) & 0xFF;

    // 发送响应
    MODBUS_SendResponse(modbus_tx_buf, resp_len);

    sys_status.last_reg_addr = reg_addr;
    sys_status.last_reg_value = reg_value;

    printf("Write Register: Addr=%d, Value=0x%04X\r\n", reg_addr, reg_value);
}

/**
  * @brief  发送异常响应
  */
void Send_ExceptionResponse(uint8_t error_code)
{
   
    uint8_t resp_len = 0;
    uint16_t crc;

    modbus_tx_buf[resp_len++] = MODBUS_SLAVE_ADDR;
    modbus_tx_buf[resp_len++] = 0x80 | modbus_rx_buf[1];  // 错误响应功能码
    modbus_tx_buf[resp_len++] = error_code;

    crc = CRC16_Calculate(modbus_tx_buf, resp_len);
    modbus_tx_buf[resp_len++] = crc & 0xFF;
    modbus_tx_buf[resp_len++] = (crc >> 8) & 0xFF;

    MODBUS_SendResponse(modbus_tx_buf, resp_len);

    printf("Exception Response: Error Code=%d\r\n", error_code);
}

/**
  * @brief  更新显示
  */
void MODBUS_UpdateDisplay(void)
{
   
    char display_buf[32];

    LCD_ShowString(0, 40, "MODBUS Status:");

    sprintf(display_buf, "RX: %lu TX: %lu", sys_status.rx_count, sys_status.tx_count);
    LCD_ShowString(0, 60, display_buf);

    sprintf(display_buf, "Func: 0x%02X", sys_status.last_func_code);
    LCD_ShowString(0, 80, display_buf);

    sprintf(display_buf, "Reg[%d]: 0x%04X", 
            sys_status.last_reg_addr, sys_status.last_reg_value);
    LCD_ShowString(0, 100, display_buf);

    // 显示部分寄存器值
    sprintf(display_buf, "R0:%04X R1:%04X", modbus_regs[0], modbus_regs[1]);
    LCD_ShowString(0, 120, display_buf);
}

2.4 串口中断处理(stm32f10x_it.c)

#include "stm32f10x_it.h"
#include "modbus_rtu.h"

extern uint8_t modbus_rx_buf[];
extern uint8_t modbus_rx_len;
extern uint8_t modbus_frame_flag;

// 帧超时检测(3.5个字符时间)
#define FRAME_TIMEOUT   (3500000 / MODBUS_BAUDRATE)  // 微秒

void USART1_IRQHandler(void)
{
   
    static uint32_t last_rx_time = 0;
    uint8_t data;

    if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)
    {
   
        data = USART_ReceiveData(USART1);

        // 检查缓冲区是否溢出
        if(modbus_rx_len < sizeof(modbus_rx_buf))
        {
   
            modbus_rx_buf[modbus_rx_len++] = data;
        }

        // 更新最后接收时间
        last_rx_time = micros();

        // 清除中断标志
        USART_ClearITPendingBit(USART1, USART_IT_RXNE);
    }

    // 在主循环中检查帧超时
    if(modbus_rx_len > 0 && (micros() - last_rx_time) > FRAME_TIMEOUT)
    {
   
        modbus_frame_flag = 1;
    }
}

2.5 调试串口输出(usart.c)

#include "usart.h"
#include <stdarg.h>
#include <stdio.h>

// 重定向printf到USART2
int fputc(int ch, FILE *f)
{
   
    USART_SendData(USART2, (uint8_t)ch);
    while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
    return ch;
}

void USART2_Init(uint32_t baudrate)
{
   
    GPIO_InitTypeDef GPIO_InitStructure;
    USART_InitTypeDef USART_InitStructure;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);

    // PA2-TX, PA3-RX
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
    GPIO_Init(GPIOA, &GPIO_InitStructure);

    USART_InitStructure.USART_BaudRate = baudrate;
    USART_InitStructure.USART_WordLength = USART_WordLength_8b;
    USART_InitStructure.USART_StopBits = USART_StopBits_1;
    USART_InitStructure.USART_Parity = USART_Parity_No;
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
    USART_Init(USART2, &USART_InitStructure);

    USART_Cmd(USART2, ENABLE);
}

三、测试工具与验证

3.1 PC端测试工具

  1. Modbus Poll(Windows)

    • 连接:选择COM口,波特率9600,RTU模式
    • 功能码03:读取寄存器
    • 功能码06:写入单个寄存器
  2. QModMaster(跨平台)

    • 开源MODBUS主站工具
    • 支持RTU/TCP

3.2 测试步骤

  1. 连接硬件:STM32通过RS485模块连接到PC

  2. 启动从机:STM32运行MODBUS从机程序

  3. 发送测试帧

    读寄存器:01 03 00 00 00 01 84 0A
    (从机地址01,功能码03,起始地址0000,读取1个寄存器)
    
  4. 观察响应

    响应帧:01 03 02 12 34 B5 33
    (从机地址01,功能码03,字节数2,数据1234,CRC校验)
    

3.3 LCD显示效果

MODBUS RTU Slave
Addr: 0x01 Baud: 9600
MODBUS Status:
RX: 125 TX: 124
Func: 0x03
Reg[0]: 0x1234
R0:1234 R1:5678

四、常见问题解决

现象 原因 解决方案
无响应 地址不匹配 检查从机地址设置
CRC错误 波特率不一致 确认双方波特率相同
数据错乱 收发切换延迟不足 增加RS485收发切换延时
丢帧 中断处理不及时 优化中断服务程序
显示乱码 LCD初始化问题 检查LCD引脚连接

参考代码 STM32+MODEBUS+485代码,串口发送,实时显示 www.youwenfan.com/contentali/56209.html

五、扩展功能建议

5.1 增加更多功能码

// 增加04功能码(读输入寄存器)
case 0x04:
    Handle_ReadInputRegisters();
    break;

// 增加05功能码(写单个线圈)
case 0x05:
    Handle_WriteSingleCoil();
    break;

5.2 数据记录与报警

// 监控寄存器变化
if(modbus_regs[0] > 0xFF00)
{
   
    // 触发报警
    GPIO_SetBits(GPIOB, GPIO_Pin_0);  // 蜂鸣器报警
    printf("Alarm Triggered! Value=0x%04X\r\n", modbus_regs[0]);
}

5.3 多从机支持

// 支持广播地址0x00
if(slave_addr == MODBUS_SLAVE_ADDR || slave_addr == 0x00)
{
   
    // 处理广播命令
    Process_BroadcastCommand();
}

六、总结

这套STM32+MODBUS+RS485方案具有以下特点:

完整协议实现:支持03/06/16功能码
实时数据显示:LCD实时显示通信状态
稳定可靠:CRC校验、超时检测、错误处理
易于扩展:模块化设计,方便添加新功能

应用场景

  • 工业自动化控制系统
  • 智能仪表数据采集
  • 楼宇自动化系统
  • 远程监控系统
相关文章
|
1月前
|
数据采集 JSON API
抖音商品详情API 实战总结(技术复盘)
本文复盘抖音商品详情API(douyin.item_get)实战经验,涵盖鉴权、风控、token管理等关键问题,优化请求队列与重试机制。支持抖音小店/精选联盟商品结构化采集,返回基础信息、价格规格、多媒体、销售及评价五大模块,稳定高效,适配电商采集中台。
|
1月前
|
机器学习/深度学习 数据采集 人工智能
田间杂草检测数据集分享(适用于YOLO系列深度学习分类检测任务)
本数据集含4000张真实农田图像(小麦/玉米/水稻田),YOLO格式标注杂草目标,覆盖多天气、光照与视角,适用于YOLO系列等目标检测模型训练,助力智能除草与精准农业研究。(239字)
381 16
|
1月前
|
SQL 人工智能 数据可视化
JimuReport 积木报表 v2.3.4 版本发布,免费的可视化 AI 报表
JimuReport AI专题研究 JimuReport积木报表 v2.3.4 版本发布说明与积木 Skills 快速使用指南 项目介绍 免费的 AI 可视化报表。一句话描述需求,AI 自动生成报表与数据大屏;同时提供类 Excel 拖拽设计器,兼容 30 余种数据源,轻松应对各类复杂报表场景
368 0
|
1月前
|
SQL 安全 程序员
《ZAKU渗透论:卓伊凡的2026渗透工程》第三章:Web攻击原理(上)——注入与SQL注入
本章详解Web攻击核心——注入与SQL注入。通过“小明输入‘小明’OR‘1’=‘1’秒变管理员”的生动案例,揭示攻击本质:程序混淆数据与代码,导致恶意SQL被执行。深入剖析万能密码、数据窃取、权限绕过等危害,并指出漏洞长期存在的根源:历史代码、意识不足与修复成本。
295 2
|
1月前
|
编解码 自然语言处理 文字识别
HiDream-O1开源:8B参数像素级统一Transformer
HiDream-O1-Image是HiDream.ai开源的8B参数像素级统一生成模型,摒弃VAE与分离文本编码器,首创UiT架构实现文本、图像、任务条件在共享token空间端到端联合建模。支持2048×2048高清生成、多镜头/多语言渲染、指令编辑与主体个性化,在GenEval等基准刷新SOTA。含50步未蒸馏版与28步Dev加速版,并集成推理驱动提示代理。
607 0
|
1月前
|
SQL 监控 关系型数据库
数据库三大日志深度解析:Redo Log、Binlog、Undo Log 如何守护你的数据
本文由“数据库小学妹”带你厘清MySQL三大核心日志:Redo Log(引擎层物理日志,保障crash-safe)、Undo Log(支撑回滚与MVCC)和Binlog(Server层逻辑日志,用于复制与恢复),详解WAL机制与两阶段提交原理,助你真正理解事务安全底层逻辑。
|
1月前
|
人工智能 缓存 运维
CC Switch路由代理技术解析:Codex CLI无缝对接DeepSeek模型实操指南
在现代AI开发与命令行智能编程场景中,Codex CLI是开发者常用的命令行智能辅助工具,能够实现代码生成、问题排查、脚本编写、项目调试等自动化能力。但原生Codex CLI存在明显的适配局限,其底层仅兼容OpenAI Responses API协议,无法直接对接DeepSeek等主流第三方大模型。市面上绝大多数第三方开源、商用大模型均采用Chat Completions API协议,两种协议在请求结构、参数格式、流式返回规则、响应字段定义上完全不互通,直接填写第三方模型接口地址会出现接口404报错、参数解析失败、流式内容中断、模型列表加载异常等各类问题,极大限制了Codex CLI的模型拓展
673 1
|
1月前
|
域名解析 数据采集 运维
Vsping在线Ping:全域网络探测技术与链路稳定性检测解析
Vsping在线Ping是一款轻量级云端网络诊断工具,依托全域分布式节点,支持多地域、多运营商同步Ping探测,无需安装、一键操作。可精准定位延迟、丢包、区域性访问异常等故障,适用于个人自查、远程办公、网站运维及服务器优化,全面提升网络排查效率与稳定性。(239字)
416 0
|
1月前
|
域名解析 数据采集 运维
Vsping在线Ping:网络链路稳定性监测与深度故障运维排查方案
Vsping在线Ping是一款云端多节点网络诊断工具,突破传统本地Ping局限,支持电信/联通/移动全网覆盖及跨境探测。一键检测延迟、丢包、连通性,可视化呈现结果,零门槛操作,精准定位故障归属,适用于个人自查与企业运维全场景。(239字)
327 0
|
1月前
|
监控 API Windows
WGCLOUD v3.6.8 正式更新
WGCLOUD v3.6.8发布:修复CPU/内存等指标偶现为0、大屏离线数据不显示等Bug;新增Windows系统服务列表及开放API;优化告警脚本执行与SNMP设备运行时间兼容性。升级方式详见官方图示。