(stm32f407)DHT11温湿度数据采集

一、接口说明
建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使用合适的上拉电阻。

1 接线图

2 电源引脚
DHT11的供电电压为3~5.5 V。传感器上电后,要等待 1s 以越过不稳定状态,在此期间无需发送任何指令。电源引脚(VDD,GND)之间可增加一个100nF 的电容,用以去耦滤波。

3 串行接口(单线双向)
DATA 用于微处理器与 DHT11之间的通讯和同步,采用单总线数据格式,一次通讯时间4ms左右,数据分小数部分和整数部分,具体格式在下面说明,当前小数部分用于以后扩展,现读出为零.操作流程如下:

(1)一次完整的数据传输为40bit,高位先出。

(2)数据格式:
8bit湿度整数数据 + 8bit湿度小数数据 + 8bi温度整数数据 + 8bit温度小数数据 + 8bit校验和

(3)数据传送正确时,校验和数据等于
“8bit湿度整数数据+8bit湿度小数数据 +8bi温度整数数据+8bit温度小数数据”所得结果的末8位

二、通信过程


(1)如下图所示,用户MCU发送一次开始信号后,DHT11从低功耗模式转换到高速模式,等待主机开始信号结束后,DHT11发送响应信号,送出40bit的数据,并触发一次信号采集,用户可选择读取部分数据。

从模式下,DHT11接收到开始信号触发一次温湿度采集,如果没有接收到主机发送开始信号,DHT11不会主动进行温湿度采集。采集数据后转换到低速模式。

(2)如下图所示,总线空闲状态为高电平,主机把总线拉低等待DHT11响应,主机把总线拉低必须大于18毫秒,保证DHT11能检测到起始信号。DHT11接收到主机的开始信号后,等待主机开始信号结束,然后发送80us低电平响应信号。主机发送开始信号结束后,延时等待20-40us后,读取DHT11的响应信号,主机发送开始信号后,可以切换到输入模式,或者输出高电平均可,总线由上拉电阻拉高。

(3)如上图所示,总线为低电平,说明DHT11发送响应信号,DHT11发送响应信号后,再把总线拉高80us,准备发送数据。

(4)如下图所示每一bit数据都以50us低电平时隙开始,高电平的长短定了数据位是0还是1。如果读取响应信号为高电平,则DHT11没有响应,请检查线路是否连接正常。当最后一bit数据传送完毕后,DHT11拉低总线50us,随后总线由上拉电阻拉高进入空闲状态。
数字0信号表示方法如下图所示:

数字1信号表示方法如下图所示:

数字0信号与数字1信号的不同之处在于高电平的时间不同,利用这点,我么们可以通过设置电平时间阈值来判断信号的种类。

三、测量分辨率与电气特性

测量分辨率分别为 8bit(温度)、8bit(湿度)。

VDD=5V,T = 25℃,除非特殊标注
在这里插入图片描述
注:最新版厂家升级,采样周期为2秒,老版为1秒。

四:源代码


#include "stm32f4xx.h"
#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "stm32f4xx_usart.h"
#include "sys.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"

static GPIO_InitTypeDef  	GPIO_InitStructure;
static USART_InitTypeDef 	USART_InitStructure;
static NVIC_InitTypeDef 	NVIC_InitStructure;		
static EXTI_InitTypeDef   EXTI_InitStructure;
static TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
static TIM_OCInitTypeDef  TIM_OCInitStructure;

static uint32_t g_freq=100,g_duty=50,g_cmp=0,g_beep=0;

static volatile uint8_t  g_usart1_recv_buf[128]={0};
static volatile uint32_t g_usart1_recv_cnt = 0;
static volatile uint32_t g_usart1_event=0;

static volatile uint8_t  g_usart3_recv_buf[128]={0};
static volatile uint32_t g_usart3_recv_cnt = 0;
static volatile uint32_t g_usart3_event=0;

//重定义fputc函数 
int fputc(int ch, FILE *f)
{ 	
	USART_SendData(USART3,ch);
	while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET);  
	
	return ch;
}   

void delay_us(uint32_t nus)
{
	SysTick->CTRL = 0; // 关闭滴答定时器
	SysTick->LOAD = (SystemCoreClock/8/1000000)*nus; // 计数值
	SysTick->VAL = 0; // 清空当前值和状态标志位
	SysTick->CTRL = 1; // 启动定时器工作
	// 检测CTRL的第16位是否为0,如果为0表示定时时间到达
	while ((SysTick->CTRL & 0x00010000)==0);
	
	SysTick->CTRL = 0; //失能(关闭)滴答定时器
}

void delay_ms(uint32_t nms)
{	
	while(nms--)
	{
		SysTick->CTRL = 0; // 关闭滴答定时器
		SysTick->LOAD = (SystemCoreClock/8/1000); // 计数值
		SysTick->VAL = 0; // 清空当前值和状态标志位
		// 选择时钟源(如果是5表示选择168M工作,如果是1选择21M工作)并启动定时器工作
		SysTick->CTRL = 1; 
		// 检测CTRL的第16位是否为0,如果为0表示定时时间到达
		while ((SysTick->CTRL & 0x00010000)==0);
		
		SysTick->CTRL = 0; //失能(关闭)滴答定时器
	}
	
} 


void USART1_Init(uint32_t baud)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); 							//使能GPIOA时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);							//使能USART1时钟

	//串口1对应引脚复用映射
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); 						//GPIOA9复用为USART1
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); 						//GPIOA10复用为USART1
	
	//USART1端口配置
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10; 						//GPIOA9与GPIOA10
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;									//复用功能
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;								//速度50MHz
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; 									//推挽复用输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; 									//上拉
	GPIO_Init(GPIOA,&GPIO_InitStructure); 											//初始化PA9,PA10

	//USART1 初始化设置
	USART_InitStructure.USART_BaudRate = baud;										//波特率设置
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;						//字长为8位数据格式
	USART_InitStructure.USART_StopBits = USART_StopBits_1;							//一个停止位
	USART_InitStructure.USART_Parity = USART_Parity_No;								//无奇偶校验位
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;	//无硬件数据流控制
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					//收发模式
	USART_Init(USART1, &USART_InitStructure); 										//初始化串口1
	
	USART_Cmd(USART1, ENABLE);  													//使能串口1 
	
	USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);									//开启相关中断

	//Usart1 NVIC 配置
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;								//串口1中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3;							//抢占优先级3
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;								//子优先级3
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;									//IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);													//根据指定的参数初始化VIC寄存器
}

void USART3_Init(uint32_t baud)
{
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);

	/* GPIOB Configuration: PB10 PB11 */
	GPIO_InitStructure.GPIO_Pin =  GPIO_Pin_10 | GPIO_Pin_11  ;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;		
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP ;
	GPIO_Init(GPIOB, &GPIO_InitStructure);
	
	/* Connect USART3_TX pins to PB10 */
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_USART3);
	
	/* Connect USART3_RX pins to PB11 */
	GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_USART3);

	/* Enable USART3 clock */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);
	
	USART_InitStructure.USART_BaudRate = baud;									
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;				
	USART_InitStructure.USART_StopBits = USART_StopBits_1;				
	USART_InitStructure.USART_Parity = USART_Parity_No;						
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;					
	USART_Init(USART3, &USART_InitStructure);

	 
	/* Enable the USARTx Interrupt */
	NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_Init(&NVIC_InitStructure);
	 
	/* Enable USART3 */
	USART_Cmd(USART3, ENABLE);
	
	/* Enable the Rx buffer empty interrupt */
	USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
}

void USART1_SendBytes(uint8_t *pbuf,uint32_t len)
{

	while(len--)
	{
		USART_SendData(USART1,*pbuf++);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); 	
	}

}

void USART1_SendString(uint8_t *pstr)
{
	while(pstr && *pstr)
	{
		USART_SendData(USART1,*pstr++);
		while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET); 		
	}
}

void USART3_SendBytes(uint8_t *pbuf,uint32_t len)
{

	while(len--)
	{
		USART_SendData(USART3,*pbuf++);
		while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET); 	
	}

}

void USART3_SendString(uint8_t *pstr)
{
	while(pstr && *pstr)
	{
		USART_SendData(USART3,*pstr++);
		while(USART_GetFlagStatus(USART3,USART_FLAG_TXE)==RESET); 		
	}
}


// 初始化dht11 PG9为输出模式
void dht11_outputMode(void)
{
	//使能GPIOB,GPIOE时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);			

	//PB6初始化设置 
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;						//PG9引脚
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_OUT;			    	//普通输出模式,
	GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;					//推挽输出,驱动LED需要电流驱动
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;		    	//100MHz			   
	GPIO_Init(GPIOG, &GPIO_InitStructure);							//初始化GPIOB,把配置的数据写入寄存器		
}

// 初始化dht11 PG9为输入模式
void dht11_inputMode(void)
{
	//使能GPIOB,GPIOE时钟
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE);			

	//PB6初始化设置 
	GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_9;						//PG9引脚
	GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IN;			    	//普通输出模式,
	GPIO_Init(GPIOG, &GPIO_InitStructure);							//初始化GPIOB,把配置的数据写入寄存器	
}

uint8_t dht11_start(void)
{
	int i  = 0;
	// dht11设置为输出模式
	dht11_outputMode();
	// 输出20ms低电平
	PGout(9) = 0;
	delay_ms(20);
	// 输出30us高电平
	PGout(9) = 1;
	delay_us(30);
	
	// 切换为输入模式
	dht11_inputMode();
	
	// 是否有低电平
	while(i < 100)
	{
		if(PGin(9) == 1) // 检查到低电平有效
		{
			break;
		}
		delay_us(1);
		i++;
	}
	
	if(i == 100)
		return 1;
	
	// 检测是否触发高电平
	i = 0;
	while(i < 100)
	{
		if(PGin(9) == 0) // 检查到高电平有效
		{
			break;
		}
		delay_us(1);
		i++;
	}
	
	// 超时
	if(i == 100)
		return 1;
	
	// 正常退出
	return 0;
	
}

// 读取一字节数据
uint8_t dht11_read_byte(void)
{
	int i = 0;
	uint8_t data = 0;
	// 等待高电平完毕
	while(PGin(9));
	
	for(i = 0; i < 8; i++)
	{
		// 检测低电平
		while(PGin(9) == 0);
		delay_us(40);
		if(PGin(9) == 1)
		{
			// 截取数据
			data |= 1 <<(7-i);
			// 等待高电平结束
			while(PGin(9));
		}
	}
	
	return data;
}

uint8_t dht11_read_data(char *dht11_data)
{
	int i = 0;
	int check_sum = 0;
	// 激活dht11工作,准备读取数据
	while(dht11_start() == 1);
	
	// 读取5字节数据
	// 5字节包括温度整数,温度小数,湿度整数,湿度小数,校验位
	for(i = 0; i < 5; i++)
	{
		dht11_data[i] = dht11_read_byte();
	}
	
	// 计算校验和
	check_sum = dht11_data[0] + dht11_data[1] + dht11_data[2] + dht11_data[3];
	
	if(check_sum != dht11_data[4])
	{
		return 1;
	}
	
	return 0;
}

int main(void)
{ 

	char buf[64]={0};
	char dht11_data[5] = {0};	

	//系统定时器初始化,时钟源来自HCLK,且进行8分频,
	//系统定时器时钟频率=168MHz/8=21MHz
	SysTick_CLKSourceConfig(SysTick_CLKSource_HCLK_Div8); 
		
	//设置中断优先级分组2
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	
	//串口1,波特率115200bps,开启接收中断
	USART1_Init(115200);
	
	//串口3,波特率9600bps,开启接收中断
	USART3_Init(9600);
	
	while(1)
	{	
		if(dht11_read_data(dht11_data) == 0)
		{
		    	//执行串口3事件
		    if(g_usart3_event)
		    {    	
		    	//将接收到的换行符'\n'变为'\0'
		    	//"temp?\n" -> "temp?" 
		    	g_usart3_recv_buf[g_usart3_recv_cnt-1] = '\0';
		    	
		    	g_usart3_recv_cnt = 0;
		    	
		    	
		    	//判断接收到的字符串为temp
		    	if(strstr((char *)g_usart3_recv_buf,"temp"))
		    	{
		    		//以等号分割字符串
		    		strtok((char *)g_usart3_recv_buf,"?");
		    		
		    		//发送给蓝牙
		    		sprintf(buf,"temp = %d.%d\r\n",dht11_data[2],dht11_data[3]);
		    		USART3_SendString(buf);
		    	
		    	}
		    	
		    	if(strstr((char *)g_usart3_recv_buf,"humi"))
		    	{
		    		//以等号分割字符串
		    		strtok((char *)g_usart3_recv_buf,"?");
		    		
		    		//发送给蓝牙
		    		sprintf(buf,"humi = %d.%d\r\n",dht11_data[0],dht11_data[1]);
		    		USART3_SendString(buf);
		    	
		    	}
		    	//串口3继续工作,允许接收数据
		    	g_usart3_event = 0;    
		    }		
		}		
	}
}

void USART1_IRQHandler(void)                				//串口1中断服务程序
{
	uint8_t d;
	
	
	if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET)  	//接收中断
	{
		//从串口1接收数据
		g_usart1_recv_buf[g_usart1_recv_cnt]=USART_ReceiveData(USART1);	
		
		//记录多少个数据
		g_usart1_recv_cnt++;
		
		//检测到换行符或接收的数据满的时候则发送数据
		if(g_usart1_recv_buf[g_usart1_recv_cnt-1]=='\n' || g_usart1_recv_cnt>=(sizeof g_usart1_recv_buf)-1)
		{
			g_usart1_event = 1;
			
		}
	} 
} 

void USART3_IRQHandler(void)
{
	uint8_t d;

	/* USART in Receiver mode */
	if (USART_GetITStatus(USART3, USART_IT_RXNE) == SET)  
	{

		//从串口3接收数据
		g_usart3_recv_buf[g_usart3_recv_cnt]=USART_ReceiveData(USART3);	
		
		g_usart3_recv_cnt++;
		
		//检测到换行符或接收的数据满的时候则发送数据 beep=on\n
		if(g_usart3_recv_buf[g_usart3_recv_cnt-1]=='\n' || g_usart3_recv_cnt>=(sizeof g_usart3_recv_buf)-1)
		{
//			printf("usart3\n\r");
			g_usart3_event = 1;
					
		}

		d=USART_ReceiveData(USART3);
		USART1_SendBytes(&d,1);

	}
}

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,下面是stm32f103通过usart2采集dht11温湿度数据并发送到串口助手的完整代码示例: ``` #include "stm32f10x.h" #include <stdio.h> // 定义DHT11数据引脚 #define DHT11_DATA_PIN GPIO_Pin_0 #define DHT11_DATA_PORT GPIOA // 定义USART2发送函数 void USART2_SendData(uint8_t data) { while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET); // 等待发送缓冲区为空 USART_SendData(USART2, data); // 发送数据 } // 初始化USART2 void USART2_Init(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO | RCC_APB2Periph_USART1, ENABLE); // 使能USART2时钟和GPIOA时钟 // 配置PA2为USART2的Tx引脚 GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStructure); // 配置PA3为USART2的Rx引脚 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); // USART2初始化设置 USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = 9600; // 波特率设置为9600 USART_InitStructure.USART_WordLength = USART_WordLength_8b; // 字长为8位数据格式 USART_InitStructure.USART_StopBits = USART_StopBits_1; // 1个停止位 USART_InitStructure.USART_Parity = USART_Parity_No; // 无奇偶校验位 USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 无硬件数据流控制 USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; // 支持收发模式 USART_Init(USART2, &USART_InitStructure); // 初始化USART2 USART_Cmd(USART2, ENABLE); // 使能USART2 } // 初始化DHT11 void DHT11_Init(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); // 使能GPIOA时钟 // 配置DHT11数据引脚为GPIO输出模式 GPIO_InitStructure.GPIO_Pin = DHT11_DATA_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 将DHT11数据引脚输出高电平 } // 从DHT11读取数据 void DHT11_ReadData(uint8_t *temp, uint8_t *humi) { uint8_t buffer[5] = {0}; uint8_t i = 0, j = 0; GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 发送起始信号 delay_ms(18); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(30); GPIO_ResetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 接收响应信号 delay_us(40); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); delay_us(10); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; // 切换DHT11数据引脚为输入模式 GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 等待DHT11拉低数据引脚 while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); // 跳过DHT11的低电平响应信号 while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 接收数据 for (j = 0; j < 5; j++) { for (i = 0; i < 8; i++) { while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == RESET); // 跳过每个数据位的低电平 delay_us(40); // 等待数据位的高电平持续时间 if (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET) // 判断高电平持续时间,如果大于等于30us,则该数据位为1,否则为0 { buffer[j] |= (1 << (7 - i)); // 将读取到的数据保存到缓冲区中 } while (GPIO_ReadInputDataBit(DHT11_DATA_PORT, DHT11_DATA_PIN) == SET); // 等待数据位的高电平结束 } } *humi = buffer[0]; // 湿度值 *temp = buffer[2]; // 温度值 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // 切换DHT11数据引脚为输出模式 GPIO_Init(DHT11_DATA_PORT, &GPIO_InitStructure); GPIO_SetBits(DHT11_DATA_PORT, DHT11_DATA_PIN); // 将DHT11数据引脚输出高电平 } int main(void) { USART2_Init(); // 初始化USART2 DHT11_Init(); // 初始化DHT11 uint8_t temp, humi; char buffer[50]; while (1) { DHT11_ReadData(&temp, &humi); // 从DHT11读取温湿度数据 sprintf(buffer, "Temperature: %d℃, Humidity: %d%%\r\n", temp, humi); // 将温湿度数据格式化成字符串 for (uint8_t i = 0; i < strlen(buffer); i++) { USART2_SendData(buffer[i]); // 发送温湿度数据到串口助手 } delay_ms(1000); // 延时1秒 } } ``` 使用以上代码,您就可以在stm32f103采集dht11温湿度数据并通过usart2发送到串口助手了。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值