GD32450Z U盘通信教程——使用USBHS利用内部全速PHY作为USB MSC主机实现U盘通信

8 篇文章 4 订阅
订阅专栏

USB高速(USBHS)支持主机模式、设备模式和OTG模式,并且包含了一个内部的全速USB PHY。对于全速和低速操作,不需要外部的USB PHY。本文为学习记录,介绍了在主机模式下,利用内部PHY实现U盘的通信。

1. USBHS基础知识介绍

1.1 USBHS 信号线描述

在主机或设备模式下,利用内部 PHY 的连接示意图如下所示。

 上图信号线的作用如下表所示。

I/O端口    类型描述
VBUS输入总线电源端口
DM输入/输出差分信号线 - 端口
DP输入/输出差分信号线 + 端口

在主机模式下,由于USBHS并不检测VBUS引脚的电平状态, VBUS引脚可以忽略。我们只需要配置DP、DM两个信号引脚,查询《GD32F450xx_Datasheet》,两引脚的配置如下:

接口CPU引脚复用
DMPB14USBHS_DM    AF12
DPPB15USBHS_DP    AF12

1.2 USB库及资料介绍

1、STM32官方程序:GD32F4xx_usb_library (用 USB host MSC模式)

2、文件系统:FatFs为官方R0.13C版。

1.2.1 USBHS 模块固件库架构

GD32F4xx 系列 MCU 的 USBFS/USBHS 接口模块固件库架构如下图所示,固件库分为三层,顶层为用户可修改的应用接口层,中间层为USB_Hos,底层为USB_Drivers,中间层和底层统称为 USB 固件库驱动,该驱动层用户不可修改。

 使用主机模式,所需要的文件及其说明如下表所示:

固件库文件名称说明
底层

usb_core.h/.c

USB 内核驱动

usb_reg.h

USB 寄存器操作

中间层

usbh_core.h/.c

USB 主机状态机处理函数

usbh_ctrl.h/.c

USB 主机控制传输处理函数

usbh_hcs.h/.c

USB 主机通道处理函数

usbh_int.h/.c

USB 主机模式中断处理函数

usbh_std.h/.c

USB 主机枚举标准处理函数
顶层

main.c

主应用程序接口

usbh_usr.c

用户应用程序接口

usb_delay.c

延迟函数实现接口

application class

设备类应用程序接口

1.2.2  FatFs文件系统

FatFs 是面向小型嵌入式系统的一种通用的 FAT 文件系统。这里我们使用R0.13c版本,一般我们只用到f_mount()、 f_open()、 f_write()、 f_read()就可以实现文件的读写操作。

本文移植过程中,涉及的文件如下:

 

2. USB配置

2.1 USB初始化配置

void Usb_PeriphInit(void)
{
	/*----------GPIO_config---------*/
	rcu_periph_clock_enable(RCU_SYSCFG);
	rcu_periph_clock_enable(RCU_GPIOB);
	gpio_af_set(GPIOB, GPIO_AF_12, GPIO_PIN_14 | GPIO_PIN_15);
	gpio_mode_set(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_PIN_14 | GPIO_PIN_15);
    gpio_output_options_set(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ, GPIO_PIN_14 | GPIO_PIN_15);
	

	/*----------48M时钟设置---------*/	
	rcu_pll48m_clock_config(RCU_PLL48MSRC_PLLQ);
	rcu_ck48m_clock_config(RCU_CK48MSRC_PLL48M);
	rcu_periph_clock_enable(RCU_USBHS);
	

	/*--------USB延迟函数设置--------*/	
    nvic_vector_table_set(NVIC_VECTTAB_FLASH, 0x00U);
    nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
    nvic_irq_enable((uint8_t)TIMER2_IRQn, 1U, 0U);
    rcu_periph_clock_enable(RCU_TIMER2);


	usbh_class_register(&usb_host_msc, &usbh_msc);
	usbh_init(&usb_host_msc,&usbh_core, USB_CORE_ENUM_HS,&usr_cb);		//register device class
	

	/*-----------中断设置----------*/	
	nvic_priority_group_set(NVIC_PRIGROUP_PRE2_SUB2);
	nvic_irq_enable((uint8_t)USBHS_IRQn, 2U, 0U);						//开启USBHS_IRQn
}

2.2  中断设置

开启TIMER2和USB_HS中断:

void TIMER2_IRQHandler(void)
{
    usb_timer_irq();
}


void USBHS_IRQHandler(void)
{
    usbh_isr(&usbh_core);
}

3. USB程序

在usbh_usr.c编写我们需要执行的程序。这里我们参考GD32官方demo案例库,插入u盘后将会枚举信息,之后显示U盘根目录文件,最后向程序中写入测试文件。

#include <string.h>
#include "usbh_usr.h"
#include "drv_usb_hw.h"
#include "usbh_msc_core.h"
#include "usbh_msc_scsi.h"
#include "usbh_msc_bbb.h"
#include "ff.h"

extern usb_core_driver usbh_core;
extern usbh_host usb_host_msc;

FATFS fatfs;
FIL file;

uint8_t line_idx = 0;
uint8_t usbh_usr_application_state = USBH_USR_FS_INIT;

/*  points to the DEVICE_PROP structure of current device */
usbh_user_cb usr_cb =
{
    usbh_user_init,
    usbh_user_deinit,
    usbh_user_device_connected,
    usbh_user_device_reset,
    usbh_user_device_disconnected,
    usbh_user_over_current_detected,
    usbh_user_device_speed_detected,
    usbh_user_device_desc_available,
    usbh_user_device_address_assigned,
    usbh_user_configuration_descavailable,
    usbh_user_manufacturer_string,
    usbh_user_product_string,
    usbh_user_serialnum_string,
    usbh_user_enumeration_finish,
    usbh_user_userinput,
    usbh_usr_msc_application,
    usbh_user_device_not_supported,
    usbh_user_unrecovered_error
};

static uint8_t explore_disk     (char* path, uint8_t recu_level);
static void toggle_leds         (void);

/*!
    \brief      user operation for host-mode initialization
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_init(void)
{
    static uint8_t startup = 0U;

    if (0U == startup) {
        startup = 1U;
        printf("> USB host library started\n");
    }
}

/*!
    \brief      user operation for device attached
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_connected(void)
{
    printf("> Device Attached.\n");
}

/*!
    \brief      user operation when unrecoveredError happens
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_unrecovered_error (void)
{
    printf("> UNRECOVERED ERROR STATE.\n");
}

/*!
    \brief      user operation for device disconnect event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_disconnected (void)
{
    printf("> Device Disconnected.\n");
}

/*!
    \brief      user operation for reset USB Device
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_reset(void)
{
    /* users can do their application actions here for the USB-Reset */
    printf("> Reset the USB device.\n");
}

/*!
    \brief      user operation for detectting device speed
    \param[in]  device_speed: device speed
    \param[out] none
    \retval     none
*/
void usbh_user_device_speed_detected(uint32_t device_speed)
{
    if (PORT_SPEED_HIGH == device_speed) {
        printf("> High speed device detected.\r\n");
    } else if(PORT_SPEED_FULL == device_speed) {
        printf("> Full speed device detected.\r\n");
    } else if(PORT_SPEED_LOW == device_speed) {
        printf("> Low speed device detected.\r\n");
    } else {
        printf("> Device Fault.\r\n");
    }
}

/*!
    \brief      user operation when device descriptor is available
    \param[in]  device_desc: device descriptor
    \param[out] none
    \retval     none
*/
void usbh_user_device_desc_available(void *device_desc)
{
    usb_desc_dev *pDevStr = device_desc;
  
    printf("\r\n > VID: %04Xh ",(uint32_t)pDevStr->idVendor);
    printf("\r\n > PID: %04Xh ",(uint32_t)pDevStr->idProduct);
}

/*!
    \brief      usb device is successfully assigned the Address 
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_address_assigned(void)
{
}

/*!
    \brief      user operation when configuration descriptor is available
    \param[in]  cfg_desc: pointer to configuration descriptor
    \param[in]  itf_desc: pointer to interface descriptor
    \param[in]  ep_desc: pointer to endpoint descriptor
    \param[out] none
    \retval     none
*/
void usbh_user_configuration_descavailable(usb_desc_config *cfg_desc,
                                           usb_desc_itf *itf_desc,
                                           usb_desc_ep *ep_desc)
{
    usb_desc_itf *id = itf_desc;

    if (0x08U == (*id).bInterfaceClass) {
        printf("\r\n > Mass storage device connected.\n");
    } else if (0x03U == (*id).bInterfaceClass) {
        printf("\r\n > HID device connected.\n");
    } else {
    
    }
}

/*!
    \brief      user operation when manufacturer string exists
    \param[in]  manufacturer_string: manufacturer string of usb device
    \param[out] none
    \retval     none
*/
void usbh_user_manufacturer_string(void *manufacturer_string)
{
  printf("\r\n > manufacture string is : %s ",(uint8_t *)manufacturer_string);
}

/*!
    \brief      user operation when product string exists
    \param[in]  product_string: product string of usb device
    \param[out] none
    \retval     none
*/
void usbh_user_product_string(void *product_string)
{
    printf("\r\n > product string is : %s ",(uint8_t *)product_string);
}

/*!
    \brief      user operatin when serialNum string exists
    \param[in]  serial_num_string: serialNum string of usb device
    \param[out] none
    \retval     none
*/
void usbh_user_serialnum_string(void *serial_num_string)
{
    printf("\r\n > Serial Number string is : %s ",(uint8_t *)serial_num_string);

}

/*!
    \brief      user response request is displayed to ask for application jump to class
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_enumeration_finish(void)
{
    printf("\r\n > Enumeration completed.");
    printf("\r\n > ------------------------------------");
    printf("\r\n > To start the MSC class operations: ");
}

/*!
    \brief      user operation when device is not supported
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_device_not_supported(void)
{
    printf("\r\n > Device not supported.");
}

/*!
    \brief      user action for application state entry
    \param[in]  none
    \param[out] none
    \retval     user response for user key
*/
usbh_user_status usbh_user_userinput(void)
{
    usbh_user_status usbh_usr_status = USBH_USER_NO_RESP;

    /*Key USER is in polling mode to detect user action */
        usbh_usr_status = USBH_USER_RESP_OK;

    return usbh_usr_status;
}

/*!
    \brief      user operation for device overcurrent detection event
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_over_current_detected (void)
{
    printf("\r\n > Overcurrent detected.");
}

/*!
    \brief      demo application for mass storage
    \param[in]  pudev: pointer to device
    \param[in]  id: no use here
    \param[out] none
    \retval     status
*/
int usbh_usr_msc_application(void)
{
    FRESULT res;
    msc_lun info;
    uint8_t WriteTextBuff[] = "GD32 Connectivity line Host Demo application using FAT_FS   ";
    uint16_t bytesWritten, bytesToWrite;

    switch(usbh_usr_application_state)
    {
        case USBH_USR_FS_INIT:
            /* initializes the file system*/
            if (FR_OK != f_mount(&fatfs, "0:/", 0)) {
                   printf("\r\n > Cannot initialize File System.");

                return(-1);
            }

            printf("\r\n > File System initialized.");

            if (USBH_OK == usbh_msc_lun_info_get(&usb_host_msc, 0, &info)){
                    printf("\r\n > Disk capacity: %ud Bytes.", info.capacity.block_nbr * info.capacity.block_size);
            }

            usbh_usr_application_state = USBH_USR_FS_READLIST;
            break;

        case USBH_USR_FS_READLIST:
            printf("\r\n > Exploring disk flash ...");
            printf("\r\n > ------To see the root content of disk-----");

            /*Key TAMPER in polling*/
            while (usbh_core.host.connect_status == 0)  { }
            explore_disk("0:/", 1);
            line_idx = 0;
            usbh_usr_application_state = USBH_USR_FS_WRITEFILE;
            break;

        case USBH_USR_FS_WRITEFILE:
            usb_mdelay(100);

            printf("\r\n > ------------- write file test -----------");

            /*key WAKEUP in polling*/
            while (usbh_core.host.connect_status==0) { }

            printf("\r\n > Writing File to disk flash ...\r\n");

            /* register work area for logical drives */
            f_mount(&fatfs, "0:/", 1);

            if (FR_OK == f_open(&file, "0:GD32.TXT", FA_CREATE_ALWAYS | FA_WRITE)) {
                /* write buffer to file */
                bytesToWrite = sizeof(WriteTextBuff); 
                res = f_write (&file, WriteTextBuff, bytesToWrite, (void *)&bytesWritten);
                /* EOF or error */
                if ((0U == bytesWritten) || (FR_OK != res)) {
                    printf("\r\n > GD32.TXT CANNOT be written.");
                } else {
                    printf("\r\n > GD32.TXT created in the disk.");
                }

                /* close file and file system */
                f_close(&file);
                f_mount(NULL, "0:/", 1); 
            } else {
                printf("\r\n > GD32.TXT created in the disk.");
            }

            usbh_usr_application_state = USBH_USR_FS_DEMOEND;
            printf("\r\n > The MSC host demo is end.");
            break;

        case USBH_USR_FS_DEMOEND:
            break;

        default:
            break;
    }

    return(0);
}

/*!
    \brief      displays disk content
    \param[in]  path: pointer to root path
    \param[in]  recu_level: recursive level
    \param[out] none
    \retval     status
*/
static uint8_t explore_disk (char* path, uint8_t recu_level)
{
    FRESULT res;
    FILINFO fno;
    DIR dir;
    char *fn;

    res = f_opendir(&dir, path);

    if (res == FR_OK) {
        while ((usbh_core.host.connect_status)) {
            res = f_readdir(&dir, &fno);
            if (FR_OK != res || 0U == fno.fname[0]) {
                break;
            }

            if ('.' == fno.fname[0]) {
                continue;
            }

            fn = fno.fname;

            line_idx++;

            if (line_idx > 4) {
                line_idx = 0;

//                printf("\r\n > Press User Key to continue....");

                /*key USER in polling*/
//                while ((usbh_core.host.connect_status) && \
//                       (SET == gd_eval_key_state_get (KEY_USER))) {
//                    toggle_leds();
//                }
            }

            if(1U == recu_level){
                printf("\r\n   |__");
            }else if(2U == recu_level){
                printf("\r\n   |   |__");
            }

            if(AM_DIR == fno.fattrib){
                printf("\r\n %s", fno.fname);
            }else{
                printf("\r\n %s", fno.fname);
            }

            if((AM_DIR == fno.fattrib) && (1U == recu_level)){
                explore_disk(fn, 2);
            }
        }
    }

    return res;
}

/*!
    \brief      toggle leds to shows user input state
    \param[in]  none
    \param[out] none
    \retval     none
*/
static void toggle_leds(void)
{
    static uint32_t i;

    if (0x10000U == i++) {
//        gd_eval_led_toggle(LED2);
//        gd_eval_led_toggle(LED3);
        i = 0;
    }
}

/*!
    \brief      deinit user state and associated variables
    \param[in]  none
    \param[out] none
    \retval     none
*/
void usbh_user_deinit(void)
{
    usbh_usr_application_state = USBH_USR_FS_INIT;
}

GD32F4xx USB cdc host驱动demo
03-29
GD32F4xx USB cdc host驱动demo,可以直接在450的开发板上跑
GD32_USBFS_USBHS_固件库用户指南_V1.0.pdf
09-13
GD32_USBFS_USBHS_固件库用户指南_V1.0
GD32】从零开始学GD32单片机 | USB通用串行总线接口+HID键盘例程(GD32F470ZGT6)
最新发布
JackieCoo的博客
08-31 1111
USB,全称通用串行总线,相信大家都非常熟悉了,日常生活只要用到手机电脑都离不开这个接口,像鼠标键盘U盘都需要使用这个接口进行数据传输,下面简单介绍一下。
基于GD32F450+USB3300的高速USB传输
weixin_43579500的博客
05-18 6929
2021.5.13(2021.5.17改) USB自定义设备类的实现 1 此例程在GD官方所提供的打印机设备类型修改而来,根据USB2.0协议修改相关的设备描述符、配置描述符和端口描述符,来实现自定义设备类型。 图1 设备描述符 图2 配置描述符 图3 端点描述符 如图3所示,IN和OUT端口数据传输类型皆为批量传输。 图4 USB设备名称 图5 编译结果 将这些描述符修改之后进行编译,结果如图5所示,编译成功,之后将板子USB与电脑相连,如图6所示,从设备管理器中看到其他设备多了一项。 图6
USB HS-PHY眼图调试
热门推荐
汽车以太网和SOA
05-06 1万+
USB HS-PHY眼图调试
GD32F307 USB主机模式 外接U盘升级 调试问题记录
LGC_764385701的博客
03-27 847
在移植USB驱动做主机U盘时遇到的问题。 问题1、移植USB驱动完成后,插入U盘,一直在 usbh_core_task 的默认case 和测试case中反复执行无法执行到后面的连接及以后得步骤。 问题2、在 usbh_core_task 函数中,一直卡在枚举的case,无法执行下面操作。具体卡在urb_wait的while循环无法跳出。
STM32/GD32USB HostU盘读取例程
07-22
USB作为主机读写U盘例程,集合Fatfs文件系统,适用于STM32F407以及GD32F407,稍加改动可适用于其他单片机。另外还有Keil5版本,请自行编译。
STM32F1 U盘通信教程-使用USBHS利用内部全速PHY作为USB MSC主机实现U盘通信
09-13
在本教程中,我们将深入探讨如何利用STM32F1的USB高速(USBHS)功能,通过其内部全速PHY(物理层)作为USB存储类设备(MSC主机实现U盘通信。这个过程涉及硬件配置、固件开发和USB协议的理解。 首先,了解...
通信与网络中的华虹NEC推出0.25微米平台USB片间PHY IP
12-03
上海华虹NEC电子有限公司,作为一家专注于集成电路晶圆代工的企业,近期在通信与网络领域推出了创新技术——0.25微米平台USB片间PHY IP(HQUSBFI001)。这一IP核心旨在优化片上系统(SoC)中不同芯片间的通信效率,...
GD32450Z(F407)平台100M以太网PHYSR8201F驱动补丁
04-09
在本文中,我们将深入探讨如何在GD32450Z平台上使用基于F407内核的微控制器实现100M以太网功能,特别是关于SR8201F PHY驱动的集成与应用。GD32450Z是北京兆易创新科技有限公司推出的一款高性能MCU,其内置的F407内核...
USB PHY—— PHY 基础
tyustli
08-29 390
HSIC (USB 2.0 High Speed Inter Chip)(高速芯片间)是USB芯片间互连的行业标准,具有2信号(选通,数据)源同步串行接口,使用240 MHz DDR信令仅提供高速率。HSIC 是 USB 2.0的芯片到芯片变体,它消除了普通USB中的传统模拟收发器。速度可达480M,是IIC的理想替代。USB 信号传输前,需要通过 PHYUSB 控制器的数字信号转成线缆上的模拟信号。芯片厂商开发了一些 USB PHY 芯片,可以把 DP、DM上的差模信号转成共模信号。
GD32USBBOOTloader+uartBOOTloader
05-05
两个工程,是GD32F3x0系列的usbIAP和串口IAP,两个均已测试成功。本人只是做了简单的测试,下载使用请自己测试整理。很久没搞这一块了,出了问题自己看下。我测试升级功能是没问题了的。
GD32450i-EVAL开发板原理图
10-19
这些接口包括电源管理、SPI通信接口、串口通讯、USB接口(全速和高速)、I2C、CAN总线、以太网连接以及模拟数字转换(AD)功能。下面将详细介绍这些接口及其在开发板中的应用和设计要点: 1. 电源管理:GD32450i-...
usb phy
weixin_42129680的博客
05-06 3071
1、charge /* Default current range by charger type. */ //默认电流 #define DEFAULT_SDP_CUR_MIN 2 //SDP 2.0 #define DEFAULT_SDP_CUR_MAX 500 #define DEFAULT_SDP_CUR_MIN_SS 150 //SDP 3.0 #define DEFAULT_SDP_CUR_MAX_SS 900 #define DEFAULT_DCP_CUR_MIN 500
USB PHY
hbcbgcx的博客
03-07 1万+
USB PHY负责最底层的信号转换,作用类似于网口的PHY。 有两种接口,一种是ULPI,一种是UTMI。 前者PIN少,后者PIN多,所以如果用ULPI,PHY一般外部另接; 用UTMI,PIN多,一般内置。 PHY内置或者外置要看芯片资料。 POWERPC的P2010,芯片资料里面定义是ULPI,需要外置PHY。 而E500MC系列,一般使用UTMI接口,芯片资料里面定义里面内置PHY。 关于...
usb-phy
hbcbgcx的博客
03-07 1141
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xuweiwei1860/article/details/53347956 usbphy 协议发展历程 UTMI UTMI USB 2.0 Transceiver Macrocell Interace* defines an interface between two IP blocks: t...
USBPHY
u011011827的博客
11-19 2097
【代码】USBPHY
使用socket phy单向通信
09-29
使用socket进行单向通信可以通过以下步骤实现: 1. 创建一个socket对象,指定协议类型和通信方式。例如,使用`socket.socket(socket.AF_INET, socket.SOCK_STREAM)`来创建一个基于TCP的socket对象。 2. 使用bind()函数将IP地址和端口号绑定到socket对象上。 3. 使用listen()函数开始监听来自客户端的连接。 4. 使用accept()函数接受客户端的连接请求,并返回一个新的socket对象和客户端的地址。 5. 使用recv()函数从客户端接收数据。 6. 使用send()函数向客户端发送数据。 7. 关闭socket连接。
18
原创
273
点赞
1508
收藏
702
粉丝
关注
私信
写文章

热门文章

  • Fluent UDF教程——壁面温度设定,实现动态高斯热源的施加,DEFINE_PROFILE宏讲解 17796
  • 基于STM32F407实现离散傅里叶变换(FFT、DFT),计算指定频率的幅值 14243
  • 基于STM32的伺服总线EtherCAT主站设计——SOEM方案 13888
  • EtherCAT运动控制——电子凸轮的实现(原理介绍、附代码) 10179
  • 基于Fluent的激光熔覆熔池流场仿真——VOF耦合融化凝固模型+源项UDF、二维模型、自由界面 9927

分类专栏

  • 电阻抗成像 4篇
  • CANopen、EtherCAT 4篇
  • STM32学习 8篇

最新评论

  • 基于Fluent的激光熔覆熔池流场仿真——VOF耦合融化凝固模型+源项UDF、二维模型、自由界面

    2401_88152325: 请问vn <8,小于逃逸速度,这个8是啥意思

  • AD导出文件供嘉利创打样及贴片——DRC校验、生产文件导出、嘉利创下单

    ‍830: 单位不用改成mm吗

  • 基于AD9226实现正弦信号的采集

    踏漠北下南洋: 您好,我在multisim14.0里复现不了这个电路?还有更完整的部分吗?

  • GD32450Z U盘通信教程——使用USBHS利用内部全速PHY作为USB MSC主机实现U盘通信

    zhouzubin: 请问这个移植后修改盘符可以吗?

  • 基于AD9954实现正弦交流信号输出——附原理图、代码

    augustus74521: 请问f1系列的可以用这个代码吗,f1系列gpio引脚最高速率只有五十赫兹,如果填五十赫兹的话会对代码功能实现有影响吗,需要改改其它地方吗

最新文章

  • 基于Fluent的激光熔覆熔池流场仿真——VOF耦合融化凝固模型+源项UDF、二维模型、自由界面
  • EtherCAT运动控制——电子凸轮的实现(原理介绍、附代码)
  • AD导出文件供嘉利创打样及贴片——DRC校验、生产文件导出、嘉利创下单
2023年12篇
2022年6篇

目录

目录

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河狸打捞员

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或 充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值

玻璃钢生产厂家玻璃钢花盆专卖玻璃钢半圆星球雕塑桥头玻璃钢卡通雕塑室外雕塑材质 玻璃钢吉林玻璃钢动物雕塑价格盐城商场美陈费用东莞玻璃钢雕塑心形花盆曲阳玻璃钢雕塑鹤雕塑玻璃钢仿铜人物雕塑牡丹江玻璃钢雕塑定制圣诞主题的商场美陈广西商场美陈玻璃钢动物雕塑型号优质的玻璃钢雕塑麋鹿天津景观玻璃钢雕塑加工东莞玻璃钢人物雕塑销售厂家商场内部绿植美陈方案南京哪里有玻璃钢雕塑厂家淮南玻璃钢雕塑浮雕厂家厦门模压法玻璃钢雕塑设计商场美陈kt板福州玻璃钢卡通雕塑定制个性化玻璃钢雕塑销售厂家宝鸡商场至陈仓园家美佳西湖区玻璃钢雕塑公司玻璃钢雕塑仿真蜜蜂玻璃钢瓜果雕塑系列贵州户内玻璃钢雕塑制作成品玻璃钢花盆研究昌平区商场美陈创意香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化