STM32驱动ADXL345三轴传感器

简介:STM32F103C8T6驱动ADXL345三轴倾斜度传感器源码介绍。

开发平台:KEIL ARM

MCU型号:STM32F103C8T6

传感器型号:ADXL345

特别提示:驱动内可能使用了某些其他组件,比如delay等,在文末外设模板下载地址内有。

1积分源码下载地址在文末!!!

接口图:

使用举例:

#include <stdio.h>
#include "ADXL345.h"

int main()
{
	float angleX, angleY, angleZ;
	ADXL345_init(); // 初始化
	while(1) {
		delayMs(1000);
		get_angle(&angleX, &angleY, &angleZ); // 获取三轴偏移角度
		printf("angle X:%f  Y:%f  Z:%f\n", angleX, angleY, angleZ);
	}
}

驱动源码:

IIC.c

#include "main.h"


#define IIC_SDA_PORT		GPIOA
#define IIC_SDA_CLK			(RCC_APB2Periph_GPIOA)
#define IIC_SDA_PIN			GPIO_Pin_5
#define IIC_SCL_PORT		GPIOA
#define IIC_SCL_CLK			(RCC_APB2Periph_GPIOA)
#define IIC_SCL_PIN			GPIO_Pin_6

#define IIC_SCL_OUT_1		IIC_SCL_PORT->BSRR = (uint32_t)IIC_SCL_PIN // 置1
#define IIC_SCL_OUT_0		IIC_SCL_PORT->BRR = (uint32_t)IIC_SCL_PIN
#define IIC_SDA_OUT_1		IIC_SDA_PORT->BSRR = (uint32_t)IIC_SDA_PIN // 置1
#define IIC_SDA_OUT_0		IIC_SDA_PORT->BRR = (uint32_t)IIC_SDA_PIN
#define IIC_SDA_IN()		((IIC_SDA_PORT->IDR & IIC_SDA_PIN) != 0)

/**
  * @brief  IIC延时
  * @param  None
  * @retval None
  */
static void IIC_Delay(void)
{
	uint8_t i;
	/* 
	 	下面的时间是通过逻辑分析仪测试得到的。
    工作条件:CPU主频72MHz ,MDK编译环境,1级优化
  
		循环次数为10时,SCL频率 = 205KHz 
		循环次数为7时,SCL频率 = 347KHz, SCL高电平时间1.5us,SCL低电平时间2.87us 
	 	循环次数为5时,SCL频率 = 421KHz, SCL高电平时间1.25us,SCL低电平时间2.375us 
	*/
	for (i = 0; i < 10; i++);
}
/**
  * @brief  SDA输出方向配置
  * @param  None
  * @retval None
  */
void Set_IIC_SDA_OUT(void)
{
  GPIO_InitTypeDef GPIO_InitStructure;	
	RCC_APB2PeriphClockCmd(IIC_SDA_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_OD;
	GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure); 						
}
/**
  * @brief  SDA输入方向配置
  * @param  None
  * @retval None
  */
void Set_IIC_SDA_IN(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;	
	RCC_APB2PeriphClockCmd(IIC_SDA_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin=IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;
	GPIO_Init(IIC_SDA_PORT,&GPIO_InitStructure);
}
/**
  * @brief  模拟IIC初始化
  * @param  None
  * @retval None
  */
void IIC_init()
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_APB2PeriphClockCmd(IIC_SDA_CLK | IIC_SCL_CLK, ENABLE);
	GPIO_InitStructure.GPIO_Pin = IIC_SDA_PIN;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD; 		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;	
	GPIO_Init(IIC_SDA_PORT, &GPIO_InitStructure);	
	GPIO_InitStructure.GPIO_Pin = IIC_SCL_PIN;
	GPIO_Init(IIC_SCL_PORT, &GPIO_InitStructure);	
	IIC_stop();
}
/**
  * @brief  模拟IIC起始信号
  * @param  None
  * @retval None
  */
void IIC_start()
{
	Set_IIC_SDA_OUT();
	IIC_SCL_OUT_1;
	IIC_SDA_OUT_1;
	IIC_Delay();
	IIC_SDA_OUT_0;
	IIC_Delay();
	IIC_SCL_OUT_0;
	IIC_Delay();
}
/**
  * @brief  模拟IIC停止信号
  * @param  None
  * @retval None
  */
void IIC_stop()
{
	Set_IIC_SDA_OUT();
	IIC_SCL_OUT_1;
	IIC_SDA_OUT_0;
	IIC_Delay();
	IIC_SDA_OUT_1;
}
/**
  * @brief  模拟IIC主机应答
  * @param  None
  * @retval None
  */
void IIC_ack()
{
	Set_IIC_SDA_OUT();
  IIC_SDA_OUT_0;
	IIC_Delay();
	IIC_SCL_OUT_1;
	IIC_Delay();
	IIC_SCL_OUT_0;
	IIC_Delay();	
	IIC_SDA_OUT_1;
}
/**
  * @brief  模拟IIC主机不应答
  * @param  None
  * @retval None
  */
void IIC_noack()
{
	Set_IIC_SDA_OUT();
  IIC_SDA_OUT_1;
	IIC_Delay();
	IIC_SCL_OUT_1;
	IIC_Delay();
	IIC_SCL_OUT_0;
	IIC_Delay();
}
/**
  * @brief  模拟IIC等待从机应答
  * @param  None
	* @retval 1: 接收应答失败 0: 接收应答成功
  */
uint8_t IIC_wait_ack()
{
	uint8_t rec = 0;
	Set_IIC_SDA_OUT();
	IIC_SDA_OUT_1;
	IIC_Delay();
	Set_IIC_SDA_IN();
	IIC_SCL_OUT_1;
	IIC_Delay();
	rec = IIC_SDA_IN();
	IIC_SCL_OUT_0;
	IIC_Delay();
	
	return rec;
}
/**
	* @brief  模拟IIC发送一个字节
  * @param  None
  * @retval None
  */
void IIC_send_byte(uint8_t txd)
{
	uint8_t i=0;
	Set_IIC_SDA_OUT();
	for(i=0;i<8;i++)
	{
		if(txd&0x80) IIC_SDA_OUT_1;
		else IIC_SDA_OUT_0;
		IIC_Delay();
		IIC_SCL_OUT_1;
		IIC_Delay(); // 发送数据
		IIC_SCL_OUT_0;
		if(i == 7) IIC_SDA_OUT_1; // 最后一位数据发送完要释放SDA总线
		txd <<= 1;
		IIC_Delay();
	}
}
/**
	* @brief  模拟IIC读取一个字节
	* @param  ack: 0,读完不产生应答 1,读完产生应答
  * @retval 返回读取到的字节
  */
uint8_t IIC_read_byte(uint8_t ack)
{
	uint8_t i,receive=0;
	Set_IIC_SDA_IN();
	for(i=0;i<8;i++)
	{
		receive <<= 1;
		IIC_SCL_OUT_1;
		IIC_Delay();
		if(IIC_SDA_IN()) receive++; // 连续读取八位
		IIC_SCL_OUT_0;
		IIC_Delay();	
	}
  if(!ack) IIC_noack();
	else IIC_ack();

	return receive; // 返回读取到的字节
}

IIC.h 

#ifndef __IIC_H
#define __IIC_H

#include "main.h"

void Set_IIC_SDA_OUT(void);
void Set_IIC_SDA_IN(void);
void IIC_init(void);
void IIC_start(void);
void IIC_stop(void);
void IIC_ack(void);
void IIC_noack(void);
uint8_t IIC_wait_ack(void);
void IIC_send_byte(uint8_t txd);
uint8_t IIC_read_byte(uint8_t ack);
#endif

ADXL345.c

/*
ADXL345三轴倾斜度模块
*/
#include "ADXL345.h"
#include "IIC.h"

/**
  * @brief  ADXL345初始化
  * @param  None
  * @retval None
  */
uint8_t ADXL345_init(void)
{
	IIC_init();
	if(ADXL345_read_reg(DEVICE_ID) == 0xE5)
	{
		ADXL345_write_reg(DATA_FORMAT,0X0B); // 低电平中断输出,13位全分辨率,输出数据右对齐,16g量程 
		ADXL345_write_reg(BW_RATE,0x0E); // 数据输出速度为100Hz
		ADXL345_write_reg(POWER_CTL,0x08); // 链接使能,测量模式,省电特性
		ADXL345_write_reg(INT_ENABLE,0x80); // 不使用中断		 
	 	ADXL345_write_reg(OFSX,0x00);
		ADXL345_write_reg(OFSY,0x00);
		ADXL345_write_reg(OFSZ,0x05);
		return 0;
	}
	return 1;
}
/**
  * @brief  ADXL345写寄存器
  * @param  None
  * @retval None
  */
uint8_t ADXL345_write_reg(u8 addr,u8 val) 
{
	IIC_start();  				 
	IIC_send_byte(slaveaddress); // 发送写器件指令	 
	if(IIC_wait_ack())
	{
		return 1;
	}    
  IIC_send_byte(addr); // 发送寄存器地址
	if(IIC_wait_ack())
	{
		return 2;
	} 	 										  		   
	IIC_send_byte(val); // 发送值					   
	if(IIC_wait_ack())
	{
		return 3;
	}   		    	   
  IIC_stop(); // 产生一个停止条件 	   
	return 0;
}
/**
  * @brief  ADXL345读寄存器
  * @param  None
  * @retval None
  */
u8 ADXL345_read_reg(u8 addr)
{
	u8 temp=0;		 
	IIC_start();  				 
	IIC_send_byte(slaveaddress); // 发送写器件指令	 
	if(IIC_wait_ack())
	{
		return 1;
	}   
  IIC_send_byte(addr); // 发送寄存器地址
	if(IIC_wait_ack())
	{
		return 2;
	}  										  		   
	IIC_start(); // 重新启动
	IIC_send_byte(regaddress); // 发送读器件指令	 
	if(IIC_wait_ack())
	{
		return 3;
	} 	   
  temp=IIC_read_byte(0); // 读取一个字节,不继续再读,发送NAK
  IIC_stop(); // 产生一个停止条件 	    
	return temp;
}
/**
  * @brief  ADXL345读取数据
  * @param  None
  * @retval None
  */
void ADXL345_read_data(short *x,short *y,short *z)
{
	u8 buf[6];
	u8 i;
	IIC_start();  				 
	IIC_send_byte(slaveaddress); // 发送写器件指令	 
	IIC_wait_ack();	   
  IIC_send_byte(0x32); // 发送寄存器地址(数据缓存的起始地址为0X32)
	IIC_wait_ack(); 	 										  		   
 
 	IIC_start(); // 重新启动
	IIC_send_byte(regaddress); // 发送读器件指令
	IIC_wait_ack();
	for(i=0;i<6;i++)
	{
		if(i==5)buf[i]=IIC_read_byte(0); // 读取一个字节,不继续再读,发送NACK  
		else buf[i]=IIC_read_byte(1);	// 读取一个字节,继续读,发送ACK 
 	}	        	   
  IIC_stop();	// 产生一个停止条件
	*x=(short)(((u16)buf[1]<<8)+buf[0]); // 合成数据    
	*y=(short)(((u16)buf[3]<<8)+buf[2]); 	    
	*z=(short)(((u16)buf[5]<<8)+buf[4]); 
}
/**
  * @brief  ADXL345连读读取几次取平均值
  * @param  None
  * @retval None
  */
void ADXL345_read_average(short *x,short *y,short *z,u8 times)
{
	u8 i;
	short tx,ty,tz;
	*x=0;
	*y=0;
	*z=0;
	if(times)//读取次数不为0
	{
		for(i=0;i<times;i++)//连续读取times次
		{
			ADXL345_read_data(&tx,&ty,&tz);
			*x+=tx;
			*y+=ty;
			*z+=tz;
			DELAYClass.DelayMs(5);
		}
		*x/=times;
		*y/=times;
		*z/=times;
	}
}
/**
  * @brief  ADXL345计算角度
  * @param  None
  * @retval None
  */
void get_angle(float *x_angle,float *y_angle,float *z_angle)
{
	short ax,ay,az;
	ADXL345_read_average(&ax,&ay,&az,10);
	*x_angle=atan(ax/sqrt((az*az+ay*ay)))*180/3.14;
	*y_angle=atan(ay/sqrt((ax*ax+az*az)))*180/3.14;
	*z_angle=atan(sqrt((ax*ax+ay*ay)/az))*180/3.14;
}

ADXL345.h

#ifndef __ADXL345_H
#define __ADXL345_H
#include "main.h"

#define X_AXLE 0   //x轴
#define Y_AXLE 1   //y轴
#define Z_AXLE 2   //z轴

#define	slaveaddress   0xA6	  //定义器件在IIC总线中的从地址,根据ALT  ADDRESS地址引脚不同修改
//                              ALT  ADDRESS引脚接地时地址为0xA6,接电源时地址为0x3A

#define THRESH_TAP     0X1D	  //敲击中断阈值(用于正常敲击检测)
//                              16g模式中,62.5mg/Bit

#define OFSX           0X1E   //X轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define OFSY           0X1F   //X轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define OFSZ           0X20   //X轴偏移寄存器  15.6mg/Bit  0xff = 4g
#define DUR            0x21   //敲击阈值时间   625uS/Bit
#define LATENT         0X22   //敲击事件到时间窗口的延迟时间,在此期间
//                              可检测第二次敲击时间  1.25mg/Bit
#define WINDOW         0X23   //敲击窗口,延迟时间满后的时间量,在此期间
//                              能开始进行第二次有效敲击  1.25mg/Bit
#define THRESH_ACT     0X24   //检测活动的阈值,活动事件的幅度与该寄存器
//                              的值进行比较  62.5mg/Bit
#define	THRESH_INACT   0X25   //检测静止的阈值,静止事件的幅度与该寄存器
//                              的值进行比较  62.5mg/Bit
#define TIME_INACT     0X26   //加速度时间量小于该寄存器的值表示静止 1S/Bit

#define ACT_INACT_CTL  0X27 
//Bit  7,3  ACT交流/直流[INACT交流/直流]:0选择直流耦合;1使能交流耦合 直流时将
//                                       当前加速度值直接与THRESH_ACT和THRESH_INACT
//                                       进行比较,确定检测到的是活动还是静止
//     6,2  ACT_X使能[INACT_X使能]:设置为1,使能X轴参与检测活动或静止;活动检测时,
//                                 所有轴为逻辑"或",有任意轴超过阈值时,活动功能触发
//                                 禁止检测时,所有轴为逻辑"与",只有当所有轴低于阈值
//                                 时,静止功能触发
//     5,1  ACT_Y使能[INACT_Y使能]:与X轴类似 
//     4,0  ACT_Z使能[INACT_Z使能]:与X轴类似
#define THRESH_FF      0X28   //阈值,用于自由落体检测,所有轴加速度与该寄存器值比较
//                              ,以确定是否发生自由落体 62.5mg/Bit,建议300mg与600mg之间
#define TIME_FF        0X29   //维持THRESH_FF阈值的最小时间,以生成自由落体中断 5mS/Bit

#define TAP_AXES       0X2A   
// Bit  7:4  0
//       3   抑制  两次敲击之间出现大于THRESH_TAP值得加速度,设置抑制会抑制双击检测
//       2   TAP_X使能  设置为1时,使能X轴进行敲击检测,0时排除该轴的敲击检测
//       1   TAP_Y使能  设置为1时,使能Y轴进行敲击检测,0时排除该轴的敲击检测
//       0   TAP_Z使能  设置为1时,使能Z轴进行敲击检测,0时排除该轴的敲击检测
#define ACT_TAP_STATUS 0X2B   /*只读寄存器*/
// Bit  7   0
//     6,2  ACT_X来源,TAP_X来源:表示涉及敲击或活动事件的第一轴,设置为1时,对应事件参与
//                              设置为0时,对应未参与.不会自动清零,新数据覆盖,中断清零前
//                              应读取该寄存器
//     5,1	ACT_Y来源,TAP_Y来源:与X相似
//     4,0	ACT_Z来源,TAP_Z来源:与X相似
//      3   休眠设置为1时,器件进入休眠状态
#define BW_RATE        0X2C  
// Bit  7:5   0
//       4	 LOW_POWER 低功耗位,0选择正常模式,1进入低功耗模式
//      3:0  速率位
#define POWER_CTL      0X2D
// Bit  7,6   0
//       5    链接   设置1时,延迟活动开始,直到检测到静止.检测到活动后,禁止检测开始,活动
//                   检测停止,设置时动态链接活动和静止交替检测;设置0时静止与活动同时检测
//       4    AUTO_SLEEP  设置1时自动休眠,检测出静止后,进行休眠模式,活动使能后被唤醒
//       3    测量   0待机 1测量模式
//       2	  休眠   0普通 1休眠
//      1,0	  唤醒(休眠模式下的读取频率) "00":8HZ  "01":4HZ  "10":2HZ  "11":1HZ
#define INT_ENABLE     0X2E  //中断使能配置
// Bit  7  DATA_READY
//      6  SINGLE_TAP
//      5  DOUBLE_TAP
//      4  Activity
//      3  Inactivity
//      2  FREE_FALL   自由落体中断
//      1  Watermark
//      0  Overrun
#define INT_MAP        0X2F   //中断映射 自读寄存器
//位与INT_ENABLE对应,,设置为0,该中断映射到INT1引脚;设置为1,该中断映射到INT2引脚
#define INT_SOURCE     0X30   //中断来源
//位与INT_ENABLE对应,1表示该功能触发
#define DATA_FORMAT    0X31
// Bit   7  SELF_TEST  设置1,自测力应用至传感器,造成输出数据转换;0时禁用自测力
//       6  SPI        1设置为3线SPI模式,0时设置4线SPI模式
//       5  INT_INVERT 0时中断高电平有效,1时低电平有效
//       4	0
//       3  FULL_RES   1时设置全分辨率模式,输出以4mg/Bit增加;0时为10位模式
//       2  Justify    1为左对齐模式;8为右对齐模式,并带有符号扩展
//      1:0 范围位     "00"±2g  "01"±4g  "10"±8g  "11"±16g
#define DATAX0         0X32
#define DATAX1         0X33  //与DATAX0组成x轴输出数据(二进制补码),DATAX1为高位,4mg/Bit
#define DATAY0         0X34
#define DATAY1         0X35  //与DATAY0组成Y轴输出数据(二进制补码),DATAY1为高位,4mg/Bit
#define DATAZ0         0X36
#define DATAZ1         0X37  //与DATAZ0组成Z轴输出数据(二进制补码),DATAZ1为高位,4mg/Bit
#define FIFO_CTL       0X38
// Bit  7,6  FIFO_MODE  "00" 旁路模式
//						"01" FIFO模式 可收集最多32个值,然后停止收集数据
//						"10" 流模式   FIFO保存最后32个数据值,FIFO满时,新数据覆盖最早数据(先进先出)
//						"11" 触发器   通过触发位触发,FIFO在触发事件前保存最后的数据样本,然后
//									  继续收集数据直到填满;填满后,不再收集新数据
//		 5   触发位     0链接触发器模式下的触发事件至INT1,1链接至INT2
//		 4:0 样本		功能取决于FIFO模式:FIFO模式时,指定触发水印中断需要的FIFO条目数
//                                         流模式时,指定触发水印中断需要的FIFO条目数
//                                         触发器模式:指定触发事件之前在FIFO缓冲区要保留的FIFO样本数
//                      样本位设置为0时,不管哪种FIFO模式,立即在INT_SOURCE寄存器设置水印状态位
#define FIFO_STATUS    0X39	  /*只读寄存器*/
// Bit   7   FIFO_TRIG  FIFO_TRIG为1时表示有触发事件发生 
//       6   0
//      5:0	 条目位 报告FIFO存储的数据值的数量

//#define slaveaddress 0XA6//write
#define regaddress 0XA7//read
#define DEVICE_ID 0X00
uint8_t ADXL345_init(void);
u8 ADXL345_read_reg(u8 addr);
uint8_t ADXL345_write_reg(u8 addr,u8 val);
void ADXL345_read_data(short *x,short *y,short *z);
void ADXL345_read_average(short *x,short *y,short *z,u8 times);
void get_angle(float *x_angle,float *y_angle,float *z_angle);
#endif

驱动下载地址:

https://download.csdn.net/download/m0_50669075/87672763

STM32工程模板、外设模板、模块模板下载地址:

stm32_template: STM32F103工程模板,外设模板,模块模板。模块模板包括:DHT11温湿度传感器,OLED屏幕,DS18B20温度传感器,DS1302时钟模块,红外测温模块,RFID模块,SIM900A短信模块,OneNET入网,ADXL345三轴传感器,离线语音识别模块,语音播报模块,甲醛传感器,PM2.5模块,SG90舵机,健康检测模块,消息队列示例,链表示例,分时调度系统示例等。

  • 22
    点赞
  • 133
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
### 回答1: ADXL345三轴数字加速度传感器,AMTEL公司设计,并广泛应用于当今市场最流行的许多电子产品。STM32是一种高性能单片机,具有高效性能和低功耗特点。本设计基于STM32ADXL345计步器主要分为两个部分:其一是硬件部分,其二是软件部分。 硬件部分: 该设计的硬件由三部分组成,即中央处理器,ADXL345传感器和显示屏。中央处理器使用STM32产品,ADXL345传感器插入到中央处理器的I2C总线上,连接传感器以开始采集数据,最后使用显示器显示观测结果。 软件部分:主处理器上需要安装适当固件,以便正确与ADXL345通信。依据模拟结果通过算法处理来获得足够精确的暴露时间以及依据计数器达到步数的功能。代码首先读取ADXL345,并将数据作为3轴数值传输到主处理器,主处理器读取此数据,使用算法计算暴露时间,并根据该时间增加步数计数器。 总之,这个基于STM32ADXL345计步设计能够实时地有效的记录用户的运动步数,而且能够通过I2C环境与其他传感器结合进一步扩展功能。 ### 回答2: ADXL345是一款三轴数字加速度传感器,可以测量加速度、倾斜度和震动等信息。而STM32是一款单片机,具备强大的计算和处理能力,在工业控制、智能家居、医疗监测等领域具有广泛的应用。结合ADXL345STM32,可以实现一个高精度的计步设计。 在该设计中,ADXL345传感器通过I2C总线与STM32单片机进行通信,传输加速度数据。STM32通过计算加速度数据来识别用户的步态,并实现计步功能。具体操作过程可参考以下步骤: 1. 配置ADXL345传感器,设置传感器的参数和采样率等,以实现高精度的加速度检测。 2. 初始化STM32单片机,设置相关参数和模块,实现与ADXL345的通信,并接受加速度数据。 3. 对接受的加速度数据进行处理,通过计算加速度的变化量,结合阈值判断,确定用户的步态,从而实现计步的功能。 4. 设计一定的界面,显示步数和相关数据,提高用户的使用体验。 5. 最后,优化算法和程序,提高计步的准确度和可靠性。 总之,基于STM32ADXL345计步设计,充分发挥了单片机的计算和处理能力,实现了高精度的计步功能,具有广泛的应用前景。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阿衰0110

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值