stm32平衡小车--(1)JGB-520减速电机+tb6612(附测试代码)

这篇具有很好参考价值的文章主要介绍了stm32平衡小车--(1)JGB-520减速电机+tb6612(附测试代码)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、JGB-520编码器减速直流电机

                                   jgb520电机介绍,STM32,stm32,嵌入式硬件,单片机

编码器

这是我用的电机,红色框框中的就是编码器

编码器是将信号(如比特流)或数据进行编制、转换为可用以通讯、传输和存储的信号形式的设备。编码器把角位移或直线位移转换成电信号,前者称为码盘,后者称为码尺。按照读出方式编码器可以分为接触式和非接触式两种;按照工作原理编码器可分为增量式和绝对式两类。

增量式编码器是将位移转换成周期性的电信号,再把这个电信号转变成计数脉冲,用脉冲的个数表示位移的大小。绝对式编码器的每一个位置对应一个确定的数字码,因此它的示值只与测量的起始和终止位置有关,而与测量的中间过程无关。

这是官方给出的,但我们只需要知道这个编码器可以通过电机的转动产生一定的脉冲,从而通过脉冲测出电机的转速和转动方向。后面我们会介绍这个。

JGB-520电机

jgb520电机介绍,STM32,stm32,嵌入式硬件,单片机

这种电机一般有6个引脚,有的引脚会与图中顺序不同(我的就是┭┮﹏┭┮)但只要连线正确就行。

这么大一个电机,我们要怎么让它动起来呢?没错,我们肯定需要一个驱动模块——tb6612

2、tb6612电机驱动模块

就是长这个样子:

                                       jgb520电机介绍,STM32,stm32,嵌入式硬件,单片机

这是它的引脚:

                            jgb520电机介绍,STM32,stm32,嵌入式硬件,单片机

3、电机的驱动

tb6612和电机的连接

TB6612 C8T6
STBY 高电平(+3.3V)
AIN1 A电机输入端1(接板子)
AIN2 A电机输入端2(接板子)
PWMA A电机控制信号输入端(PWM输入)
AO1 A电机电源M+
AO2 A电机电源M-
VM 12V
VCC 3.3V
GND 和单片机共地

这是一个电机的引脚连接,另一个电机与此类似。如果只用于电机驱动而不用测速的话,只用接电机的M+和M-即可

当AIN或BIN产生电势差,电机就会转动。

jgb520电机介绍,STM32,stm32,嵌入式硬件,单片机

4、转速的测量

如果我们要让我们的平衡车真的实现平衡,就肯定需要使用PWM驱动电机,然后再使用编码器测量速度,再使用PID算法进行闭环控制。

原理:

接收编码器的A、B相产生的正交信号,根据编码器产生的正交信号脉冲,自动控制CNT自增或自减,根据计数方向和编码器的信号关系来指示编码器的位置、旋转方向和旋转速度利用脉冲值来计算电机的转动位移

大概就是编码器上会有两个用来产生脉冲的东西,电机每转动一圈,他们会产生相差九十度的相同数量的脉冲,然后会有一个计数器去捕获脉冲的上升沿和下降沿,然后每隔一段时间去读取计数器的值(转动的圈数=计数器的数值/一圈产生的脉冲数),这样就能算出这一段时间转了多少圈,从而算出转速。

定时器的编码器接口模式

可以用来捕获上升沿和下降沿并计数。(Stm32中的定时器只有TIM1-5和TIM8才有编码器接口功能,而且只有CH1通道和CH2通道有用)。

4倍频计数:

采用的是编码器模式3,在TI1和TI2边沿都计数,也就是在一个周期内对A相和B相的上升沿下降沿都计数一个周期内计4次,所以采用这种模式后,相应的计数值(CNT)就会变成4倍。

线数:

电机转动一圈产生的脉冲数就是线数。比如我的电机线束是30,那么我的电机转一圈就会产生30个脉冲。

5、相关代码的配置

电机的驱动代码如下:

这个没有什么好讲的,大家应该都能看懂。

//moto1,moto2  左轮PWM、右轮PWM
void Set_Pwm(int moto1,int moto2)
{
	if(moto1<0)			AIN2=1,			AIN1=0;
	else 	          AIN2=0,			AIN1=1;
	PWMA=myabs(moto1);
	if(moto2<0)	BIN1=1,			BIN2=0;
	else        BIN1=0,			BIN2=1;
	PWMB=myabs(moto2);	
}

int myabs(int a)
{ 		   
	  int temp;
		if(a<0)  temp=-a;  
	  else temp=a;
	  return temp;
}

测速代码:

我左右轮分别使用的TIM2和TIM3,这段代码就是读取计数器的值。

/**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回  值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
    int Encoder_TIM;    
   switch(TIMX)
	 {
	   case 2:  Encoder_TIM= (short)TIM2 -> CNT;  TIM2 -> CNT=0;break;
		 case 3:  Encoder_TIM= (short)TIM3 -> CNT;  TIM3 -> CNT=0;break;	
		 default: Encoder_TIM=1;
	 }
		return Encoder_TIM;
}


PWM的配置

Motor_PWM_Init(7199,0);//不分频,初始化PWM 10KHZ,驱动电机

编码器模式的配置

预分频(psc)一般就为‘0’就好;

重装载值(arr)我这里配置的重装载值为65535,是最大值。这样定时器不会溢出,方便计算。也可以使用别的重装载值:

比如我的电机线数为30,即一圈产生30个脉冲,那么我如果使用编码器模式3的4倍频计数,那么转一圈会计数器值为30*4,如果我设置重装载值为120,那是不是电机每转一圈定时器就会溢出一次,我们再在定时器的溢出中断中加上一个计数器cnt,每次进中断,cnt的值就++,那在采样的时候计数器的值就为:cnt*重装载值+计数器的值

#define ENCODER_TIM_PERIOD (u16)(65535)   //103的定时器是16位 2的16次方最大是65536


 
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数  

6、硬件连接

电机A

M+——AO1

M- ——AO2

A   ——PA6

B   ——PA7

VCC——3.3V

GND——GND

电机B

M+——BO1

M- ——BO2

A   ——PA0

B   ——PA1

VCC——3.3V

GND——GND

tb6612

VM——12V

VCC——3.3V

GND——GND

PWMA——PA8

AIN2——PB15

AIN1——PB14

STBY——3.3V

BIN1——PB13

BIN2——PB12

PWMB——PA11

7、完整代码

main.c

#include "stdio.h"
#include "led.h"
#include "delay.h"
#include "sys.h"
#include "usart.h"	
#include "motor_pwm.h"
#include "encoder.h"


 int main(void)
 {	
//	u16 led0pwmval=0;    
//	u8 dir=1;	
    uart_init(9600);	     //串口1初始化
	delay_init();	    	 //延时函数初始化	  
	LED_Init();		  	//初始化与LED连接的硬件接口
    NVIC_Configuration();	//中断优先级
    Motor_Init();       //
	Motor_PWM_Init(7199,0);//不分频,初始化PWM 10KHZ,驱动电机
   	Encoder_Init_TIM2();//TIM2初始化为编码器接口模式
    Encoder_Init_TIM3();//TIM3初始化为编码器接口模式
     
    while(1)
	{ 
//		if(dir)led0pwmval++;
//		else led0pwmval--;	 
// 		if(led0pwmval>300)dir=0;
//		if(led0pwmval==0)dir=1;
//		TIM_SetCompare1(TIM1,led0pwmval);
        Set_Pwm(6000,7000);
        printf("%d\t",Read_Encoder(2));
        printf("%d",Read_Encoder(3));
        printf("\r\n");
        delay_ms(1000);
        Set_Pwm(-5000,-4000);
        printf("%d\t",Read_Encoder(2));
        printf("%d",Read_Encoder(3));
        printf("\r\n");
        delay_ms(1000);
        
	} 
}

encoder.c

#include "encoder.h"

void Encoder_Init_TIM2(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  TIM_ICInitTypeDef TIM_ICInitStructure;  
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);//使能定时器4的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PB端口时钟
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0|GPIO_Pin_1;	//端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOB
  
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
  TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = 10;
  TIM_ICInit(TIM2, &TIM_ICInitStructure);
  TIM_ClearFlag(TIM2, TIM_FLAG_Update);//清除TIM的更新标志位
  TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM_SetCounter(TIM2,0);
  TIM_Cmd(TIM2, ENABLE); 
}
/**************************************************************************
函数功能:把TIM3初始化为编码器接口模式
入口参数:无
返回  值:无
**************************************************************************/
void Encoder_Init_TIM3(void)
{
	TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;  
  TIM_ICInitTypeDef TIM_ICInitStructure;  
  GPIO_InitTypeDef GPIO_InitStructure;
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);//使能定时器4的时钟
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//使能PB端口时钟
	
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//端口配置
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; //浮空输入
  GPIO_Init(GPIOA, &GPIO_InitStructure);					      //根据设定参数初始化GPIOB
  
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);
  TIM_TimeBaseStructure.TIM_Prescaler = 0x0; // 预分频器 
  TIM_TimeBaseStructure.TIM_Period = ENCODER_TIM_PERIOD; //设定计数器自动重装值
  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;//选择时钟分频:不分频
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM向上计数  
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);//使用编码器模式3
  TIM_ICStructInit(&TIM_ICInitStructure);
  TIM_ICInitStructure.TIM_ICFilter = 10;
  TIM_ICInit(TIM3, &TIM_ICInitStructure);
  TIM_ClearFlag(TIM3, TIM_FLAG_Update);//清除TIM的更新标志位
  TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);
  //Reset counter
  TIM_SetCounter(TIM3,0);
  TIM_Cmd(TIM3, ENABLE); 
}

/**************************************************************************
函数功能:单位时间读取编码器计数
入口参数:定时器
返回  值:速度值
**************************************************************************/
int Read_Encoder(u8 TIMX)
{
    int Encoder_TIM;    
   switch(TIMX)
	 {
	   case 2:  Encoder_TIM= (short)TIM2 -> CNT;  TIM2 -> CNT=0;break;
		 case 3:  Encoder_TIM= (short)TIM3 -> CNT;  TIM3 -> CNT=0;break;	
		 default: Encoder_TIM=1;
	 }
		return Encoder_TIM;
}


encoder.h

#ifndef __ENCODER_H
#define __ENCODER_H
#include <sys.h>	 


#define ENCODER_TIM_PERIOD (u16)(65535)   //103的定时器是16位 2的16次方最大是65536


void Encoder_Init_TIM2(void);
void Encoder_Init_TIM3(void);
int Read_Encoder(u8 TIMX);
#endif

motor_pwm.c

#include "motor_pwm.h"
#include "led.h"



//PWM输出初始化
//arr:自动重装值
//psc:时钟预分频数
void Motor_Init(void)	//IN引脚初始化
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //使能PB端口时钟
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;	//端口配置
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;      //推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //50MHZ
    GPIO_Init(GPIOB, &GPIO_InitStructure);					      //根据设定参数初始化GPIOB 
	AIN1=0,AIN2=0;
	BIN1=0,BIN1=0;
}
void Motor_PWM_Init(u16 arr,u16 psc)	//PWM引脚初始化
{
    GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);// 
 	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA , ENABLE);  //使能GPIO外设时钟使能
    //设置该引脚为复用输出功能,输出TIM1 CH1 CH4的PWM脉冲波形
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11; //TIM_CH1 //TIM_CH4
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;  //复用推挽输出
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA, &GPIO_InitStructure);
	
	TIM_TimeBaseStructure.TIM_Period = arr; //设置在下一个更新事件装入活动的自动重装载寄存器周期的值	 
	TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置用来作为TIMx时钟频率除数的预分频值  不分频
	TIM_TimeBaseStructure.TIM_ClockDivision = 0; //设置时钟分割:TDTS = Tck_tim
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  //TIM向上计数模式
	TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure); //根据TIM_TimeBaseInitStruct中指定的参数初始化TIMx的时间基数单位

 
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; //选择定时器模式:TIM脉冲宽度调制模式1
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; //比较输出使能
	TIM_OCInitStructure.TIM_Pulse = 0;                            //设置待装入捕获比较寄存器的脉冲值
	TIM_OCInitStructure.TIM_Pulse = arr >> 1;
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;     //输出极性:TIM输出比较极性高
	TIM_OC1Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx
	TIM_OC4Init(TIM1, &TIM_OCInitStructure);  //根据TIM_OCInitStruct中指定的参数初始化外设TIMx

    TIM_CtrlPWMOutputs(TIM1,ENABLE);	//MOE 主输出使能	

	TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH1预装载使能	 
	TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);  //CH4预装载使能	 
	
	TIM_ARRPreloadConfig(TIM1, ENABLE); //使能TIMx在ARR上的预装载寄存器
	
	TIM_Cmd(TIM1, ENABLE);  //使能TIM1
}
//moto1,moto2  左轮PWM、右轮PWM
void Set_Pwm(int moto1,int moto2)
{
	if(moto1<0)			AIN2=1,			AIN1=0;
	else 	          AIN2=0,			AIN1=1;
	PWMA=myabs(moto1);
	if(moto2<0)	BIN1=1,			BIN2=0;
	else        BIN1=0,			BIN2=1;
	PWMB=myabs(moto2);	
}

int myabs(int a)
{ 		   
	  int temp;
		if(a<0)  temp=-a;  
	  else temp=a;
	  return temp;
}

motor_pwm.h文章来源地址https://www.toymoban.com/news/detail-766309.html

#ifndef __PWM_H
#define __PWM_H
#include "sys.h"	 

#define PWMA   TIM1->CCR1  //PA8  PWMA  TIM1_CH1
#define AIN2   PBout(15)
#define AIN1   PBout(14)

#define PWMB   TIM1->CCR4  //PA11 PWMB  TIM1_CH4
#define BIN1   PBout(13)
#define BIN2   PBout(12)

void Motor_Init(void);
void Motor_PWM_Init(u16 arr,u16 psc);
int myabs(int a);
void Set_Pwm(int moto1,int moto2);

#endif

到了这里,关于stm32平衡小车--(1)JGB-520减速电机+tb6612(附测试代码)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 直流减速编码电机的使用(STM32f103c8t6)L298N电机驱动模块

    直接减速电机就是在直流电机上加上霍尔编码器,霍尔编码器可用于电机转动的测速,A、B相会产生相位相差90°的方波信号。stm32可以使用硬件资源或者软件模拟来捕获编码器信号。这里我介绍的是stm32自带的编码器模式来使用直流减速电机。 以下是直流减速电机的商品图 ​

    2024年02月13日
    浏览(37)
  • 基于STM32单片机直流电机控制加减速正反转系统proteus仿真原理图程序

    功能: 0.本项目采用STM32F103C8T6作为单片机系统的控制MCU 1.通过按键可以控制电机,正转、反转、加速、减速、停止。 2.总共六个功能按键可实现正转、反转、加速、减速、停止。 3.启停和正反转均有指示灯,测试采用的霍尔传感器方案 4.采用DC002作为电源接口可直接输入5V给

    2024年02月12日
    浏览(35)
  • stm32步进电机S型加减速程序源码与详细分析,资料为算法实现以及算法的相关讲解

    stm32步进电机S型加减速程序源码与详细分析,资料为算法实现以及算法的相关讲解,例程中有stm32f103步进电机S型加减速的完整工程代码,对步进电机s型加减速控制很有帮助 标题:基于STM32的步进电机S型加减速控制程序源码与详细分析 摘要:本文介绍了一种基于STM32的步进电

    2024年01月25日
    浏览(22)
  • K_A08_005 基于 STM32等单片机驱动XY-160D模块按键控制直流电机正反转加减速启停

    目录 一、资源说明 二、基本参数 四、部分代码说明         接线说明                 1、STC89C52RC+XY-160D模块                  2、STM32F103C8T6+XY-160D模块 五、基础知识学习与相关资料下载 六、视频效果展示与程序资料获取 七、项目所有材料清单 八、注意事项 九

    2024年02月14日
    浏览(32)
  • STM32F103RCT6+BTN7971B+JGB37-520+PWM驱动电机

    1.STM32F103RCT6最小系统板如图1所示 2.BTN7971B电机驱动器   3.GB37-520带减速器和编码器直流电机  4.电机测试(不接单片机)  5.电机测试,联接单片机  按照如图所示,联接 GB37-520电机 BTN7971B模块 电源电机侧 BTN7971B模块 单片机侧 最小系统板 1 M+ OUT1 5V+ 2 M- OUT2 IN1 PC6 3 GND VCC IN2 P

    2024年02月15日
    浏览(24)
  • 【32单片机学习】(3)霍尔编码器减速直流电机控制及测速

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 目录 前言 1.实验现象 2.实验接线及原理图 接线图 原理图  电机接线图 3.代码部分 1.主函数  main.c 2.按键部分   key.c  key.h pwm代码   pwm.c  pwm.h 电机驱动   motor.c   motor.h  OLED显示 oled.c oled.h  编码器

    2024年02月11日
    浏览(32)
  • STM32 HAL库PID控制电机 第二章 TB6612FNG芯片驱动GB37-520电机

    1 电路图 2 TB6612简介 TB6612是双驱动,可同时驱动两个电机 STBY:接单片机的IO口清零电机全部停止,置1通过AIN1 AIN2,BIN1,BIN2 来控制正反转 VM:建议接10V以内电源( 瞬间上电12V可能会有尖峰电压击穿器件 ) VCC:接5V电源 GND:接电源负极 PWMA:接单片机的PWM口 ,控制转速 PWM

    2023年04月22日
    浏览(69)
  • 步进电机运动八大加减速算法

         引导一种模块化(Module)设计思想,将传统步进电机的控制器(controller)、驱动器(Driver)、运动算法(Arithmetic)三合一。 对比国内外步进电机驱动原理和已有工作,结合各种硬件特性,改进或实现了可实际移植并用于步进电机控制八大算法。本产品为步进电机实际控制算法实现

    2024年02月16日
    浏览(17)
  • STM32单片机PWM控制实现电机调速度(小车运动,STM32F103C8T6&TB6612&TT电机)

    作者:公子易平 时间:2023/6/6 前段时间做一个智能小车的相关项目时,发现很少有人能够将STM32的PWM控制讲清楚,故而书此文,希望对后来的学习者有所帮助。 STM32F103C8T6最小系统板 直流TT电机 电机驱动芯片(TB6612) 杜邦线若干 接线情况: TB6612引脚说明: STM32主控芯片与TB6612接

    2024年02月15日
    浏览(24)
  • 基于51单片机的直流电机转速显示+加速减速启停

    做了一个实战项目,这个实战项目主要是实现对直流电机转速的控制,可以实现电机加速,减速,报警、启停以及显示转速。在本电路的基础上也可以进行一些拓展改变电机正反转的状态,只需要外加一个按键和修改部分程序即可,在文章的最后会对拓展进行一个说明。基础

    2023年04月27日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包