FPGA实现ESP8266驱动且进行数据包收发

一. 简介

本次将使用正点原子的ESP8266 WIFI模块,来实现PC与FPGA之间的TCP通讯,其中ESP8266与FPGA之间的接口是UART。

二. 正点原子的ESP8266 WIFI模块介绍

模块实物图如下,到手就可以使用了,RST和IO_0两个IO口不接或者接高电平就可以了。

请添加图片描述

在使用之前,需要通过AT指令对模块进行配置,比如说是AP模式,还是STA模式。AP模式就是模块作为无线 WIFI 热点,允许其他 WIFI 设备连接到本模块;STA模式就是连接到其它的WIFI设备。具体的指令可以在正点原子论坛上下载。

三. ESP8266初始化

本次是将ESP8266配置成AP模式,充当TCP服务器,配置的AT指令如下(每个指令末尾均带有换行)。FPGA端只需要通过串口将这些AT指令依次发送出去即可完成配置。

请添加图片描述

先将这些指令的数据存储到memory中,就像下面这样。

reg[7:0]    rom0[14:0];
reg[7:0]    rom1[10:0];
reg[7:0]    rom2[43:0];
reg[7:0]    rom3[15:0];
reg[7:0]    rom4[44:0];

always@(*)begin
    rom0[0] = "A";
    rom0[1] = "T";
    rom0[2] = "+";
    rom0[3] = "C";
    rom0[4] = "W";
    rom0[5] = "M";
    rom0[6] = "O";
    rom0[7] = "D";
    rom0[8] = "E";
    rom0[9] = "=";
    rom0[10] = "2";
    rom0[11] = 8'h0D;
    rom0[12] = 8'h0A;
end

然后再初始化模块中依次发送出去即可,需要注意的是,每个指令的发送需要间隔一定的时间,因为ESP8266每接收到一个指令会返回一个应答(通常是OK),不等待的话,可能会导致下条指令接收错误。

全部发送完成后,模块会跳到S7状态,向外部发送初始化完成信号。

localparam S0 = 'd0;   //IDLE
localparam S1 = 'd1;   //AT + CWMODE = 2
localparam S2 = 'd2;   //AT + RST
localparam S3 = 'd3;   //AT + CWSP="ATK-ESP8266","12345678",1,4
localparam S4 = 'd4;   //AT + CIPMUX = 1
localparam S5 = 'd5;   //AT+CIPSERVER=1,8086
localparam S6 = 'd6;   //wait 10ms
localparam S7 = 'd7;   //ack

四. 发送数据

由于ESP8266配置的模式不支持透传模式,所以每次发送数据的时候,需要发送一个发送的AT指令,如下。这条AT指令发送完成后,也不能立马发送数据,需要等ESP8266做出响应后才能。这里发送数据的时候,不需要带换行。ID0: 第一个连接到tcp服务器的客户端。

请添加图片描述

五. 数据接收

当ESP8266模块,接收到数据的时候,会做出如下的响应。其中4是第四个连接到tcp服务器的客户端。
请添加图片描述

在接收数据的时候,需要先解析前面的+IPD,4,n: 这些字符。解析正确后,就将后面接收到的n字节数据作为有效数据。

//检测头部序列 是否正确
always@(posedge clk or negedge rst_n) begin
    if( rst_n == 1'b0 )
        head_index <= 'd0;
    else if( state == S_HEAD )
        if( head_index == 'd0 && esp8266_rx_done_i == 1'b1 )
            if( esp8266_rx_data_i == "+" )
                head_index <= head_index + 1'b1;
            else
                head_index <= 'd0;
        else if( head_index == 'd1 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "I" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd2 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "P" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd3 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "D" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd4 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "," )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd5 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "0" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd6 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "," )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd7 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "1" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd8 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == "6" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else if( head_index == 'd9 && esp8266_rx_done_i == 1'b1)
            if( esp8266_rx_data_i == ":" )
                head_index <= head_index + 1'b1;
            else if( esp8266_rx_data_i == "+" )
                head_index <=  'd1;
            else
                head_index <= 'd0;
        else
            head_index <= head_index;
    else
        head_index <= 'd0;
end

六. 整体设计

本次的设计主要是为了完成如下数据包格式的收发,所以设计不仅仅是单纯的收发,还包括数据包的整合和解析。有相同需求的,可以参考参考。

请添加图片描述

整个设计模块的层次图如下(高云的EDA软件RTL图有点拉胯)

请添加图片描述

关注微信公众号 FPGA之旅 回复 FPGA_ESP8266 获取完整工程。

猜你喜欢

转载自blog.csdn.net/weixin_44678052/article/details/130904940