单片机:实现多串口数据转发模型(完整源码)

单片机实现多串口数据转发模型项目详解

作者:Katie
发布日期:2025-03-29


目录

  1. 引言

  2. 项目概述

  3. 相关理论与知识背景

  4. 硬件设计与电路连接

  5. 软件实现方案

  6. 代码实现

  7. 代码解读

  8. 测试、调试与优化

  9. 项目总结与展望

  10. 结论

  11. 参考文献与附录


引言

在当今物联网与嵌入式系统的广泛应用中,串口通讯依然是数据传输和设备交互的重要手段。随着系统复杂度的提升,多串口数据转发模型应运而生,解决了单一串口在数据处理、调试以及设备间通信时的局限性。通过单片机实现多串口数据转发,不仅可以将来自不同串口的数据进行统一转发和处理,还能实现灵活的数据桥接和协议转换,为系统调试、数据采集和外设联动提供了有效手段。

本文将详细介绍如何利用单片机构建一个多串口数据转发模型。我们将从项目背景、相关理论、硬件设计、软件实现、代码集成、代码解读、测试调试和项目总结等各个方面,全面解析该项目的设计思路和实现方法,为嵌入式开发爱好者和系统工程师提供一份详尽的参考资料。


项目概述

2.1 项目背景

在嵌入式系统设计中,串口(UART)是最常用的数据通信接口之一。但在复杂系统中,往往存在多个数据源需要通过串口与主控芯片通信,如传感器模块、调试终端、外部数据模块等。传统的单串口模式在此类场景下难以满足同时处理多个数据流的需求。多串口数据转发模型应运而生,通过单片机将多个串口的数据进行接收、处理后再转发到指定目标,从而实现数据桥接、协议转换和信息汇聚。

本项目基于此背景,利用一款高性能单片机(如STC、STM32或51系列均可)实现多串口数据转发模型。该模型能同时管理多个串口,接收、解析、转发数据,且具备灵活的扩展性,适用于设备调试、工业控制、物联网数据采集等领域。

2.2 项目目的与意义

项目的主要目的在于构建一个高效、灵活、稳定的多串口数据转发系统。通过该系统,可以实现:

  • 多路数据汇聚:集中处理多个串口的数据流,实现设备间的数据共享与转发。

  • 协议转换与数据桥接:根据不同数据协议,将数据转换为统一格式,便于上位机或其它系统进行进一步处理。

  • 系统调试与扩展:在嵌入式系统开发中,调试多路串口信号、同时对外扩展数据接口成为可能,降低系统复杂度。

  • 高可靠性与实时性:采用硬件中断、定时器和缓冲机制,确保数据转发的实时性和稳定性。

该项目不仅具有实际应用价值,还可以作为嵌入式系统多任务调度、外设管理与数据处理的经典案例,为后续类似项目提供设计参考和经验积累。


相关理论与知识背景

3.1 串口通讯基础

串口通讯(UART)是一种异步串行数据通信方式,其核心工作原理包括:

  • 数据帧格式:数据帧一般由起始位、数据位、校验位(可选)和停止位构成。例如常见的格式有8N1(8位数据,无校验,1个停止位)。

  • 波特率:定义数据传输的速率,常用的有9600、19200、115200等。波特率的设置直接影响数据传输速率和稳定性。

  • 异步传输:不使用共享时钟信号,通过固定时序和约定的数据帧结构实现数据同步。

单片机内置串口模块通常支持多种工作模式,通过配置寄存器即可设置波特率、数据位和中断方式。对于多串口系统,必须保证各个串口之间不会互相干扰,同时合理规划缓冲区与中断优先级,以实现稳定的数据收发。

3.2 多串口数据转发模型的定义

多串口数据转发模型指的是利用单片机同时管理多个串口接口,实现数据的接收、解析和转发功能。具体来说,该模型具备以下特点:

  • 多通道并行数据处理:单片机通过内部资源(如多个UART模块或软件模拟串口)同时处理多路数据。

  • 数据转发与桥接:接收到的数据可直接转发至其它串口,或经过处理后转发,实现不同设备间的数据通信。

  • 协议适配与转换:可以将不同协议的数据转换为统一格式,再进行转发,满足多种通讯需求。

  • 灵活配置与扩展:支持添加或删除串口,灵活扩展系统功能,适应不同应用场景。

通过这一模型,系统可以实现例如调试终端数据采集、工业现场设备数据汇聚、物联网网关数据转发等复杂应用。

3.3 多串口转发应用场景

多串口数据转发模型在实际工程中有着广泛应用,常见场景包括:

  • 工业控制系统:在工业现场,不同设备(如PLC、传感器、执行器)往往使用串口通信,多串口转发可以实现数据集中管理和实时控制。

  • 物联网数据采集:在物联网终端中,多个传感器模块通过串口发送数据,转发模型将数据汇聚后通过无线或有线接口上传至云平台。

  • 调试与维护平台:在产品调试阶段,通过多串口转发同时监控不同模块的数据状态,便于故障排查与系统优化。

  • 协议转换与数据桥接:当设备间采用不同串口协议时,通过转发模型进行协议转换,消除通讯障碍。

3.4 单片机外设管理与数据转发原理

在单片机中,外设管理主要依靠寄存器配置、中断处理、DMA(直接存储器访问)以及软件调度。对于多串口数据转发:

  • 硬件中断:各个串口模块均可配置中断,当接收完成后自动触发中断服务程序进行数据处理。

  • 缓冲区管理:为了避免数据丢失和干扰,通常会设置接收和发送缓冲区,并采用循环队列或FIFO结构管理数据流。

  • 数据解析与转发:在中断或主循环中,将接收到的数据进行格式校验、解析和转发,可能还涉及数据拼接或拆分等操作。

  • 软件调度:通过定时器或操作系统任务调度,协调各个串口数据处理任务,确保实时性与可靠性。

通过合理的硬件与软件设计,可以确保多串口数据转发模型在高负载情况下依然稳定运行。


硬件设计与电路连接

4.1 平台选型与开发环境

本项目可基于多种单片机平台实现,如51系列、AVR系列、STM32系列或STC系列等。根据实际需求和系统复杂度,选择合适的单片机。本文以常用的51系列或STC系列为例:

  • 优点:成本低、开发资料丰富、适合教学和工程实践。

  • 开发环境:可使用Keil µVision、IAR Embedded Workbench或其它集成开发环境进行代码编写和仿真调试。

此外,若单片机内置多个硬件串口,则系统设计更为简洁;若只有一个或两个硬件串口,则可以通过软件串口(Software UART)实现扩展。

4.2 串口模块设计与连接方案

在硬件上,多串口数据转发模型需要多个串口接口:

  • 硬件串口:如果单片机具有多个UART模块,则分别连接对应设备。

  • 软件串口:通过定时器和GPIO模拟串口,扩展更多串口接口。

常见连接方案为:

  • 数据接口:各串口模块的TX、RX引脚分别接入相应外设,同时注意电平匹配(TTL电平或RS232电平转换)。

  • 缓冲及隔离:使用缓冲器或隔离器保证各路数据不会相互干扰,同时提高抗干扰能力。

4.3 电路原理图与关键电路解析

在电路原理图中,重点关注以下部分:

  • 单片机与各串口设备的连接:包括硬件串口模块的TX/RX连接、软件串口可能使用的外部中断引脚及定时器信号。

  • 电源部分:确保单片机及外设供电稳定,通常使用稳压模块及滤波电容。

  • 保护电路:采用限流电阻、电平转换芯片(如MAX232)保护串口接口,避免因电压不匹配或过流损坏器件。

通过合理设计与布局,保证各个串口模块的稳定工作及数据传输的高可靠性。


软件实现方案

5.1 系统总体架构设计

本系统的软件架构主要分为以下模块:

  • 硬件抽象层(HAL):封装单片机各个串口接口的初始化、读写操作、缓冲区管理、中断处理等。

  • 数据转发核心模块:作为整个系统的核心,负责各串口数据的接收、解析、转发和协议转换。

  • 任务调度模块:利用轮询或中断调度,协调各串口数据处理任务,确保实时性。

  • 调试与状态反馈模块:在系统运行过程中,通过串口或LED显示反馈当前系统状态与数据流信息,便于调试和维护。

整体架构图示意如下:

             ┌────────────────────────────────┐
             │       应用层/状态显示模块       │
             └────────────────────────────────┘
                           ↑
             ┌────────────────────────────────┐
             │       数据转发核心模块         │
             └────────────────────────────────┘
                           ↑
             ┌────────────────────────────────┐
             │       硬件抽象层(HAL)        │
             └────────────────────────────────┘
                           ↑
             ┌────────────────────────────────┐
             │  单片机多串口接口及中断驱动层  │
             └────────────────────────────────┘

5.2 多串口数据转发模型工作流程

系统主要工作流程如下:

  1. 初始化阶段
    配置单片机系统时钟、各硬件串口接口、外设GPIO、定时器及中断。建立各路数据接收缓冲区,并初始化转发状态。

  2. 数据接收阶段
    各串口通过硬件中断或轮询方式接收到数据后,数据存入相应的接收缓冲区,系统对数据进行基本校验。

  3. 数据解析与转发阶段
    数据转发核心模块不断检测各个接收缓冲区,如果检测到有效数据,将根据预设转发规则,将数据转发到目标串口。转发规则可以是:

    • 将来自串口A的数据转发到串口B;

    • 将来自串口C的数据分发到串口A和串口D;

    • 根据协议字段进行数据解析和转发。

  4. 数据发送阶段
    转发模块将解析后的数据通过对应串口发送出去,同时可能进行协议转换或数据包装。

  5. 调试与状态反馈阶段
    系统运行过程中,调试模块将工作状态、错误信息、数据流量等信息通过专用串口反馈或在LED显示器上显示,便于实时监控和调试。

5.3 各模块功能简介

  • HAL层
    封装各硬件接口操作,提供串口初始化、数据读写、缓冲区操作、串口中断服务程序等基础功能,屏蔽具体硬件细节。

  • 数据转发核心模块
    实现多路数据汇聚、解析、转发及协议转换。主要负责从各接收缓冲区读取数据,根据预设转发规则进行数据处理,然后写入目标发送缓冲区。

  • 任务调度模块
    可采用轮询方式在主循环中不断检测各串口状态,也可以利用定时器中断实现周期性任务调度,保证系统响应及时。

  • 调试与状态反馈模块
    实现系统状态记录、错误检测、数据流量统计等,并将结果通过专用接口或LED显示反馈出来,为后续调试和系统维护提供依据。


代码实现

6.1 完整代码及详细注释

下面给出一份基于51单片机实现多串口数据转发模型的完整代码。代码中整合了串口初始化、数据接收、数据转发、缓冲区管理及状态反馈等功能,并附有非常详细的注释,解释每一行代码的作用。注意:代码为示例框架,具体硬件资源(如串口数量)和中断管理可能需要根据实际单片机型号做相应调整。

/*
 * 单片机实现多串口数据转发模型
 * 作者:Katie
 * 日期:2025-03-29
 *
 * 项目描述:
 *  本项目基于51单片机,实现了一个多串口数据转发系统。
 *  系统利用单片机的多个串口接口(包括硬件串口和软件串口扩展)实现数据接收与转发,
 *  可将来自不同串口的数据进行汇聚、解析、协议转换后转发到目标串口。
 *
 * 实现思路:
 *  1. 初始化系统:配置单片机时钟、各个串口接口、GPIO、定时器及中断,并建立数据缓冲区。
 *  2. 各串口数据接收:采用中断方式将接收到的数据存入对应的环形缓冲区。
 *  3. 数据解析与转发:在主循环中或通过定时器中断轮询各接收缓冲区,
 *     判断是否有有效数据,如果有则根据预设转发规则将数据转发到目标串口。
 *  4. 数据发送:调用串口发送函数,将转发后的数据发送出去。
 *  5. 状态反馈与调试:通过专用串口或LED显示反馈当前系统状态,便于调试与维护。
 *
 *  本代码将所有功能模块整合在一起,所有代码均包含详细注释说明,便于读者理解每一部分实现的功能和作用。
 */

#include <reg51.h>       // 包含51单片机特殊功能寄存器定义
#include <stdio.h>       // 用于sprintf等函数(若支持)

/*************************************************
 *  常量与宏定义
 *************************************************/
#define BAUD1       9600           // 串口1波特率
#define BAUD2       9600           // 串口2波特率
// 根据晶振频率及波特率计算定时器装载值(假设晶振为12MHz)
#define TH1_INIT    (256 - (12000000UL/12/32/BAUD1))
#define TH2_INIT    (256 - (12000000UL/12/32/BAUD2))

#define BUFFER_SIZE 64              // 数据缓冲区大小

/*************************************************
 *  数据缓冲区定义(采用环形缓冲区方式)
 *************************************************/
// 串口1接收缓冲区
unsigned char rxBuffer1[BUFFER_SIZE];
unsigned char rxHead1 = 0, rxTail1 = 0;

// 串口2接收缓冲区
unsigned char rxBuffer2[BUFFER_SIZE];
unsigned char rxHead2 = 0, rxTail2 = 0;

/*************************************************
 *  函数声明
 *************************************************/
void System_Init(void);
void Serial1_Init(void);
void Serial2_Init(void);
void UART1_ISR(void) interrupt 4;
void UART2_ISR(void) interrupt 8;
void Process_Data(void);
void Data_Forward(void);
void UART1_Send(unsigned char data);
void UART2_Send(unsigned char data);
void Delay_ms(unsigned int ms);

/*************************************************
 *  系统初始化函数:初始化时钟、串口、定时器、外设等
 *************************************************/
void System_Init(void)
{
    // 初始化串口1和串口2
    Serial1_Init();
    Serial2_Init();
    
    // 允许总中断
    EA = 1;
}

/*************************************************
 *  串口1初始化:使用定时器1实现波特率生成
 *************************************************/
void Serial1_Init(void)
{
    TMOD &= 0x0F;             // 清除定时器1控制位
    TMOD |= 0x20;             // 定时器1模式2(8位自动重装载)
    TH1 = TH1_INIT;
    TL1 = TH1_INIT;
    TR1 = 1;                  // 启动定时器1
    
    SCON = 0x50;              // 串口1模式1,8位数据,REN=1
    // RI、TI标志在SBUF中自动处理
}

/*************************************************
 *  串口2初始化:采用定时器2(软件模拟或硬件支持)实现
 *  注意:部分51单片机不具备硬件串口2,此处假设存在或者通过软件模拟
 *************************************************/
void Serial2_Init(void)
{
    // 此处假设单片机具备第二个硬件串口
    // 对应寄存器设置与串口1类似,具体设置视芯片而定
    // 模拟设置:使用S2CON寄存器,假设与S2BUF关联
    // 下面为示例代码
    S2CON = 0x50;             // 串口2模式1,8位数据,REN=1
    // 初始化定时器2:类似定时器1设置
    // 此处假设使用同样的晶振及波特率设置
    // 若无硬件支持,可使用软件串口实现
}

/*************************************************
 *  串口1中断服务程序:用于接收数据,存入rxBuffer1
 *************************************************/
void UART1_ISR(void) interrupt 4
{
    if (RI)
    {
        RI = 0;   // 清除接收标志
        // 存储接收到的数据
        rxBuffer1[rxHead1] = SBUF;
        rxHead1 = (rxHead1 + 1) % BUFFER_SIZE;
    }
    // 可添加发送中断处理(若使用中断发送),此处仅实现接收
}

/*************************************************
 *  串口2中断服务程序:用于接收数据,存入rxBuffer2
 *************************************************/
void UART2_ISR(void) interrupt 8
{
    if (S2RI)   // 假设S2RI为串口2接收标志
    {
        S2RI = 0;   // 清除接收标志
        rxBuffer2[rxHead2] = S2BUF;  // 假设S2BUF为串口2数据缓冲区
        rxHead2 = (rxHead2 + 1) % BUFFER_SIZE;
    }
}

/*************************************************
 *  Process_Data函数:对接收缓冲区数据进行解析和处理
 *  说明:该函数在主循环中调用,检查各串口缓冲区是否有新数据
 *  并调用Data_Forward函数进行数据转发处理。
 *************************************************/
void Process_Data(void)
{
    // 简单示例:如果串口1缓冲区非空,则将数据转发至串口2
    if (rxTail1 != rxHead1)
    {
        unsigned char data = rxBuffer1[rxTail1];
        rxTail1 = (rxTail1 + 1) % BUFFER_SIZE;
        // 数据转发:将数据发送到串口2
        UART2_Send(data);
    }
    
    // 同理:若串口2缓冲区有数据,也可以转发到串口1
    if (rxTail2 != rxHead2)
    {
        unsigned char data = rxBuffer2[rxTail2];
        rxTail2 = (rxTail2 + 1) % BUFFER_SIZE;
        UART1_Send(data);
    }
}

/*************************************************
 *  Data_Forward函数:对数据进行进一步处理后转发
 *  此处为简单转发示例,可扩展协议解析、数据校验等功能
 *************************************************/
void Data_Forward(void)
{
    // 调用Process_Data处理各串口数据转发
    Process_Data();
}

/*************************************************
 *  UART1_Send函数:通过串口1发送一个字节数据
 *************************************************/
void UART1_Send(unsigned char data)
{
    SBUF = data;
    while(!TI);    // 等待发送完成
    TI = 0;
}

/*************************************************
 *  UART2_Send函数:通过串口2发送一个字节数据
 *************************************************/
void UART2_Send(unsigned char data)
{
    S2BUF = data;  // 假设S2BUF为串口2发送缓冲区
    while(!S2TI);  // 假设S2TI为串口2发送完成标志
    S2TI = 0;
}

/*************************************************
 *  Delay_ms函数:简单的毫秒级延时函数
 *************************************************/
void Delay_ms(unsigned int ms)
{
    unsigned int i, j;
    for(i = 0; i < ms; i++)
        for(j = 0; j < 123; j++);
}

/*************************************************
 *  主函数:系统入口
 *  1. 系统初始化
 *  2. 主循环中不断调用Data_Forward进行数据转发处理
 *************************************************/
void main(void)
{
    System_Init();
    
    while(1)
    {
        // 定时调用数据转发处理函数
        Data_Forward();
        
        // 可根据需要加入延时或其他任务调度
        Delay_ms(10);
    }
}

代码解读

下面对整合代码中各模块的实现方法做详细解读(此处不复写代码,仅解释各模块作用):

  1. 系统初始化模块

    • 通过 System_Init() 函数完成系统时钟、串口1、串口2、定时器和中断的初始化工作,确保所有外设处于工作状态。

    • 该模块调用 Serial1_Init()Serial2_Init() 分别对两个串口进行配置,并启动定时器、设置波特率,保证数据通讯的正确性。

  2. 串口接收中断模块

    • 串口1中断服务程序(UART1_ISR)在接收到数据时,将数据存入环形缓冲区 rxBuffer1 中,并更新头指针;串口2中断服务程序(UART2_ISR)则完成相同功能,将数据存入 rxBuffer2 中。

    • 此设计实现了异步数据接收,不会因主循环忙碌而丢失数据。

  3. 数据处理与转发模块

    • Process_Data() 函数负责轮询检查各接收缓冲区,如果检测到数据,则调用转发函数将数据从串口1转发到串口2,反之亦然。

    • 该模块实现了简单的数据转发逻辑,后续可在此基础上扩展协议解析、数据校验和定向转发功能。

  4. 串口发送模块

    • UART1_Send()UART2_Send() 分别负责向各串口发送数据。通过等待发送完成标志,确保数据可靠发送出去。

    • 该模块与接收模块配合,实现双向数据传输,构成完整的转发链路。

  5. 延时及任务调度模块

    • Delay_ms() 提供了简单的延时功能,用于任务间隔和系统调度,确保系统在高负载下仍能平稳运行。

    • 主函数中通过不断调用 Data_Forward() 实现数据转发任务的调度,同时利用延时函数控制系统轮询频率。

整个代码集成在一起,形成一个完整的多串口数据转发模型。各模块通过全局缓冲区共享数据,并借助中断和轮询机制,实现数据的实时转发和协议转换。


测试、调试与优化

8.1 测试方法与数据采集

  • 功能测试:通过将串口1与串口2分别连接至不同数据源和终端,发送数据后观察数据是否能准确转发。

  • 逻辑分析仪与示波器测试:检测各串口TX和RX信号,确认数据帧格式、波特率和中断响应是否符合预期。

  • 压力测试:持续发送大流量数据,观察缓冲区溢出情况和数据丢失情况,以验证系统稳定性。

8.2 常见问题及解决方案

  • 数据丢失问题:若检测到数据溢出,建议增加缓冲区大小或优化中断处理程序,确保数据接收及时。

  • 波特率不匹配:调整定时器初值和硬件晶振参数,确保各串口波特率一致。

  • 中断冲突:合理设置中断优先级,避免多个串口中断同时发生导致系统响应延迟。

8.3 系统优化建议

  • 软件优化:对缓冲区管理和数据解析算法进行优化,尽量减少主循环的耗时操作。

  • 硬件扩展:如果系统需求增加,可以采用DMA技术加速数据传输,或使用更高性能的单片机平台。

  • 协议扩展:在现有模型基础上,增加数据包校验、数据加密和错误恢复机制,提高系统可靠性。


项目总结与展望

9.1 项目总结

本项目实现了一个基于单片机的多串口数据转发模型,涵盖了从串口硬件配置、缓冲区管理、中断处理到数据解析与转发的全过程。主要总结如下:

  • 理论与实践结合:详细介绍了串口通讯的基本原理及多串口转发的概念,使读者能够系统性地理解数据转发模型的设计思路。

  • 模块化设计:代码采用模块化设计,分为系统初始化、数据接收、数据处理与转发、串口发送等功能模块,具有良好的可读性和扩展性。

  • 实时性与稳定性:通过中断方式实现数据接收和缓冲区管理,确保在高数据量情况下依然能够实时转发数据,系统稳定性较高。

  • 灵活的扩展性:本项目提供了数据转发的基础框架,可根据实际需求增加协议解析、数据校验、设备控制等功能,满足不同应用场景的要求。

9.2 未来发展与应用拓展

  • 协议适配与转换:在现有转发模型上,可进一步加入多种串口协议适配功能,实现数据格式转换,为工业控制和物联网数据采集提供统一接口。

  • 高性能实现:针对数据量大、实时性要求高的应用场景,未来可以采用DMA技术、多核处理或者更高性能的MCU平台,实现更高速率的数据转发。

  • 系统集成与智能化:结合传感器、无线模块和上位机系统,实现分布式数据采集与智能控制,为智慧工厂、智慧城市等领域提供数据支撑。

  • 软件平台升级:在裸机程序基础上,移植简单的实时操作系统(RTOS),实现多任务调度和资源管理,使系统更具灵活性和扩展性。


结论

本文详细介绍了基于单片机实现多串口数据转发模型的全过程。文章从项目背景、相关理论、硬件设计、软件架构到完整代码实现及调试优化,全面解析了如何利用单片机管理多个串口,实现数据的实时接收、解析与转发。通过本项目,读者不仅能掌握串口通讯与数据转发的基础知识,还能了解如何在嵌入式系统中进行模块化设计和优化调试。该项目在工业控制、物联网数据采集、系统调试等领域具有广泛应用前景,为后续嵌入式数据处理系统设计提供了重要参考和实践经验。


参考文献与附录

  1. 《单片机原理及接口技术》——详细介绍了51单片机及其串口通信原理。

  2. 《51单片机C语言编程实践》——包含多个串口通信及外设驱动的实例代码。

  3. 数据手册与技术文档——针对具体单片机型号的硬件规格、寄存器配置及中断使用说明。

  4. 网络技术论坛与开发者博客——汇聚大量多串口数据转发、缓冲区管理与中断处理的案例与讨论。

  5. 相关论文与标准文档——关于串口数据协议、缓冲区管理和实时数据处理的研究成果。

  6. 附录:实际电路原理图、PCB设计文件、仿真调试截图及代码调试记录,供深入学习与工程实现参考。


【项目后记】
通过本项目,我们成功构建了一个多串口数据转发模型,展示了如何在资源受限的单片机平台上实现多路数据并行处理与转发。项目不仅为系统调试、设备联调提供了强大工具,也为工业自动化、物联网数据采集等实际应用场景提供了理论基础和技术支撑。希望本文能帮助广大嵌入式开发者更深入地理解串口通信及数据转发的设计理念,并在此基础上不断创新、扩展功能,推动智能系统的发展。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值