当前位置: 首页 > news >正文

17.【NXP 号令者RT1052】开发——实战-输入捕获

17.【NXP 号令者RT1052】开发——实战-输入捕获

前面两章,我们介绍了 RT1052 的四定时器(QTMR)和 FlexPWM 模块作为 PWM 输出的使用方法,这一章,我们将向大家介绍通用定时器(GPTx)作为输入捕获的使用。在本章中,我们将用 GPT2 的捕获通道 2(CAPTURE2)来做输入捕获,捕获 P326 上低电平的脉宽(按KEY2 按键输入低电平),通过串口打印低电平脉宽时间.

17.1 输入捕获简介

输入捕获模式可以用来测量脉冲宽度或者测量频率。我们以测量脉宽为例,用一个简图来说明输入捕获的原理
在这里插入图片描述
如图所示,就是输入捕获测量低电平脉宽的原理,假设定时器工作在向上计数模式,
图中 t1~t2 时间,就是我们需要测量的低电平时间。测量方法如下:首先设置定时器输入捕获通道 x 为下降沿捕获,这样,t1 时刻,就会捕获到当前的 CNT 值,然后立即清零 CNT,并设置输入捕获通道 x 为上升沿捕获,这样到 t2 时刻,又会发生捕获事件,得到此时的 CNT 值,记为 ICRx2。这样,根据定时器的计数频率,我们就可以算出 t1~t2 的时间,从而得到低电平脉宽。

在 t1~\t2 之间,可能产生 N 次定时器溢出,这就要求我们对定时器溢出做处理,防止低电平太长,导致数据不准确。如图所示,t1~t2 之间,CNT 计数的次数等于:N*2^32+ICRx2,有了这个计数次数,再乘以 CNT 的计数周期,即可得到 t2-t1 的时间长度,即低电平持续时间。
输入捕获的原理,我们就介绍到这。

RT1052 有 GPT1 和 GPT2 两个通用定时器,每个 GPT 定时器又包含 2 个输入捕获通道:CAPTURE1 和 CAPTURE2。RT1052 通用定时器的输入捕获,就是通过检测 GPTx_CAPy 上的边沿信号,在边沿信号发生跳变(比如上升沿/下降沿)的时候,将当前定时器的值(GPTx_CNT)存放到对应通道的捕获寄存器(GPTx_ICRy)里面,完成一次捕获。同时还可以配置捕获时是否触发中断

RT1052 GPT2 输入捕获配置步骤

1. 设置 GPIO3_IO26 复用功能

IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_40_GPT2_CAPTURE2,0); 
IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_40_GPT2_CAPTURE2,0xF0F1);

2. 使能 GPT2 时钟

CLOCK_EnableClock(kCLOCK_Gpt2)

此函数会被 GPT_Init 调用,无需显式调用。


3. 初始化 GPT2

gpt_config_t gpt2_onfig;
GPT_GetDefaultConfig(&gpt2_onfig); //先初始化 GPT2 为默认值
gpt2_onfig.divider=75; //设置分频值
gpt2_onfig.clockSource=kGPT_ClockSource_Periph; //设置时钟源
GPT_Init(GPT2,&gpt2_onfig); //初始化 GPT2

4. 设置 GPT2 为下降沿捕获

void GPT_SetInputOperationMode(GPT_Type * base,gpt_input_capture_channel_t channel,gpt_input_operation_mode_t mode)
可选模式
typedef enum _gpt_input_operation_mode
{kGPT_InputOperation_Disabled = 0U, //不捕获kGPT_InputOperation_RiseEdge = 1U, //上升沿捕获kGPT_InputOperation_FallEdge = 2U, //下降沿捕获kGPT_InputOperation_BothEdge = 3U, //双边沿捕获(上升沿和下降沿一起)
} gpt_input_operation_mode_t;
示例代码
GPT_SetInputOperationMode(GPT2,kGPT_InputCapture_Channel2,kGPT_InputOperation_FallEdge);

5. 配置溢出中断和输入捕获中断

GPT_EnableInterrupts(GPT2,kGPT_InputCapture2InterruptEnable); //使能 GPT2 捕获中断
GPT_EnableInterrupts(GPT2,kGPT_RollOverFlagInterruptEnable); //使能 GPT2 溢出中断

6. 使能 GPT2

GPT_StartTimer(GPT2); //开始定时器

7. 设置中断优先级并开启 GPT2 中断

RT1052_NVIC_SetPriority(GPT2_IRQn,7,0); //设置 GPT2 中断优先级
EnableIRQ(GPT2_IRQn); //使能 GPT2 中断

8. 编写中断服务函数

  • 在中断服务函数中实现捕获机制:
    • 第一次捕获下降沿
    • 第二次捕获上升沿
    • 处理可能的定时器溢出
  • 通过中断正确捕获低电平脉宽。

17.2 硬件设计

本实验用到的硬件资源有:

  1. 指示灯 DS0
  2. KEY2 按键
  3. 串口
  4. 通用定时器 2(GPT2)
    前面 3 个,在之前的章节均有介绍。本节我们,我们将捕获 GPT2_CAP2(P326)上的低电平脉宽,通过 KEY2 按键输入低电平,并从串口打印低电平脉宽。GPT2_CAP2 和 KEY2 的连接原理图如图所示:
    在这里插入图片描述
    图中的连接关系在硬件上都是直接连好的,无需任何硬件变动。

17.3 软件设计

本章,我们依旧是在前一章的基础上修改代码,先打开之前的工程,双击 HARDWARE 分组,添加 gpttimer.c(该文件在第十一章的时候就已经创建了,在工程:HARDWARE→GPTIMER文件夹下)

#include "gptimer.h"
#include "led.h"gpt_config_t gpt1_onfig;//初始化GPTIMER1,时钟源为perclk_clk_root=75MHz
//pre:分频值,0~4096
//comcount:比较计数值,0~0xFFFFFFFF
//当ocrx==CNT时,产生中断.
//定时时间=ocrx*(psc+1)/PERCLK_CLK_ROOT
void GPT1_Int_Init(u16 psc,u32 ocrx)
{GPT_GetDefaultConfig(&gpt1_onfig);	//先初始化GPT1为默认值gpt1_onfig.clockSource=kGPT_ClockSource_Periph;	//初始化时钟源perclk_clk_rootgpt1_onfig.divider=psc;	        //设置分频值GPT_Init(GPT1,&gpt1_onfig);GPT_SetOutputCompareValue(GPT1,kGPT_OutputCompare_Channel1,ocrx);	    //设置比较计数值GPT_EnableInterrupts(GPT1,kGPT_OutputCompare1InterruptEnable);			//使能GPT比较通道1中断RT1052_NVIC_SetPriority(GPT1_IRQn,5,0);									//抢占优先级5,子优先级0EnableIRQ(GPT1_IRQn);	//使能GPT1中断GPT_StartTimer(GPT1);	//开始定时器	
}//初始化GPT2 CAP2输入捕获
//psc : 预分频器,0~4095
//最大计数时间=(2^32)*(psc+1)/PERCLK_CLK_ROOT=234562.5秒,基本上不可能溢出
void GPT2_CAP2_Init(u16 psc)
{gpt_config_t gpt2_onfig;//配置GPT2_CAP2相关IO(GPIO_EMC_40)的功能//高转换速度,驱动R0/6,速度为200Mhz,关闭开路功能,使能pull/keepr//选择pull功能,上拉22K Ohm IOMUXC_SetPinMux(IOMUXC_GPIO_EMC_40_GPT2_CAPTURE2,0);	  IOMUXC_SetPinConfig(IOMUXC_GPIO_EMC_40_GPT2_CAPTURE2,0xF0F1);GPT_GetDefaultConfig(&gpt2_onfig);	//先初始化GPT2为默认值gpt2_onfig.divider=psc;	            //设置分频值gpt2_onfig.clockSource=kGPT_ClockSource_Periph;	//设置时钟源GPT_Init(GPT2,&gpt2_onfig);         //初始化GPT2//设置CAP2为下降沿捕获GPT_SetInputOperationMode(GPT2,kGPT_InputCapture_Channel2,kGPT_InputOperation_FallEdge);GPT_EnableInterrupts(GPT2,kGPT_InputCapture2InterruptEnable);   //使能GPT2捕获中断GPT_EnableInterrupts(GPT2,kGPT_RollOverFlagInterruptEnable);    //使能GPT2溢出中断GPT_StartTimer(GPT2);	            //开始定时器//中断设置RT1052_NVIC_SetPriority(GPT2_IRQn,7,0);//设置GPT2中断优先级EnableIRQ(GPT2_IRQn);	            //使能GPT2中断
}//GPT1中断服务函数
void GPT1_IRQHandler(void) 
{//OCR1中断if(GPT_GetStatusFlags(GPT1,kGPT_OutputCompare1Flag)){LED1_Toggle;			//LED1灯翻转GPT_ClearStatusFlags(GPT1,kGPT_OutputCompare1Flag);//清除中断标志位}__DSB();				//数据同步屏蔽指令
}//捕获状态
//[7]:0,没有成功的捕获;1,成功捕获到一次.
//[6]:0,还没捕获到下降沿;1,已经捕获到下降沿了.
//[5:0]:捕获低电平后溢出的次数(对于32位定时器来说,1us计数器加1,溢出时间:42949.67秒)
u8  GPT2CAP2_CAPTURE_STA=0;	//输入捕获状态		    				
u32	GPT2CAP2_CAPTURE_VAL;	//输入捕获值(GPT2是32位)// GPT2中断服务函数
void GPT2_IRQHandler(void)
{if ((GPT2CAP2_CAPTURE_STA & 0X80) == 0) // 还未成功捕获{if (GPT_GetStatusFlags(GPT2, kGPT_RollOverFlag)) // 溢出中断{if (GPT2CAP2_CAPTURE_STA & 0X40) // 已经捕获到高电平了{if ((GPT2CAP2_CAPTURE_STA & 0X3F) == 0X3F) // 高电平太长了{GPT2CAP2_CAPTURE_STA |= 0X80; // 标记成功捕获了一次GPT2CAP2_CAPTURE_VAL = 0XFFFFFFFF;}elseGPT2CAP2_CAPTURE_STA++;}}if (GPT_GetStatusFlags(GPT2, kGPT_InputCapture2Flag)) // 捕获2发生捕获事件{if (GPT2CAP2_CAPTURE_STA & 0X40) // 捕获到一个下降沿{GPT2CAP2_CAPTURE_STA |= 0X80; // 标记捕获到一次低电平脉宽// 获取当前的捕获值.GPT2CAP2_CAPTURE_VAL = GPT_GetInputCaptureValue(GPT2, kGPT_InputCapture_Channel2);// 设置捕获下降沿GPT_SetInputOperationMode(GPT2, kGPT_InputCapture_Channel2, kGPT_InputOperation_FallEdge);}else // 还未开始,第一次捕获上升沿{GPT2CAP2_CAPTURE_STA = 0;	  // 清空GPT2CAP2_CAPTURE_VAL = 0;	  // 捕获值清零GPT2CAP2_CAPTURE_STA |= 0X40; // 标记捕获到下降沿GPT_StopTimer(GPT2);		  // 关闭GPT2// 设置捕获上升沿GPT_SetInputOperationMode(GPT2, kGPT_InputCapture_Channel2, kGPT_InputOperation_RiseEdge);GPT_StartTimer(GPT2); // 使能GPT2}}}GPT_ClearStatusFlags(GPT2, kGPT_RollOverFlag);		// 清除溢出中断标志位GPT_ClearStatusFlags(GPT2, kGPT_InputCapture2Flag); // 清除捕获2中断标志位__DSB();											// 数据同步屏蔽指令
}

此部分代码包含两个函数,其中 GPT2_CAP2_Init 函数用于 GPT2 输入捕获通道 2 的设置,其设置和我们上面讲的步骤是一样的,这里就不多说,接下来,重点来看看第二个函数。
GPT2_IRQHandler 是 GPT2 的中断服务函数,该函数用到了两个全局变量,用于辅助实现低电平捕获。其中GPT2CAP2_CAPTURE_STA,是用来记录捕获状态,该变量类似我们在lpuart.c里面自行定义的 LPUART_RX_STA 寄存器(其实就是个变量,只是我们把它当成一个寄存器那样来使用)。GPT2CAP2_CAPTURE_STA 各位描述如表所示:

GPT2CAP2_CAPTURE_STA
bit7bit6bit5-0
捕获完成标志捕获到下降沿标志捕获低电平后定时器溢出的次数

现在我们来介绍一下,捕获低电平脉宽的思路:首先,设置 GPT2_CAP2 捕获下降沿,这在 GPT2_CAP2_Init 函数执行的时候就设置好了,然后等待下降沿中断到来,当捕获到下降沿中断,此时如果 GPT2CAP2_CAPTURE_STA 的第 6 位为 0,则表示还没有捕获到新的下降沿,就先把GPT2CAP2_CAPTURE_STA、GPT2CAP2_CAPTURE_VAL 和 CNT 计数器(先设置 EN=0,再设置 EN=1,间接清零 CNT,详见前面 ENMOD 位的说明)等清零,然后再设置GPT2CAP2_CAPTURE_STA 的第 6 位为 1,标记捕获到低电平,最后设置为上升沿捕获,等待上升沿到来。如果等待上升沿到来期间,定时器发生了溢出(对 32 位定时器来说,很难溢出),就在 GPT2CAP2_CAPTURE_STA 里面对溢出次数进行计数,当最大溢出次数来到的时候,就强制标记捕获完成(虽然此时还没有捕获到上升沿)。当上升沿到来的时候,先设置GPT2CAP2_CAPTURE_STA 的第 7 位为 1,标记成功捕获一次低电平,然后读取此时的定时器
计数器值到 GPT2CAP2_CAPTURE_VAL 里面,最后设置为下降沿捕获,回到初始状态。

这样,就完成一次低电平捕获了,只要 GPT2CAP2_CAPTURE_STA 的第 7 位一直为 1,那就不会进行第二次捕获,我们在 main 函数处理完捕获数据后,将 GPT2CAP2_CAPTURE_STA置零,就可以开启第二次捕获

gptimer.h

#ifndef __TIMER_H
#define __TIMER_H
#include "sys.h"void GPT1_Int_Init(u16 psc,u32 ocrx);
void GPT2_CAP2_Init(u16 psc);				//GPT2 CAP2输入捕获设置
#endif

main.c

#include "sys.h"
#include "lpuart.h"
#include "delay.h"
#include "led.h"
#include "key.h"
#include "exti.h"
#include "wdog.h"
#include "rtwdog.h"
#include "gptimer.h"
#include "pitimer.h"
#include "qtimer.h"
#include "pwm.h"
#include "xbar.h"
#include "flexpwm.h"extern u8  GPT2CAP2_CAPTURE_STA;		//输入捕获状态		    				
extern u32	GPT2CAP2_CAPTURE_VAL;		//输入捕获值int main(void)
{u8 key=0;MPU_Memory_Protection();    //初始化MPURT1052_Clock_Init();	    //配置系统时钟DELAY_Init(600);		    //延时函数初始化LPUART1_Init(115200);       //初始化串口1RT1052_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);//优先级分组4
#ifdef LED_DEBUGu8 led0sta=1,led1sta=1;     //LED0,LED1的当前状态LED_Init();				    //初始化LED
#endif
#ifdef KEY_DEBUGKEY_Init();                 //初始化KEY
#endif
#ifdef LPUART_DEBUGu8 len;					//接收数据长度u16 times=0;            //延时计数器LED0(0);					//先点亮红灯 
#endif
#ifdef EXTIX_DEBUGEXTIX_Init();			    //初始化外部中断
#endif
#ifdef WDOG_DEBUGWDOG1_Init(3,2);		    //初始化看门狗1,2秒溢出,提前1秒进入中断,方便喂狗LED0(0);               	    //先点亮LED灯delay_ms(300);				//延时300ms再初始化看门狗,LED0的变化"可见"
#endif
#ifdef RTWDOG_DEBUGLED_Init();				    //初始化LED KEY_Init();                 //初始化KEYdelay_ms(100);         	    //延时100ms再初始化看门狗,LED0的变化"可见"MYRTWDOG_Init(1,0,32768,0);	//初始化RT看门狗,1秒溢出,非窗口模式LED0(0);               	    //先点亮LED灯
#endif
#ifdef GPT1_DEBUGLED_Init();				    //初始化LED  KEY_Init();                 //初始化按键GPT1_Int_Init(3750-1,10000); //设置GPT1 0.5秒钟产生一次中断
#endif
#ifdef PIT_DEBUGLED_Init();				    //初始化LED  PIT_CH0_Int_Init(75000000/2);	//设置PIT 0.5秒钟产生一次中断
#endif
#ifdef QTMR_DEBUGKEY_Init();                 //初始化按键LED_Init();				            //初始化LEDQTMR1_CH0_Int_Init(15,46875);	//设置QTMR1 0.04秒钟产生一次中断
#endif
#ifdef QTMR_PWM_DEBUGu8 dir=1; u16 led1pwmval=0;    gpio_pin_config_t led_config;LED_Init();				    //初始化LED  KEY_Init();                 //初始化按键//初始化PWM,定时器时钟为:150/64=2.34375Mhz,设置频率为5Khz,50%占空比QTMR4_CH3_PWM_Init(14,5000,0);//设置P103为输入模式,防止干扰PWMled_config.direction=kGPIO_DigitalInput;	//输出led_config.interruptMode=kGPIO_NoIntmode;	//不使用中断功能led_config.outputLogic=0;					//默认高电平,LED灯关闭GPIO_PinInit(GPIO1,3,&led_config); 	        //初始化GPIO1_3
#endif
#ifdef XBAR_DEBUGu8 dir=1; u16 led1pwmval=0;  //初始化PWM,定时器时钟为:150/64=2.34375Mhz,设置频率为5Khz,50%占空比QTMR4_CH3_PWM_Init(14,5000,50); IOMUXC_SetPinMux(IOMUXC_GPIO_AD_B0_03_XBAR1_INOUT17,0);	//GPIO_AD_B0_03配置为ALT1,即XBAR1_INOUT17XBARA1_Signal_Set(kXBARA1_InputQtimer4Tmr3Output,kXBARA1_OutputIomuxXbarInout17);   //QTMR4_CH3输出到XBARA1_INOUT17上面.//即:通过GPIO_AD_B0_03(GPIO1_IO03)输出QMR4_CH3的波形.
#endif
#ifdef FLEPWM_DEBUGu8 dir=1; u16 led1pwmval=0;  LED_Init();				    //初始化LED  KEY_Init();                 //初始化按键PWM2_SM3_PWMAB_Init(7,1000,50);    //初始化PWM2,128分频,1K频率,50%占空比
#endifu8 i=0;long long temp=0;  LED_Init();				    //初始化LED  KEY_Init();                 //初始化按键GPT2_CAP2_Init(75);	        //设置GPT2 CAP2的参数:1Mhz计数频率,精度:1uswhile(1){delay_ms(10);  		 if(GPT2CAP2_CAPTURE_STA&0X80)		//成功捕获到了一次低电平{temp=GPT2CAP2_CAPTURE_STA&0X3F; temp*=0XFFFFFFFF;		 		//溢出时间总和temp+=GPT2CAP2_CAPTURE_VAL;		//得到总的高电平时间printf("LOW:%lld us\r\n",temp);	//打印总的高点平时间,单位:usGPT2CAP2_CAPTURE_STA=0;			//开启下一次捕获}i++;if(i==50)							//500ms闪灯一次{i=0;LED0_Toggle;}
#ifdef FLEPWM_DEBUGdelay_ms(10);	 if(dir)led1pwmval++;else led1pwmval--;	 if(led1pwmval>=100)dir=0;if(led1pwmval==0)dir=1;	 PWM2_SM3_DutySet(led1pwmval); 
#endif
#ifdef XBAR_DEBUGdelay_ms(10);	 if(dir)led1pwmval++;else led1pwmval--;	 if(led1pwmval>=100)dir=0;if(led1pwmval==0)dir=1;	 QTMER4CH3_PWM_DutySet(14,5000,led1pwmval);
#endif
#ifdef QTMR_PWM_DEBUGdelay_ms(10);	 if(dir)led1pwmval++;else led1pwmval--;	 if(led1pwmval>=100)dir=0;if(led1pwmval==0)dir=1;	 QTMER4CH3_PWM_DutySet(14,5000,led1pwmval);
#endif
#ifdef QTMR_DEBUGLED0_Toggle;delay_ms(1000);
#endif
#ifdef PIT_DEBUGLED0_Toggle;delay_ms(1000);
#endif
#ifdef GPT1_DEBUGLED0_Toggle;delay_ms(1000);
#endif
#ifdef RTWDOG_DEBUGkey=KEY_Scan(0);if(key==WKUP_PRES)		//如果按键按下,则喂狗.{RTWDOG_Feed();} delay_ms(10);
#endif
#ifdef WDOG_DEBUGLED0(1);				//关闭DS0,如不复位,DS0将一直处于关闭状态.delay_ms(100);
#endif
#ifdef EXTIX_DEBUGprintf("Int example driver!\r\n");delay_ms(1000);
#endif
#ifdef KEY_DEBUGkey=KEY_Scan(0); 		    //得到键值if(key){	switch(key){				 case WKUP_PRES:	//控制LED0,LED1互斥点亮led1sta=!led1sta;led0sta=!led1sta;break;case KEY2_PRES:	//控制LED0翻转led0sta=!led0sta;break;case KEY1_PRES:	//控制LED1翻转	 led1sta=!led1sta;break;case KEY0_PRES:	//同时控制LED0,LED1翻转 led0sta=!led0sta;led1sta=!led1sta;break;}LED0(led0sta);		//控制LED0状态LED1(led1sta);		//控制LED1状态}else delay_ms(10);
#endif // KEY_DEBUG
#ifdef LPUART_DEBUGif(LPUART_RX_STA&0x8000){					   len=LPUART_RX_STA&0x3fff;//得到此次接收到的数据长度printf("\r\n发送的消息为:\r\n");LPUART_WriteBlocking(LPUART1,LPUART_RX_BUF,len);//发送接收到的数据printf("\r\n\r\n");//插入换行LPUART_RX_STA=0;}else{times++;if(times%5000==0){printf("\r\nALIENTEK RT1052开发板 串口实验\r\n");}if(times%200==0)printf("请输入数据,以回车键结束\r\n");  if(times%30==0)LED0_Toggle;//闪烁LED,提示系统正在运行.delay_ms(10);   }
#endif // LPUART_DEBUG}
}

main 函数的代码和之前的代码非常类似,我们在初始化时钟、串口和 LED 后,调用我们前面介绍的 GPT2_CAP2_Init 函数,设置分频系数为 75,这样 GPT2 的计数频率为 1Mhz,精度为 1us。
在主循环里面,通过 GPT2CAP2_CAPTURE_STA 的第 7 位,来判断有没有成功捕获到一次低电平,如果成功捕获,则将低电平时间通过串口输出到电脑。

编译,下载

可以看到 DS0 开始闪烁。说明程序已经正常在跑了,我们再打开串口调试助手,选择对应的串口,然后按 KEY2 按键,可以看到串口打印的低电平持续时间,如图:
在这里插入图片描述
在这里插入图片描述

从上图可以看出,其中有 3 次高电平在 100us 左右,这种就是按键按下时发生的抖动。这就是为什么我们按键输入的时候,一般都需要做防抖处理,防止类似的情况干扰正常输入。

总结

本章主要介绍了 GPT2 输入捕获的原理:通过定时器在下降沿和上升沿发生时记录计数器值,计算两次捕获之间的时间差,从而得到低电平脉宽;在捕获过程中还需处理定时器溢出情况,保证测量结果准确。实验中利用 KEY2 按键产生低电平信号,GPT2 的 CAPTURE2 通道完成捕获,并通过串口输出脉宽时间,实现对输入信号持续时间的测量。
OK!谢谢大家!

http://www.dtcms.com/a/611988.html

相关文章:

  • 网站的数据库选择网址我的上网主页
  • 百度突然搜不到网站网站建设可行性报告
  • 专业做设计的网站一个域名两个网站
  • 什么内容能提高网站流量wordpress手机端怎么用
  • 怎么做文化传播公司网站成华区微信网站建设公
  • 网站后台登入密码忘记了合肥科技网站建设
  • 13.vector(上)
  • 阿里云免费网站备案房地产基础知识300问
  • 第35节:全局光照与路径追踪探索
  • 企业网站建设方案书范文百度做任务的网站
  • 郑州做花店网站大学生做爰网站
  • 工程施工行业在哪个网站容易找事做社交网站制作
  • 廊坊网站自助建站网站内页跳转wap
  • 营销网站建设与管理无锡新吴区建设局网站
  • 数据结构与算法 第一天
  • 武威市凉州区建设局网站佛山深圳建网站
  • wordpress 缩略图裁剪贵阳seo排名
  • C语言--位段(Struct)
  • 睢县网站建设有哪些做西点及烘焙的网站
  • 仪陇建设局网站wordpress 幻灯片主题
  • 广西建设厅网站绿色建筑标识个人主页页面
  • 海南美容网站建设网站界面设计方案
  • 宣传京津风筝网站的建设目的最全资源搜索引擎
  • 厦门维品网站建设做泵阀生意到哪个网站
  • 番禺网站建设系统云南网站开发费用
  • 网站首页排名seo搜索优化WordPress和哪个好用
  • 广告制作开票大类是什么吉林seo基础
  • 建设网站大概多少钱品牌营销推广策划方案
  • 为什么CAD 3D模型需要AI大模型?
  • 海口专业做网站网站开发技术支持