GXHTC3温湿度芯片,STM32、C51驱动程序

GXHTC3温湿度芯片,STM32、C51驱动程序

 一、资源说明 

 二、基本参数

 三、参考驱动

 四、注意事项

一、资源说明

        GXHTC3温湿度芯片,是新型高精度单芯片集成温湿度传感IC是“在硅基CMOS晶圆上集成高灵敏度MEMS湿敏元件,把温度补偿和标定数据都集成在一个电路里”,实现湿敏电容结构和信号处理电路的单芯片集成,减少并降低了传感器的体积和成本,同时降低信号传输带来的干扰,提高产品精度、可靠性、一致性。

        GXHTC3是一款低功耗的温湿度传感器,工作电压1.6 ~ 5.5V,温度测量范围为-45°C ~ 135°C,湿度测量范围为 0 ~ 100%RH,可支持二次过标准回流焊接,限制最高温度为260℃,焊接完成无需水合处理,常温下24小时自然恢复,并有防尘透气膜、可喷三防漆膜版本可选。

二、基本参数

        GXHTC3 基本电器参数如下:

 三、参考驱动

1、GXHTC3芯片引脚定义图

 2、GXHTC3芯片硬件参考电路图

        GXHTC3使用标准IIC通信协议,支持400KHZ通信速率,SCL、SDA通信引脚开漏输出,需要加1-10K可选上拉电阻,VDD和GND之间需要加100nF的去耦电容,该电容离传感器越近越好。

 3、芯片IIC器件地址

        GXHTC3芯片只有一个固定的IIC器件通信地址,0x70。

 4、温湿度测量和数据读取 

         每一次测量都包含四组命令,并且以 STRAT 信号开 始,终止于 STOP 信号。具体执行顺序如下:

        1) 唤醒命令(0x3517)

        2) 测量命令(0x7866 正常模式 温度在前湿度在后)

        3.)读出命令

        4.)休眠命令(0xB098)

5、典型测量时序图

6、驱动实例

        STM32F103 + GXHTC3温湿度芯片驱动实例
        GXHTC3.h文件
#ifndef _GXHTC3_H
#define _GXHTC3_H

#include "stm32f10x.h"
#include "string.h"
#include "stdio.h"


//如果移植程序时只要改一下三个地方就行了
/* 定时使用的IO口 */
#define GXHTC3_SCL GPIO_Pin_5	  //PA5
#define GXHTC3_SDA GPIO_Pin_6	  //PA6
#define GPIO_GXHTC3 GPIOA

#define GXHTC3_SCL_H GPIO_SetBits(GPIO_GXHTC3,GXHTC3_SCL)
#define GXHTC3_SCL_L GPIO_ResetBits(GPIO_GXHTC3,GXHTC3_SCL)

#define GXHTC3_SDA_H GPIO_SetBits(GPIO_GXHTC3,GXHTC3_SDA)
#define GXHTC3_SDA_L GPIO_ResetBits(GPIO_GXHTC3,GXHTC3_SDA)

/* 声明全局函数 */
void GXHTC3_INIT(void);
void GXHTC3_SDA_OUT(void);
void GXHTC3_SDA_IN(void);
void GXHTC3_SDA_in(void);

void GXHTC3_StarT(void);
void GXHTC3_StoP(void);
void GXHTC3_Ack(void);
void GXHTC3_NAck(void);
u8   GXHTC3_Wait_Ack(void);
void GXHTC3_Send_Byte(u8 txd);
u8   GXHTC3_Read_Byte(u8 ack);
void GXHTC3_read_result(u8 addr);

void al_get_gxth30_temp(void);

#endif
GXHTC3.C文件
#include "GXHTC3.h"
#include "delay.h"

#define write 0
#define read  1
float GXHTC3_temp,GXHTC3_humi,GXHTC3_Temperature,GXHTC3_Humidity;

/*
* @name   CRC_8
* @brief  CRC-8校验
* @param  Crc_ptr -> 校验数据首地址
		  LEN     -> 校验数据长度
* @retval CRC_Value -> 校验值      
*/
static uint8_t CRC_8(uint8_t *Crc_ptr,uint8_t LEN)
{
	uint8_t CRC_Value = 0xFF;
	uint8_t i = 0,j = 0;

	for(i=0;i<LEN;i++)
	{
		CRC_Value ^= *(Crc_ptr+i);
		for(j=0;j<8;j++)
		{
			if(CRC_Value & 0x80)
				CRC_Value = (CRC_Value << 1) ^ 0x31;
			else
				CRC_Value = (CRC_Value << 1);
		}
	}
	return CRC_Value;
}


/****************************************************************************
* Function Name  : GXHTC3_INIT
* Description    : 初始化GPIO.
****************************************************************************/
void GXHTC3_INIT()
{	
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin = GXHTC3_SDA;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
			
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	GPIO_InitStructure.GPIO_Pin = GXHTC3_SCL;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);

	GXHTC3_SCL_H;
	GXHTC3_SDA_H;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_SDA_OUT
* 函数功能		   : SDA输出配置	   
*******************************************************************************/
void GXHTC3_SDA_OUT()
{
  GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHTC3_SDA;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_10MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

/*******************************************************************************
* 函 数 名         : GXHTC3_SDA_IN
* 函数功能		   : SDA输入配置	   
*******************************************************************************/
void GXHTC3_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHTC3_SDA;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_OD;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

void GXHTC3_SDA_in(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	
	GPIO_InitStructure.GPIO_Pin=GXHTC3_SDA;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
}

/*******************************************************************************
* 函 数 名         : GXHTC3_StarT
* 函数功能		   : 产生起始信号
*******************************************************************************/
void GXHTC3_StarT(void)
{
  GXHTC3_SDA_OUT();
	
	GXHTC3_SDA_H;
	GXHTC3_SCL_H;
	delay_us(5);
	GXHTC3_SDA_L;
	delay_us(6);
	GXHTC3_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_StoP
* 函数功能		   : 产生停止信号
*******************************************************************************/
void GXHTC3_StoP(void)
{
   GXHTC3_SDA_OUT();

   GXHTC3_SCL_L;
   GXHTC3_SDA_L;
   GXHTC3_SCL_H;
   delay_us(6);
   GXHTC3_SDA_H;
   delay_us(6);
}

/*******************************************************************************
* 函 数 名         : GXHTC3_Ack
* 函数功能		   : 主机产生应答信号ACK
*******************************************************************************/
void GXHTC3_Ack(void)
{
   GXHTC3_SCL_L;
   GXHTC3_SDA_OUT();
   GXHTC3_SDA_L;
   delay_us(2);
   GXHTC3_SCL_H;
   delay_us(5);
   GXHTC3_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_NAck
* 函数功能		   : 主机不产生应答信号NACK
*******************************************************************************/
void GXHTC3_NAck(void)
{
   GXHTC3_SCL_L;
   GXHTC3_SDA_OUT();
   GXHTC3_SDA_H;
   delay_us(2);
   GXHTC3_SCL_H;
   delay_us(5);
   GXHTC3_SCL_L;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_Wait_Ack
* 函数功能		   : 等待从机应答信号
  返回值:            1 接收应答失败
		  	         0 接收应答成功
*******************************************************************************/
u8 GXHTC3_Wait_Ack(void)
{
	u8 tempTime=0;
	GXHTC3_SDA_IN();
	GXHTC3_SDA_H;
	delay_us(1);
	GXHTC3_SCL_H;
	delay_us(1);

	while(GPIO_ReadInputDataBit(GPIO_GXHTC3,GXHTC3_SDA))
	{
		tempTime++;
		delay_us(1);
		if(tempTime>250)
		{
			GXHTC3_StoP();
			return 1;
		}	 
	}
	GXHTC3_SCL_L;
	delay_us(1);
	return 0;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_Send_Byte
* 函数功能		   : GXHTC3 发送一个字节
*******************************************************************************/
void GXHTC3_Send_Byte(u8 txd)
{
	u8 i=0;
	GXHTC3_SDA_OUT();
	GXHTC3_SCL_L;//拉低时钟开始数据传输

	for(i=0;i<8;i++)
	{
		if((txd&0x80)>0) //0x80  1000 0000
			GXHTC3_SDA_H;
		else
			GXHTC3_SDA_L;

		txd<<=1;
		delay_us(1);
		GXHTC3_SCL_H;
		delay_us(2); //发送数据
		GXHTC3_SCL_L;
		delay_us(2);
	}
}

/*******************************************************************************
* 函 数 名         : GXHTC3_Read_Byte
* 函数功能		   : GXHTC3 主机读取一个字节
*******************************************************************************/
u8 GXHTC3_Read_Byte(u8 ack)
{
   u8 i=0,receive=0;

   GXHTC3_SDA_in();
   for(i=0;i<8;i++)
   {
   		GXHTC3_SCL_L;
		delay_us(2);
		GXHTC3_SCL_H;
		while(!GPIO_ReadInputDataBit(GPIO_GXHTC3,GXHTC3_SCL));
		receive<<=1;
		if(GPIO_ReadInputDataBit(GPIO_GXHTC3,GXHTC3_SDA))
		   receive++;
		delay_us(1);	
   }

   	if(ack==0)
	   	GXHTC3_NAck();
	else
		GXHTC3_Ack();

	return receive;
}

/*******************************************************************************
* 函 数 名         : GXHTC3_read_result
* 函数功能		   : GXHTC3 读6个字节数据
*******************************************************************************/
void GXHTC3_read_result(u8 addr)
{
	u16 tem,hum;
	unsigned char buff[6];

	float Temperature=0;
	float Humidity=0;
		
	GXHTC3_StarT();
	GXHTC3_Send_Byte(addr<<1 | write);//写7位GXHTC3设备地址加0作为写取位,1为读取位
	GXHTC3_Wait_Ack();
	GXHTC3_Send_Byte(0x78);
	GXHTC3_Wait_Ack();
	GXHTC3_Send_Byte(0x66);
	GXHTC3_Wait_Ack();
	GXHTC3_StoP();
	
	delay_ms(15);                    //数据转换等待时间
	
	GXHTC3_StarT();
	GXHTC3_Send_Byte(addr<<1 | read);//写7位GXHTC3设备地址加0作为写取位,1为读取位
	
	if(GXHTC3_Wait_Ack()==0)
	{
		GXHTC3_SDA_in();
			
		buff[0]=GXHTC3_Read_Byte(1);
		buff[1]=GXHTC3_Read_Byte(1);
		buff[2]=GXHTC3_Read_Byte(1);
		buff[3]=GXHTC3_Read_Byte(1);
		buff[4]=GXHTC3_Read_Byte(1);
		buff[5]=GXHTC3_Read_Byte(0);
		GXHTC3_StoP();
		
		if(CRC_8(buff, 2) == buff[2] && CRC_8(buff + 3, 2) == buff[5])
		{
			tem = ((buff[0]<<8) | buff[1]);//温度拼接
			hum = ((buff[3]<<8) | buff[4]);//湿度拼接
			/*转换实际温度*/
			Temperature= (175.0*(float)tem/65535.0-45.0) ;// T = -45 + 175 * tem / (2^16-1)
			Humidity= (100.0*(float)hum/65535.0);// RH = hum*100 / (2^16-1)
		}
		else
		{
			GXHTC3_temp = 0;
			GXHTC3_humi = 0;
		}
		
		
}
	
	if((Temperature>=-20)&&(Temperature<=125)&&(Humidity>=0)&&(Humidity<=100))//过滤错误数据
	{
		GXHTC3_temp = Temperature;
		GXHTC3_humi = Humidity;
	}

	tem = 0;
	hum = 0;
}

/*******************************************************************************
* 函 数 名         : al_float_buffer_sort
* 函数功能		   : 多次读数值排序取中间值平均
*******************************************************************************/
void al_float_buffer_sort(float *buf, uint8_t length)
{
	uint8_t i, j;
	float tmp;
	for (i = 0; i < length; i++)
	{
		for (j = i + 1; j < length; j++)
		{
			if (buf[j] < buf[i])
			{
				tmp = buf[j];
				buf[j] = buf[i];
				buf[i] = tmp;
			}
		}
	}
}


void al_get_gxth30_temp(void)
{
	float buff_temp[20],buff_humi[20];
	for(u8 i = 0;i < 10;i++)
	{	
		GXHTC3_read_result(0x70);
		buff_temp[i] = GXHTC3_temp;
		buff_humi[i] = GXHTC3_humi;
	}
	
	al_float_buffer_sort(buff_temp,10);
	al_float_buffer_sort(buff_humi,10);
	
	GXHTC3_Temperature = (buff_temp[4] + buff_temp[5]) / 2;
	GXHTC3_Humidity = (buff_humi[4] + buff_humi[5]) / 2;
	
	printf("温度:%0.2f, 湿度:%0.2f",GXHTC3_Temperature,GXHTC3_Humidity);
}

        C51 + GXHTC3温湿度芯片驱动实例
        GXHTC3.h文件
#ifndef _GXHTC3_H_
#define _GXHTC3_H_

#include "main.h"

sbit SCL  = P3^5;    //I2C时钟线
sbit SDA  = P3^6;    //I2C数据线

#define ACK	0
#define NACK	1

extern float Temp,Humi;

// Error codes
typedef enum{
  NO_ERROR       = 0x00, // no error
  ACK_ERROR      = 0x01, // no acknowledgment error
  CHECKSUM_ERROR = 0x02, // checksum mismatch error
  TIMEOUT_ERROR  = 0x04, // timeout error
  PARM_ERROR     = 0x80, // parameter out of range error
}etError;

extern etError error;

// Sensor Commands
typedef enum
{
	
	CMD_Low_Power_Mode	= 0x7CA2,   //read low power mode cmd
	CMD_Sleep						= 0xB098,
	CMD_Wakeup					    = 0x3517,

}etCommands;

#define GXHTC3ADDR 0x70                 //GXHTC3的I2C地址
#define GXHTC3WriteHeader GXHTC3ADDR<<1
#define GXHTC3ReadHeader  GXHTC3WriteHeader | 1

extern void Sys_IIC_Init(void);
extern etError GXHTC3_XHGetTempAndHumi(float        *temp,
                                       float        *humi);

extern void al_get_gxthc3_tempandhumi(void);

#endif
 GXHTC3.c文件
#include "gxhtc3.h"
#include "delay.h"
#include "io.h"

#include <stdio.h>
#include <intrins.h>

float gxhtc3_temp_val,gxhtc3_humi_val;

void Sys_IIC_Init(void)
{	
	SCL = 1;       		//I2C时钟线
    SDA = 1;       		//I2C数据线
}


#define POLYNOMIAL  0x31 // P(x) = x^8 + x^5 + x^4 + 1 = 00110001

etError error;

unsigned char GXHTC3_CalcCrc(unsigned char *crcdata, unsigned char nbrOfBytes)
{
  unsigned char Bit;        // bit mask
  unsigned char crc = 0xFF; // calculated checksum
  unsigned char byteCtr;    // byte counter
  
  // calculates 8-Bit checksum with given polynomial 
  for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
  {
    crc ^= (crcdata[byteCtr]);
    for(Bit = 8; Bit > 0; --Bit)
    {
      if(crc & 0x80) crc = (crc << 1) ^ POLYNOMIAL;
      else           crc = (crc << 1);
    }
  }
	return crc;
}


///*******I2C总线启动函数*************/
void I2C_Start(void)
{
    SDA = 1;
    delay_5us();
    SCL = 1;
    delay_5us();
    SDA = 0;
    delay_5us();
    SCL = 0;
    delay_5us();
}

///*******I2C总线停止函数*************/
void I2C_Stop(void)
{
    SDA = 0;
		SCL = 0;
    delay_5us();
    SCL = 1;
    delay_5us();
    SDA = 1;
    delay_5us();
}


///*================================================================
//【名 称】unsigned char I2CWRByte(unsigned char WRByte)
//【功 能】I2C写一个字节数据,返回ACK或者NACK
//【备 注】从高到低,依次发送
//================================================================*/
etError I2CWRByte(unsigned char WRByte)
{
	unsigned char i;
	
	SCL = 0;
	for(i=0;i<8;i++)
	{
		if(WRByte&0x80)
		{
			SDA = 1;	
		}
		else
		{
			SDA = 0;
		}
		delay_5us();
		SCL=1;			//输出SDA稳定后,拉高SCL给出上升沿,从机检测到后进行数据采样
		delay_5us();
		SCL=0;
		delay_5us();
		WRByte <<= 1;
	} 
	SDA = 1;
	SCL = 1;
	delay_5us();
	if(SDA==1)			//SDA为高,收到NACK
	{
		SCL=0;
		delay_5us();
		return NO_ERROR;	
	}
	else 				//SDA为低,收到ACK
	{
		SCL=0;
		delay_5us();
		return ACK_ERROR;
	}
}

///*================================================================
//【名 称】unsigned char I2CRDByte(unsigned char AckValue)
//【功 能】I2C读一个字节数据,入口参数用于控制应答状态,ACK或者NACK
//【备 注】从高到低,依次接收
//================================================================*/
unsigned char I2CRDByte(unsigned char AckValue)
{
	unsigned char i,RDByte=0;
	
	SCL = 0;
	SDA = 1;			//释放总线	
	for (i=0;i<8;i++) 
	{
		RDByte <<= 1;	//移位
		SCL = 1;		//给出上升沿
		delay_5us();	//延时等待信号稳定
		if(SDA==1) 		//采样获取数据
		{
			RDByte |= 0x01;
		}
		else
		{
			RDByte &= 0xfe;
		}
		SCL = 0;   		//下降沿,从机给出下一位值
		delay_5us();
	}  

	
	SDA =  AckValue;	//应答状态
	delay_5us();
	SCL = 1;                         
    delay_5us();        
    SCL = 0;
    SDA = 1;                
    delay_5us();

	return RDByte;
}

etError GXHTC3_WriteCommand(etCommands cmd)
{
  etError error; // error code
  // write the upper 8 bits of the command to the sensor
  error  = I2CWRByte(cmd >> 8);
  // write the lower 8 bits of the command to the sensor
  error |= I2CWRByte(cmd & 0xFF);
	
  return error;
}

///*================================================================
//【名 称】void GXHTC3_WAKE_UP(void)
//【功 能】唤醒芯片
//================================================================*/
void GXHTC3_WAKE_UP(void)
{
	I2C_Start();                //启动总线
	I2CWRByte(GXHTC3WriteHeader);
	GXHTC3_WriteCommand(CMD_Wakeup);
	I2C_Stop();
	delay_5us();
}

///*================================================================
//【名 称】void GXHTC3_INTO_SLEEP(void)
//【功 能】配置芯片进入休眠
//================================================================*/
void GXHTC3_INTO_SLEEP(void)
{
	I2C_Start();                //启动总线
	I2CWRByte(GXHTC3WriteHeader);
	GXHTC3_WriteCommand(CMD_Sleep);
	I2C_Stop();
	delay_5us();
}

etError GXHTC3_XHGetTempAndHumi(float        *temp,
                                float        *humi)
{
  float    rawValueTemp,rawValueHumi;    // temperature raw value from sensor	
  unsigned char i;
  unsigned char buff[6];

  GXHTC3_WAKE_UP();
  
  I2C_Start();
  error  = I2CWRByte(GXHTC3WriteHeader);	
	
  // if no error ...
  if(error == NO_ERROR)
  {
     error = GXHTC3_WriteCommand(CMD_Low_Power_Mode);
		 I2C_Stop();
  }
	
  delay_ms(20);	                        //等待数据完成转换
	
  if(error == NO_ERROR)
  {
		I2C_Start();
		error  = I2CWRByte(GXHTC3ReadHeader);
	}

	// if no error, read temperature and humidity raw values
  if(error == NO_ERROR)
  {			
		for(i=0;i<5;i++)
		{
			buff[i] = I2CRDByte(ACK);
		}
    buff[i] = I2CRDByte(NACK);
		
		I2C_Stop();	
		if(buff[2]!=GXHTC3_CalcCrc(buff,2))     error = CHECKSUM_ERROR;
	  if(buff[5]!=GXHTC3_CalcCrc(&buff[3],2)) error = CHECKSUM_ERROR;	
  }
  // if no error, calculate temperature in  and humidity in %RH
	if(error == NO_ERROR)
	{
		rawValueTemp =(buff[0] * 256) + buff[1];		
		rawValueHumi =(buff[3] * 256) + buff[4];
		
        *temp =175.0 * rawValueTemp / 65535 - 45.0;        //  --温度真实值 * 10    
		*humi =100 * rawValueHumi / 65535;              //  --湿度真实值 * 10
	}
  
	rawValueTemp = 0;
	rawValueHumi = 0;
	
	GXHTC3_INTO_SLEEP();
	
    return error;
}

/*******************************************************************************
* 函 数 名         : al_float_buffer_sort
* 函数功能		   : 多次读数值排序取中间值平均
*******************************************************************************/
void al_float_buffer_sort(float *buf, uint8_t length)
{
	uint8_t i, j;
	float tmp;
	for (i = 0; i < length; i++)
	{
		for (j = i + 1; j < length; j++)
		{
			if (buf[j] < buf[i])
			{
				tmp = buf[j];
				buf[j] = buf[i];
				buf[i] = tmp;
			}
		}
	}
}

void al_get_gxthc3_tempandhumi(void)
{
	float buff_temp[4],buff_humi[4];
	uint8_t i;
	
	for(i = 0;i < 4;i++)
	{	
		GXHTC3_XHGetTempAndHumi(&gxhtc3_temp_val,&gxhtc3_humi_val);	
		buff_temp[i] = gxhtc3_temp_val;
		buff_humi[i] = gxhtc3_humi_val;
	}
		
	al_float_buffer_sort(buff_temp,4);
	al_float_buffer_sort(buff_humi,4);
	
	gxhtc3_temp_val = (buff_temp[1] + buff_temp[2]) / 2;
	gxhtc3_humi_val = (buff_humi[2] + buff_humi[2]) / 2;
}





四、注意事项

1、IIC总线SCL、SDA必须加上拉电阻,建议1~10K,一般选择4.7K或者10K即可;
2、主机发送完数据转换命令,必须加一定的延时(参考规格书),确保芯片完成数据转换,再读数据;
3、主机读6个字节数据,最好加上CRC校验,确保数据没问题,最后一个字节发送NACK,终止IIC通信。

友情提示:

欢迎各位伙伴咨询、测试GXHTC3温湿度传感器,有任何问题可随时沟通交流。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值