bh1745nuc彩色传感器开发,采集RGB数据,计算色温和亮度,附模拟i2c源码

本文介绍BH1745颜色传感器的功能特点及应用,包括如何通过RGB数据计算色温和亮度,提供了详细的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  最近到手了一个罗姆系列的颜色传感器 ,叫做bh1745nuc,它可以通过运用特有的红外线去除技术和运算方式实现业界最高的红外线去除特性,将红外线的影响降低至以往产品的1/10以下。以往彩色传感器,即便是受到红外线影响无法正确感应的昏暗(透射率低)的光学窗口,也能精确检测出照度、色温。

一、什么是RGB

  从它官方的datasheet上了解到,它输出数据为16bit的RGBC,什么是RGBC呢?通俗点说,R代表red也就是红色,同理,G是green,B是blue,C是clear。我们可以通过RGB数据计算得出对应的色温和照度,由于我技术有限,没能找到有关照度计算的资料,所以就用亮度来替代照度,还望有大神看完后可以不吝提供一下方案。

二、色温

  色温简称CCT,所谓色温就是我们常说的冷色、暖色等等,色温的单位是K(开尔文)。那怎么通过RGB数据计算出色温呢?通过查找资料了解到,计算色温的步骤是:

  1.计算出三个刺激值X,Y,Z;

  2.通过三个刺激值计算出色坐标(x,y);

  3.通过色坐标与色温的换算公式计算出色温。

  首先,计算三个刺激值X,Y,Z。通过查找资料,刺激值与RGB转换公式为:

  \begin{bmatrix} X\\ Y\\ Z \end{bmatrix}= \begin{bmatrix} 2.789&1.7517& 1.1302 \\ 1&4.5907&0.0601 \\ 0 &0.0565 & 5.5943 \end{bmatrix}\begin{bmatrix} R\\ G\\ B \end{bmatrix}

  其次,计算色坐标(x,y),色坐标计算公式为:

  x = X / (X + Y + Z)
  y = Y / (X + Y + Z)

  最后,计算色温,计算公式为:

  n = (x - 0.3320) / (0.1858 - y)    
  CCT = 437 * n * n * n + 3601 * n * n + 6831 * n + 5517,CCT就是色温了。    

  附上代码:

/*
  * @func    Calculate_Color_Temperature
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static double Calculate_Color_Temperature(uint16_t R, uint16_t G, uint16_t B)
{
    static double M[3][3] = { {2.789, 1.7517, 1.1302},
                              {1,     4.5907, 0.0601},
                              {0,     0.0565, 5.5943} };
    double X = 0, Y = 0, Z = 0;    //三刺激值
    double x = 0, y = 0;           //色坐标
    double CCT = 0;                //色温
    double n = 0;
														
    X = M[0][0] * R + M[0][1] * G + M[0][2] * B;
    Y = M[1][0] * R + M[1][1] * G + M[1][2] * B;
    Z = M[2][0] * R + M[2][1] * G + M[2][2] * B;	

    x = X / (X + Y + Z);
    y = Y / (X + Y + Z);

    n = (x - 0.3320) / (0.1858 - y);	
    CCT = 437 * n * n * n + 3601 * n * n + 6831 * n + 5517;		

    return CCT;														
}

  色温的结果出来后,可以通过简单的比较来确定是否属于冷色、中间色、暖色其中之一,后面会有代码。

三、亮度

  亮度比较简单,直接附上代码:

/*
  * @func    Calculate_Brightness
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static uint16_t Calculate_Brightness(uint16_t R, uint16_t G, uint16_t B)
{
    return (uint16_t)((0.299 * R) + (0.587 * G) + (0.114 * B));
}

  最后是接口函数,调用上面两个函数:(我的程序里这一部分是属于color_analyses.c,对外提供一个接口) 

  先是结构体定义

//色温等级结构
typedef enum {
    warm = 0,  //暖色
    middle,   //中间色
    cold      //冷色
} Temperature_Rank;

//环境值结构
typedef struct {
    double CCT;  //色温
    uint16_t brightness;  //亮度
    Temperature_Rank t_rank;  //色温等级
} Enviroment_Typedef;
/*
  * @func    Color_Analyses
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
void Color_Analyses(Enviroment_Typedef *enviroment, const Color_DataTypedef *color)
{
    enviroment->CCT = Calculate_Color_Temperature(color->red_data, color->green_data, color->blue_data);
    //大于5000是冷色,3300~5000是中间色,小于3300是暖色
    if (enviroment->CCT > 5000)  enviroment->t_rank = cold;
    else if (enviroment->CCT > 3300) enviroment->t_rank = middle;
    else enviroment->t_rank = warm;	
    enviroment->brightness = Calculate_Brightness(color->red_data, color->green_data, color->blue_data);
}

 

四、关于bh1745

  根据官方给的datasheet,写了它的.h和.c

  bh1745.h:

/*
  * @file    bh1745.h
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/7
*/

#ifndef __BH1745_H
#define __BH1745_H

#include "stm32f10x.h"
#include "stdbool.h"
//---------------------------------------------------------------------------------------------------
#define BH1745_ADDRESS             ((uint8_t)0x38) //ADDR = 'L' ;ADDR = 'H' is 0x71h
#define BH1745_WRITE               ((BH1745_ADDRESS << 1) | 0x00) 
#define BH1745_READ                ((BH1745_ADDRESS << 1) | 0x01) 
#define SYSTEM_CONTROL_ID          ((uint8_t)0x0b)
//---------------------------------------------------------------------------------------------------
/*
system control register
*/
#define SYSTEM_CONTROL             ((uint8_t)0x40)
//---------------------------------------------------------------------------------------------------
/*
function setting registers
*/
#define MODE_CONTROL_BASE          ((uint8_t)0x41)
#define MODE_CONTROL_ONE           ((uint8_t)(MODE_CONTROL_BASE + 0x00))
#define MODE_CONTROL_TWO           ((uint8_t)(MODE_CONTROL_BASE + 0x01))
#define MODE_CONTROL_THREE         ((uint8_t)(MODE_CONTROL_BASE + 0x02))
//---------------------------------------------------------------------------------------------------
/*
color data registers
*/
#define COLOR_DATA_BASE            ((uint8_t)0x50)
#define RED_DATA_LSBs              ((uint8_t)(COLOR_DATA_BASE + 0x00))
#define RED_DATA_MSBs              ((uint8_t)(COLOR_DATA_BASE + 0x01))
#define GREEN_DATA_LSBs            ((uint8_t)(COLOR_DATA_BASE + 0x02))
#define GREEN_DATA_MSBs            ((uint8_t)(COLOR_DATA_BASE + 0x03))
#define BLUE_DATA_LSBs             ((uint8_t)(COLOR_DATA_BASE + 0x04))
#define BLUE_DATA_MSBs             ((uint8_t)(COLOR_DATA_BASE + 0x05))
#define CLEAR_DATA_LSBs            ((uint8_t)(COLOR_DATA_BASE + 0x06))
#define CLEAR_DATA_MSBs            ((uint8_t)(COLOR_DATA_BASE + 0x07))
//---------------------------------------------------------------------------------------------------
/*
internal data registers
*/
#define INTERNAL_DATA_BASE         ((uint8_t)0x58)
#define DINT_DATA_LSBs             ((uint8_t)(INTERNAL_DATA_BASE + 0x00))
#define DINT_DATA_MSBs             ((uint8_t)(INTERNAL_DATA_BASE + 0x01))
//---------------------------------------------------------------------------------------------------
/*
Interrupt setting register
*/
#define INTERRUPT                  ((uint8_t)0x60)
//---------------------------------------------------------------------------------------------------
/*
Persistence setting register
*/
#define PERSISTENCE                ((uint8_t)0x61)
//---------------------------------------------------------------------------------------------------
/*
threshold data registers
*/
#define THRESHOLD_DATA_BASE        ((uint8_t)0x62)
#define TH_LSBs                    ((uint8_t)(THRESHOLD_DATA_BASE + 0x00))
#define TH_MSBs                    ((uint8_t)(THRESHOLD_DATA_BASE + 0x01))
#define TL_LSBs                    ((uint8_t)(THRESHOLD_DATA_BASE + 0x02))
#define TL_MSBs                    ((uint8_t)(THRESHOLD_DATA_BASE + 0x03))
//---------------------------------------------------------------------------------------------------
/*
Manufacturer ID register
*/
#define MANUFACTURER_ID            ((uint8_t)0x92) 
//---------------------------------------------------------------------------------------------------
//颜色数据结构体
typedef struct {
    uint16_t red_data;
    uint16_t green_data;
    uint16_t blue_data;
    uint16_t clear_data;
} Color_DataTypedef;

bool BH1745_Init(void);
void Get_Color_Data(Color_DataTypedef *);

#endif

  bh1745.c

 

/*
  * @file    bh1745.c
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/

#include "bh1745.h"
#include "soft_i2c.h"

/*
  * @func    Get_Red_Data
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static uint16_t Get_Red_Data(void)
{
    uint8_t H = 0, L = 0;
    uint16_t data = 0;
	
    I2C_Read_Reg(BH1745_READ, RED_DATA_MSBs, &H);
    data |= (uint16_t)H;
    I2C_Read_Reg(BH1745_READ, RED_DATA_LSBs, &L);
    data = (data << 8) | (uint16_t)L;
	
    return data;
}

/*
  * @func    Get_Green_Data
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static uint16_t Get_Green_Data(void)
{
    uint8_t H = 0, L = 0;
    uint16_t data = 0;
	
    I2C_Read_Reg(BH1745_READ, GREEN_DATA_MSBs, &H);
    data |= (uint16_t)H;
    I2C_Read_Reg(BH1745_READ, GREEN_DATA_LSBs, &L);
    data = (data << 8) | (uint16_t)L;
	
    return data;
}

/*
  * @func    Get_Blue_Data
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static uint16_t Get_Blue_Data(void)
{
    uint8_t H = 0, L = 0;
    uint16_t data = 0;
	
    I2C_Read_Reg(BH1745_READ, BLUE_DATA_MSBs, &H);
    data |= (uint16_t)H;
    I2C_Read_Reg(BH1745_READ, BLUE_DATA_LSBs, &L);
    data = (data << 8) | (uint16_t)L;
	
    return data;
}

/*
  * @func    Get_Clear_Data
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
static uint16_t Get_Clear_Data(void)
{
    uint8_t H = 0, L = 0;
    uint16_t data = 0;
	
    I2C_Read_Reg(BH1745_READ, CLEAR_DATA_MSBs, &H);
    data |= (uint16_t)H;
    I2C_Read_Reg(BH1745_READ, CLEAR_DATA_LSBs, &L);
    data = (data << 8) | (uint16_t)L;
	
    return data;
}

/*
  * @func    Get_Color_Data
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
void Get_Color_Data(Color_DataTypedef *color)
{
    color->red_data = Get_Red_Data();
    color->green_data = Get_Green_Data();
    color->blue_data = Get_Blue_Data();
    color->clear_data = Get_Clear_Data();
}

/*
  * @func    BH1745_Init
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/18
*/
bool BH1745_Init(void)
{
    uint8_t error_times = 0;  //错误次数
    uint8_t data = 0;
	
    //确认芯片id正确
    if (I2C_Read_Reg(BH1745_READ, MANUFACTURER_ID, &data) == false)  return false;	
    while (data != BH1745_ADDRESS << 2)  //0xe0,是BH1745_ADDRESS 左移两位
    {
        error_times++;
        if (error_times > 5)  return false;
        if (I2C_Read_Reg(BH1745_READ, MANUFACTURER_ID, &data) == false)  return false;	 
    }
    error_times = 0;
	
    //确认系统控制寄存器id正确
    if (I2C_Read_Reg(BH1745_READ, SYSTEM_CONTROL, &data) == false)  return false;
    while ((data & 0x3f) != SYSTEM_CONTROL_ID)
    {
        error_times++;
        if (error_times > 5)  return false;		
        if (I2C_Read_Reg(BH1745_READ, SYSTEM_CONTROL, &data) == false)  return false;
    }
	
    //开启复位
    if (I2C_Write_Reg(BH1745_WRITE, SYSTEM_CONTROL, 0x8b) == false) return false;
    
    //数据更新周期为160ms,这是最快了,还有320ms等
    if (I2C_Write_Reg(BH1745_WRITE, MODE_CONTROL_ONE, 0x00) == false) return false;	
	
    //设置AD为16位精度,并使能bh1745
    if (I2C_Write_Reg(BH1745_WRITE, MODE_CONTROL_TWO, 0x12) == false) return false;		
	
    return true;
}

  其中要注意的是id寄存器中的值是addr左移两位,再者就是数据更新周期的设定和ad精度的设定不能忘,其它也没什么了,按照官方 datasheet写就行了。其实采集函数还不全,只写了RGBC采集,后序可以逐步添加要采集的数据函数,这些本质是一样的。

  五、基于stm32平台上的模拟i2c

  模拟i2c就直接附上代码吧。。

  soft_i2c.h:

/*
  * @file    soft_i2c.h
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/

#ifndef __SOFT_I2C_H
#define __SOFT_I2C_H

#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stdio.h"
#include "stdbool.h"
#include "sys.h"
//---------------------------------------------------------------------------------------------------
//i2c引脚设置,我这里用的是C0和C2
#define I2C_GPIO                  GPIOC
#define I2C_CLOCK_ON              RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE)
#define I2C_SDA_PIN               0
#define I2C_SCL_PIN               2
#define GPIO_I2C_SDA_PIN          GPIO_Pin_0
#define GPIO_I2C_SCL_PIN          GPIO_Pin_2
#define SDA_PIN_0_7               1              //SDA引脚范围(0~7或8~15)
//---------------------------------------------------------------------------------------------------
#define SOFT_I2C_DELAY_LEVEL      10            //模拟i2c延时等级
//---------------------------------------------------------------------------------------------------
#if SDA_PIN_0_7                   //SDA引脚在0~7内,所以用CLR寄存器																																				   
#define I2C_SDA_OUT()           { I2C_GPIO->CRL &= ~((uint32_t)0xf << 4 * I2C_SDA_PIN);\
                                  I2C_GPIO->CRL |=  ((uint32_t)0x3 << 4 * I2C_SDA_PIN); }        //推挽输出,速度50MHZ 	
#define I2C_SDA_IN()            { I2C_GPIO->CRL &= ~((uint32_t)0xf << 4 * I2C_SDA_PIN);\
                                  I2C_GPIO->CRL |=  ((uint32_t)0x4 << 4 * I2C_SDA_PIN); }	       //浮空输入

#else                             //SDA引脚在8~15内,所以CRH寄存器																														
#define I2C_SDA_OUT()           { I2C_GPIO->CRH &= ~((uint32_t)0xf << 4 * (I2C_SDA_PIN - 8));\
                                  I2C_GPIO->CRH |=  ((uint32_t)0x3 << 4 * (I2C_SDA_PIN - 8)); }  //推挽输出,速度50MHZ 	 
#define I2C_SDA_IN()            { I2C_GPIO->CRL &= ~((uint32_t)0xf << 4 * (I2C_SDA_PIN - 8));\
                                  I2C_GPIO->CRL |=  ((uint32_t)0x4 << 4 * (I2C_SDA_PIN - 8)); }  //浮空输入
#endif
//---------------------------------------------------------------------------------------------------
//更换GPIO时一定不能忘了改这里
#define I2C_SDA_H                (PCout(I2C_SDA_PIN) = 1)                  
#define I2C_SDA_L                (PCout(I2C_SDA_PIN) = 0)
#define I2C_SCL_H                (PCout(I2C_SCL_PIN) = 1)                  
#define I2C_SCL_L                (PCout(I2C_SCL_PIN) = 0)												
#define I2C_SDA_IN_DATA          PCin(I2C_SDA_PIN)   																		
//---------------------------------------------------------------------------------------------------
																		
void Soft_I2C_Init(void);
bool I2C_Read_Buff(uint8_t addr_with_read, uint8_t reg_addr, uint8_t *buff, size_t size);
bool I2C_Read_Reg(uint8_t addr_with_read, uint8_t reg_addr, uint8_t *data);
bool I2C_Write_Reg(uint8_t addr_with_write, uint8_t reg_addr, uint8_t data);																		
																		
#endif

  soft_i2c.c

 

/*
  * @file    soft_i2c.h
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/

#include "soft_i2c.h"

/*
  * @func    I2C_Delay
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_Delay(uint8_t t)
{
    uint8_t i = 0;
	
    while (t--)
    {
        i = SOFT_I2C_DELAY_LEVEL;
        while (i--);
    }
}

/*
  * @func    I2C_Start
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_Start(void)
{
    I2C_SDA_OUT();
    I2C_SDA_H;
    I2C_SCL_H;
    I2C_Delay(2);
    I2C_SDA_L;
    I2C_Delay(2);
    I2C_SCL_L;	
    I2C_Delay(2);
}

/*
  * @func    I2C_Stop
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_Stop(void)
{
    I2C_SDA_OUT();
    I2C_SCL_L;	
    I2C_SDA_L;
    I2C_Delay(2);
    I2C_SCL_H;
    I2C_Delay(2);
    I2C_SDA_H;	
    I2C_Delay(2);
}

/*
  * @func    I2C_Wait_Ack
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static bool I2C_Wait_Ack(void)
{
    uint8_t err_time = 0;
	
    I2C_SCL_L;
    I2C_Delay(1);
    I2C_SDA_H;
    I2C_Delay(1);
    I2C_SDA_IN();
    I2C_Delay(1);
    I2C_SCL_H;
    I2C_Delay(1);
	
    while (I2C_SDA_IN_DATA)
    {
        err_time++;
        if (err_time > 250)
            return true;
    }
	
    I2C_SCL_L;
    I2C_Delay(1);
	
    return false;
}

/*
  * @func    I2C_Ack
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_Ack(void)
{
    I2C_SCL_L;
    I2C_Delay(1);
    I2C_SDA_OUT();
    I2C_SDA_L;
    I2C_Delay(1);
    I2C_SCL_H;
    I2C_Delay(1);
    I2C_SCL_L;
    I2C_Delay(1);	
}

/*
  * @func    I2C_NAck
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_NAck(void)
{
    I2C_SCL_L;
    I2C_Delay(1);
    I2C_SDA_OUT();
    I2C_SDA_H;
    I2C_Delay(1);
    I2C_SCL_H;
    I2C_Delay(1);
    I2C_SCL_L;
    I2C_Delay(1);	  	
}

/*
  * @func    I2C_Send_Byte
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static void I2C_Send_Byte(uint8_t data)
{
    uint8_t i;
	
    I2C_SDA_OUT();
    I2C_SCL_L;
	
    for (i = 0; i < 8; i++)
    {
        if ((data & (uint8_t)0x80) >> 7)
            I2C_SDA_H;
        else
            I2C_SDA_L;		
        data <<= 1;
        I2C_Delay(1);
        I2C_SCL_H;
        I2C_Delay(1);		
        I2C_SCL_L;
        I2C_Delay(1);
    }
}	

/*
  * @func    I2C_Read_Byte
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
static uint8_t I2C_Read_Byte(void)
{
    uint8_t i, reveive_byte = 0;
	
    I2C_SDA_IN();
	
    for (i = 0; i < 8; i++)
    {
        I2C_SCL_L;
        I2C_Delay(1);
        I2C_SCL_H;
        I2C_Delay(1);	
		
        reveive_byte <<= 1;
        if (I2C_SDA_IN_DATA)
        reveive_byte |= (uint8_t)0x01;
    }
	
    return reveive_byte;
}

/*
  * @func    I2C_Write_Reg
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
bool I2C_Write_Reg(uint8_t addr_with_write, uint8_t reg_addr, uint8_t data)
{
    I2C_Start();
	
    I2C_Send_Byte(addr_with_write);
    if (I2C_Wait_Ack())  return false;
	
    I2C_Send_Byte(reg_addr);
    if (I2C_Wait_Ack())  return false;
	
    I2C_Send_Byte(data);
    if (I2C_Wait_Ack())  return false;

    I2C_Stop();
    return true;	
}	

/*
  * @func    I2C_Read_Reg
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
bool I2C_Read_Reg(uint8_t addr_with_read, uint8_t reg_addr, uint8_t *data)
{	
    I2C_Start();
	
    I2C_Send_Byte(addr_with_read & (uint8_t)0xfe);
    if (I2C_Wait_Ack())  return false;	

    I2C_Send_Byte(reg_addr);
    if (I2C_Wait_Ack())  return false;	
	
    I2C_Start();
	
    I2C_Send_Byte(addr_with_read);
    if (I2C_Wait_Ack())  return false;	

    *data = I2C_Read_Byte();
    I2C_NAck();
    I2C_Stop();

    return true;	
}

/*
  * @func    I2C_Read_Buff
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
bool I2C_Read_Buff(uint8_t addr_with_read, uint8_t reg_addr, uint8_t *buff, size_t size)
{
    uint8_t i;
	
    I2C_Start();
	
    I2C_Send_Byte(addr_with_read & (uint8_t)0xfe);
    if (I2C_Wait_Ack())  return false;	

    I2C_Send_Byte(reg_addr);
    if (I2C_Wait_Ack())  return false;	
	
    I2C_Start();
	
    I2C_Send_Byte(addr_with_read);
    if (I2C_Wait_Ack())  return false;	

    for (i = 0; i < size; i++)
    {
        *buff++ = I2C_Read_Byte();
        if (i < size - 1)
            I2C_Ack();
    }
    I2C_NAck();
    I2C_Stop();
	
    return true;
}

/*
  * @func    Soft_I2C_Init
  * @author  taoshi
  * @version V1.0.0
  * @date    2018/9/16
*/
void Soft_I2C_Init(void)
{
    GPIO_InitTypeDef GPIO_Init_Structure;
	
    I2C_CLOCK_ON;	
    GPIO_Init_Structure.GPIO_Pin = GPIO_I2C_SDA_PIN | GPIO_I2C_SCL_PIN;
    GPIO_Init_Structure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_Init_Structure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(I2C_GPIO, &GPIO_Init_Structure);
    GPIO_SetBits(I2C_GPIO, GPIO_I2C_SDA_PIN | GPIO_I2C_SCL_PIN);	
}

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值