【LWIP】(补充)STM32H743(M7内核)CubeMX配置LWIP并ping通

这篇具有很好参考价值的文章主要介绍了【LWIP】(补充)STM32H743(M7内核)CubeMX配置LWIP并ping通。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言

之前我写了一个用CubeMX配置LWIP以太网通讯的博客:
【LWIP】stm32用CubeMX配置LwIP+Ping+TCPclient+TCPserver发送信息到PC(操作部分)
当时用的是F207、F407加上LAN8720、DP83848做了测试,效果都是很好的。但是当我第一次在STM32H743的时候突然傻眼了,H743用CubeMX配置以太网方法与其他内核的芯片有很大不同,估计很多同学在从F1\F2\F4转到STM32 M7系列配置以太网的时候都和我一样,一开始信心满满,然后一头雾水。
于是我经过两天琢磨,搞出来一个STM32H743(M7内核)的CubeMX配置LWIP以太网的ping通教程。包教包会!

接下来开始做事(由于某些特殊原因~,无法上传高清图片,很抱歉,请各位摘下眼镜将就看看)

1、配置CubeMX

打开CubeMX,选择完芯片后:
在CORTEX_M7里面:使能DCache。MPU控制模第三个“only+disable”
(M7内核相对于其他常见的学习板不同,是有缓存的,而且芯片内部有两段内存是不允许外设访问的,所以你不配置这mpu就绝对ping不通。)
第一个配置如图,主要是先开起来MPU功能,随便配置一个就好,这样生成的代码就带有MPU的设置和初始化,后面我们替换成自己写好的MPU代码。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
RCC:因为我这块板子上只有外部高速晶振,所以使能外部高速晶振,各位按实际硬件的来就好。
然后把电源调节器电压范围选择scale0,这样我们就能把主频调到最高。(很多刚用H7的新手会发现主频率调不高,大概就是这里的问题)。
这里把时钟配置到400,因为我的项目之前是这么配的,所以要一致。这里配480完全可以。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

直接自动配置,很方便!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
为了调试,必然要打开串口,根据实际硬件进行配置。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
ETH:因为硬件是RMII,所以选择RMII。你硬件是MII就可以选MII。(但特别注意,MII需要在CLK引脚上提供25M时钟,而RMII需要50M时钟,如果没有配置外部晶振,就要在时钟配置中用MCO给这条线上供给时钟,不同的PHY芯片对外部晶振提供的时钟又有不同的处理方式,比如8720能把外部25M时钟内部倍频出50M,而DP83848RMII模式下就得老老实实焊一个50M晶振,这里很容易出错)
注意IO口和硬件要对应,速度一定要是高速,我有一次忘记配置,默认低速就无法ping通。
然后接收和发送缓存描述符默认就行,注意接收缓存地址我选择30040200才ping通,心里要稍微记住这几个数值,有需要可以研究着改改。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
姑且把中断勾起来,这样想用中断的时候就能直接用了。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
配置LWIP:
只有LAN8742,别无选择,,8720可以通用,如果不是8742系列,后面我会带着大家修改寄存器。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
为了方便,开发板改成静态IP,这个IP一定要和你的主机在同一个子网下,也就是主机号相同,我这边是192.168.0,这个可以在自己电脑上查一下。ICMP(ping功能)和TCP开起来,这俩应该是默认开的。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
这个回调功能打开来,就可以自己在这里写点函数,应该都是默认的。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
生成keil代码!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

2、接下来是配置MDK!

打开keil5(MDK),勾上这两个,其他的常规配置不用多说了,大家都懂的,前面的教程也说过。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
串口重定向,不用多说!
养成好习惯,串口设置好后编译一下,看看能不能正常输出,这也是为了之后方便打开.h头文件。
#include "stdio.h"放在需要用到串口打印的文件中(都是十分基础的东西)。

int fputc(int ch, FILE *f)
{
//具体哪个串口可以更改huart1为其它串口
HAL_UART_Transmit(&huart1 , (uint8_t *)&ch, 1 , 0x0f);
return ch;
}

stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
主循环加入这个功能。这就在主循环里轮询检查了,当然这样更耗资源,但我们不是勾选了中断嘛,先ping通,后面再说怎么用中断。
MX_LWIP_Process();

stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
在时钟配置之后加入一个100毫秒的延时,我在这里出过BUG,不知道是啥原因,反正延时了就好了,不碍事就加上吧!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

在PHY层芯片初始化(GPIO、CLOCK、NVIC和传输模式配置)之前加入一个复位!其实就是连接PHY芯片复位引脚的那个GPIO拉低拉高一下。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

复制替换MPU配置代码!我们在cubeMX中打开了MPU,这个函数就会出现,我们灵活根据需要修改就好了。我这边是设立了两个MPU,这很关键!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
MPU代码复制:

void MPU_Config(void)
{
MPU_Region_InitTypeDef MPU_InitStruct;

/* Disable the MPU */
HAL_MPU_Disable();

/* Configure the MPU attributes as Device not cacheable
for ETH DMA descriptors */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as Cacheable write through
for LwIP RAM heap which contains the Tx buffers */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;

HAL_MPU_ConfigRegion(&MPU_InitStruct);

  /* Enables the MPU */
  HAL_MPU_Enable(MPU_PRIVILEGED_DEFAULT);

}

在lwip.c的头文件下找到lwipopt.h,加入debug代码,这样就能在串口看到你的网络出什么问题了(注意在实际工程中要关闭debug代码,否则打印太耗资源,ping通时间会长达100ms,关闭后就正常1ms ping通了)
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络LWIP调试代码如下,很好用!

#define LWIP_DEBUG

#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
/* USER CODE BEGIN 1 */
#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_OFF
//#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_WARNING
//#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_SERIOUS
//#define LWIP_DBG_MIN_LEVEL              LWIP_DBG_LEVEL_SEVERE
 
#define LWIP_DBG_TYPES_ON               LWIP_DBG_ON
//#define LWIP_DBG_TYPES_ON               (LWIP_DBG_ON|LWIP_DBG_TRACE|LWIP_DBG_STATE|LWIP_DBG_FRESH)
 
#define ETHARP_DEBUG                    LWIP_DBG_ON     
#define NETIF_DEBUG                     LWIP_DBG_ON     
#define PBUF_DEBUG                      LWIP_DBG_ON
#define API_LIB_DEBUG                   LWIP_DBG_ON
#define API_MSG_DEBUG                   LWIP_DBG_ON
#define SOCKETS_DEBUG                   LWIP_DBG_ON
#define ICMP_DEBUG                      LWIP_DBG_ON
#define IGMP_DEBUG                      LWIP_DBG_ON
#define INET_DEBUG                      LWIP_DBG_ON
#define IP_DEBUG                        LWIP_DBG_ON     
#define IP_REASS_DEBUG                  LWIP_DBG_ON
#define RAW_DEBUG                       LWIP_DBG_ON
#define MEM_DEBUG                       LWIP_DBG_ON
#define MEMP_DEBUG                      LWIP_DBG_ON
#define SYS_DEBUG                       LWIP_DBG_ON
#define TCP_DEBUG                       LWIP_DBG_ON
#define TCP_INPUT_DEBUG                 LWIP_DBG_ON
#define TCP_FR_DEBUG                    LWIP_DBG_ON
#define TCP_RTO_DEBUG                   LWIP_DBG_ON
#define TCP_CWND_DEBUG                  LWIP_DBG_ON
#define TCP_WND_DEBUG                   LWIP_DBG_ON
#define TCP_OUTPUT_DEBUG                LWIP_DBG_ON
#define TCP_RST_DEBUG                   LWIP_DBG_ON
#define TCP_QLEN_DEBUG                  LWIP_DBG_ON
#define UDP_DEBUG                       LWIP_DBG_ON     
#define TCPIP_DEBUG                     LWIP_DBG_ON
#define PPP_DEBUG                       LWIP_DBG_ON
#define SLIP_DEBUG                      LWIP_DBG_ON
#define DHCP_DEBUG                      LWIP_DBG_ON     
#define AUTOIP_DEBUG                    LWIP_DBG_ON
#define SNMP_MSG_DEBUG                  LWIP_DBG_ON
#define SNMP_MIB_DEBUG                  LWIP_DBG_ON
#define DNS_DEBUG                       LWIP_DBG_ON

重头戏来了,因为cubeMX只预置了LAN8742的配置,而我们用的是DP83848,应该是ping不通的,所以寄存器要更改。
首先,在配置cube的时候会发现,在207、407的配置里,会要求填写PHY Address,这个和上电时PHYAD引脚上的电平有关,但H7系列配置的时候并没有要求填写,为什么呢?我们来看这一段程序,在lan8720.c中。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

原来cube中用了这一段程序来循环检查PHY芯片中存有PHY地址的寄存器,实现自动读取,这个寄存器在lan8742中偏移18,而在DP83848中偏移0x19,所以我们要把红圈部分修改为0x19。(如果你对你的硬件很有把握,知道上电后PHYAD引脚的状态,可以直接注释掉上面截图中的所有代码,用两行代码直接给下面两个变量赋值。pObj->DevAddr = DP83848_PHY_ADDRESS; status = LAN8742_STATUS_OK; 这里的DP83848_PHY_ADDRESS是你的PHY地址值,比如83848,五根PHYADx引脚,上电时如果没有硬件拉高或拉低,那就由于PHYAD0内部弱上拉,其余四根内部弱下拉,所以就是1)

本来到了这一步网上一些教程说可以ping通了,但是我依然没有ping通,果然网上的东西还是不靠谱,得多自己研究!

后来发现,LAN8742_PHYSCSR寄存器有问题,在LAN8742中是特殊功能寄存器,它在LAN8742.h代码中是这样显示的:
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

很显然,里面有一位用于开启自适应,有3位用于配置速度以及单/双工

这时候来看看我们DP83848的这个寄存器:↓↓↓
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
发现了不一样,于是我们在代码上进行修改:
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

最后烧录开机,完全OK!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
特别注意,因为我开了lwip的debug,会进行大量串口输出,所以ping的时间长达200ms,这时候我们已经调通了,debug代码就完全不需要了,我回到lwipopt.h中注释掉它们,再ping一次,发现完全正常了。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

3、ping通之后我还有一些要补充的:

3.1 高速通讯要清除缓存

我们实际项目中往往需要高速发送,这时候 及时清除缓存就有必要了。注意在需要高速数据发送的情况下,在ethernetif.c中加入两行缓存清除代码:
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

3.2 字符串发送出现乱码解决

在我以前的博客里,有用407给大家配置一个客户端和服务器端,这两个代码我试了一下都可以用,但就是莫名其妙的没在407上这么好用,会出现一些问题。于是我研究着改了改。
首先是tcpserver部分代码,字符串传输回电脑会看见乱码。
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
但我们只要做出一些小小的修改就行了,如图:
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
把字符串输出的size的长度减一,这样显示就正常了!

3.3 中断接收

我们上面展示的程序是在主循环里不断地轮询,但是轮询是很消耗资源的,所以我们来尝试一下使用中断来接收信息。
还记得我在上面说过的嘛,配置CubeMX的时候要顺手勾选以太网中断,这下就能用上了!
首先在ethernetif.c里把方框里的改掉
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络

然后,我们在lwip.c中注释掉这一行,并把这一行放在stm32h7xx_it.c的ETH_IRQHandler函数中,并在这个函数中注释掉HAL_ETH_IRQHandler(&heth);
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
可以看到这里报错了,是没有添加头文件的原因,我们只要在stm32h7xx_it.c的头部添上这两行就行了
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络
最后直接ping通了!
stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络注意,中断模式并不只是为了节约资源,更重要的一点是解决丢包。在轮询模式ping通后,很多人就忘乎所以拿去用了,其实如果你们测一测丢包率,会发现存在%5的丢包,这在实际项目中是非常致命的!但是改用中断接收后,丢包率下降为0(如下图)。

stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络stm32h743 lwip 6.9.1,STM32,LWIP,stm32,网络可以看见确实通过改轮询方式为中断方式后,丢包消失了!

3.4 ping不通,但debug显示了前面一大段,但后面没动静了,这是怎么回事?

出现这种情况我碰见过两种原因:
第一种是你的缓冲区忘记更改了,也许你把缓冲区大小从C0改为200就行了。
第二种是芯片复位的问题,因为有些程序你不会给网卡PHY芯片配置RESET也能用,但有时候是不行的,这时候你需要给你的开发板断电然后上电,网络就能用了。

总结

以上我们就实现了一个基于cubeMX生成的代码修改后的H743+lwip的ping通程序,比207、407芯片的配置有较大不同,因为内核不同,速度也更快了,所以加入了缓存和内存保护MPU,同时代码上也有一些些不同,最重要的是只有LAN8742的配置,除此之外的所有PHY芯片都会因为引脚不同或者寄存器不同而需要或多或少的修改。
我这里主要是一个ping通操作,所以改动了两个寄存器,但是你不可能光ping通而不进行其他操作,如果你需要用到中断之类的功能,你就要去查找相应的功能的8742寄存器代码段,然后对应着DP83848手册把这些寄存器的偏移量和它里面不同功能的掩码修改成DP83848的数值。
可以用keil5自带的CMSIS生成83848头文件里的寄存器设置进行参考辅助。当然,有厉害的人可以直接利用CMSIS的代码加入工程,但我没试过,如果有试过的,希望能做成一期博客分享给我。

希望能帮上大家,希望大家踊跃留言,有建议和优化请在评论区留言,我都会看并及时回复并更正的,谢谢!文章来源地址https://www.toymoban.com/news/detail-679524.html

到了这里,关于【LWIP】(补充)STM32H743(M7内核)CubeMX配置LWIP并ping通的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • EtherCAT主站源码 基于STM32F407和STM32H743两款芯片 通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能

    EtherCAT主站源码基于STM32F407和STM32H743两款芯片,通过移植开源SOME主站代码,使两款芯片具有EtherCAT主站功能,支持DC同步功能。可支持汇川IS620N、松下A5B/A6B、欧姆龙G5系列、埃斯顿ProNet、迈信EP3E、台达A2-E,伟创SD700这几款EtherCAT总线伺服。支持的这些驱动器可以混用,主站自动

    2024年02月04日
    浏览(52)
  • STM32H723 + DP83848 + LWIP + RT-Thread(FreeRTOS) + STM32CubeMX + Keil MDK 超详细

    MCU:STM32H723ZGT ETH PHY :DP83848 RT-Thread:RT-Thread nano 3.1.5 Software Pack:STM32CubeH7 Firmware Package V1.10.0 / 11-February-2022 STM32H723配置以太网+Freertos注意事项 STM32H723+Lwip+ETH+CUBE 完整配置(排了巨多坑!) Cube配置STM32H743+DP83848以太网工程 STM32H743+CubeMX-梳理MPU的设置 首先使用 CubeMX配置相关外

    2024年02月13日
    浏览(52)
  • STM32CUBEMX配置STM32H750时钟480M时失败

    STM32H750最高的时钟是支持480M的,但是在CUBEMX新建工程配置始终时,却无法设置为480M。 解决方案如下: 原因是电压级别设置的问题。STM32CUBEMX默认设置的事VOS3,是不能支持480M运行的。 在H750的参考手册中有相应的描述 必须设置为0时,系统的时钟才能达到最高的480MHz ‍ ‍

    2024年02月16日
    浏览(61)
  • 【LWIP】stm32用CubeMX(6.4版)配置LwIP+Ping+TCPclient+TCPserver发送信息到PC(操作部分)

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 这是我写的第一篇博客,欢迎大家给点鼓励和提出建议! 本人由于理想和爱好,辞去土木工作,于不到一个月前入职某科技公司开始从事嵌入式,专业能力和刚毕业的大学生一样都是很薄弱的。然后被

    2024年02月03日
    浏览(32)
  • 【物联网学习笔记】CubeMx+STM32F407ZGT6+LWIP最最最基础配置

    使用正点原子探索者开发板 板载芯片:STM32F407ZGT6 PHY芯片:LAN8720 LWIP版本:2.1.2 本次目标:先ping通开发板再说! 修订: · 2024.4.23经评论区反馈又重新下载6.10版本CubeMX,发现确实没有Advanced Parameters,目前使用6.6.1存在,如有需要可以改成这个版本。 更改引脚 在ethernetif.c中找

    2024年04月27日
    浏览(73)
  • 【通过STM32CubeMx配置LWIP+FreeRTOS并通过Socket实现TCP_Client/Sever】

    测试平台 → Nucleo_F429ZI 软件工具 → STM32CubeMx 6.6.1 MDK 5.3.0 网络调试助手V1.2 在CubeMx上面选择NUCLEO-F429ZI开发板,并采用默认配置 使能FreeRTOS 修改defaultTask的栈大小 由于使用了FreeRTOS,因此系统的TimeBase Source修改成TIM1 使能LWIP,并且先禁用DHCP,设置好静态IP Platform选择LAN8742 修改

    2024年02月08日
    浏览(46)
  • STM32 CubeMX LwIP + freertOS 移植

    开发板: 官方 STM32F746  MCU型号:STM32F746NGH 网卡型号:LAN8742A  原理图如下 先用裸机测试LAN8742A的网卡驱动 使用CubeMX创建工程 系统时钟和时基定时器如下 无系统LWIP协议栈设置,静态IP地址,关闭DHCP 生产代码,下载进开发板。开发板网口与电脑网口通过网线直连,设置电脑本

    2024年01月16日
    浏览(87)
  • STM32 CubeMX 无法将 STM32H7 的最大 CPU 频率设置为 480 MHz

    使用stm32cubemx设置时钟树为480MHz时,提示 cpu clock frequency must be =200MHZ 对于STM32H7 需要CPU修订版 为 V 才能达到 480 MHz 的最大频率。 使用STM32Programmer查看芯片修订版,确认是V版本: 在STM32CubeMX PinConfiguration 界面修改RCC选项,将Product Version设置为V: 此时时钟树界面已可以设置48

    2024年02月16日
    浏览(50)
  • (STM32H5系列)STM32H573RIT6、STM32H573RIV6、STM32H573ZIT6嵌入式微控制器基于Cortex®-M33内核

    工业(PLC、工业电机控制、泵和压缩机) 智能家居(空调、冰箱、冰柜、中央警报系统、洗衣机) 个人电子产品(键盘、智能手机、物联网标签、跟踪设备) 智能城市(工业通信、照明控制、数字电源) 医疗和保健(CPAP和呼吸器、透析机、药丸分配器、电动病床) 1、ST

    2024年02月09日
    浏览(44)
  • STM32H5开发(5)----串口打印配置

    在使用STM32CUBEIDE开发STM32H5项目时,串口打印被证明是一项极其有益的调试工具,能够在开发过程中实时输出信息和调试数据,起到了至关重要的作用。通过充分利用串口打印功能,开发者可以轻松地在代码中插入打印语句,通过串口将这些信息传输至连接于PC端的终端软件,

    2024年02月11日
    浏览(38)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包