中科昊芯DSP_RISC-V笔记(3)_SPI-Flash访问

中科昊芯DSP_RISC-V笔记(3)_SPI-Flash访问

●1.功能:实现SPI_FIash数据访问,要求:8位数据传输,无延迟,增强FIFO模式,不使用中断
●写入数据为upper_100[128]={0x55,0x55,0x55,0x98,Q×56,0x78,0x45,0x34},
读出数据upper_128[128]与写入数据一致
●2.SPI模块讲解:(1)参数功能讲解,结合手册P49-51
●(2)收发逻辑
●(3)接收/发送FIFO
●(4)主机发送模式
●(5)中断触发
●(6)波特率选择与时钟模式
●3.如何配置SPI:(1)SPI的FIFO配置,(2)SPI初始化配置
●4.结合Flash说明书对W25Q64Flash原理讲解,J104的1-2短接
●5.详细讲解程序(1)SPI配置(2)Flash按手册编程实现收发功能(3)主函数执行调用步骤与逻辑
●6.调试:读写成功,D401持续闪灯一持续读数,D400常亮一读出与发送的数据一致

同步串行通信接口(SPI)模块

HXS320F2803X 器件包括 2 个四引脚的同步串行通信接口(SPI)模块。SPI 是一个高速、 同步串行 I/O 端口,此端口可在设定的位传输速率上将一个设定长度(1 至 16 位)的串行 比特流移入和移出器件。

在这里插入图片描述
在这里插入图片描述

SPI-A 寄存器

在这里插入图片描述

SPI收发逻辑

●包含移位及传输缓冲器,FIFO及状态控制逻辑等部件组成,移位寄存器SPIDAT在时钟作用下完成数据移入移出,实现数据传输.传输缓冲器SPITXBUF/SPIRXBUF负责在合适的时刻向SPIDAT中加载需要发送的数据,或读取SPIDAT中已接收完成的数据,并触发响应的状态及中断控制信号等.FIFO部分在模块使能FIFO功能时提供了发送的数据源及接收的目的,同时产生中断及状态控制信号等.状态控制逻辑通过状态机控制发送和接收状态.

●收发原理:环形总线结构,由SPISTE、SPICLK、MISO、MOSI构成,其时序主要是在SPICLK的控制下,两个双向移位寄存器进行数据交换。SPIDAT寄存器为16位寄存器,由于发送数据字长度可以在1~16位之间配置,因而在数据长度小于16位时,数据按照左对齐的方式存入SPIDAT中,即MSB对应SPIDAT的位15。数据传输的过程中,MSB经过MOSI/MISO发送到对方SPIDAT的LSB中,当传输完成后,数据字按照右对齐的方式存放在SPIDAT中,即LSB对应SPIDAT的位O。

●非FIFO模式下,SPITXBUF发送缓冲寄存器接收来自于CPU的待发送数据。当SPITXBUF被写入数据时,若此时没有SPI传输发生,SPITXBUF被写入的数据将加载至SPIDAT,从而发起SPI传输;若SPI传输正在进行,SPITXBUF保留数据并设置BUF_FULL标志位,当SPI传输完成时,数据加载至SPIDAT开始SPI传输,同时清除标志位。FIFO模式下,SPITXBUF的数据来源于相应的发送FIFO,在FIFO控制逻辑作用下依次触发SPIDAT的加载实现SPI传输。

●SPI传输完成时,SPIDAT接收到的内容会加载到接收缓冲器SPIRXBUF中。非FIFO模式下,SPIRXBUF中的数据需要CPU读取。当CPU未及时读取数据,会产生溢出事件,可以触发相应中断。FIFO模式下,读取SPITXBUF数据会直接读取RXFIFO的内容,使RXFIFO指针减1。

接收/发送FIFO

4x16位大小,FIFO模式使能时,对SPITXBUF寄存器写入发送数据会导致数据写入TXFIFO,从而使得FIFO指针增加。写入TXFIFO的数据在延迟控制下按照一定的频率写入SPITXBUF,启动SPI传输,FIFO指针减少。使能FIFO模式下,SPI接收到数据,将数据存入接收FIFO中,导致FIFO指针增加。读取SPIRXBUF寄存器会实际上读取RXFIFO中的数据,使得FIFO指针减少。当与FIFO相关的中断使能时,RX/TXFIFO中的数据现存数目满足设定值范围时,将触发相应的中断,故需要的FIFO深度为4,宽度为16位,需要输出当前FIFO的状态信号如full,empty以及当前存储的数据数目num。读写设置为无延迟。

主机发送模式

包括6个状态:
●a)idle:系统初始化时,状态保持在idle状态,当sPIDAT中写入数据时即datful_flag有效,进入到start状态准备产生SPI时钟。
●b)start:根据不同的时钟相位模式选择开始传输的时机,进入到发送数据状态transmit。
●c)transmit:发送数据向外发出,并计算已发送的比特数。SPI时钟的合适边沿进入到接收状态。
●d)receive:接收来自从设备的数据,根据当前已发送的数据判断是否传输完成。如果还有未发送完成的数据则在合适的时刻回到transmit,否则进入end状态结束传输。
●e)end:给出一些标志位及结束信号结束SPISTE,之后进入delay状态。
●f)delay:等待半个SPI时钟周期,保持SPISTE无效一段时间再结束回到初始状态。

中断触发

●非FIFO模式下:
●(1)传输完成触发中断:INT_FLAG表示SPI模块已经完成了发送或接收的最后一位,同时已经做好再次被访问的准备。标志位置位,接收到的字符会被放在接收缓冲器SPIRXBUF中,若SPIINTENA置位,标志位将触发SPI中断;
●(2)接收溢出标志触发中断:OVERRUN_FLAG指示了一次发送或接收行为的完成,同时上一次接收的字符还未被从接收缓冲器SPIRXBUF中读取。标志位会触发一个SPI中断,相应OVERRUNINTENA标志位被置位,此时标志位已被清除。
●FIFO模式下:
●SPI中断产生依赖于相应的匹配事件。
●(1)当RXFFST大于等于RXFFIL时,接收FIFO的中断标志RXFFINT将会被置位,如果接收FIFO中断被使能(RXFFIENA=1),那么此时SPIRXINT中断触发
●(2)TXFFST小于等于TXFFIL时,发送FIFO中断标志位TXFFINT将会被置位,如果发送FIFO中断被使能(TXFFIENA=1),那么此时SPITXINT中断触发

波特率选择与时钟模式

●(1)波特率选择:支持125种不同波特率,根据不同的主从模式,SPICLK会接收外部的时钟信号或由本模块向外提供SPI时钟。
●从模式中,SPI时钟由SPICLK引脚从外部接收时钟源,同时时钟速率最快不能超过LSPCLK/4。
●主模式,SPI时钟由SPI模块产生并由SPICLK引脚输出,最大不超过LSPCLK/4。
●(2)时钟模式:由极性选择(SPICCR.CLKPOLARITY)和相位选择(SPICTL.CLK_PHASE)控制:CLKPOLARITY选择有效边缘,上升沿/下降沿;CLK PHASE选择是否半时钟周期延迟。
●a)上升沿无延迟O0:SPICLK低有效。SPI数据传输发生在SPICLK的上升沿前半个SPICLK周期处,数据接收发
生在SPICLK的下降沿。
●b)上升沿有延迟O1:SPICLK低有效。SPI数据传输发生在SPICLK的上升沿前半个SPICLK周期处,数据接收发
生在SPICLK的上升沿。
●c)下降沿无延迟10:SPICLK高有效。SPI数据传输发生在SPICLK的下降沿,数据接收发生在SPICLK的上升沿。
●d)下降沿有延迟11:SPICLK高有效。SPI数据传输发生在SPICLK的上升沿,数据接收发生在SPICLK的下降沿。

配置SPI

●(1)SPI的FIFO配置
● a)复位:上电进入到普通SPI模式,FIFO模式被禁止SPIFFTX.SPIRST=1
● b)改变模式:增强FIFO模式选择,通过SPIFFTX.SPIFENA=1配置
● c)激活寄存器:SPIFFTX.TXFFST=1SPIFFRX.RXFFST=1
● d)中断:两种中断:发送/接收FIFO中断接收错误/接收FIFO溢出中断TXFFIENA/RXFFIENA
● e)缓冲:4字FIFO SPIFFRX.RXFFIL
● f)延迟发送SPIFFCT.alI
●(2)SPI初始化配置

SPI初始化配置

●SPISWRESET=O,进入复位状态
●按需配置SPI:
●(1)传输数据长度SPICHAR
●(2)时钟模式选择
●(3)主从模式选择
●(4)波特率配置
●(5)清除SPI标志
●(6)3线模式
●(7)FIFO模式配置
●(8)酌情配置中断
● 设置SPISWRESET=1,释放SPI模块
● 对于FIash访问还需配置SPI优先级SPIPRI.FREE=1自由运行,
● SPIPRI.CS_PRIORITY=O片选处于最高优先级

电路图部分

在这里插入图片描述

W25Q16DV(华邦)简介

储存空间限制在256,16位的一个数据空间。工作电源在2.7V至3.6V。
页面擦除可分为16组(4KB扇区擦除)、128组(32KB块擦除)、256组(64KB块擦除)或整个芯片(芯片擦除)。W25Q16DV有512个可擦扇区和32个可擦块。较小的4KB扇区为需要数据和参数存储的应用程序提供了更大的灵活性。

在这里插入图片描述

Flash按手册编程实现收发功能

●(1)读FIash.ID ●(8)写使能:
●(2)读Flash.SReg状态 ●(9)擦除芯片
●(3)写使能: ●(10)延时等待4个周期
●(4)读出写寄存器状态: ●(11)读数据
●(5)读Flash.SReg状态; ●(12)写使能
●(6)延时等待; ●(13)写入数据
●(7)读Flash.SReg状态: ●(14)延时等待
●(15)读出数据

代码部分

引脚初始化 - GPIO16、GPIO17、GPIO18为SPI功能,GPIO19为片选引脚
GPAQSEL2 选择为011的原因时 控制MISO的信号同步的速率,比系统时钟速度远比系统时钟速度要慢很多,所以我们选择他的异步 就是(011)

void SPI_IOinit(void)
{
	EALLOW;
	/*将 GPIO19 引脚配置为:通用输入/输出*/
	GpioCtrlRegs.GPAMUX2.bit.GPIO19 = 0;
	/*将 GPIO19引脚配置为输出*/
	GpioCtrlRegs.GPADIR.bit.GPIO19 = 1;
	/*//使能内部上拉*/
	GpioCtrlRegs.GPAPUD.bit.GPIO16 = 0;
	GpioCtrlRegs.GPAPUD.bit.GPIO17 = 0;
	GpioCtrlRegs.GPAPUD.bit.GPIO18 = 0;
	/*异步*/
	GpioCtrlRegs.GPAQSEL2.bit.GPIO16 = 3;
	GpioCtrlRegs.GPAQSEL2.bit.GPIO17 = 3;
	GpioCtrlRegs.GPAQSEL2.bit.GPIO18 = 3;
	/*SPISIMOA-SPI-A 从机输入,主机输出 (I/O)*/
	GpioCtrlRegs.GPAMUX2.bit.GPIO16 = 1;
	GpioCtrlRegs.GPAMUX2.bit.GPIO17 = 1;
	GpioCtrlRegs.GPAMUX2.bit.GPIO18 = 1;
	EDIS;
}

SPIFFTX 类型定义

// SPI Individual Register Bit Definitions:
//
// SPI FIFO Transmit register bit    definitions:
struct  SPIFFTX_BITS {       // bit    description
   Uint32 TXFFIL:5;          // 4:0    Interrupt level
   Uint32 TXFFIENA:1;        // 5      Interrupt enable
   Uint32 TXFFINTCLR:1;      // 6      Clear INT flag ///??  0
   Uint32 TXFFINT:1;         // 7      INT flag
   Uint32 TXFFST:5;          // 12:8   FIFO status
   Uint32 TXFIFO:1;          // 13     FIFO reset
   Uint32 SPIFFENA:1;        // 14     Enhancement enable
   Uint32 SPIRST:1;          // 15     Reset SPI
   Uint32 rsvd:16;           // 31:16  reserved 
};

初始化SPI的FIFO寄存器

void SPI_fifo_init(void)
{
	SpiaRegs.SPIFFTX.bit.SPIRST = 1;//1h (R/W) = SPI FIFO 可以恢复发送或接收。对 SPI 寄存 器位没有影响。
	SpiaRegs.SPIFFTX.bit.SPIFFENA = 1;		//使能SPIFIFO增强型功能。
	SpiaRegs.SPIFFTX.bit.TXFFST = 1;			//发送 FIFO 有 1 个字。
	SpiaRegs.SPIFFTX.bit.TXFFINTCLR = 1;	//写 1 以清除 SPIFFTX[TXFFINT]标志。
	SpiaRegs.SPIFFTX.bit.TXFFIENA = 0;		//TX FIFO 中断使能

	SpiaRegs.SPIFFRX.bit.RXFFOVFCLR = 1;	//给此位写 1 清除 SPIFFRX[RXFFOVF]。
	SpiaRegs.SPIFFRX.bit.RXFFINTCLR = 1;	//写 1 以清除 SPIFFRX[RXFFINT]标志。
	SpiaRegs.SPIFFRX.bit.RXFFST = 1;			//接收 FIFO 有一个字
	SpiaRegs.SPIFFRX.bit.RXFFIENA = 0;	//接收 FIFO 中断基于 RXFFIL 匹配(大于或 等于)的将被启用

	SpiaRegs.SPIFFRX.bit.RXFFIL = 4;		//=一个 RX FIFO 中断请求产生时,有 4 个字 在接收缓冲区

	SpiaRegs.SPIFFCT.all = 0;	//上一个字传输完成后,TX FIFO 缓冲区 中的下一个字立刻被传输到 SPITXBUF。
}

初始化SPI的控制寄存器

void spi_init(void)
{
	GpioDataRegs.GPASET.bit.GPIO19 = 1;	//GPIO19置1 从W25Q16DV时序图中看出

	SpiaRegs.SPICCR.bit.SPISWRESET = 0;	//清除接收端溢出标志 位(SPISTS.7)、SPI INT 标志位(SPISTS.6)
	SpiaRegs.SPICCR.bit.SPICHAR = 7;		//字符长度控制位7h (R/W) = 8-bit word
	SpiaRegs.SPICCR.bit.CLKPOLARITY = 1;	//数据在下降边输出,上升边输入。

	SpiaRegs.SPICTL.bit.CLK_PHASE = 0;		//正常的 SPI 时钟方案,取决于 时钟极性位(SPICCR.6)
	SpiaRegs.SPICTL.bit.MASTER_SLAVE = 1;	//设置为主机

	SpiaRegs.SPIBRR = 2;								//SPI 波特率= LSPCLK / 4。
	SpiaRegs.SPICCR.bit.SPISWRESET = 1;		//准备发生或接收下一字

	SpiaRegs.SPIPRI.bit.FREE = 1;				//自由运行,无论挂起或何时发生挂起,继续 SPI 操作。
	SpiaRegs.SPIPRI.bit.STEINV = 0;				//SPISTEn 活跃低(正常)
}

在这里插入图片描述

查询ID信息

输出制造商的ID信息;储存型号的ID信息;还有容量的ID信息;三个ID信息需要定义三个变量。

/******************************************************************
 *发送一个字节。
 ******************************************************************/
uint8_t Send_Byte(uint16 a)
{
	uint16 rdata;
	SpiaRegs.SPICTL.bit.TALK = 1;						//传输路径选择发送
	SpiaRegs.SPITXBUF = (a << 8) & 0xff00;		//左对齐命令
	while (SpiaRegs.SPIFFRX.bit.RXFFST == 0)	//是否完成了一个接收的传输,等待引脚激活
	{
	}
	rdata = SpiaRegs.SPIRXBUF;
	return rdata;
}

/******************************************************************
 *接收一个字节。
 ******************************************************************/
uint16 Get_Byte(void)
{
	uint8_t rdata;
	SpiaRegs.SPICTL.bit.TALK = 0;			//传输路径选择接收
	SpiaRegs.SPITXBUF = DummyData		//Flash芯片储存字节 为0xA5 表示可以存储165个字节
	;
	while (SpiaRegs.SPIFFRX.bit.RXFFST == 0)
	{
	}
	rdata = SpiaRegs.SPIRXBUF;
	return rdata;
}

/******************************************************************
 *函数名:unsigned long Jedec_ID_Read(void)
 *参 数:无
 *返回值:W25Q16 ID参数
 *作 用:*《W25Q16BV.pdf》
 *P17  W25Q16 ID参数
 *P20  ID 指令表格与读取指令的通信格式
 ******************************************************************/
unsigned long Jedec_ID_Read(void)
{
	unsigned long temp1, temp2, temp3;
	temp1 = 0;
	temp2 = 0;
	temp3 = 0;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x9F);//查询ID信息的指令。
	temp1 = Get_Byte();
	temp2 = Get_Byte();
	temp3 = Get_Byte();
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
	/* 数据在SPIRXBUF中是右对齐存储的*/
	temp1 = ((temp1 << 16) | (temp2 << 8) | (temp3)) & 0x00FFFFFF;
	return temp1;
}

读取Flash状态寄存

在这里插入图片描述

/******************************************************************
 *函数名:uint16 Read_Status_2Reg(void)
 *参 数:无
 *返回值:状态寄存器1和状态寄存器2中的值
 *作 用:读状态寄存器1和状态寄存器2的值
 ******************************************************************/
uint16 Read_Status_2Reg(void)
{
	uint16 wbyte1, wbyte2;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	/*读状态寄存器1指令,返回Status Register1*/
	Send_Byte(0x05);
	wbyte1 = Get_Byte();
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	/*READ_STATUS_REG_IST  读状态寄存器2指令,返回Status Register2*/
	Send_Byte(0x35);
	wbyte2 = Get_Byte();
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;

	wbyte2 <<= 6;
	wbyte2 &= 0xff00;
	wbyte2 += wbyte1 & 0xff;
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;

	return wbyte2;
}

写使能

在这里插入图片描述

void WREN(void)
{
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x06);
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

写入Flash

在这里插入图片描述
在这里插入图片描述

void WrSReg(uint16 setReg)
{
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x01);
	Send_Byte(setReg & 0x00ff);//传低8位。
	Send_Byte((setReg & 0x0300) >> 8);//传高8位,Flash是从0x0300开始的
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

等待延时

在这里插入图片描述

unsigned char Read_Status_Register(void)
{
	uint16 byte;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x05);
	byte = Get_Byte();
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
	return byte;
}

void Wait_Busy(void)
{
	uint32 waitcnt;
	unsigned char Wbusy;
	Wbusy = Read_Status_Register();
	waitcnt = 600000;
	while ((Wbusy & 0x01) == 0x01)
	{
		Wbusy = Read_Status_2Reg();
		if (waitcnt == 0)
		{
			WREN();
			WrSReg(0x0000);
			SPIFlash.SReg = Read_Status_2Reg();
		}
		else
			waitcnt--;
	}
}

擦除

在这里插入图片描述

void Chip_Erase(void)
{
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x60);
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

读取数据

在这里插入图片描述

void ReadData(unsigned char Dst, unsigned char *Rxbuf, unsigned long len)
{
	unsigned long i = 0;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x03);
	Send_Byte((Dst & 0xFFFFFF) << 16);
	Send_Byte((Dst & 0xFFFF) << 8);
	Send_Byte(Dst & 0xff);
	for (i = 0; i < len; i++)
	{
		*(Rxbuf++) = Get_Byte();
	}

	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

写入数据

跟读取数据时序差不多。
在这里插入图片描述

void PageProgram(unsigned char Dst, unsigned char *byte, unsigned char len)
{
	unsigned char i = 0;
	/*GPIO19置0*/
	GpioDataRegs.GPACLEAR.bit.GPIO19 = 1;
	Send_Byte(0x02);
	Send_Byte((Dst & 0xFFFFFF) << 16);
	Send_Byte((Dst & 0xFFFF) << 8);
	Send_Byte(Dst & 0xff);
	for (i = 0; i < len; i++)
	{
		Send_Byte(*(byte++));
	}
	/*GPIO19置1*/
	GpioDataRegs.GPASET.bit.GPIO19 = 1;
}

主函数部分

#include "dsc_config.h"
#include <syscalls.h>
#include "IQmathLib.h"

#include "spi.h"

extern void InitLED(void);
uint8_t upper_100[128] = { 0x55, 0x55, 0x55, 0x98, 0x56, 0x78, 0x45, 0x34 };

uint16 k = 0;
bool_t status = true;

int main(void)
{
	/*初始化系统控制:PLL,WatchDog,使能外设时钟*/
	InitSysCtrl();
	/*初始化LED*/
	InitLED();

	/*初始化GPIO为SPI引脚功能*/
	SPI_IOinit();
	/*初始化SPI的FIFO寄存器*/
	SPI_fifo_init();
	/*初始化SPI的控制寄存器*/
	spi_init();

	/*读取ID信息*/
	SPIFlash.Jedec_ID = Jedec_ID_Read();
	/*读取flash状态*/
	SPIFlash.SReg = Read_Status_2Reg();
	/*flash写使能*/
	WREN();
	/*写状态*/
	WrSReg(0x0000);
	/*读取flash状态*/
	SPIFlash.SReg = Read_Status_2Reg();
	/*等待延时*/
	Wait_Busy();
	/*读取flash状态*/
	SPIFlash.SReg = Read_Status_2Reg();
	/*写使能*/
	WREN();
	/*擦除*/
	Chip_Erase();
	Wait_Busy();//等待4个周期。
	Wait_Busy();
	Wait_Busy();
	Wait_Busy();
	/*读取数据*/
	ReadData(0, upper_128, 128);
	/*写使能*/
	WREN();
	/*写入*/
	PageProgram(0, upper_100, 128);

	Wait_Busy();
	/*读取数据*/
	ReadData(0, upper_128, 128);

	for (k = 0; k < 128; k++)
	{
		/*判断数组内的元素是否相同*/
		if (upper_128[k] != upper_100[k])
		{
			status = false;
		}
	}

	if (status == true)
	{
		GpioDataRegs.GPACLEAR.bit.GPIO6 = 1;
	}
	else
	{
		GpioDataRegs.GPASET.bit.GPIO7 = 1;
	}

	while (1)
	{

	}

	return 0;
}
  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

谢谢~谢先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值