深入解析‘mavlink_status_t‘未声明错误:从ROS编译到MAVLink协议适配

mavlink的入门资料;适合纯粹的mavlink小白 mavlink的入门资料;适合纯粹的mavlink小白,配合笔者的博文介绍,助你理解深入理解mavlink协议。 尊重原著未删减,原名叫“MavLink Tutorial for Absolute Dummies (Part –I)” 支持开源,不要资源分。 立即下载

1. 理解'mavlink_status_t'未声明错误的本质

最近在ROS环境下编译rotors_simulator时,不少开发者遇到了一个让人头疼的错误:'mavlink_status_t' has not been declared。这个错误通常出现在编译rotors_hil_interface包时,系统提示在mavlink_msg_protocol_version.h文件中找不到mavlink_status_t的定义。

这个错误的核心在于类型声明缺失。mavlink_status_t是MAVLink协议中用于跟踪通信状态的重要数据结构,它包含了消息解析状态、丢包统计、通信质量等关键信息。在MAVLink v2.0协议中,这个类型被定义在mavlink_types.h头文件中,但如果在包含头文件的顺序或条件编译上出现问题,编译器就无法找到这个类型的定义。

我实际遇到过这种情况,当时正在开发一个基于ROS和PX4的无人机仿真项目。编译过程中突然报出这个错误,让我一度怀疑是不是MAVLink库安装有问题。经过仔细排查,发现问题的根源并不在MAVLink库本身,而是在于rotors_hil_interface包中的头文件包含策略。

这种错误特别容易发生在混合使用不同版本的MAVLink库或者在不同模块间传递MAVLink消息时。因为mavlink_status_t类型在协议中扮演着重要角色,它确保了消息的完整性和可靠性。当编译器无法识别这个类型时,就意味着整个MAVLink通信链路可能无法正常工作。

2. 深入分析错误产生的根本原因

让我们仔细看看这个错误的具体表现。编译错误信息指向了mavlink_msg_protocol_version.h文件中的两个函数:mavlink_msg_protocol_version_encode_status和mavlink_msg_protocol_version_pack_status。这两个函数都需要mavlink_status_t类型的参数,但编译器却找不到这个类型的定义。

问题的根源在于头文件的包含顺序和条件编译宏的定义。在rotors_hil_interface.h文件中,原有的代码是这样的:

#ifndef MAVLINK_H
typedef mavlink::mavlink_message_t mavlink_message_t;
#include <mavlink/v2.0/common/mavlink.h>
#endif

这里使用了条件编译宏MAVLINK_H来避免重复包含,但只对mavlink_message_t进行了类型重定义,却没有处理mavlink_status_t。当编译器处理到mavlink_msg_protocol_version.h文件时,由于MAVLINK_H已经被定义,后续的mavlink.h包含被跳过,导致mavlink_status_t类型没有被正确引入。

我在实际项目中还发现,这个问题可能与MAVLink协议版本有关。MAVLINK_MSG_ID_PROTOCOL_VERSION是MAVLink v2.0协议中引入的消息类型,用于协商通信双方使用的协议版本。如果系统中存在多个版本的MAVLink库,或者编译时链接了不匹配的头文件,就容易出现这种类型声明缺失的错误。

另一个可能的原因是编译器的包含路径设置问题。ROS系统通常会自动设置一系列包含路径,但有时候自定义的编译配置可能会干扰这个过程。特别是在使用catkin_make与catkin build混合编译时,容易出现头文件查找路径的混乱。

3. MAVLink协议版本兼容性深度解析

MAVLink协议版本的兼容性问题往往是这类错误的潜在根源。MAVLink v2.0相比v1.0有了显著的变化,不仅增加了新的消息类型如MAVLINK_MSG_ID_PROTOCOL_VERSION,还引入了更严格的类型检查和扩展机制。

protocol_version消息是v2.0协议中的重要组成部分,它允许通信双方协商使用的协议版本和特性。这个消息的编码和解码函数需要mavlink_status_t类型来跟踪处理状态,这就是为什么在mavlink_msg_protocol_version.h中会频繁使用这个类型。

在实际开发中,我遇到过因为协议版本不匹配导致的各种奇怪问题。有一次,我使用的MAVLink库是v2.0版本,而某个依赖包却期望使用v1.0的API,结果就出现了类似的类型声明错误。这种问题往往很难直接从错误信息中看出根源,需要仔细检查各个组件的版本兼容性。

typedef在MAVLink协议中扮演着关键角色,它提供了平台无关的类型定义。mavlink_status_t实际上是通过typedef定义的类型别名,在不同的平台上可能有不同的具体实现。这种设计提高了代码的可移植性,但也增加了编译时类型解析的复杂性。

为了解决版本兼容性问题,我建议在项目开始时就明确指定使用的MAVLink版本,并确保所有依赖包都使用相同的版本。可以使用rosdep工具来统一管理依赖版本,或者在CMakeLists.txt中显式指定需要的MAVLink版本。

4. 完整的解决方案实施步骤

根据原始文章提供的解决方案,我们需要修改rotors_hil_interface包中的头文件。具体路径是:rotors_simulator/rotors_hil_interface/include/rotors_hil_interface/hil_interface.h

修改前的代码:

#ifndef MAVLINK_H
typedef mavlink::mavlink_message_t mavlink_message_t;
#include <mavlink/v2.0/common/mavlink.h>
#endif

修改后的代码:

#ifndef MAVLINK_H
typedef mavlink::mavlink_message_t mavlink_message_t;
typedef mavlink::mavlink_status_t mavlink_status_t;
#include <mavlink/v2.0/common/mavlink.h>
#endif

这个解决方案的核心在于添加了mavlink_status_t的类型重定义。通过提前声明这个类型,确保编译器在处理mavlink_msg_protocol_version.h时已经知道mavlink_status_t的存在。

我在实施这个解决方案时,建议按照以下步骤操作:

首先备份原始文件,这是一个好习惯:

cp rotors_simulator/rotors_hil_interface/include/rotors_hil_interface/hil_interface.h rotors_simulator/rotors_hil_interface/include/rotors_hil_interface/hil_interface.h.bak

然后使用文本编辑器打开文件进行修改。我更喜欢使用vim或nano这样的命令行编辑器,但在ROS开发中也可以使用ROS专用的IDE如Qt Creator或VS Code with ROS插件。

修改完成后,需要重新编译项目:

cd ~/catkin_ws
catkin_make clean
catkin_make

如果使用catkin build工具,命令略有不同:

cd ~/catkin_ws
catkin clean
catkin build

在重新编译过程中,要特别注意观察是否有其他相关的错误出现。有时候解决一个错误会暴露出其他隐藏的问题,这是很正常的调试过程。

5. 预防类似错误的开发最佳实践

为了避免今后再遇到类似的编译错误,我总结了一些开发最佳实践。首先是在使用外部库时,要特别注意头文件的包含顺序和条件编译宏的使用。条件编译宏虽然能避免重复包含,但也容易导致类型声明缺失的问题。

我建议在编写头文件时,采用统一的包含策略。对于MAVLink这样的库,可以在一个统一的头文件中处理所有必要的类型重定义和包含操作。例如:

#ifndef MAVLINK_WRAPPER_H
#define MAVLINK_WRAPPER_H

#ifndef MAVLINK_H
// 提前声明所有需要的MAVLink类型
typedef mavlink::mavlink_message_t mavlink_message_t;
typedef mavlink::mavlink_status_t mavlink_status_t;
typedef mavlink::mavlink_heartbeat_t mavlink_heartbeat_t;
// 其他需要的类型...

#include <mavlink/v2.0/common/mavlink.h>
#endif

// 项目特定的MAVLink相关声明和函数

#endif // MAVLINK_WRAPPER_H

另一个重要实践是保持开发环境的一致性。在使用ROS进行开发时,尽量使用相同版本的ROS发行版和MAVLink库。可以通过rosdep工具来自动安装依赖,确保团队所有成员使用相同的库版本。

在CMakeLists.txt中,可以显式指定需要的MAVLink版本和包含路径:

find_package(MAVLink REQUIRED)
include_directories(
  ${MAVLink_INCLUDE_DIRS}
  # 其他包含目录...
)

对于大型项目,我建议建立持续的集成测试流程。每次代码提交后自动编译整个项目,这样可以及早发现兼容性问题和编译错误。使用Docker容器来标准化编译环境也是很好的选择。

最后,保持良好的文档习惯。在项目的README文件中记录使用的库版本和特殊的编译配置,这样新加入项目的开发者能够快速搭建正确的开发环境。

6. 深入理解MAVLink消息处理机制

要彻底解决这类编译错误,还需要深入理解MAVLink的消息处理机制。mavlink_status_t类型在MAVLink通信中扮演着至关重要的角色,它负责跟踪每个通信通道的状态信息。

mavlink_status_t结构体通常包含以下重要字段:

  • msg_received:已接收到的消息数量
  • buffer_overrun:缓冲区溢出次数
  • parse_error:解析错误计数
  • packet_rx_drop_count:丢包计数
  • packet_rx_success_count:成功接收包计数

这些统计信息对于监控通信质量和调试通信问题非常有用。在实际项目中,我经常通过检查这些状态信息来诊断通信问题。

MAVLink的消息编码和解码函数使用mavlink_status_t来保持解析状态。例如,当处理分段传输的大型消息时,mavlink_status_t会保存中间状态,确保消息能够正确重组。

理解了这个机制,就能明白为什么mavlink_msg_protocol_version_encode_status和mavlink_msg_protocol_version_pack_status函数需要mavlink_status_t参数。这些函数不仅需要编码消息内容,还需要更新通信状态信息。

在自定义MAVLink消息处理时,确保正确初始化和使用mavlink_status_t变量很重要。我通常会在通信初始化阶段创建status变量,并在整个通信生命周期内保持使用同一个实例。

mavlink_status_t status;
mavlink_init_status(&status);

// 在消息处理循环中
while (receive_data()) {
    mavlink_message_t msg;
    if (mavlink_parse_char(channel, byte, &msg, &status)) {
        // 处理完整消息
        handle_mavlink_message(&msg);
    }
}

这种模式确保了通信状态的连续性,对于维持稳定的MAVLink通信至关重要。

7. ROS与MAVLink集成开发经验分享

在ROS项目中集成MAVLink时,我积累了一些实用经验。首先要注意ROS消息与MAVLink消息的转换机制。虽然有些ROS包提供了自动转换功能,但理解底层的转换过程对于调试问题很有帮助。

我建议在开发初期就建立清晰的消息流架构。确定哪些消息需要从MAVLink转换到ROS,哪些需要反向转换,以及转换的频率和时机。这有助于避免不必要的性能开销和消息延迟。

在实际项目中,我发现使用mavros包可以大大简化ROS与MAVLink的集成。mavros提供了丰富的功能,包括消息转换、参数管理和航点规划等。但是要注意mavros的版本兼容性,确保与使用的MAVLink版本匹配。

对于性能要求较高的应用,可以考虑直接使用MAVLink C库而不是通过mavros。这样减少了中间层,提高了消息处理效率。但是需要自行处理更多的底层细节,包括消息序列化、状态管理和错误处理等。

调试MAVLink通信时,我经常使用mavlink Inspector工具来监控消息流。这个工具可以显示所有正在传输的MAVLink消息,帮助识别通信问题和分析消息内容。

另一个有用的技巧是记录MAVLink通信日志。可以在代码中添加日志记录功能,保存重要的通信事件和状态变化。这些日志在分析偶发的通信问题时特别有价值。

最后,不要忽视硬件层面的影响。在我遇到的一些案例中,看似软件层面的编译错误实际上是由硬件兼容性问题引起的。确保使用的飞控硬件、通信模块和驱动程序都完全兼容使用的MAVLink版本。

Ubuntu20.04/Debian10安装向日葵远程控制踩坑实录(附依赖问题解决方案) 本文详细介绍了在Ubuntu 20.04/Debian 10系统上安装向日葵远程控制软件的全过程,重点解决了常见的依赖问题,特别是libwebkitgtk相关错误。通过自动修复、手动修改.deb包依赖和使用兼容层三种解决方案,帮助用户顺利完成安装并优化远程控制体验。 阅读详情

相关推荐

Cursor Agent模式下如何优雅切换conda环境运行Python脚本?3种实用方法实测

本文针对Cursor Agent模式下运行Python脚本时环境错配的痛点,实测了三种优雅切换conda环境的实用方法。通过Shell全局配置、项目级.cursorrc文件定制以及对话中直接指令,开发者可以确保AI助手在正确的虚拟环境中执行代码,从而提升开发效率和协作流畅度。

redis7keeper的博客 597

error: ‘mavlink_status_t’ has not been declared

找到rotors_simulator/rotors_hil_interface/include/rotors_hil_interface/hil_interface.h。别的都不用动,我是用ros自带的mavlink编译的,这样改了就好了。加入一句typedef。

qq_39743953的博客 1019

Springboot + vue 实现导出word

Springboot + vue 实现导出word 后端代码 使用word先创建好已知的模板 使用word工具另存为.xml格式的文件 使用freemarker ftl模板 将修改后的xml文件复制到开发工具中,将文件后缀修改为ftl文件,并且将里面的动态值使用${}包裹例如:${zyjn} word工具类 /*** * * Project Name:maventest * <p>生成word工具类<br> * * @ClassName: WordUtil *

qq_45542373的博客 2895

rotors编译报错

rotors编译报错 本博客参考https://blog.youkuaiyun.com/qq_41628231/article/details/86534591 在此致谢! 部分错误如下: catkin_ws/src/rotors_simulator-master/rotors_hil_interface/include/rotors_hil_interface/hil_interface.h:105:3: ...

jywucamille的博客 721

Android息屏后台任务保活实战:从定时器失效到厂商白名单破解

本文深入探讨了Android应用在息屏后定时任务失效的根源,即系统为省电而触发的休眠机制。文章提供了从传统方案失效分析到实战破解的完整路径,核心在于引导用户将应用加入电池优化白名单并开启自启动权限,从而合法绕过限制。同时,结合WorkManager、AlarmManager等可靠定时方案,实现稳定的后台任务执行。

weixin_28475533的博客 422

PCB布局布线要求及多层电路板叠加原则

例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。提示:以下是本篇文章正文内容,下面案例可供参考本文主要针对PCB布局布线中的要点进行了总结,并对多层电路板的叠加原则进行了解释。

Ka_wyb的博客 2934

error has not been declared错误原因总结

可能忘了在使用Class的文件中包含class.h,也就是忘了加头文件。 可能Class名称写错了,或者头文件名写错了,少写、大小写。 忘记修改保护#define的名称。 命名空间是否有错误,没有在命名空间内或者命名空间错误。 可能正在使用模板,而不希望两阶段查找按其方式工作。 可能已经使Class成为仅在包含Class.h之后才定义的宏,在这种情况下,看到的Class被宏预处理器替换为其他宏。 可能已经在问题文件.h以外的头文件中定义了问题类,然后问题类.h实际上定义了其他内容。 ...

m0_37854651的博客 4万+

13、多实例任务(multi instance)

多实例任务,是指一个类型的任务需要循环执行多次,包括串行多实例任务和并行多实例任务。

leyoliu的博客 3203

MavLink通信协议 C++应用详细教程

MavLink C++应用教程 0.前言 网上的各类MavLink通信协议教程,往往只对协议本身进行介绍,而不对开发中如何应用进行详述。有介绍应用的往往也都浅尝辄止,讲完HeartBeat然后就让你自己触类旁通。笔者在自学时遇到了不少困难,一步步摸爬滚打后,总算对其有了一定的认识,在这里将心得与大家分享。 如果你读到这篇博文,说明你至少已经对MavLink有了一定了解,其各种特征笔者就不再赘述了,但是值得一提的是,MavLink通信协议是与通信方式密切相关的,本文仅介绍MavLink协议的应用,并不会介绍通

kolento的博客 1万+

爬取B站评论+AI情感分析:Python批量抓数据+BERT正负向分类(全流程)

B站作为年轻群体聚集的内容平台,评论区蕴含海量用户真实态度(如好评、吐槽、中立观点),是情感分析的优质数据源!本文分享完整流程:批量爬取B站视频评论→数据清洗去噪→BERT模型情感分类→可视化分析,基于预训练BERT模型实现高精度正负向判断,新手也能快速复刻情感分析系统! 前置配置(关键!获取B站API访问权限) B站评论通过官方API接口返回,无需复杂解析,只需配置用户Cookie即可正常请求: 2. 完整代码(直接复制运行) 三、使用步骤(5步搞定,新手友好) 步骤1:配置关键参数 打开,在类中修改

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1068

6、SAP HANA 建模全解析

本文全面解析了 SAP HANA 建模的核心内容,包括属性视图、分析视图和计算视图的创建与使用。文章详细介绍了建模工具的安装、不同视图类型的适用场景及操作步骤,并通过对比和案例分析帮助读者更好地理解建模流程。此外,还涵盖了建模过程中的注意事项及性能优化建议,为 SAP HANA 用户提供实用的建模指导。

juice的博客 203

【无标题】

error has not been declared 报错分析

lin287631983的博客 989

51单片机 DHT11温湿度传感器LCD显示+串口打印+Proteus仿真

DHT11+LCD1602+串口输出+Proteus仿真

perseverance51博客 7198

解决ROS Noetic下rotors_simulator编译错误:‘mavlink_status_t‘未声明的实战指南

本文提供了在ROS Noetic环境下解决rotors_simulator编译错误'mavlink_status_t未声明'的实战指南。通过分析MAVLink命名空间冲突问题,给出在hil_interface.h中添加typedef mavlink::mavlink_status_t mavlink_status_t的具体解决方案,帮助开发者快速修复编译错误并顺利完成无人机仿真环境搭建。

pear55的博客 1007

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

解决ROS Noetic下‘mavlink_status_t‘未声明编译错误的实战指南

本文针对ROS Noetic环境下编译rotors_simulator时遇到的'mavlink_status_t'未声明错误,提供了详细的解决方案。通过分析MAVLink v2.0命名空间变化,指导用户在包含MAVLink头文件前手动添加typedef定义,有效解决编译错误,确保MAVLINK_H兼容性。

star5的专栏 211

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

ROS开发中的隐式依赖战争:以MAVLINK_H宏为盾的防御性编程实践

本文探讨ROS开发中隐式依赖问题的根源与解决方案,重点分析MAVLINK_H宏在防御性编程中的关键作用。通过实战案例解析编译错误如'mavlink_status_t未声明'的成因,提供头文件设计、条件编译和依赖管理等最佳实践,帮助开发者构建更健壮的ROS系统。

tgb34567890的博客 712

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

error: ‘***‘ has not been declared 头文件相互包含的问题

明明在开头包含了头文件,却告诉我***类没有被定义 记录一个敲代码时犯的一个小错误,写了一个中型的一个项目,20多个头文件,难免出现一点小纰漏 明明在开头包含了头文件,但是还是出现了***类未被定义的错误,查看两个头文件后发现是头文件相互包含了,这时候就要去看你的程序当中哪个类会先被调用,把后被调用的那个类的头文件当中的#include "???.h"替换成class ???; 分析可知,如果出现头文件相互包含,那么在编译的时候就可能会出现在#include那里找不到相应的类的问题(想不明白的话可以在

m0_58645501的博客 7644

mavlink 避坑指南

单片机移植mavlink中的一些坑

ben392797097的专栏 421

从‘mavlink_status_t’未定义错误,聊聊ROS开发中的头文件包含陷阱与命名空间战争

本文深入分析ROS开发中因头文件包含顺序和命名空间冲突导致的'mavlink_status_t'未定义编译错误,探讨MAVLink库的分层机制和条件编译陷阱,并提供头文件管理、命名空间设计及CMake配置的最佳实践,帮助开发者规避常见编译问题。

a1b2c3d的博客 988

PIXHAWK(ardupilot4.52)Mavlink消息解析学习

摘要:文章详细解析了飞控系统如何接收和处理地面站发送的Mavlink消息。核心流程包括:通过串口接收数据、调用mavlink_frame_char_buffer函数进行消息帧解析、使用packetReceived函数处理有效消息、并通过handle_message函数根据消息ID进行分发处理。重点以MISSION_ITEM_INT(73)航点消息为例,展示了从消息解码到航点数据存储的全过程。对于自定义Mavlink消息,需要在handle_message中添加对应case并调用生成的头文件中的解码函数。

H2z1220的博客 1010

ROS与MAVLink的共生之痛:以rotors_simulator为例看生态兼容性陷阱

本文以rotors_simulator为例,深入分析了ROS与MAVLink集成中的生态兼容性陷阱,特别是mavlink_status_t未声明错误的根源。探讨了版本迭代导致的依赖断裂、条件编译最佳实践及自动化检测工具,为无人机开发者提供构建健壮MAVLink-ROS接口的系统性解决方案。

desk3的博客 915

Mavlink地面站编写之一--协议分析

Pixhawk/APM都是采用MAVLINK协议实现的飞控的数据链路传输。先简单介绍下mavlink协议。Mavlink协议最早由 苏黎世联邦理工学院 计算机视觉与几何实验组 的 Lorenz Meier于2009年发布,并遵循LGPL开源协议。Mavlink协议是在串口通讯基础上的一种更高层的开源通讯协议,主要应用在微型飞行器(micro aerial vehicle)的通讯上。Mavlink是

AMOVLAB(阿木实验室) 2万+

源码方式安装MAVROS包报错

很明显,问题出现在编译mavros_extras这一块。经检查,发现是MavLink包过旧,导致MAVROS的依赖关系不完全。解决方案,安装最新版本的MavLink包。,注意不要使用--upstream,否则有可能版本不对编译不通过。

Leoo_oo的博客 1251

Mavlink协议

Mavlink协议简介Mavlink协议简介 一Mavlink协议 二数据结构 三协议支持的数据类型 四性能 五航点协议 读取MAV的航点列表 写MAV的航点列表 清除MAV的航点列表 设置当前MAV航点 六参数的读写 读取参数列表 读取单个参数 写参数 七增加新的mavlink消息 XML文件中消息的定义 建立消息定义文件 编绎XML文件 八消息的发送与解析 九通用的Mavlink消息 参考资料

pengl的博客 2万+

mavlink协议详解_MAVLink通讯协议在STM32上移植,并自定义协议

mavlink全称是(Micro Air Vehicle Message Marshalling Library),从名字可以看出,mavlink是主要面向飞控的一种开源通信协议。因此它默认定义了很多适用于飞控的信息格式,比如heartbeat(心跳信号,每隔一两秒主从通信一次,以验证通信是否正常)。首先要说明的是,mavlink作为一个非常可靠(至少两字节校验)、支持类型丰富(message I...

weixin_35470511的博客 4254

Ardupilot飞控Mavlink代码学习

摘自:https://blog.youkuaiyun.com/lixiaoweimashixiao/article/details/80919995 Ardupilot飞控Mavlink代码学习 魔城烟雨 2018-07-05 23:36:33 4302 收藏 19 分类专栏: ardupilot学习 版权 目录 目录 摘要 1.Ardupilot怎么实现Mavlink初始化 2.Mavlink消息通信过程 摘要 本节主要记录自己学习Ardupilot的M...

自主无人机 PX4 ROS SLAM 路径规划 MVS等技术分享 2942
上一篇: Zynq SD卡控制器实战:FATFS文件系统读写与性能优化
下一篇: 从零构建:为RT1052定制J-Link Flash下载算法的完整指南
寂静夜空35
博客等级 码龄3年 59粉丝 1797原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值