传感器驱动系列之BMP180大气压传感器

一、大气压传感器简介

        BMP180是一种数字式大气压传感器,由德国博世公司开发。它采用了微电子机械系统(MEMS)技术,可以测量大气压力和温度。BMP180传感器具有高精度、低功耗和小尺寸的特点。BMP180传感器通过测量大气压力来推算海拔高度和气压变化,可以用于气象观测、气候研究以及天气预报等应用领域。此外,它还可以通过测量温度来提供环境温度数据。其实物图说明见下图1。

图1  BMP180大气压传感器实物

        BMP180传感器的工作原理是利用压阻式传感器来测量大气压力,其内部附带温度传感器,可对气压测量值进行补偿提高测量精度。它采用I2C数字接口,可以与微控制器或单片机进行通信,以获取传感器提供的数据。BMP180传感器是一种常用于大气压力和温度测量的数字式传感器,具有高精度、低功耗和小尺寸的特点,广泛应用于气象观测、气候研究和天气预报等领域。

二、工作原理

2.1 工作模式

        BMP180共有四种工作模式,每种模式有不同的采样数量、转换速度和噪声等参数的不同。可以通过写入ctrl_meas寄存器来设置模式,默认为第一个ultra low power超低功耗。说明见下图2。

图2  BMP180四种工作模式

        2.2 校准参数

        BMP180的气压和温度数值并不是可以直接读取的,每个不同的传感器中,都有自己独特的校准数值,存储在内置的E2PROM存储器中。当微处理器读取传感器的原始温度和气压数值后,再根据E2PROM中的校准数值进行转换,才能得到真正的温度、气压数据。每个校准数值的存储的寄存器地址如下图3所示,微处理器可以通过这些地址读取校准数值。

图3  BMP180传感器校准参数寄存器地址

        2.3 读取传感器数据

        读取传感器的数据可查看传感器手册得知,一般流程如下:

  • 读取校准数值

        把16位的校准数值读取到微处理器中,可以看到一共有11个数值。需要注意的是高位存储在MSB地址,低位存储在LSB地址。例如数值AC1,高八位存储在0xAA地址,低八位存储在0xAB地址。如下图4。

图4  读取传感器校准参数寄存器值
  • 读取温度、气压初始值

温度初始值读取步骤:往寄存器0xf4写入0x2e,等待4、5ms;→读取0xf6(高八位)和0xf7(低八位)两个寄存器;→换算: UT=MSB <<8 +LSB。

气压初始值读取步骤:往寄存器0xf4写入0x34(如果不是默认的工作模式,需要加上oss左移六位的结果,oss为设置工作模式的寄存器0xf4的bit7、bit6位),等待4、5ms;→读0xf6(16-23位)、0xf7(8-15位)和0xf8(0-7位)三个寄存器;→换算: UP=MSB <<16 + LSB<<8 + XLSB >> (8-oss(这个同温度初始值读取一样))。具体读取过程见下图5。

图5  读取温度、气压初始数据
  • 计算温度、气压

        根据第一步读出来的校准系数和第二步读出来的UT、UP进行换算,最后得出来的T(温度,每个数值代表0.1摄氏度),p(气压,每个数值代表1帕)。具体过程如下图6。

图6  计算温度、气压数据
  • 计算海拔高度

        根据手册提供公式,可以根据气压计算出海拔高度,但此式过于复杂,具体参考下图7。在3000M范围内,每升高12M,大气压减小1mmHg,大约133Pa。0海拔高度大约是101325 pa,所以据此可以进行简单近似的计算:altitude = (101325 - p) /133 * 12。

图7  计算海拔高度

三、STM32驱动源码

        bmp180.c驱动实现如下:

#include "bmp180.h"
#include "delay.h"

static STRUCT_BMP180_TYPEDEF bmp180;    /* 定义结构体用来保存bmp180传感器参数 */

/*
 * ----------------------------------------------------------------------------------------------
 * ------------------------------------- BMP180 IIC 驱动函数 -------------------------------------
 * ----------------------------------------------------------------------------------------------
 */
 
/*
 * 函数名称: bmp180_iic_init
 * 函数功能: 初始化IIC
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_iic_init(void)
{
    RCC_APB2PeriphClockCmd(BMP180_SDA_RCC_CLK | BMP180_SCL_RCC_CLK, ENABLE);
    GPIO_InitTypeDef  GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    
    /* SDA GPIO初始化设置 */
    GPIO_InitStructure.GPIO_Pin = BMP180_SDA_GPIO_PIN;
    GPIO_Init(BMP180_SDA_GPIO_PORT, &GPIO_InitStructure);
    
    /* SCL GPIO初始化设置 */
    GPIO_InitStructure.GPIO_Pin = BMP180_SCL_GPIO_PIN;
    GPIO_Init(BMP180_SCL_GPIO_PORT, &GPIO_InitStructure);
    
    BMP180_SCL(1); BMP180_SDA(1);
}

/*
 * 函数名称: bmp180_sda_inout
 * 函数功能: 配置SDA线为输入/输出模式
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_sda_inout(uint8_t dir)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(BMP180_SDA_RCC_CLK, ENABLE);

    if(dir) {
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; /* 推挽输出 */
    } else {
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;/* 浮空输入 */
    }
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_InitStructure.GPIO_Pin = BMP180_SDA_GPIO_PIN;
    GPIO_Init(BMP180_SDA_GPIO_PORT, &GPIO_InitStructure);
}

/*
 * 函数名称: bmp180_iic_start
 * 函数功能: 产生IIC起始信号
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_iic_start(void)
{
    bmp180_sda_inout(1); /* 配置sda线为输出模式 */
    BMP180_SDA(1);
    BMP180_SCL(1);
    delay_us(4);
    BMP180_SDA(0);   /* 开始信号 CLK高电平时,SDA从高变低 */
    delay_us(4);
    BMP180_SCL(0);   /* 钳住I2C总线,准备发送或接收数据 */
}

/*
 * 函数名称: bmp180_iic_stop
 * 函数功能: 产生IIC停止信号
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_iic_stop(void)
{
    bmp180_sda_inout(1);  /* 配置sda线为输出模式 */
    BMP180_SCL(0);
    BMP180_SDA(0);   /* 停止信号 CLK高电平时,SDA从低变高 */
    delay_us(4);
    BMP180_SCL(1);
    BMP180_SDA(1);   /* 发送I2C总线结束信号 */
    delay_us(4);
}

/*
 * 函数名称: bmp180_iic_waitAck
 * 函数功能: 等待应答信号到来
 * 参    数: 无
 * 返 回 值: 1-接收应答失败; 0-接收应答成功
 */
static uint8_t bmp180_iic_waitAck(void)
{
    uint8_t ucErrTime = 0;
    bmp180_sda_inout(0); /* SDA设置为输入模式 */
    
    BMP180_SDA(1);
    delay_us(1);
    BMP180_SCL(1);
    delay_us(1);
    while(BMP180_READ_SDA) {
        ucErrTime ++;
        if(ucErrTime>250) {
            bmp180_iic_stop();
            return 1;
        }
    }
    BMP180_SCL(0);
    return 0;
} 

/*
 * 函数名称: bmp180_iic_ack
 * 函数功能: 产生ACK应答
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_iic_ack(void)
{
    BMP180_SCL(0);
    bmp180_sda_inout(1);
    BMP180_SDA(0);
    delay_us(2);
    BMP180_SCL(1);
    delay_us(2);
    BMP180_SCL(0);
}

/*
 * 函数名称: bmp180_iic_nAck
 * 函数功能: 不产生ACK应答
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_iic_nAck(void)
{
    BMP180_SCL(0);
    bmp180_sda_inout(1);
    BMP180_SDA(1);
    delay_us(2);
    BMP180_SCL(1);
    delay_us(2);
    BMP180_SCL(0);
}

/*
 * 函数名称: bmp180_iic_sendByte
 * 函数功能: 发送一个字节
 * 参    数: txd
 * 返 回 值: 1,有应答;0,无应答
 */
static void bmp180_iic_sendByte(uint8_t txd)
{
    uint8_t tx_flag;
    bmp180_sda_inout(1);
    BMP180_SCL(0);
    for(uint8_t i=0;i<8;i++) {
        tx_flag = (txd&0x80) >> 7;
        if(tx_flag == 0) {
            BMP180_SDA(0);
        } else {
            BMP180_SDA(1);
        }
        txd <<= 1;
        delay_us(2);
        BMP180_SCL(1);
        delay_us(2); 
        BMP180_SCL(0);
        delay_us(2);
    }
}
 
/*
 * 函数名称: bmp180_iic_readByte
 * 函数功能: 读1个字节
 * 参    数: ack (ack=1 发送ACK; ack=0 发送nACK)
 * 返 回 值: receive 接收到的数据
 */
static uint8_t bmp180_iic_readByte(uint8_t ack)
{
    uint8_t receive = 0;
    bmp180_sda_inout(0);/* SDA设置为输入 */
    
    for(uint8_t i=0;i<8;i++ ) {
        BMP180_SCL(0);
        delay_us(2);
        BMP180_SCL(1);
        
        receive <<= 1;
        if(BMP180_READ_SDA)
            receive ++;
        delay_us(1); 
    }
    if (!ack) {
        bmp180_iic_nAck();  /* 发送nACK */
    } else {
        bmp180_iic_ack();   /* 发送ACK */
    }
    return receive;
}

/*
 * 函数名称: Multiple_read
 * 函数功能: 连续读出两个内部数据
 * 参    数: reg_addr 存储单元地址
 * 返 回 值: 读取出的16位数据 
 */
static uint16_t bmp180_multiRead(uint8_t reg_addr)
{
    uint8_t msb, lsb;
    
    bmp180_iic_start();                 /* 起始信号 */
    bmp180_iic_sendByte(BMP180_ADDR_WR);/* 发送设备地址+写信号 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_sendByte(reg_addr);      /* 发送存储单元地址 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_start();                 /* 起始信号 */
    bmp180_iic_sendByte(BMP180_ADDR_RD);/* 发送设备地址+读信号 */
    while(bmp180_iic_waitAck());

    msb = bmp180_iic_readByte(1);       /* BUF[0]存储 */
    lsb = bmp180_iic_readByte(0);       /* 最后一个数据需要回NOACK */
    bmp180_iic_stop();                  /* 停止信号 */
    delay_ms(5);
    
    return (msb << 8 | lsb);
}

/*
 * 函数名称: bmp180_readTemperatureReg
 * 函数功能: BMP180 读取温度值
 * 参    数: 无
 * 返 回 值: 16位温度数据 
 */
static uint16_t bmp180_readTemperatureReg(void)
{
    bmp180_iic_start();                 /* 起始信号 */
    bmp180_iic_sendByte(BMP180_ADDR_WR);/* 发送设备地址+写信号 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_sendByte(0xF4);          /* 温度数据 寄存器地址 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_sendByte(0x2E);          /* 向寄存器地址写入数据 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_stop();                  /* 发送停止信号 */
    delay_ms(10);
    
    return bmp180_multiRead(0xF6);
}

/*
 * 函数名称: bmp180_readPressureReg
 * 函数功能: 读取气压值
 * 参    数: 无
 * 返 回 值: 16位气压数据 
 */
static uint16_t bmp180_readPressureReg(void)
{
    bmp180_iic_start();                 /* 起始信号 */
    bmp180_iic_sendByte(BMP180_ADDR_WR);/* 发送设备地址+写信号 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_sendByte(0xF4);          /* 气压数据 寄存器地址 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_sendByte(0x34);          /* 向寄存器地址写入数据 */
    while(bmp180_iic_waitAck());
    
    bmp180_iic_stop();                  /* 发送停止信号 */
    delay_ms(20);
    
    return bmp180_multiRead(0xF6);
}

/*
 * 函数名称: bmp180_struct_init
 * 函数功能: 初始化气压传感器结构体参数
 * 参    数: 无
 * 返 回 值: 无
 */
static void bmp180_struct_init(void)
{
    bmp180.adjust.ac1 = bmp180_multiRead(0xAA);
    bmp180.adjust.ac2 = bmp180_multiRead(0xAC);
    bmp180.adjust.ac3 = bmp180_multiRead(0xAE);
    bmp180.adjust.ac4 = bmp180_multiRead(0xB0);
    bmp180.adjust.ac5 = bmp180_multiRead(0xB2);
    bmp180.adjust.ac6 = bmp180_multiRead(0xB4);
    bmp180.adjust.b1 =  bmp180_multiRead(0xB6);
    bmp180.adjust.b2 =  bmp180_multiRead(0xB8);
    bmp180.adjust.mb =  bmp180_multiRead(0xBA);
    bmp180.adjust.mc =  bmp180_multiRead(0xBC);
    bmp180.adjust.md =  bmp180_multiRead(0xBE);
    
    bmp180.temperature = 0.f;
    bmp180.temp_offset = 0.f;
    bmp180.pressure = 0.f;
    bmp180.pres_offset = 0.f;
    bmp180.altitude = 0.f;
    bmp180.alti_offset = 0.f;
}

/* ------------------------------------- 接口函数 ---------------------------------------- */

/*
 * 函数名称: bmp180_init
 * 函数功能: 初始化 气压传感器
 * 参    数: 无
 * 返 回 值: 无
 */
void bmp180_init(void)
{
    bmp180_iic_init();
    bmp180_struct_init();
}

/*
 * 函数名称: bmp180_measure
 * 函数功能: 测量一次大气压传感器
 * 参    数: 无
 * 返 回 值: 无
 */
void bmp180_measure(void)
{
    long UT, UP;
    long x1, x2, b5, b6, x3, b3, p;
    unsigned long b4, b7;
    
    UT = bmp180_readTemperatureReg();  /* 读取温度 */
    UP = bmp180_readPressureReg();     /* 读取压强 */
    
    /* ------------------------ 温度值计算 ------------------------ */
    x1 = ((UT - (long)bmp180.adjust.ac6)*(long)bmp180.adjust.ac5) >> 15;
    x2 = ((long) bmp180.adjust.mc << 11) / (x1 + bmp180.adjust.md);
    b5 = x1 + x2;
    bmp180.temperature = (((b5 + 8) >> 4)/10.f) + (((b5 + 8) >> 4)%10/10.f);/* 获取温度值 */
    
    /* ------------------------ 气压值计算 ------------------------ */
    b6 = b5 - 4000;
    /* 计算 b3 */
    x1 = (bmp180.adjust.b2 * (b6 * b6) >> 12) >> 11;
    x2 = (bmp180.adjust.ac2 * b6) >> 11;
    x3 = x1 + x2;
    b3 = (((((long)bmp180.adjust.ac1)*4 + x3) << BMP180_OSS) + 2) >> 2;
    /* 计算 b4 */
    x1 = (bmp180.adjust.ac3 * b6) >> 13;
    x2 = (bmp180.adjust.b1 * ((b6 * b6) >> 12)) >> 16;
    x3 = ((x1 + x2) + 2) >> 2;
    b4 = (bmp180.adjust.ac4 * (unsigned long)(x3 + 32768)) >> 15;
    b7 = ((UP - b3) * (50000 >> BMP180_OSS));
    if (b7 < 0x80000000) {
        p = (b7 << 1) / b4;
    } else {
        p = (b7 / b4) << 1;
    }
    x1 = (p >> 8) * (p >> 8);
    x1 = (x1 * 3038) >> 16;
    x2 = (-7357 * p) >> 16;
    /* 得到气压值 */
    bmp180.pressure = (p + ((x1 + x2 + 3791) >> 4))/1000.0 + ((float)(( p +((x1 + x2 + 3791) >> 4))%1000)/1000.0);
    
    /* ------------------------ 海拔高度计算 ------------------------ */
    bmp180.altitude =  (BMP180_ZeroAltitude - p) / 133.0 * 12.0;
}

/*
 * 函数名称: bmp180_getTemperature
 * 函数功能: 获取大气压传感器温度数据
 * 参    数: 无
 * 返 回 值: 温度值 单位 ℃
 */
float bmp180_getTemperature(void)
{
    return (bmp180.temperature + bmp180.temp_offset);
}

/*
 * 函数名称: bmp180_getPressure
 * 函数功能: 获取大气压传感器大气压数据
 * 参    数: 无
 * 返 回 值: 气压值 单位 kPa
 */
float bmp180_getPressure(void)
{
    return (bmp180.pressure + bmp180.pres_offset);
}

/*
 * 函数名称: bmp180_getAltitude
 * 函数功能: 获取大气压传感器海拔高度
 * 参    数: 无
 * 返 回 值: 海拔高度 单位 m
 */
float bmp180_getAltitude(void)
{
    return (bmp180.altitude + bmp180.alti_offset);
}

/*
 * 函数名称: bmp180_set_temperature_offset
 * 函数功能: 设置温度数据补偿值
 * 参    数: 温度数据补偿值
 * 返 回 值: 无
 */
void bmp180_set_temperature_offset(float offset)
{
    bmp180.temp_offset = offset;
}

/*
 * 函数名称: bmp180_set_pressure_offset
 * 函数功能: 设置大气压数据补偿值
 * 参    数: 大气压数据补偿值
 * 返 回 值: 无
 */
void bmp180_set_pressure_offset(float offset)
{
    bmp180.pres_offset = offset;
}

/*
 * 函数名称: bmp180_set_altitude_offset
 * 函数功能: 设置海拔高度数据补偿值
 * 参    数: 海拔高度数据补偿值
 * 返 回 值: 无
 */
void bmp180_set_altitude_offset(float offset)
{
    bmp180.alti_offset = offset;
}

        bmp180.h驱动实现如下:

#ifndef __BMP180_H
#define __BMP180_H

#include "stm32f10x.h"

/* 定义结构体用来保存校准数值参数 */
typedef struct {
    short ac1;
    short ac2;
    short ac3;
    unsigned short ac4;
    unsigned short ac5;
    unsigned short ac6;
    short   b1;
    short   b2;
    short   mb;
    short   mc;
    short   md;
} STRUCT_BMP180_ADJUST_TYPEDEF;

/* bmp180结构体 */
typedef struct {
    STRUCT_BMP180_ADJUST_TYPEDEF adjust;    /* 传感器寄存器校准值 */
    float temperature;  /* 温度值 */
    float pressure;     /* 气压值 */
    float altitude;     /* 海拔高度 */
    float temp_offset;  /* 温度补偿 */
    float pres_offset;  /* 气压补偿 */
    float alti_offset;  /* 海拔补偿 */
} STRUCT_BMP180_TYPEDEF;

/* -------------------------------- BMP180 IIC 引脚定义 ------------------------------- */
#define     BMP180_SCL_RCC_CLK      RCC_APB2Periph_GPIOA
#define     BMP180_SCL_GPIO_PORT    GPIOA
#define     BMP180_SCL_GPIO_PIN     GPIO_Pin_2

#define     BMP180_SDA_RCC_CLK      RCC_APB2Periph_GPIOA
#define     BMP180_SDA_GPIO_PORT    GPIOA
#define     BMP180_SDA_GPIO_PIN     GPIO_Pin_3

#define     BMP180_SCL(x)           GPIO_WriteBit(BMP180_SCL_GPIO_PORT, BMP180_SCL_GPIO_PIN, (BitAction)x)
#define     BMP180_SDA(x)           GPIO_WriteBit(BMP180_SDA_GPIO_PORT, BMP180_SDA_GPIO_PIN, (BitAction)x)
#define     BMP180_READ_SDA         GPIO_ReadInputDataBit(BMP180_SDA_GPIO_PORT, BMP180_SDA_GPIO_PIN)

/* ---------------------------- BMP180 寄存器地址 ----------------------------------- */
#define     BMP180_ADDR_WR          (0xEE)  /* 气压传感器器件地址+写指令 */
#define     BMP180_ADDR_RD          (0xEF)  /* 气压传感器器件地址+读指令 */
#define     BMP180_OSS              (0)     /* BMP180 OSS 等级 */
#define     BMP180_ZeroAltitude     (101325)/* 0海拔高度的气压值 单位Pa */


/* ----------------------------------- 函数清单 ----------------------------------- */
void        bmp180_init(void);                          /* bmp180初始化 */
void        bmp180_measure(void);                       /* 采集一次大气压传感器数据 */
float       bmp180_getTemperature(void);                /* 获取大气压传感器温度数据 */
float       bmp180_getPressure(void);                   /* 获取大气压传感器大气压数据 */
float       bmp180_getAltitude(void);                   /* 获取大气压传感器海拔高度数据 */
void        bmp180_set_temperature_offset(float offset);/* 设置温度数据补偿值 */
void        bmp180_set_pressure_offset(float offset);   /* 设置大气压数据补偿值 */
void        bmp180_set_altitude_offset(float offset);   /* 设置海拔高度数据补偿值 */

#endif

        代码一般驱动和使用流程如下:

1. 在bmp180.h文件中修改传感器IIC的接口引脚宏定义,使之适配自己的端口引脚;

2. 调用bmp180_init()函数用于初始化传感器引脚;

3. 周期性的调用bmp180_measure()函数用于测量传感器数据(注意:这里的测量/采集数据并没有返回值进行数据返回);

4. 在需要获取温度和湿度数据的地方调用bmp180_getTemperature()、bmp180_getPressure()、bmp180_getAltitude()三个函数分别获取传感器的温度、大气压、海拔数据。
 

  • 31
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 8
    评论
BMP180是一款高精度的气压传感器,广泛应用于气压和海拔测量。它具有低功耗和低噪声等特点,并且内部附带温度传感器,可以对气压测量值进行补偿。在STM32中使用BMP180传感器,可以通过I2C通信方式进行操作。在代码中,首先需要初始化BMP180传感器和串口,然后在while循环中测量温度、大气压和海拔高度的值,并通过printf()函数将这些数值发送出去。具体的代码示例可以参考引用\[2\]中提供的源码。\[1\]\[2\] 如果您有关于BMP180大气压传感器在STM32中的更具体问题,请提供更多细节,我将尽力为您解答。 #### 引用[.reference_title] - *1* *3* [BMP180气压传感器详解与示例(STM32 附带源码)](https://blog.csdn.net/weixin_50622833/article/details/118611152)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [基于STM32F030驱动BMP180气压传感器](https://blog.csdn.net/xhj1021/article/details/124093437)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insert_down1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值