FPGA与STM32通过ESP8266模块实现远程通信
1. 前言 (引言)
在嵌入式系统开发中,我们经常面临“异构协同”的需求:FPGA 擅长高速并行数据采集(如AD采样、图像处理),而 STM32 擅长复杂逻辑控制、人机交互和网络通信。
如何将这两者无线连接起来?
本项目实现了一个低成本、高可靠性的无线通信方案。系统让 FPGA 采集传感器数据,通过 ESP8266 Wi-Fi 模块,以自定义数据包的形式实时发送给 STM32,STM32 作为服务器进行接收、校验和解析。
FPGA 端:实现了“盲发”状态机与透明传输,极大降低了 Verilog 解析 AT 指令的复杂度。
STM32 端:作为 AP(热点)和 TCP Server,构建了稳定的局域网环境。
协议层:设计了包含帧头、帧尾的通信协议,确保数据传输的完整性。
2. 系统架构(系统架构)
FPGA的RTL视图如下:

系统采用 Client-Server 架构:
- 服务端(服务器)- STM32:
- 模式:AP 模式 (热点) + TCP Server。
- IP地址:固定为
192.168.4.1 - 职责:建立 Wi-Fi 网络,监听端口 ,解析数据包。
8080
- 客户端(客户端)- FPGA:
- 模式:Station 模式(站点) + TCP Client + 透传模式。
职责:主动连接热点,建立 TCP 连接,将采集的数据打包发送。

3. 通信协议设计(协议设计)
为了防止数据在无线传输中发生粘包或错位,就没有发送裸数据,而是设计了一个简单的定长数据包协议。
协议格式 (6 Bytes):
| 字节索引 | 内容 | 十六进制 | 说明 |
| 0 | 帧头 1 | 0xAA | 帧同步标识 |
| 1 | 帧头 2 | 0x55 | 帧同步标识 |
| 2 | 数据高位 | Data_H | 16位传感器数据的高8位 |
| 3 | 数据低位 | Data_L | 16位传感器数据的低8位 |
| 4 | 帧尾 1 | 0x55 | 结束校验 |
| 5 | 帧尾 2 | 0xAA | 结束校验 |
4. 关键实现步骤
第一步:STM32 端配置
STM32 的核心任务是建立一个稳定的“房间”让 FPGA 进来。我们使用 AT 指令初始化 ESP8266。关键配置代码:
void ESP8266_ApTcpServer ( void ) { // 1. 设置为 AP 模式 (让 FPGA 能搜到我) ESP8266_Cmd ( "AT+CWMODE=2", "OK", NULL, 2000 ); // 2. 建立热点 (SSID: STM32_Net, Pass: 12345678) // 这一步至关重要,必须与 FPGA 代码中的暗号完全一致 ESP8266_BuildAP ( "STM32_Net", "12345678", WPA2_PSK ); // 3. 开启多连接 (Server 模式必须开启 MUX=1) ESP8266_Cmd ( "AT+CIPMUX=1", "OK", NULL, 1000 ); // 4. 开启 TCP Server 监听端口 8080 ESP8266_Cmd ( "AT+CIPSERVER=1,8080", "OK", NULL, 1000 ); }第二步:FPGA 端配置 (玩家/客户端)
FPGA 处理字符串解析非常痛苦,因此我们采用了 “盲发状态机 (Blind FSM)” 策略。FPGA 不去判断 ESP8266 回复的 “OK”,而是根据经验时间,按顺序发送指令,强行将模块配置进入 透传模式。
初始化流程 (Verilog):
AT+RST(复位) -> 延时 2秒AT+CWMODE=1(Station模式) -> 延时 0.5秒AT+CWJAP="STM32_Net","12345678"(连接热点) -> 延时 6秒 (等待连接稳定)AT+CIPMUX=0(单连接,透传必须) -> 延时 0.5秒AT+CIPSTART="TCP","192.168.4.1",8080(连接服务器) -> 延时 6秒AT+CIPMODE=1(开启透传功能) -> 延时 0.5秒AT+CIPSEND(开始发送) -> 延时 2秒 -> 进入数据传输状态
数据打包状态机 (Verilog): 一旦初始化完成 ( 置 1),FPGA 切换到业务状态机,按协议发送数据:init_done
// 简单的发送序列 case(pkt_state) PKT_HEAD1: begin uart_data <= 8'hAA; ... end PKT_HEAD2: begin uart_data <= 8'h55; ... end PKT_DATA1: begin uart_data <= sensor_data[15:8]; ... end PKT_DATA2: begin uart_data <= sensor_data[7:0]; ... end ... endcase第三步:STM32 数据解析
当 ESP8266 (Server) 收到数据时,它会通过串口发送 格式的数据给 STM32。我们需要剥离这个头,提取真实数据。+IPD,<ID>,<len>:<data>
// 核心解析逻辑 if ( *pRealData == 0xAA && *(pRealData+1) == 0x55 ) // 检查帧头 { if ( *(pRealData+4) == 0x55 && *(pRealData+5) == 0xAA ) // 检查帧尾 { uint16_t val = (pRealData[2] << 8) | pRealData[3]; // 合并数据 printf("Packet Received! Val = %d\n", val); } }5. 调试中遇到的坑与解决方案(故障排除)
在项目调试过程中,记录如下:
- “无限重启”循环(Power Brownout)
- 现象:FPGA 端的 ESP8266 刚连上 WiFi 就断开,串口不断打印
CLOSED-CONNECT - 原因:ESP8266 发射瞬间电流高达 300mA+,FPGA 开发板 3.3V 供电不足导致模块复位。
- 解决:我用的是龙邱电源模块如图所示,为 ESP8266 提供独立的电源供电,一定要共地线。
- 现象:FPGA 端的 ESP8266 刚连上 WiFi 就断开,串口不断打印
- 指令截断 (String Length)
- 现象:无法建立 TCP 连接。
- 原因:Verilog 中 ROM 存储的 字符串长度计算错误,导致指令没发全(少了端口号)。
AT+CIPSTART - 解决:仔细核对 ASCII 码数量,宁多勿少。
- 连接超时 (Timing)
- 现象:显示连接 WiFi 成功,但无法进入透传。
- 原因:FPGA 发送 太快,此时 TCP 连接还没完全握手建立。
AT+CIPSEND - 解决:将 TCP 连接后的延时从 4 秒增加到 6-8 秒,确保连接稳固后再开启透传。

6. 最终效果 (结果)
经过调试,系统稳定运行。FPGA 将内部的计数器数据打包发送,STM32 串口助手上成功打印出连续递增的数据:

7. 总结
本项目展示了在不使用作系统的情况下,如何通过 Verilog 状态机 实现复杂的网络初始化流程。通过合理的架构设计(STM32 AP + FPGA Transparent Client),我们成功避开了在 FPGA 上处理复杂 AT 指令解析的难题,实现了一条稳定、高速的无线数据通道。
代码如下:
放在github端口了,有需要的自行去取,链接gggggodv1/FPGA_STM32_8266 at master
