基于FPGA OV7670摄像头初始化配置

目录

一、OV7670摄像头简介

二、ov7670 SCCB协议简介

三、OV7670初始化寄存器配置

四、OV7670初始化代码编写

1、初始化过程

2、RTL设计

五、仿真测试


一、OV7670摄像头简介

OV7670/OV7171 图像传感器,体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影响数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、饱和度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。

其功能框图如图所示:

 所用模块如图:

主要引出的信号引脚如下:

SCL:SCCB时钟口

SDA:SCCB数据口

VSYNC:场同步(帧同步)信号

HREF:行同步信号

PCLK:像素时钟

XCLK:系统时钟输入

D0-D7:数据位

RESET:初始化所有寄存器到默认值 0:RESET 模式 1:一般模式

PWDN:POWER DOWN模式选择 0:工作 1:POWER DOWN

其中,对OV7670初始化配置只使用SCL和SDA两个信号线。

二、ov7670 SCCB协议简介

对OV7670初始化使用的是SCCB协议,由数据线SDA和时钟线SCL组成,SCCB协议和I2C协议基本一样,是简化的I2C协议,前面博客中已经讲过I2C协议,需要可以去看看。

SCCB(SeriaI Camera ControlBus)是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’t care和NA。Don’t care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。另外,SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。不然在发送读命令时,从机将不能产生Don’t care响应信号。

其写周期如下:

(1)首先发送设备ID地址:

(2)发送寄存器地址

 (3)写寄存器数据

 SCCB时序图如图:

这里采用的是100KHz的SCL。

三、OV7670初始化寄存器配置

在OV7670数据手册中只讲了其各种寄存器的列表,没有对具体如何配置进行讲解,可以看一下《OV7670 software application note》这个手册,里边有讲如何配置OV7670寄存器。

OV7670摄像头共201个寄存器,需要配置的有一百六十几个,这个具体看数据手册吧,下边代码中会有配置寄存器的数据。

四、OV7670初始化代码编写

1、初始化过程

(1)上电等待3ms等电平稳定

(2)发送初始化开始标志,通过SCCB协议对寄存器进行配置

(3)配置结束后,发送初始化完成标志,供后边读取图像数据作为开始标志。

2、RTL设计

(1)SCCB发送模块,因为没用用到读的功能,这里只写了SCCB的写数据功能。


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-11 16:53:19
// Revise Data    : 2020-09-11 16:53:19
// File Name      : SCCB_sender.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : SCCB接口协议发送数据,用于OV7670,线性序列机编写代码


module SCCB_sender(
	input				clk			,//系统时钟50MHz
	input				rst_n		,//系统复位
	input				send_en		,//发送使能
	input		[7:0]	addr		,//发送寄存器地址
	input		[7:0]	value		,//发送寄存器地址对应数据

	output	reg			done		,//发送结束标志
	output	reg			state		,//发送状态,忙为0,不忙为1
	output	reg			scl			,//输出时钟线

	inout				sda			 //输出数据线	
	);

	reg	[7:0]	addr_r;
	reg	[7:0]	value_r;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			addr_r <= 8'd0;
			value_r <= 8'd0;
		end
		else if (send_en) begin
			addr_r <= addr;
			value_r <= value;
		end
		else begin
			addr_r <= addr_r;
			value_r <= value_r;
		end
	end


	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			state <= 1;
		end
		else if (send_en) begin
			state <= 0;
		end
		else if (done) begin
			state <= 1;
		end
		else begin
			state <= state;
		end
	end

	localparam SCL_CNT_NUM = 9'd500;//100kHz
	reg	[8:0]	scl_cnt;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			scl_cnt <= 1;
		end
		else if (state==0) begin
			if (scl_cnt==SCL_CNT_NUM-1'b1 || done) begin
				scl_cnt <= 0;
			end
			else begin
				scl_cnt <= scl_cnt + 1'b1;
			end
		end
	end

	wire	scl_high_mid;
	wire	scl_low_mid	;
	assign scl_high_mid = scl_cnt==SCL_CNT_NUM/4-1'b1;
	assign scl_low_mid  = scl_cnt==SCL_CNT_NUM-SCL_CNT_NUM/4-1'b1;

	reg	[5:0]	scl_mid_cnt;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			scl_mid_cnt <= 0;
		end
		else if (scl_high_mid || scl_low_mid) begin
			
			scl_mid_cnt <= scl_mid_cnt + 1'b1;
			
		end
		else if (done) begin
			scl_mid_cnt <= 0;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			scl <= 1;
		end
		else if (state==0) begin
			if (scl_cnt<=SCL_CNT_NUM/2-1) begin
				scl <= 1;
			end
			else begin
				scl <= 0;
			end
		end
		else begin
			scl <= 1;
		end
	end

	reg	sda_en;
	reg	sda_reg;
	assign sda = sda_en ? sda_reg : 1'bz;

	parameter device_id = 8'b0100_0010;
	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			sda_reg <= 1;
		end
		else if (state==0 && (scl_high_mid || scl_low_mid)) begin
			case(scl_mid_cnt)
				6'd0:  sda_reg <= 0;
				6'd1:  sda_reg <= device_id[7];
				6'd3:  sda_reg <= device_id[6];
				6'd5:  sda_reg <= device_id[5];
				6'd7:  sda_reg <= device_id[4];
				6'd9:  sda_reg <= device_id[3];
				6'd11: sda_reg <= device_id[2];
				6'd13: sda_reg <= device_id[1];
				6'd15: sda_reg <= device_id[0];

				6'd19: sda_reg <= addr_r[7];
				6'd21: sda_reg <= addr_r[6];
				6'd23: sda_reg <= addr_r[5];
				6'd25: sda_reg <= addr_r[4];
				6'd27: sda_reg <= addr_r[3];
				6'd29: sda_reg <= addr_r[2];
				6'd31: sda_reg <= addr_r[1];
				6'd33: sda_reg <= addr_r[0];

				6'd37: sda_reg <= value_r[7];
				6'd39: sda_reg <= value_r[6];
				6'd41: sda_reg <= value_r[5];
				6'd43: sda_reg <= value_r[4];
				6'd45: sda_reg <= value_r[3];
				6'd47: sda_reg <= value_r[2];
				6'd49: sda_reg <= value_r[1];
				6'd51: sda_reg <= value_r[0];

				6'd55: sda_reg <= 0;
				6'd56: sda_reg <= 1;

				default:sda_reg <= sda_reg;
			endcase
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			sda_en <= 0;
		end
		else if (state==0) begin
			if (scl_mid_cnt==6'd18 || scl_mid_cnt==6'd19 || scl_mid_cnt==6'd36 || scl_mid_cnt==6'd37 || scl_mid_cnt==6'd54 || scl_mid_cnt==6'd55) begin
				sda_en <= 0;
			end
			else begin
				sda_en <= 1;
			end
		end
		else begin
			sda_en <= 0;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			done <= 0;
		end
		else if (scl_mid_cnt==6'd57 && scl_cnt==SCL_CNT_NUM/2-2) begin
			done <= 1;
		end
		else begin
			done <= 0;
		end
	end
endmodule

(2)OV7670寄存器数据配置


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-12 19:09:43
// Revise Data    : 2020-09-12 20:06:25
// File Name      : ov7670_config.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : ov7670配置模块

module ov7670_config(
	input				clk			,
	input				rst_n		,
	input				SCCB_done	,
	
	output	reg	flag		,
	output	reg			data_vld	,
	output	wire	[7:0]	addr		,
	output	wire	[7:0]	value		
	);
	
	reg	SCCB_done_r;
	reg	[7:0]	cnt;
	reg	[15:0]	dout;

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			SCCB_done_r <= 0;
		end
		else begin
			SCCB_done_r <= SCCB_done;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			data_vld <= 0;
		end
		else if (SCCB_done_r && flag==0) begin
			data_vld <= 1;
		end
		else begin
			data_vld <= 0;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			cnt <= 7'd0;
		end
		else if (SCCB_done && flag==0) begin
			cnt <= cnt + 1'b1;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			flag <= 0;
		end
		else if (cnt==8'd165) begin
			flag <= 1;
		end
	end

	always @(posedge clk or negedge rst_n) begin
		if (!rst_n) begin
			dout <= 0;
		end
		else begin
			case(cnt)
				8'd1:  dout <= 16'h1204;
				8'd2:  dout <= 16'h40d0;
				8'd3:  dout <= 16'h3a04;
				8'd4:  dout <= 16'h3dc8;
				8'd5:  dout <= 16'h1e31;
				8'd6:  dout <= 16'h6b00;
				8'd7:  dout <= 16'h32b6;
				8'd8:  dout <= 16'h1713;
				8'd9:  dout <= 16'h1801;
				8'd10: dout <= 16'h1902;
				8'd11: dout <= 16'h1a7a;
				8'd12: dout <= 16'h030a;
				8'd13: dout <= 16'h0c00;
				8'd14: dout <= 16'h3e10;
				8'd15: dout <= 16'h7000;
				8'd16: dout <= 16'h7100;
				8'd17: dout <= 16'h7211;

				8'd18: dout <= 16'h7300;
				8'd19: dout <= 16'ha202;
				8'd20: dout <= 16'h1180;
				8'd21: dout <= 16'h7a20;
				8'd22: dout <= 16'h7b1c;
				8'd23: dout <= 16'h7c28;
				8'd24: dout <= 16'h7d3c;
				8'd25: dout <= 16'h7e55;
				8'd26: dout <= 16'h7f68;
				8'd27: dout <= 16'h8076;
				8'd28: dout <= 16'h8180;
				8'd29: dout <= 16'h8288;
				8'd30: dout <= 16'h838f;
				8'd31: dout <= 16'h8496;
				8'd32: dout <= 16'h85a3;
				8'd33: dout <= 16'h86af;

				8'd34: dout <= 16'h87c4;
				8'd35: dout <= 16'h88d7;

				8'd36: dout <= 16'h89e8;
				8'd37: dout <= 16'h13e0;
				8'd38: dout <= 16'h0010;
				8'd39: dout <= 16'h1000;
				8'd40: dout <= 16'h0d00;
				8'd41: dout <= 16'h1428;
				8'd42: dout <= 16'ha505;
				8'd43: dout <= 16'hab07;
				8'd44: dout <= 16'h2475;
				8'd45: dout <= 16'h2563;
				8'd46: dout <= 16'h26a5;
				8'd47: dout <= 16'h9f78;
				8'd48: dout <= 16'ha068;
				8'd49: dout <= 16'ha103;
				8'd50: dout <= 16'ha6df;
				8'd51: dout <= 16'ha7df;
				8'd52: dout <= 16'ha8f0;

				8'd53: dout <= 16'ha990;
				8'd54: dout <= 16'haa94;
				8'd55: dout <= 16'h13ef;
				8'd56: dout <= 16'h0e61;
				8'd57: dout <= 16'h0f4b;
				8'd58: dout <= 16'h1602;
				8'd59: dout <= 16'h2102;
				8'd60: dout <= 16'h2291;
				8'd61: dout <= 16'h2907;
				8'd62: dout <= 16'h330b;
				8'd63: dout <= 16'h350b;
				8'd64: dout <= 16'h371d;
				8'd65: dout <= 16'h3871;
				8'd66: dout <= 16'h392a;
				8'd67: dout <= 16'h3c78;
				8'd68: dout <= 16'h4d40;
				8'd69: dout <= 16'h4e20;
				8'd70: dout <= 16'h6900;
				8'd71: dout <= 16'h7419;
				8'd72: dout <= 16'h8d4f;
				8'd73: dout <= 16'h8e00;
				8'd74: dout <= 16'h8f00;
				8'd75: dout <= 16'h9000;
				8'd76: dout <= 16'h9100;
				8'd77: dout <= 16'h9200;
				8'd78: dout <= 16'h9600;
				8'd79: dout <= 16'h9a80;
				8'd80: dout <= 16'hb084;
				8'd81: dout <= 16'hb10c;
				8'd82: dout <= 16'hb20e;
				8'd83: dout <= 16'hb382;

				8'd84:  dout <= 16'hb80a;
				8'd85:  dout <= 16'h4314;
				8'd86:  dout <= 16'h44f0;
				8'd87:  dout <= 16'h4534;
				8'd88:  dout <= 16'h4658;
				8'd89:  dout <= 16'h4728;
				8'd90:  dout <= 16'h483a;
				8'd91:  dout <= 16'h5988;
				8'd92:  dout <= 16'h5a88;
				8'd93:  dout <= 16'h5b44;
				8'd94:  dout <= 16'h5c67;
				8'd95:  dout <= 16'h5d49;
				8'd96:  dout <= 16'h5e0e;
				8'd97:  dout <= 16'h6404;
				8'd98:  dout <= 16'h6520;
				8'd99:  dout <= 16'h6605;
				8'd100: dout <= 16'h9404;
				8'd101: dout <= 16'h9508;
				8'd102: dout <= 16'h6c0a;
				8'd103: dout <= 16'h6d55;
				8'd104: dout <= 16'h6e11;
				8'd105: dout <= 16'h6f9f;
				8'd106: dout <= 16'h6a40;
				8'd107: dout <= 16'h0140;
				8'd108: dout <= 16'h0240;
				8'd109: dout <= 16'h13e7;

				8'd110: dout <= 16'h1500;
				8'd111: dout <= 16'h4f80;
				8'd112: dout <= 16'h5080;
				8'd113: dout <= 16'h5100;
				8'd114: dout <= 16'h5222;
				8'd115: dout <= 16'h535e;
				8'd116: dout <= 16'h5480;

				8'd117: dout <= 16'h589e;
				8'd118: dout <= 16'h4108;
				8'd119: dout <= 16'h3f00;
				8'd120: dout <= 16'h7505;
				8'd121: dout <= 16'h76e1;
				8'd122: dout <= 16'h4c00;
				8'd123: dout <= 16'h7701;
				8'd124: dout <= 16'h4b09;
				8'd125: dout <= 16'hc9F0;
				8'd126: dout <= 16'h4138;
				8'd127: dout <= 16'h5640;

				8'd128: dout <= 16'h3411;
				8'd129: dout <= 16'h3b02;

				8'd130: dout <= 16'ha489;
				8'd131: dout <= 16'h9600;
				8'd132: dout <= 16'h9730;
				8'd133: dout <= 16'h9820;
				8'd134: dout <= 16'h9930;
				8'd135: dout <= 16'h9a84;
				8'd136: dout <= 16'h9b29;
				8'd137: dout <= 16'h9c03;
				8'd138: dout <= 16'h9d4c;
				8'd139: dout <= 16'h9e3f;
				8'd140: dout <= 16'h7804;

				8'd141: dout <= 16'h7901;
				8'd142: dout <= 16'hc8f0;
				8'd143: dout <= 16'h790f;
				8'd144: dout <= 16'hc800;
				8'd145: dout <= 16'h7910;
				8'd146: dout <= 16'hc87e;
				8'd147: dout <= 16'h790a;
				8'd148: dout <= 16'hc880;
				8'd149: dout <= 16'h790b;
				8'd150: dout <= 16'hc801;
				8'd151: dout <= 16'h790c;
				8'd152: dout <= 16'hc80f;
				8'd153: dout <= 16'h790d;
				8'd154: dout <= 16'hc820;
				8'd155: dout <= 16'h7909;
				8'd156: dout <= 16'hc880;
				8'd157: dout <= 16'h7902;
				8'd158: dout <= 16'hc8c0;
				8'd159: dout <= 16'h7903;
				8'd160: dout <= 16'hc840;
				8'd161: dout <= 16'h7905;
				8'd162: dout <= 16'hc830;
				8'd163: dout <= 16'h7926;
				8'd164: dout <= 16'h0903;
				8'd165: dout <= 16'h3b42;
				default:;
			endcase
		end
	end

	assign addr = dout[15:8];
	assign value = dout[7:0];
endmodule

(3)OV7670初始化顶层模块


// Company  : 
// Engineer : 
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534    PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date    : 2020-09-13 10:18:23
// Revise Data    : 2020-09-13 10:18:23
// File Name      : ov7670_init.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions  : Vivado 2019.2
// Revision       : V1.1
// Editor         : sublime text3, tab size (4)
// Description    : ov7670初始化操作

module ov7670_init(
	input			clk		,//50MHz
	input			rst_n	,

	output			scl		,
	inout			sda		,
	output			init_done
	);
	
	localparam device_id = 8'b0100_0010;

	wire			send_en	;
	wire	[7:0]	addr	;
	wire	[7:0]	value	;
	wire			done	;
	wire			state	;
	wire			flag	;

	reg				init_en	;

	assign init_done = flag&&done;

	reg [17:0]	cnt_3ms;//上电等待3ms电平稳定后再初始化寄存器
	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			cnt_3ms <= 0;
		end
		else if(cnt_3ms<=18'd150000)begin
			cnt_3ms <= cnt_3ms + 1'd1;
		end
	end

	always @(posedge clk or negedge rst_n)begin
		if(!rst_n)begin
			init_en <= 0;
		end
		else if(cnt_3ms==18'd150000-1)begin
			init_en <= 1'b1;
		end
		else begin
			init_en <= 0;
		end
	end

	SCCB_sender #(
		.device_id(device_id)
	) inst_SCCB_sender (
		.clk     (clk),
		.rst_n   (rst_n),
		.send_en (send_en),
		.addr    (addr),
		.value   (value),
		.done    (done),
		.state   (state),
		.scl     (scl),
		.sda     (sda)
	);

	ov7670_config inst_ov7670_config
		(
			.clk       (clk),
			.rst_n     (rst_n),
			.SCCB_done (init_en || done),
			.flag	   (flag),
			.data_vld  (send_en),
			.addr      (addr),
			.value     (value)
		);

endmodule

五、仿真测试

测试代码如下:


`timescale 1ns/1ns

module ov7670_init_tb (); /* this is automatically generated */

	reg clk;

	localparam device_id = 8'b0100_0010;

	localparam clk_period = 20;

	reg  rst_n;
	reg  init_en;
	wire  scl;
	wire  sda;
	wire  init_done;

	pullup(sda);

	ov7670_init inst_ov7670_init (
		.clk(clk), 
		.rst_n(rst_n), 
		.scl(scl), 
		.sda(sda),
		.init_done(init_done)
		);

	initial clk = 0;
	always #(clk_period/2) clk = ~clk;

	initial begin
		#2;
		rst_n = 0;
		init_en = 0;
		#(clk_period*20);
		rst_n = 1;
		#(clk_period*10);

		init_en = 1;
		#clk_period;
		init_en = 0;

		#(clk_period*15000*168);
		$stop;

	end

endmodule

仿真图如下:

(1)单个寄存器配置SCCB发送

(2)整体配置如图

通过对OV7670摄像头进行配配置后,在开发板上下板测试,使用quartus在线逻辑分析仪功能读取摄像头输出口数据,查看接收情况。第一次没有对RESET和PWDN信号进行操作,输出的像素时钟PCLK一直拉低,当把RESET拉高,PWDN拉低时,能正常接收到数据。如下图在线逻辑分析仪显示的接收结果:

(1)缩小图

(2)细节图

可以看到数据在行同步信号为高时,正常输出数据,和数据手册中输出形式一样。

 

欢迎下载研华科技主题白皮书: 【深度剖析】研华多核异构ARM核心板之机器视觉应用案例 [摘要] TI Sitara系列AM5718/5728是采用ARM+DSP多核异构架构,可以实现图像采集、算法处理、显示、控制等功能,具有实时控制、低功耗、多标准工业控制网络互联、工业人机界面的优化、2D/3D图形处理、1080 HD的高清视频应用、工业控制设备的小型化等特点。广泛应用在机器视觉、工业通讯、汽车多媒体、医疗影像、工厂自动化、工业物联网等领域。 https://www.eefocus.com/resource/advantech/index.p... 前言: 使用单片机方案的简单图像处理在很多情况下有应用,比如颜色的跟踪识别,给智能控制的机器人带来的视觉系统,能使设计更加的智能化。在各种机器人大赛中都有图像处理应用的身影,低调却非常的有用。虽然只是对图像的颜色跟踪,但是这样却可以应用到很多的场合。 本方案介绍的是基于Colibri_GD32F207+OV7670+SPI_LCD的图像处理->颜色跟踪。 系统框图如下: 实物PIN脚连接图: 管脚配置: 设计应用描述及心得总结: 1. Colibri_GD32F207这个板子的MCU是带有camera的接口的,但是没有引出来,使用使用了FIFO的OV7670摄像头,数据口使用GPIO。OV7670是30W的摄像头最大是支持VGA 640*480的像素,但是应为液晶的分辨率只有320*240,所以讲OV7670配置为QVGA 320*240的像素输出。 2. 同样板子上的MCU是带有LCD 的接口的,但是也是应为没有将这部分的IO全部引出来,所以使用SPI LCD ,这样可以节省很多的 IO,但是也造成了使用GD32f207处理图片的时候速度变慢。如果这部分做些修改,处理的速度将达到每秒7帧以上。 3.本设计发挥了GD32F207的最大的速度,主频配置为了120MHZ。 4. 本设计集成了对图片设定的识别颜色条件为:Condition={30,70,130,255,100,170,40,40,320,240}; 5. 识别使用的是HSV空间,这个和RGB的区别是,HSV更加符合人眼对颜色的认知模式。H是色调,S是色饱和度,V是色温。其中的S值不会受到环境亮度的影响。 6. 识别的算法做了对目标的大小,坐标等的识别,集成了图像搜索的膨胀、腐蚀算法。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值