STM32+WiFi模块实现手机远程控制LED和舵机

发布时间:2026/10/13 4:39:40
STM32+WiFi模块实现手机远程控制LED和舵机 搞这个项目的人十有八九是被手机远程控制这几个字吸引过来的。我在实验室带的几个同学大一刚学完单片机就想做这个买了一块板子和一个串口WiFi模块折腾一个多星期最后卡在了怎么让手机和单片机真正聊上天这一步。其实整个项目拆开看一点都不神秘就是三件事WiFi模块把手机发来的数据变成串口数据单片机解析串口数据然后再根据不同的指令控制LED和舵机。难就难在中间这一环WiFi模块的配置、串口数据的接收、协议的约定任何一个地方没想清楚都会卡壳。这篇文章就围绕这个项目从方案选型、硬件接线、数据通路、控制逻辑、手机端到联调排错把我实际跑通的整套思路写出来。整个过程完全用常见模块和最小改动的思路来实现不依赖那些看起来很炫但门槛很高的方案适合刚接触物联网方向的嵌入式初学者也适合实验室做入门Demo的参考。1. 先想清楚这个项目到底解决什么问题方案怎么选1.1 拆解需求控制链路和三个核心模块别看标题只有一句话拆开之后你就能看到这个项目的边界。整个控制链路是手机 - WiFi模块 - STM32串口 - 控制逻辑 - LED/舵机这个链路里手机端负责发指令WiFi模块负责把无线数据翻译成串口数据STM32负责听懂指令并执行。真正需要你动手的点其实是三个模块各自的内部逻辑以及它们之间的接口。第一点是WiFi模块和STM32的串口对接。WiFi模块一般都走AT指令协议上电之后先用AT指令把它配置成透传模式或者配置成TCP Server让它能接收来自手机的连接。串口波特率、数据位、停止位必须和STM32侧保持一致这是新人最容易忽略的。第二点是STM32侧的串口接收。WiFi模块是外设它往串口发数据是不等你的所以接收必须放到中断或者DMA里。直接在主循环里轮询接收标志会丢数据。第三点是协议约定也就是手机发什么格式的字符串单片机才知道要干什么。这一步没有统一标准我后面会给出一套最省事的文本协议。1.2 无线方案横评为什么WiFi是这个项目的最优选做远程控制市面上能选的无线方案有好几种各有各的使用场景。方案通信距离手机支持开发成本适合场景蓝牙BLE10米左右需要做APP或小程序低近距离控制、穿戴设备433MHz透传几十到上百米不支持低遥控开关、传感采集WiFi本文方案路由器覆盖范围浏览器/调试助手中局域网控制、IoT入门蓝牙的优势是手机自带但你需要写一个APP或者小程序这个工作量不比写单片机端小。433模块模拟开关很好用但手机原生不支持还得配一个网关。利用WiFi的好处显而易见手机不需要装额外的东西一个浏览器、一个网络调试助手就能直接和单片机通信。你家里的路由器本来就开着WiFi模块连上路由器就有一个局域网IP手机也在同一个网络里直接把指令发过去就行。这个项目选WiFi本质上不是因为它技术多高级而是它把手机作为控制端这件事的成本降到了最低。你不需要为手机端做专门开发这是非常适合快速跑通Demo的路径。1.3 模块选型串口WiFi模块哪家强确定用WiFi之后市面上常见的方案有这么几类主控自带WiFi比如WiFi SoC芯片的方案不需要外部模块但开发环境和STM32不是一套体系要换IDE甚至换语言。串口WiFi模块和STM32通过串口连接MCU端不用关心无线协议细节只需要处理串口数据。对入门项目来说串口WiFi模块是更合理的选择。因为你可以把精力全部压在STM32端无线链路对你来说只是一个能把网络数据变成串口数据的外设。模块型号我就不做广告了你搜索串口WiFi模块能找到大量选项基本都兼容乐鑫的AT指令集。选择时重点看三个参数是否支持透传模式、是否支持TCP Server模式、串口波特率是否可调。这三个参数直接决定你后面书写不书。透传模式让WiFi模块和单片机之间的串口通信变得透明TCP Server模式让手机端可以主动连上来波特率可调是为了配合单片机的时钟配置。2. 硬件接线与供电细节看着简单最容易翻车的其实是这里2.1 需要的物料清单这个项目不需要什么高端器件清单如下STM32最小系统板或开发板一块我用的系列带三个以上的定时器方便同时输出PWM和控制灯串口WiFi模块一个带天线那一类F型/IPEX型天线都行USB转TTL模块一个板载带串口转USB芯片的开发板可以不用LED灯珠或LED灯板一个串一个330欧左右的限流电阻舵机一个常用的SG90或类似9克舵机杜邦线若干、面包板一块手机Android或iOS都行安装一个网络调试助手类APP或者直接用浏览器2.2 接线表照这个接基本不会错接线是整个项目里最琐碎但也有细节讲究的一步。我直接给一张我跑通的接线表STM32引脚连接说明PA9USART1_TXWiFi模块RXD单片机发数据给WiFi模块PA10USART1_RXWiFi模块TXDWiFi模块发数据给单片机GNDWiFi模块GND共地必须接3.3VWiFi模块VCC注意供电能力PB0电阻LED阳极灯的控制引脚PA8TIM1_CH1舵机信号线PWM输出外部5V舵机VCC舵机供电单独接外部GND舵机GND舵机地和系统共地这里很关键的一点串口交叉接法。TX接RXRX接TX很多人第一次接反了模块死活不回数据其实是把收发接反了。2.3 舵机供电是第一个经验坑舵机这个东西启动瞬间的电流能到几百毫安反复转的时候电流波动很大。如果你的舵机直接从STM32开发板的3.3V或者板载5V取电经常会出现这样的现象正常跑一会儿忽然单片机复位了或者WiFi模块掉线了。这不是代码问题是供电问题。舵机电机会把整个系统的电压拖垮低于单片机的复位阈值系统就重启。解决办法是单独给舵机准备一路电源。用USB转TTL模块的5V输出或者一个外部5V电源适配器直接给舵机供电然后只把舵机的GND与STM32的GND连在一起也就是共地但不共电源。信号线连到STM32的PWM输出引脚就可以。这个共地不共电源的思路在电机、舵机这类感性负载的控制项目里是通用的。单片机的地和负载的地必须连在一起这样控制信号才有电压基准但电源要分开避免负载的电流波动倒灌进主控系统。2.4 串口电平匹配3.3V和5V的问题另一个容易踩的坑是电平匹配。现在的串口WiFi模块基本都是3.3V逻辑电平STM32系列主控的IO口一般也是3.3V两者直接连没问题。但如果你用的是带板载USB转串口的老开发板或者某些5V容错的引脚严谨的做法是确认两侧逻辑电平一致。如果模块是用3.3V供电的逻辑就绝对不要接在5V的串口上长期工作会烧掉模块的收发引脚。判断方法很简单看模块的VCC是不是3.3V如果是串口逻辑就是3.3V不要去接5V的TTL电平设备。3. WiFi模块与STM32之间的数据通路AT指令、透传和DMA接收3.1 AT指令配置的完整流程WiFi模块出厂一般默认是AT指令固件。第一次使用先不要接单片机直接用USB转TTL模块把它插到电脑上用串口助手和它对话。AT指令配置这件事其实就是把模块设置成你想要的网络角色。整个流程我总结成五步发AT如果回OK说明串口通信正常。发ATCWMODE1设置成Station模式让模块去连接家里的路由器。发ATCWJAP路由器SSID,路由器密码让它上网。发ATCIPMUX1开启多连接这样手机可以连上来。发ATCIPSERVER1,8080开启TCP Server端口选8080或任意不冲突的端口。配置完后模块会把自己变成一个类似小服务器的角色在路由器局域网里监听8080端口的连接请求手机通过网络调试工具就能连上它。如果不想让它连路由器也可以让模块自己开热点把ATCWMODE改成2模块自带AP热点手机连上模块的WiFi就能通信。这种方式在野外、现场没有任何路由器的场景非常实用实际测试下来直接SPP/Socket连接会比走路由器省一道转发延迟更低。3.2 透传模式让你不用关心TCP数据包格式如果你用的是带透传功能的AT固件配置完TCP的工作后还需要用ATCIPMODE1开启透传模式然后输入ATCIPSEND进入发送状态。进入之后模块和单片机之间的串口链路就透明了手机发来任何数据模块会直接原样扔到TXD引脚上单片机发到RXD引脚的串口数据模块也会原样转发到手机上。透传模式的价值在于单片机的串口代码完全不用感知我是经过WiFi还是经过一根线通信的你只需要处理串口数据的收发逻辑就行。这是给MCU端减负的最省心方案。但透传模式有个副作用单片机再也无法直接给模块发AT指令了因为串口数据全被当成业务数据转发出去了。所以如果需要改模块配置要么重新上电再进AT模式要么先用非透传模式把配置写好再切到透传。我一般直接先配好再烧录最终固件省得反复折腾。3.3 DMA接收不定长数据的核心代码ST官方标准库和HAL库都能实现串口接收但标准的接收一个字符进一次中断方式在高频数据下容易丢。我在这个项目里用的是空闲中断IDLE结合DMA接收的方案一次性收完一整帧主循环再去解析。这种方案的原理很简单DMA一直在后台把串口收到的数据搬到内存缓冲区里当一根线空闲下来也就是一帧收完了串口会产生一个空闲中断。在空闲中断里关掉DMA算一下DMA搬了多少字节置一个消息标志主循环看到标志就处理。基于标准库的代码核心片段如下#define RX_BUF_LEN 256 uint8_t rx_buf[RX_BUF_LEN]; // DMA接收缓冲区 uint8_t rx_len 0; // 本次接收到的一帧长度 volatile uint8_t rx_flag 0; // 收到一帧的标志 void USART1_DMA_Init(void) { DMA_InitTypeDef DMA_InitStructure; USART_DMACmd(USART1, USART_DMAReq_RX, ENABLE); DMA_InitStructure.DMA_PeripheralBaseAddr (uint32_t)USART1-DR; DMA_InitStructure.DMA_MemoryBaseAddr (uint32_t)rx_buf; DMA_InitStructure.DMA_DIR DMA_DIR_PeripheralSRC; DMA_InitStructure.DMA_BufferSize RX_BUF_LEN; DMA_InitStructure.DMA_PeripheralInc DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode DMA_Mode_Circular; // 循环模式 DMA_InitStructure.DMA_Priority DMA_Priority_High; DMA_InitStructure.DMA_M2M DMA_M2M_Disable; DMA_Init(DMA1_Channel5, DMA_InitStructure); DMA_Cmd(DMA1_Channel5, ENABLE); } void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_IDLE) SET) { USART_ReceiveData(USART1); // 读DR清IDLE标志 DMA_Cmd(DMA1_Channel5, DISABLE); // 暂停DMA rx_len RX_BUF_LEN - DMA_GetCurrDataCounter(DMA1_Channel5); rx_flag 1; // 通知主循环有数据 DMA_SetCurrDataCounter(DMA1_Channel5, RX_BUF_LEN); DMA_Cmd(DMA1_Channel5, ENABLE); } }这样处理之后主循环里面只管判断rx_flag取rx_len个字节解析。不要在主循环里用HAL的HAL_UART_Receive那个是阻塞的会卡死其他逻辑。3.4 通信协议怎么定简单文本协议最省心WiFi模块把数据变成串口数据之后你必须定义一段数据怎么看懂一条指令。我见过不少同学直接在中断里比较\r\n或者直接拿收到的原始数据去匹配指令那在数据长了之后非常容易出bug。我的建议是定一套简单的文本协议格式如下LED:ON LED:OFF LED:BRIGHT:120 SERVO:90 SERVO:0 SERVO:180每条指令以换行符结尾。STM32侧在DMA中断里收集数据然后在主循环里按冒号拆字段。第一个字段是设备名第二个字段是动作LED那边还有第三个字段表示亮度值。选文本协议而不是二进制协议的原因因为是手机端太好测试了。你用网络调试助手直接手敲一个SERVO:90回车就能看到舵机动排查问题非常直观。如果用二进制协议你发的每一帧字节都要用十六进制输入调试体验会很痛苦。4. 控制逻辑核心灯光亮度与舵机角度的实现4.1 灯的控制从简单的开闭到呼吸灯效果灯的开关是最基本的GPIO控制。PB0配置成推挽输出收到LED:ON就拉高收到LED:OFF就拉低这没什么特别的。真正有意思的是让灯支持亮度调节这就需要PWM了。STM32的定时器输出PWM可以通过改变比较寄存器CCR的值也就是改变占空比来控制LED亮度。关键代码是配置一个定时器输出PWM然后写一个简单的映射函数把0到255的亮度值映射到CCR上// 假设定时器ARR设置为999那么PWM频率 72MHz / (PSC 1) / (ARR 1) // 配置PSC为71ARR为999PWM频率 1MHz / 1000 1kHz适合LED控制 void led_brightness_set(uint8_t brightness) { uint16_t ccr; if (brightness 100) brightness 100; // 0~100 映射到 0~999 ccr (uint16_t)(brightness * 10) - 1; if (brightness 0) ccr 0; TIM_SetCompare3(TIM3, ccr); }如果你想让灯有呼吸效果很简单在主循环的状态机里每10毫秒把当前亮度加1或减1生成正弦或三角波的渐变就实现了呼吸灯。这个呼吸灯逻辑可以作为一个美妙的调试手段因为只要灯能一笔一画地亮暗渐变就说明定时器中断和主循环调度都在正常工作。4.2 舵机的PWM控制20ms周期和角度映射舵机的控制原理不复杂。舵机内部有一个基准电位输入PWM信号的高电平宽度决定了输出轴的目标角度。常见舵机的PWM周期是20ms也就是50Hz脉冲宽度范围从0.5ms到2.5ms对应0度和180度。在STM32上我用的是TIM1的通道1输出PWM配置时把ARR设置为19999预分频设为71这样计数器频率是1MHz一个计数周期就是1us。那么CCR的值就直接等于脉冲宽度us0度对应0.5msCCR 50090度对应1.5msCCR 1500180度对应2.5msCCR 2500角度和CCR的线性映射关系void servo_set_angle(uint8_t angle) { uint32_t ccr; if (angle 180) angle 180; // 0~180度映射到 500~2500 us ccr 500 (uint32_t)angle * 2000 / 180; TIM_SetCompare1(TIM1, ccr); }这里有一个对新手来说非常重要的提醒不要每5毫秒就刷新一次舵机PWM的CCR值。对于标准舵机来说它会根据你刷新的频率来决定自己的运动速度。如果你在循环里快速改变目标角度舵机会以全速奔过去或者出现抖动。正确的做法是收到一个角度指令设置一次CCR然后让舵机自己转到目标位置它内部有反馈电位计会自己去闭环。4.3 主循环与状态机让系统不乱这个项目虽然简单但主循环还是应该用一个简单的状态机来组织别把逻辑全堆在中断里也别让主循环做成一个大死循环轮询。我推荐的主循环结构是这样的while (1) { // 1. 处理串口指令 if (rx_flag) { protocol_parse(rx_buf, rx_len); rx_flag 0; rx_len 0; } // 2. 呼吸灯渐变定时处理 breathe_timer_tick(); // 3. 超时保护长时间没收到指令让舵机回中/灯保持最后状态 watchdog_timer_tick(); // 4. 状态回传定时通过串口发回当前状态可选 status_report_tick(); }状态机的本质是让你的当前状态和输入事件解耦。每个循环周期系统先看有没有新指令有就处理没就继续执行周期性任务。这样即使手机连发多条指令也不会互相干扰。4.4 指令解析与错误处理解析协议的时候有个细节值得写一下。strtok这类函数在北京标准库的多线程环境下会保持全局状态但在单线程单片机上用没问题。不过我在实际代码里更倾向自己写一个简单的拆分循环避免隐式依赖void protocol_parse(uint8_t *buf, uint16_t len) { // 忽略空数据 if (len 2) return; // 把缓冲区变成字符串 buf[len] \0; if (strncmp((char*)buf, LED:, 4) 0) { // LED:ON / LED:OFF / LED:BRIGHT:value if (strstr((char*)buf, ON)) led_set_state(1); else if (strstr((char*)buf, OFF)) led_set_state(0); else if (strstr((char*)buf, BRIGHT:)) { int val atoi((char*)buf 10); led_brightness_set(val); } } else if (strncmp((char*)buf, SERVO:, 6) 0) { int angle atoi((char*)buf 6); servo_set_angle(angle); } else { // 未知指令忽略或回传错误标志 } }这个解析没有用复杂的JSON库就用了字符串匹配和atoi。原因很简单这个项目的指令集只有几条完全不需要引入JSON解析库增加代码量。指令格式固定用字符串函数就能可靠地解析。5. 手机端控制从网络调试助手到网页化进阶5.1 第一步跑通网络调试助手手机端的遥控器有两种实现路径。先讲最容易跑通的。在应用商店搜索网络调试助手或TCP调试助手这一类工具就是用来和TCP Server通信的。打开之后选择TCP Client模式输入WiFi模块在路由器上获取到的IP地址端口填8080点击连接。连上之后底下的输入框直接输入LED:ON点发送灯就应该亮了。这一步是整条链路的冒烟测试。如果灯亮了说明无线链路、串口链路、协议解析、控制逻辑全部正常。我强烈建议先把这一步跑通再去做花哨的手机界面否则你会同时调试好几层问题非常崩溃。5.2 手机端IP地址查看与固定每次模块上电都会从路由器动态获取IP。如果你连路由器模式手机上要填的IP可能会变。一个省心的做法是在路由器后台给WiFi模块绑定一个固定的IP地址大部分家用路由器都支持在DHCP列表里找到模块的MAC地址然后把它绑定到指定IP。这样手机端只需要填一次IP。如果你用的是模块自带AP热点的方案模块的IP固定是192.168.4.1手机连上这个热点后直接填这个IP就行完全不需要路由器。5.3 进阶做一个本地HTML网页当遥控器演示用网络调试助手没问题但如果你想把这个项目拿去展示或者给别人玩一个网页遥控器会更有说服力。这里需要一个技巧你的WiFi模块此时已经作为一个小的TCP服务存在了手机浏览器不能直接和TCP服务器通信。浏览器只能访问HTTP服务。所以网页控制方案需要额外做一个转发角色。最省事的做法是在STM32端不用TCP Server而让WiFi模块工作在双模式另一路用HTTP监听。但AT固件对普通用户来说配置这点比较绕如果模块不支持就用下面的方案手机装一个支持WebSocket的调试工具或者直接写个简单的APP页面把JavaScript和网络调试助手结合用但这就又增加了工具依赖。如果你只是想在局域网演示还可以用一台电脑做中介浏览器打开页面电脑通过网络调试助手发指令。不过这种方式带出去演示略显繁琐。真正的进阶方向是两个一是换用支持Web Server固件的WiFi方案把HTML页面直接存进模块的文件系统里二是STM32侧挂一个简单的HTTP解析框架直接在单片机上开一个小网页服务。这两个方向都有参考实现等这个项目跑通后再去折腾会顺很多。5.4 局域网控制和公网控制的边界标题里写的远程在很多人的理解里其实是不在同一个路由器下也能控制。这一点一定要提前说明白。本文讲的所有通信前提都是手机和WiFi模块在同一个局域网内。如果你想实现从办公室控制家里的灯还需要一步路由器的端口映射把外网的某个端口映射到WiFi模块的内网IP上或者用云平台做中转。这一步涉及公网IP、端口转发、内网穿透等内容复杂度会明显上升。我建议初学阶段先吃透局域网控制把链路通起来再做公网也不迟。连局域网都做不通的直接上公网只会被一波问题淹没。6. 联调排错几个高频故障的完整排查链路6.1 故障一串口助手发AT指令没反应这是最最常见的第一个坑。你把WiFi模块插到USB转TTL上打开串口助手发送AT什么都回不了。排查顺序是看USB转TTL模块的TX/RX是否和WiFi模块反了。TX接RXRX接TX。用万用表测一下模块TXD引脚对GND的电压只接通电源的话应该是3.3V附近接反线的情况电压表现不同。确认串口助手的波特率和模块默认一致。大多数串口WiFi模块出厂默认是115200但有些模块是9600或者38400看模块丝印或者说明书别想当然。确认是否勾选了发送新行。AT指令要求以回车换行结尾串口助手发送区右下角一定要勾选发送新行否则模块不认为指令结束。按这个顺序走下来大部分没反应都能解决。我见过有一半的人的没反应其实是忘了勾发送新行。6.2 故障二数据收不全或者乱码串口收到的数据出现乱码最常见的原因是波特率不一致。WiFi模块的工作波特率和STM32串口初始化时设置的波特率必须一模一样。AT指令配置里改了模块的波特率之后如果单片机侧还是旧的波特率就会直接乱码。数据收不全还有一个隐藏原因串口中断优先级太低在处理其他中断的时候串口数据被覆盖。尤其是当你在舵机控制的中断里耗时过久串口的接收缓冲溢出。解决方法是给串口中断一个相对高的抢占优先级以及把串口接收放到DMA里去DMA搬运不需要CPU介入大量降低延迟。6.3 故障三舵机抖动或者不动舵机不动的时候先看信号线接对没有再看PWM频率。用逻辑分析仪或者示波器看波形最直观如果没有仪器就先把PWM周期固定为20ms然后用官方库的示例程序验证舵机能否工作。舵机抖动的情况则几乎可以断定是供电不足。你在舵机上电转动的瞬间用万用表测舵机电源引脚和GND之间的电压如果电压从5V掉到4V以下基本就是电源问题。加一个220uF以上的电解电容在舵机电源附近储能或者换成独立的供电适配器抖动立刻消失。6.4 故障四手机连接不上模块的TCP服务手机用网络调试助手连接模块的问题排查链路是这样手机上先确认和模块是否在同一个局域网里看手机的IP和模块IP的前三段。用电脑上的TCP调试工具在同一网络里试着连一下模块IP和端口连不上的话是模块配置问题连得上的话是手机的问题。检查模块的ATCIFSR返回的IP地址确认它就是当前的路由器分配地址。确认模块开启了多连接模式ATCIPMUX1默认状态是单连接Server模式起不来。这一套走完之后绝大多数连接问题都能定位到某一个环节。6.5 加一个系统级看门狗和状态回传最后提一个提升稳定度的小技巧。WiFi模块偶尔会死机或者网络连接断开后模块处于半死状态这时候手机发什么都不动。我的做法是在STM32主循环里加一个软件看门狗如果超过10秒没有收到任何有效指令就通过GPIO控制WiFi模块的复位引脚给它重新上电然后重新执行AT配置流程。这样等于给整个无线环节加了一层自愈能力。对于无人值守的物联网设备来说这个设计是很有必要的。加入之后系统的稳定性会有质的提升即使WiFi模块偶尔掉线系统也能自动恢复不用你去现场断电重启。7. 写在最后的一些体会这个项目看着简单但把链路真正跑通之后你对嵌入式物联网的整个数据通路会有一个非常直观的理解。手机端发一条指令经过空中、模块、串口、DMA、协议栈最后变成引脚上的电平变化这个过程里的每一层都有明确的边界和职责。我在带新同学做这个项目时最大的体会是先跑通链路再优化细节。别一开始就想着搞完美的APP界面、搞公网穿透、搞平台接入先用手敲命令把灯点亮把舵机转起来。这个从0到1的过程是理解所有上层复杂技术的基础。后续可以扩展的方向有两个一是把控制端从网络调试助手换成带界面的小程序二是加入传感器反向采集让STM32不仅接收指令还能上报温度、湿度、光照数据。思路都是通的你在这个项目里建立的串口链路和协议设计能力可以直接迁移过去。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询