ADC理解(ADC多通道定时器触发DMA转运数据学习总结)

前提:本人使用STM32F103标准库学习,其他芯片可以参考其原理

        各部分配置我会进行详细讲解,一些很基础简单的如开启时钟我就会略过

一、ADC配置

        (1).GPIO配置

                1.选择ADC引脚

                查找芯片手册:这里我选择ADC1_IN10 即PC0 和  ADC1_IN11 即PC1

                2.GPIO初始化配置
标准库代码:
    GPIO_InitTypeDef  GPIO_InitStructure; //GPIO_InitStructure用于存放GPIO的参数

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);  //使能GPIOC的时钟


    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;    //设置引脚
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; //设置输入类型
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO的输出速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);  //根据参数初始化GPIO 

    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;    //设置引脚
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; //设置输入类型
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO的输出速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);  //根据参数初始化GPIO
详细讲解: 

        (2).ADC初始化配置

              1.  ADC初始化配置流程:

                        1.1  配置ADC时钟(选择分频系数);

                        1.2  开启时钟

                        1.3  选择ADC的模式

                        1.4  是否开启扫描模式

                        1.5  是否开启连续转换模式

                        1.6  ADC外部触发的选择

                        1.7  选择ADC数据的对齐方式

                        1.8  选择ADC的通道数

                        1.9  初始化ADC

                        1.10 配置规则组通道的参数

                        1.11 使能ADC,允许外部触发ADC

                        1.12 进行ADC的复位校准过程

标准库代码:
    ADC_InitTypeDef   ADC_InitStructure;  //ADC_InitStructure用于存放ADC的参数

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟分频,ADCCLK=PCLK2/6=12MHz
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1  , ENABLE);  //使能ADC1的时钟

    ADC_InitStructure.ADC_Mode                      = ADC_Mode_Independent;//设置独立转换模式
    ADC_InitStructure.ADC_ScanConvMode              = ENABLE;              //使能扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode        = DISABLE;             //禁止连续转换模式
    ADC_InitStructure.ADC_ExternalTrigConv          = ADC_ExternalTrigConv_T3_TRGO; //配置T3触发
    ADC_InitStructure.ADC_DataAlign                 = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel              = 2;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);


    ADC_Cmd(ADC1, ENABLE);                      //使能ADC1
    ADC_ExternalTrigConvCmd(ADC1, ENABLE);      //使用外部事件启动ADC转换

//ADC校验

    ADC_ResetCalibration(ADC1);                 //启动ADC复位校准,即将RSTCAL赋值为1
    while(ADC_GetResetCalibrationStatus(ADC1)); //读取并判断RSTCAL,RSTCAL为0跳出while语句
    ADC_StartCalibration(ADC1);                 //启动ADC校准,即将CAL赋值为1
    while(ADC_GetCalibrationStatus(ADC1));      //读取并判断CAL,CAL为0跳出while语句
2.详细讲解:
        2.1设置ADC的时钟频率(选择分频系数)

根据参考手册可知,ADC输入频率不得超过14MHz:

 据参考手册的时钟树:这里我配置的APB2位72Mhz,所以这里最少选择6分频,ADC时钟为12Mhz

        2.2 选择ADC模式

参考手册:

标准库对应原码:

#define ADC_Mode_Independent                       ((uint32_t)0x00000000)
#define ADC_Mode_RegInjecSimult                    ((uint32_t)0x00010000)
#define ADC_Mode_RegSimult_AlterTrig               ((uint32_t)0x00020000)
#define ADC_Mode_InjecSimult_FastInterl            ((uint32_t)0x00030000)
#define ADC_Mode_InjecSimult_SlowInterl            ((uint32_t)0x00040000)
#define ADC_Mode_InjecSimult                       ((uint32_t)0x00050000)
#define ADC_Mode_RegSimult                         ((uint32_t)0x00060000)
#define ADC_Mode_FastInterl                        ((uint32_t)0x00070000)
#define ADC_Mode_SlowInterl                        ((uint32_t)0x00080000)
#define ADC_Mode_AlterTrig                         ((uint32_t)0x00090000)

        2.3 扫描模式和连续转换模式

参考手册介绍:

补充:CONT位 即寄存器的连续转换设置位:0:单次转换模式,1:连续转换模式

理解:

开启多ADC通道:开启扫描模式,自动依此扫描规则通道的ADC。

开启连续扫描:结束一轮后,将从头开始,开始新一轮扫描,不会停止。

开启DMA转态下: 在每个通道结束后,DMA将转运数据到指定地址。

        2.4ADC外部触发选择

参考手册介绍:

 标准库对应原码:

#define ADC_ExternalTrigConv_T1_CC1                ((uint32_t)0x00000000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T1_CC2                ((uint32_t)0x00020000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T2_CC2                ((uint32_t)0x00060000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T3_TRGO               ((uint32_t)0x00080000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_T4_CC4                ((uint32_t)0x000A0000) /*!< For ADC1 and ADC2 */
#define ADC_ExternalTrigConv_Ext_IT11_TIM8_TRGO    ((uint32_t)0x000C0000) /*!< For ADC1 and ADC2 */

#define ADC_ExternalTrigConv_T1_CC3                ((uint32_t)0x00040000) /*!< For ADC1, ADC2 and ADC3 */
#define ADC_ExternalTrigConv_None                  ((uint32_t)0x000E0000) /*!< For ADC1, ADC2 and ADC3 */

#define ADC_ExternalTrigConv_T3_CC1                ((uint32_t)0x00000000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T2_CC3                ((uint32_t)0x00020000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_CC1                ((uint32_t)0x00060000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T8_TRGO               ((uint32_t)0x00080000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC1                ((uint32_t)0x000A0000) /*!< For ADC3 only */
#define ADC_ExternalTrigConv_T5_CC3                ((uint32_t)0x000C0000) /*!< For ADC3 only */

 这里我会这篇主要涉及定时器触发的使用,稍微提一下软件触发模式

 要是使用软件触发选择ADC_ExternalTrigConv_None

 然后用标准库的   ADC_SoftwareStartConvCmd(ADC1, ENABLE); 开启和关闭转换

        2.5 ADC数据对齐方式

这里转换数据将存在16位的寄存器中,可以选择左对齐和右对齐

#define ADC_DataAlign_Right                        ((uint32_t)0x00000000)
#define ADC_DataAlign_Left                         ((uint32_t)0x00000800)
        2.6 ADC的通道选择和配置

注意:这里有规则组和注入组概念

                规则组通道大小1-16逐个扫描,注入组优先级高于规则组,这里我主要用规则组。

首选选择要开启规则通道的数目 

 ADC_InitStructure.ADC_NbrOfChannel              = 2; 

然后配置通道的参数 :

括号内依此是: (选择ADC1/2 选择ADC的哪个通道第几个(转换顺序)ADC采样时间

ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);

这里我们开始已经通过查芯片手册选择了:ADC1的通道10和通道11。

关于ADC的采样时间:

采样时间越长,数据精准度越好

最后就是校准复位操作,按照上述代码就行。

二、定时器触发配置

        (1).定时器触发初始化配置

标准库代码:

static void ConfigTimer3(u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //TIM_TimeBaseStructure用于存放TIM3的参数

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能TIM3的时钟
    
    TIM_DeInit(TIM3);  
    TIM_TimeBaseStructure.TIM_Period        = arr;  //设置自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler     = psc;  //设置预分频器值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割:tDTS = tCK_INT
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up; //设置向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);               //根据参数初始化定时器 

    TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);          //选择更新事件为触发输入
  

    TIM_Cmd(TIM3, ENABLE);  //使能定时器

}

这里配置的原理和上一篇

DAC理解(DAC定时器触发DMA转运学习总结)-CSDN博客

这里就不赘述;

三、DMA配置

        (1).DMA通道选择,查找对应的要搬运的数据地址

 1.DMA通道选择,通过查找参考手册,可看见DMA的每个通道的作用,这里选择DMA1_CH1

即选择ADC1。

        (2).DMA初始化配置

标准库代码:

static void ConfigDMA1Ch1(u16* s_arrADC1Data) 
{
    DMA_InitTypeDef DMA_InitStructure;  //DMA_InitStructure用于存放DMA的参数

     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA1的时钟

    DMA_DeInit(DMA1_Channel1);  //将DMA1_CH1寄存器设置为默认值

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;           //设置外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)s_arrADC1Data;        //设置存储器地址
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;           //设置为外设到存储器模式
    DMA_InitStructure.DMA_BufferSize         = 2;                               //设置要传输的数据项数目
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;       //设置外设为非递增模式
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;            //设置存储器为递增模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //设置外设数据长度为半字
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;     //设置存储器数据长度为半字
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;               //设置为循环模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;             //设置为中等优先级
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                 //禁止存储器到存储器访问
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);  //根据参数初始化DMA1_Channel1

    DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA1_Channel1

}

四、联合使用

接下来就是配合起来一起使用:

(1)计算ADC的转换时间:

ADC转换时间:T  = [(转换周期+12.5) * 每个周期的时间]  * 通道个数

例:

        T = [(239.5+12.5) * 1/12Mhz] * 2 = 42us;

(2)ADC整体初始化配置代码:
/*
 ADC配置
    定时器触发,1ms一次
    ADC转换时间:(239.5+12.5)/12MHZ = 21us, 两次42us,时间足够

*/
void InitADC(void)
{
		
    ConfigDMA1Ch1(ADC_Data); //DMA初始化
    ConfigADC1();            //ADC初始化
    ConfigTimer3(100, 720);  //定时器触发配置,1ms触发一次,1ms >> 42us 可以转换完成
}
贴一下完整工程:

ADC.c

#include "ADC.h"
u16 ADC_Data[2]={};


/*
 ADC配置
    定时器触发,1ms一次
    ADC转换时间:(239.5+12.5)/12MHZ = 21us, 两次42us,时间足够

*/
void InitADC(void)
{
		
    ConfigDMA1Ch1(ADC_Data);
    ConfigADC1();
    ConfigTimer3(100, 720);
}
/*
 配置ADC函数

    模式:      独立转换模式,扫描模式,禁止连续转换,使用定时器触发转换
    通道配置:  PC0--ADC1_IN10 , PC1--ADC2_IN11 


*/
static void ConfigADC1(void)
{

    GPIO_InitTypeDef  GPIO_InitStructure; //GPIO_InitStructure用于存放GPIO的参数
    ADC_InitTypeDef   ADC_InitStructure;  //ADC_InitStructure用于存放ADC的参数

    RCC_ADCCLKConfig(RCC_PCLK2_Div6); //设置ADC时钟分频,ADCCLK=PCLK2/6=12MHz
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1  , ENABLE);  //使能ADC1的时钟
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC , ENABLE);  //使能GPIOC的时钟
// PC1配置 ADC1_IN10
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_0;    //设置引脚
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; //设置输入类型  
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO的输出速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);  //根据参数初始化GPIO 
// PC1配置 ADC2_IN11
    GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;    //设置引脚
    GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AIN; //设置输入类型
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; //设置GPIO的输出速度
    GPIO_Init(GPIOC, &GPIO_InitStructure);  //根据参数初始化GPIO


    ADC_InitStructure.ADC_Mode                      = ADC_Mode_Independent;//设置独立转换模式
    ADC_InitStructure.ADC_ScanConvMode              = ENABLE;              //使能扫描模式
    ADC_InitStructure.ADC_ContinuousConvMode        = DISABLE;             //禁止连续转换模式
    ADC_InitStructure.ADC_ExternalTrigConv          = ADC_ExternalTrigConv_T3_TRGO; //配置T3触发
    ADC_InitStructure.ADC_DataAlign                 = ADC_DataAlign_Right;
    ADC_InitStructure.ADC_NbrOfChannel              = 2;
    ADC_Init(ADC1, &ADC_InitStructure);

    ADC_RegularChannelConfig(ADC1, ADC_Channel_10, 1, ADC_SampleTime_239Cycles5);
    ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 2, ADC_SampleTime_239Cycles5);

                    //使能ADC1的DMA

    
    ADC_Cmd(ADC1, ENABLE);                      //使能ADC1
    ADC_ExternalTrigConvCmd(ADC1, ENABLE);      //使用外部事件启动ADC转换
    ADC_DMACmd(ADC1, ENABLE);  

//ADC校验

    ADC_ResetCalibration(ADC1);                 //启动ADC复位校准,即将RSTCAL赋值为1

    while(ADC_GetResetCalibrationStatus(ADC1)); //读取并判断RSTCAL,RSTCAL为0跳出while语句
    ADC_StartCalibration(ADC1);                 //启动ADC校准,即将CAL赋值为1
    while(ADC_GetCalibrationStatus(ADC1));      //读取并判断CAL,CAL为0跳出while语句


}
/*
 配置DMA函数

    通道配置:  
    通道数:    2
    通道缓冲区:ADC_Data
*/
static void ConfigDMA1Ch1(u16* s_arrADC1Data) 
{
    DMA_InitTypeDef DMA_InitStructure;  //DMA_InitStructure用于存放DMA的参数

     RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);  //使能DMA1的时钟

    DMA_DeInit(DMA1_Channel1);  //将DMA1_CH1寄存器设置为默认值

    DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;           //设置外设地址
    DMA_InitStructure.DMA_MemoryBaseAddr     = (uint32_t)s_arrADC1Data;        //设置存储器地址
    DMA_InitStructure.DMA_DIR                = DMA_DIR_PeripheralSRC;           //设置为外设到存储器模式
    DMA_InitStructure.DMA_BufferSize         = 2;                               //设置要传输的数据项数目
    DMA_InitStructure.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;       //设置外设为非递增模式
    DMA_InitStructure.DMA_MemoryInc          = DMA_MemoryInc_Enable;            //设置存储器为递增模式
    DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord; //设置外设数据长度为半字
    DMA_InitStructure.DMA_MemoryDataSize     = DMA_MemoryDataSize_HalfWord;     //设置存储器数据长度为半字
    DMA_InitStructure.DMA_Mode               = DMA_Mode_Circular;               //设置为循环模式
    DMA_InitStructure.DMA_Priority           = DMA_Priority_Medium;             //设置为中等优先级
    DMA_InitStructure.DMA_M2M                = DMA_M2M_Disable;                 //禁止存储器到存储器访问
    DMA_Init(DMA1_Channel1, &DMA_InitStructure);  //根据参数初始化DMA1_Channel1

    DMA_Cmd(DMA1_Channel1, ENABLE); //使能DMA1_Channel1

}
/*
 TIM3配置
    配置更新事件触发,不中断

*/
static void ConfigTimer3(u16 arr, u16 psc)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure; //TIM_TimeBaseStructure用于存放TIM3的参数

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);  //使能TIM3的时钟

    TIM_TimeBaseStructure.TIM_Period        = arr;  //设置自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler     = psc;  //设置预分频器值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;       //设置时钟分割:tDTS = tCK_INT
    TIM_TimeBaseStructure.TIM_CounterMode   = TIM_CounterMode_Up; //设置向上计数模式
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);               //根据参数初始化定时器 

    TIM_SelectOutputTrigger(TIM3,TIM_TRGOSource_Update);          //选择更新事件为触发输入

    TIM_Cmd(TIM3, ENABLE);  //使能定时器

}

ADC.h

#ifndef _ADC_H_
#define _ADC_H_

#include "stm32f10x_conf.h"

extern u16 ADC_Data[2];

void InitADC(void);  //初始化ADC模块
static void ConfigADC1(void);
static void ConfigDMA1Ch1(u16* s_arrADC1Data);
static void ConfigTimer3(u16 arr, u16 psc);


#endif

  • 30
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
以下是基于HAL库的stm32f407定时器触发adc dma通道采样代码: 首先,需要初始化定时器ADC: ``` TIM_HandleTypeDef htim; ADC_HandleTypeDef hadc; void MX_TIM_Init(void) { TIM_MasterConfigTypeDef sMasterConfig = {0}; htim.Instance = TIMx; htim.Init.Prescaler = TIMx_PRESCALER; htim.Init.CounterMode = TIM_COUNTERMODE_UP; htim.Init.Period = TIMx_PERIOD; htim.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; htim.Init.RepetitionCounter = 0; HAL_TIM_Base_Init(&htim); sMasterConfig.MasterOutputTrigger = TIM_TRGO_UPDATE; sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE; HAL_TIMEx_MasterConfigSynchronization(&htim, &sMasterConfig); } void MX_ADC_Init(void) { ADC_ChannelConfTypeDef sConfig = {0}; hadc.Instance = ADCx; hadc.Init.ClockPrescaler = ADC_CLOCKPRESCALER_PCLK_DIV2; hadc.Init.Resolution = ADC_RESOLUTION_12B; hadc.Init.ScanConvMode = ENABLE; hadc.Init.ContinuousConvMode = DISABLE; hadc.Init.DiscontinuousConvMode = DISABLE; hadc.Init.NbrOfDiscConversion = 0; hadc.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_RISING; hadc.Init.ExternalTrigConv = ADC_EXTERNALTRIGCONV_Tx_TRGO; hadc.Init.DataAlign = ADC_DATAALIGN_RIGHT; hadc.Init.NbrOfConversion = ADC_CHANNEL_NUM; hadc.Init.DMAContinuousRequests = ENABLE; hadc.Init.EOCSelection = ADC_EOC_SEQ_CONV; HAL_ADC_Init(&hadc); for (int i = 0; i < ADC_CHANNEL_NUM; ++i) { sConfig.Channel = ADC_CHANNEL_x[i]; sConfig.Rank = i + 1; sConfig.SamplingTime = ADC_SAMPLETIME_15CYCLES; HAL_ADC_ConfigChannel(&hadc, &sConfig); } } ``` 然后,需要初始化DMA和中断: ``` DMA_HandleTypeDef hdma_adc; void MX_DMA_Init(void) { hdma_adc.Instance = DMAx_STREAMx; hdma_adc.Init.Channel = DMA_CHANNELx; hdma_adc.Init.Direction = DMA_PERIPH_TO_MEMORY; hdma_adc.Init.PeriphInc = DMA_PINC_DISABLE; hdma_adc.Init.MemInc = DMA_MINC_ENABLE; hdma_adc.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; hdma_adc.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; hdma_adc.Init.Mode = DMA_CIRCULAR; hdma_adc.Init.Priority = DMA_PRIORITY_HIGH; hdma_adc.Init.FIFOMode = DMA_FIFOMODE_DISABLE; HAL_DMA_Init(&hdma_adc); __HAL_LINKDMA(&hadc, DMA_Handle, hdma_adc); } void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) { if (hadc->Instance == ADCx) { HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin); } } ``` 最后,在main函数中启动定时器DMA: ``` int main(void) { HAL_Init(); MX_TIM_Init(); MX_ADC_Init(); MX_DMA_Init(); HAL_TIM_Base_Start(&htim); HAL_ADC_Start_DMA(&hadc, (uint32_t*)adc_buf, ADC_CHANNEL_NUM); while (1) { HAL_Delay(1000); } } ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值