EasyArm-i.mx280a开发板入门-adc示例代码编译(WSL+ubuntu20.04)

1.解压开发板上面的linux内核代码

把光盘上面的linux-2.6.35.3.tar.bz2复制到d:\imx280a_exe_folder/

wsl linux子系统终端运行命令,解压linux内核代码

cd /home/dengxm2024

tar xvf /mnt/d/imx280a_exe_folder/linux-2.6.35.3.tar.bz2

现在内核代码文件夹已经解压到/home/dengxm2024,名称是linux-2.6.35.3 ,路径全程:/home/dengxm2024/linux-2.6.35.3

2.复制编译adc驱动示例代码:

~/linuxProgDir/kernelside_code/imx280a_adc_drv

驱动:/home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/Makefile

第一行添加内核源码的路径

KERNEL_PATH := /home/dengxm2024/linux-2.6.35.3

obj-m:=lradc.o
PWD:=$(shell pwd)
KDIR:=$(KERNEL_PATH)
all:
	$(MAKE) -C $(KDIR) M=$(PWD) 
clean:
	rm -rf *.ko *.order *.symvers *.cmd *.o *.mod.c *.tmp_versions .*.cmd .tmp_versions

/home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/lradc.c

/*********************************************Copyright (c)***********************************************
**                                Guangzhou ZLG MCU Technology Co., Ltd.
**
**                                        http://www.zlgmcu.com
**
**      广州周立功单片机科技有限公司所提供的所有服务内容旨在协助客户加速产品的研发进度,在服务过程中所提供
**  的任何程序、文档、测试结果、方案、支持等资料和信息,都仅供参考,客户有权不使用或自行参考修改,本公司不
**  提供任何的完整性、可靠性等保证,若在客户使用过程中因任何原因造成的特别的、偶然的或间接的损失,本公司不
**  承担任何责任。
**                                                                        ——广州周立功单片机科技有限公司
**
**--------------File Info---------------------------------------------------------------------------------
** File name:               lradc.c
** Last modified date:      2013年11月28日15:57:38
** Last version:            
** Descriptions:           
**
**--------------------------------------------------------------------------------------------------------
** Created by:              周华
** Created date:            2013年11月28日15:57:44
** Version:           	    v1.0
** Descriptions:            ADC驱动,读取
**--------------------------------------------------------------------------------------------------------
** Modified by:       	cxf 
** Modified date:       2014-09-22
** Version:            
** Descriptions:        ADC Vref = Bandgap Reference(channel 14) = 1.85V
**			如果电压大于1.85V,需要开启硬件除2
**			ADC为12位
**			每个寄存器都有四个,分别用来 r/w 、set 、clear 、trogger 
**                          名称类似 HW_LRADC_CTRL0、HW_LRADC_CTRL0_SET、
**                          HW_LRADC_CTRL0_CLR、HW_LRADC_CTRL0_TOG       
**  HW_LRADC_CTRL0      SFTRST(31)  CLKGATE(30) SCHEDULE(7~0)   
**  HW_LRADC_CTRL1      CHn_IRQ_EN(23~16)   CHn_IRQ(7~0)        主要为触屏、ADC中断
**  HW_LRADC_CTRL2      CHn_DIV/2(31~24)                        主要为温度控制
**  HW_LRADC_CTRL3      DISCARD(25、24) CYCLE_TIME(9、8)HIGH_TIME(5/4)DELAY_CLK(1)INVERT_CLK(0)忽略、时钟
**  HW_LRADC_CTRL4      4*8 channels 0-16 channel selector
**                      
*********************************************************************************************************/

#include<linux/module.h>                                                /* module                       */
#include<linux/fs.h>                                                    /* file operation               */
#include<asm/uaccess.h>                                                 /* get_user()                   */
#include<linux/miscdevice.h>                                            /* miscdevice                   */
#include<asm/io.h>                                                      /* ioctl                        */
#include <mach/regs-lradc.h>						/* #define                      */

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/sysdev.h>
#include <linux/platform_device.h>
#include <linux/bitops.h>
#include <linux/io.h>
#include <linux/err.h>
#include <linux/ioport.h>
#include <linux/irq.h>
#include <linux/delay.h>

#include <mach/hardware.h>
#include <mach/device.h>
#include <mach/regs-lradc.h>
#include <mach/lradc.h>

#include "lradc.h"

#define  ZLG_IMX_283   0
#define  ZLG_IMX_287   1
#define  ZLG_IMX_280   2

extern int zlg_board_type;

static void __iomem *adc_base = NULL;


/*********************************************************************************************************
 文件操作接口
*********************************************************************************************************/
static int adc_open (struct inode *inode, struct file *fp) 
{

	try_module_get(THIS_MODULE);    

	//modified by cxf 2014-10-22 for imx280 ADCs
	if(ZLG_IMX_280 == zlg_board_type) {
		writel(BM_LRADC_CTRL0_SFTRST,adc_base + HW_LRADC_CTRL0_SET);
		udelay(1);
		writel(BM_LRADC_CTRL0_SFTRST,adc_base + HW_LRADC_CTRL0_CLR);
		/* Clear the Clock Gate for normal operation */
		writel(BM_LRADC_CTRL0_CLKGATE,adc_base + HW_LRADC_CTRL0_CLR);
	}
	writel(0xC0000000, adc_base + HW_LRADC_CTRL0_CLR);              /* 开启CLK,关闭复位模式        */
	writel(0x18430000, adc_base + HW_LRADC_CTRL1_CLR);              /* 关闭0-1-6通道及按键中断      */ 
	writel(0x30000000, adc_base + HW_LRADC_CTRL3_SET);              /* 忽略上电前三次采集数据       */     
	writel(0x76543210, adc_base + HW_LRADC_CTRL4);                  /* 设置对应的数据存放位置       */
	
	return 0;
}
static int adc_release (struct inode *inode, struct file *fp)
{
	module_put(THIS_MODULE);
    
	return 0;
}
/*********************************************************************************************************
**   cmd: 
**	不开启除2:
**	10:CH0 	11:CH1 	12:CH2 	13:CH3 	14:CH4  15:CH5  16:CH6 	 17:Vbat(内部除4)	  
**	开启除2: 
**      20:CH0	21:CH1  22:CH2  23:CH3  24:CH4  25:CH5  26:CH6 
**
**   被注释部分为3.0以上内核函数定义形式
*********************************************************************************************************/

//static int adc_ioctl(struct file *fp, struct file *flip, unsigned int cmd, unsigned long arg)
static int adc_ioctl(struct inode *inode, struct file *flip, unsigned int cmd, unsigned long arg)
{
    	int iRes;
	int iTmp;
	
/*
	if(cmd < 10 || cmd > 27) {
		return -1;
	}

	iTmp = cmd % 10;
	//CH2 ~ CH5 only for imx280
	if((zlg_board_type != ZLG_IMX_280) && (iTmp > 1) && (iTmp < 6)) {
		printk("Not ZLG_IMX_280 board.\n");
		return -1;
	} 
*/
	iTmp = _IOC_NR(cmd) % 10;

	switch(cmd){
	case IMX28_ADC_CH0:
		writel(0x01000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;

	case IMX28_ADC_CH0_DIV2:
		writel(0x01000000, adc_base + HW_LRADC_CTRL2_SET);
       		break; 

	case IMX28_ADC_CH1:
		writel(0x02000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;	
	
	case IMX28_ADC_CH1_DIV2:
                writel(0x02000000, adc_base + HW_LRADC_CTRL2_SET);
		break;
	
	case IMX28_ADC_CH2:
		writel(0x04000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;
	
	case IMX28_ADC_CH2_DIV2:
		writel(0x04000000, adc_base + HW_LRADC_CTRL2_SET);
       		break; 
	
	case IMX28_ADC_CH3:
		writel(0x08000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;	
	
	case IMX28_ADC_CH3_DIV2:
                writel(0x08000000, adc_base + HW_LRADC_CTRL2_SET);
		break;
	
	case IMX28_ADC_CH4:
		writel(0x10000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;
	
	case IMX28_ADC_CH4_DIV2:
		writel(0x10000000, adc_base + HW_LRADC_CTRL2_SET);
       		break; 
	
	case IMX28_ADC_CH5:
		writel(0x20000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;	
	
	case IMX28_ADC_CH5_DIV2:
                writel(0x20000000, adc_base + HW_LRADC_CTRL2_SET);
		break;
	
	case IMX28_ADC_CH6:
		writel(0x40000000, adc_base + HW_LRADC_CTRL2_CLR);
		break;
        
	case IMX28_ADC_CH6_DIV2:
                writel(0x40000000, adc_base + HW_LRADC_CTRL2_SET);
		break;

	case IMX28_ADC_VBAT:	
        case IMX28_ADC_VBAT_DIV4:
		break;

	default:
		printk("adc control cmd invalid!!\n");
		return -1;
	}

        /* Clear the accumulator & NUM_SAMPLES */
        __raw_writel(0xFFFFFFFF,
                     adc_base + HW_LRADC_CHn_CLR(iTmp));

        /* Clear the interrupt flag */
        __raw_writel(1 << iTmp,
                     adc_base + HW_LRADC_CTRL1_CLR);
        
        __raw_writel(BF_LRADC_CTRL0_SCHEDULE(1 << iTmp),
                     adc_base + HW_LRADC_CTRL0_SET);

        /* wait for completion */
        while ((__raw_readl(adc_base + HW_LRADC_CTRL1)
                & (1 << iTmp)) != (1 << iTmp))
                cpu_relax();

        /* Clear the interrupt flag */
        __raw_writel(1 << iTmp,
                     adc_base + HW_LRADC_CTRL1_CLR);

        iRes =  __raw_readl(adc_base + HW_LRADC_CHn(iTmp)) &
                           BM_LRADC_CHn_VALUE;
   	copy_to_user((void *)arg, (void *)(&iRes), sizeof(int));
    
    	return 0;
}
/*********************************************************************************************************
Device Struct
*********************************************************************************************************/
struct file_operations adc_fops = 
{
	.owner		= THIS_MODULE,
	.open		= adc_open,
	.release	= adc_release,
    	.ioctl      	= adc_ioctl,
};
static struct miscdevice adc_miscdev = 
{
	.minor	        = MISC_DYNAMIC_MINOR,
   	.name	        = "magic-adc",
    	.fops	        = &adc_fops,
};
/*********************************************************************************************************
Module Functions
*********************************************************************************************************/
static int __init adcModule_init (void)
{
    	int iRet=0;

	if (ZLG_IMX_283 == zlg_board_type) {
		printk("zlg EasyARM-imx283 adc driver up. \n");
	} else if(ZLG_IMX_287 == zlg_board_type) {
		printk("zlg EasyARM-imx287 adc driver up. \n");
	} else if(ZLG_IMX_280 == zlg_board_type) {
		//printk("zlg EasyARM-imx280 adc driver up. \n");
	} 	
	adc_base = ioremap(0x80050000, 0x180*4);    
    	iRet = misc_register(&adc_miscdev);
	if (iRet) {
		printk("register failed!\n");
	} 
	return iRet;
}
static void __exit adcModule_exit (void)                                /* warning:return void          */
{
	printk("zlg EasyARM-imx28xx adc driver down.\n");
	misc_deregister(&adc_miscdev);
}
/*********************************************************************************************************
Driver Definitions
*********************************************************************************************************/
module_init(adcModule_init);
module_exit(adcModule_exit);

MODULE_LICENSE("Dual BSD/GPL");
MODULE_AUTHOR("admin@9crk.com");
MODULE_DESCRIPTION("EasyARM283 By zhouhua");
/*********************************************************************************************************
End File
*********************************************************************************************************/


/home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/lradc.h

#ifndef __LRADC_H
#define __LRADC_H

#define IMX28_ADC_IOC_MAGIC     'j'

#define IMX28_ADC_CH0     	_IOW(IMX28_ADC_IOC_MAGIC, 10, int)	/* 通道0			*/
#define IMX28_ADC_CH1     	_IOW(IMX28_ADC_IOC_MAGIC, 11, int)	/* 通道1			*/
#define IMX28_ADC_CH2     	_IOW(IMX28_ADC_IOC_MAGIC, 12, int)	/* 通道2			*/
#define IMX28_ADC_CH3   	_IOW(IMX28_ADC_IOC_MAGIC, 13, int)	/* 通道3			*/
#define IMX28_ADC_CH4     	_IOW(IMX28_ADC_IOC_MAGIC, 14, int)	/* 通道4			*/
#define IMX28_ADC_CH5     	_IOW(IMX28_ADC_IOC_MAGIC, 15, int)	/* 通过5			*/
#define IMX28_ADC_CH6     	_IOW(IMX28_ADC_IOC_MAGIC, 16, int)	/* 通道6			*/
#define IMX28_ADC_VBAT     	_IOW(IMX28_ADC_IOC_MAGIC, 17, int)	/* 测量电池电压			*/

#define IMX28_ADC_CH0_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 20, int)	/* 通道0,开启除 2		*/
#define IMX28_ADC_CH1_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 21, int)	/* 通道1,开启除 2		*/
#define IMX28_ADC_CH2_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 22, int)	/* 通道2,开启除 2		*/
#define IMX28_ADC_CH3_DIV2   	_IOW(IMX28_ADC_IOC_MAGIC, 23, int)	/* 通道3,开启除 2		*/
#define IMX28_ADC_CH4_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 24, int)	/* 通道4,开启除 2		*/
#define IMX28_ADC_CH5_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 25, int)	/* 通过5,开启除 2		*/
#define IMX28_ADC_CH6_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 26, int)	/* 通道6,开启除 2		*/
#define IMX28_ADC_VBAT_DIV4     _IOW(IMX28_ADC_IOC_MAGIC, 27, int)	/* 测量电池电压,开启除4		*/

#endif

源码文件夹下面运行make命令:

dengxm2024@PC-202105142413:~/linuxProgDir/kernelside_code/imx280a_adc_drv$ make
make -C /home/dengxm2024/linux-2.6.35.3 M=/home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv 
make[1]: Entering directory '/home/dengxm2024/linux-2.6.35.3'
  LD      /home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/built-in.o
  CC [M]  /home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/lradc.o
  Building modules, stage 2.
  MODPOST 1 modules
  CC      /home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/lradc.mod.o
  LD [M]  /home/dengxm2024/linuxProgDir/kernelside_code/imx280a_adc_drv/lradc.ko
make[1]: Leaving directory '/home/dengxm2024/linux-2.6.35.3'

复制生成的lradc.ko到web服务器主文件夹:

 cp lradc.ko /mnt/d/imx280a_exe_folder/

3.复制编译adc用户侧调用的示例代码:

/home/dengxm2024/linuxProgDir/userside_code/ap-283demo-adc/lradc_test.c

/*********************************************************************************
**   ADC参考电压为1.85V,外部输入电压不能超过3.7V,内部带有一个模拟除2电路。
*********************************************************************************/

#include<stdio.h>	/* using printf()        */
#include<stdlib.h>      /* using sleep()         */
#include<fcntl.h>       /* using file operation  */
#include<sys/ioctl.h>   /* using ioctl()         */
#include "lradc.h"

int main(int argc, char *argv[])
{
	int fd;
	int iRes;
	int time = 50;
	double val;

	fd = open("/dev/magic-adc", 0);
	if(fd < 0){
		printf("open error by APP- %d\n",fd);
		close(fd);
		return 0;
	}
	while(time--){
		sleep(1);		
		#if 0						/* 对于EasyARM-iMX280A,请设置为1 */
		ioctl(fd,IMX28_ADC_CH0_DIV2, &iRes);		/* 开启除2     CH0    */
		val = (iRes * 3.7) / 4096.0;
		printf("CH0:%.2f  ", val);

		ioctl(fd,IMX28_ADC_CH1, &iRes);                 /* 不开除2     CH1    */
		val = (iRes * 1.85) / 4096.0;
       		printf("CH1:%.2f  ", val);
		
		
		ioctl(fd,IMX28_ADC_CH2_DIV2, &iRes);		/* 开启除2     CH2    */
		val = (iRes * 3.7) / 4096.0;
		printf("CH2:%.2f  ", val);

		ioctl(fd, IMX28_ADC_CH3, &iRes);                /* 不开除2     CH3    */
		val = (iRes * 1.85) / 4096.0;
       		printf("CH3:%.2f  ", val);
		
		ioctl(fd,IMX28_ADC_CH4_DIV2, &iRes);		/* 开启除2     CH4    */
		val = (iRes * 3.7) / 4096.0;
		printf("CH4:%.2f  ", val);

		ioctl(fd,IMX28_ADC_CH5, &iRes);                 /* 不开除2     CH5    */
		val = (iRes * 1.85) / 4096.0;
       		printf("CH5:%.2f  ", val);
		
        	ioctl(fd,IMX28_ADC_CH6_DIV2, &iRes);            /* 开启除2     CH6    */
		val = (iRes * 3.7) / 4096.0;
        	printf("CH6:%.2f  ", val);

        	ioctl(fd,IMX28_ADC_VBAT_DIV4, &iRes);                /* 电池电压默认除4    */
		val = (iRes * 7.4) / 4096.0;
        	printf("Vbat:%.2f  ", val);

#endif
ioctl(fd,IMX28_ADC_CH5, &iRes);                 /* 不开除2     CH5    */
		val = (iRes * 1.85) / 4096.0;
       		printf("CH5:%.2f  ", val);
		printf("\n");
	}
	close(fd);
}

/home/dengxm2024/linuxProgDir/userside_code/ap-283demo-adc/lradc.h

#ifndef __LRADC_H
#define __LRADC_H

#define IMX28_ADC_IOC_MAGIC     'j'

#define IMX28_ADC_CH0     	_IOW(IMX28_ADC_IOC_MAGIC, 10, int)	/* 通道0			*/
#define IMX28_ADC_CH1     	_IOW(IMX28_ADC_IOC_MAGIC, 11, int)	/* 通道1			*/
#define IMX28_ADC_CH2     	_IOW(IMX28_ADC_IOC_MAGIC, 12, int)	/* 通道2			*/
#define IMX28_ADC_CH3   	_IOW(IMX28_ADC_IOC_MAGIC, 13, int)	/* 通道3			*/
#define IMX28_ADC_CH4     	_IOW(IMX28_ADC_IOC_MAGIC, 14, int)	/* 通道4			*/
#define IMX28_ADC_CH5     	_IOW(IMX28_ADC_IOC_MAGIC, 15, int)	/* 通过5			*/
#define IMX28_ADC_CH6     	_IOW(IMX28_ADC_IOC_MAGIC, 16, int)	/* 通道6			*/
#define IMX28_ADC_VBAT     	_IOW(IMX28_ADC_IOC_MAGIC, 17, int)	/* 测量电池电压			*/

#define IMX28_ADC_CH0_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 20, int)	/* 通道0,开启除 2		*/
#define IMX28_ADC_CH1_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 21, int)	/* 通道1,开启除 2		*/
#define IMX28_ADC_CH2_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 22, int)	/* 通道2,开启除 2		*/
#define IMX28_ADC_CH3_DIV2   	_IOW(IMX28_ADC_IOC_MAGIC, 23, int)	/* 通道3,开启除 2		*/
#define IMX28_ADC_CH4_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 24, int)	/* 通道4,开启除 2		*/
#define IMX28_ADC_CH5_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 25, int)	/* 通过5,开启除 2		*/
#define IMX28_ADC_CH6_DIV2     	_IOW(IMX28_ADC_IOC_MAGIC, 26, int)	/* 通道6,开启除 2		*/
#define IMX28_ADC_VBAT_DIV4     _IOW(IMX28_ADC_IOC_MAGIC, 27, int)	/* 测量电池电压,开启除4		*/

#endif

/home/dengxm2024/linuxProgDir/userside_code/ap-283demo-adc/Makefile

#CROSS_COMPILE是环境变量,是交叉编译工具的前缀,隐式声明编译器
CC = $(CROSS_COMPILE)gcc
CXX = $(CROSS_COMPILE)g++

#显示声明编译器
#CC = arm-fsl-linux-gnueabi-gcc
#CXX = arm-fsl-linux-gnueabi-g++

EXEC = ./bin/lradc_test
OBJS = lradc_test.o
SRC  = lradc_test.c

#CC = arm-fsl-linux-gnueabi-gcc 
CFLAGS += 
LDFLAGS += 
all:$(EXEC)

$(EXEC):$(OBJS)
	$(CC) $(LDFLAGS) -o $@ $(OBJS) 

%.o:%.c
	$(CC) $(CFLAGS) -c $< -o $@ 

clean:
	@rm -vf $(EXEC) *.o *~

执行编译:

dengxm2024@PC-202105142413:~/linuxProgDir/userside_code/ap-283demo-adc$ make
arm-fsl-linux-gnueabi-gcc  -c lradc_test.c -o lradc_test.o 
arm-fsl-linux-gnueabi-gcc  -o bin/lradc_test lradc_test.o 

复制编译结果到web服务器文件夹

dengxm2024@PC-202105142413:~/linuxProgDir/userside_code/ap-283demo-adc$ cp ./bin/lradc_test /mnt/d/imx280a_exe_folder/

4.运行测试

转到开发板终端窗口,运行命令,从web服务器获取刚才编译好的执行文件

root@EasyARM-iMX28x ~# wget http://192.168.0.233:443/imx280a_exe_folder/lradc.ko
Connecting to 192.168.0.233:443 (192.168.0.233:443)
lradc.ko             100% |*******************************|  5528   0:00:00 ETA
root@EasyARM-iMX28x ~# wget http://192.168.0.233:443/imx280a_exe_folder/lradc_te
st
Connecting to 192.168.0.233:443 (192.168.0.233:443)
lradc_test           100% |*******************************| 14279   0:00:00 ETA

添加可执行属性
root@EasyARM-iMX28x ~# chmod +x lradc_test 
root@EasyARM-iMX28x ~# chmod +x lradc.ko 

加载adc驱动模块

root@EasyARM-iMX28x ~# insmod lradc.ko

运行采集程序,转动AP-283demo扩展板上面的电位器,可以看到电压变化:

root@EasyARM-iMX28x ~# ./lradc_test 
CH5:0.95  
CH5:0.95  
CH5:0.95  
CH5:0.95  
CH5:0.95  
CH5:0.94  
CH5:0.95  
CH5:0.94  
CH5:0.97  
CH5:0.98  
CH5:0.98  
CH5:0.98  
CH5:0.99  
CH5:1.01  
CH5:1.02  
CH5:1.01  
CH5:1.01  
CH5:1.02  
CH5:1.02  
CH5:1.01  
CH5:1.02  
CH5:1.02  
CH5:1.02  
CH5:1.04  
CH5:1.05  
CH5:1.05  

为什么是adc的第5通道?

官方给的开发板原理中线号编的不一致,要仔细对比看:

AP-283demo原理图:

找接口原理图,ADC_IN0连接到了图纸1的adc0上面:

再查看i.mx280a的电路原理图:

所以ap-283demo扩展板的电位器采集的电压接入到了adc第5通道。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值