FPGA——ESP8266发送0、1实验

一、实验内容。

定义两个串口,分别接收两个按键输入0、1,或接收PC发送的AT指令,两个输入,通过按键切换输入到esp8266,从而完成WiFi连接、TCP服务器连接、以及数据0、1发送。

二、系统架构。

整体架构

三、RTL视图

在这里插入图片描述

四、项目代码。

uart_tx.v串口发送模块

// uart_tx.v
`include "param.v"
module uart_tx(
	input wire 			clk	,
	input wire 			rst_n	,
	input wire 			tx_req,//发送请求
	input wire [7:0] 	tx_din,//并行数据输入
	
	output reg        tx_dout,//串行数据输出
	output wire       dout_vld//并转串完成标志
	

);
reg [12:0] cnt_bps		;//波特率计数寄存器	
wire       add_cnt_bps	;//波特率计数开始
wire       end_cnt_bps  ;//波特率计数结束

reg [3:0]  cnt_bit      ;//比特计数寄存器
wire       add_cnt_bit  ;//比特计数开始
wire       end_cnt_bit  ;//比特计数结束

reg        tx_flag      ;//发送标志

reg [9:0]  tx_data      ;

//波特率计数器设计
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bps <= 13'd0;
	end 
	else if(add_cnt_bps)begin
		if(end_cnt_bps)begin
			cnt_bps <= 13'd0;
		end 
		else begin
			cnt_bps <= cnt_bps + 1'd1;
		end 
	end 
	else begin
		cnt_bps <= cnt_bps;
	end 
end 

assign add_cnt_bps = tx_flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == (`SYS_FRQ/`BAUD_MAX) - 1'd1;

always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bit <= 4'd0;
	end 
	else if(add_cnt_bit)begin
		if(end_cnt_bit)begin
			cnt_bit <= 4'd0;
		end 
		else begin
			cnt_bit <= cnt_bit + 1'd1;
		end 
	end 
	else begin
		cnt_bit <= cnt_bit;
	end 
end 

assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 9;

//发送标志tx_flag
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_flag <= 1'b0;
	end 
	else if(tx_req)begin
		tx_flag <= 1'b1;
	end 
	else if(end_cnt_bit)begin
		tx_flag <= 1'b0;
	end 
	else begin
		tx_flag <= tx_flag;
	end 
end 


//数据缓存,tx_data
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_data <= 10'b0;
	end 
	else if(tx_req)begin
		tx_data <= {1'b1, tx_din, 1'b0};
	end
	else begin
		tx_data <= tx_data;
	end 
end 

//tx_dout数据串行输出
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_dout <= 1'b1;
	end 
	else if(tx_flag && cnt_bps == 1)begin
		tx_dout <= tx_data[cnt_bit];
	end 
	else begin
		tx_dout <= tx_dout;
	end 
end 

//dout_vld约束
assign dout_vld = ~tx_flag;

endmodule 

uart_rx.v串口接收模块

`include "param.v"
module uart_rx(
	input wire 			clk		,
	input wire 			rst_n		,
	input wire 			rx_din	,//串行数据输入
	
	output wire [7:0] rx_dout	,//并行数据输出
	output reg 		   dout_vld//串转并完成标志
);

reg [12:0] cnt_bps		;//波特率计数寄存器
wire       add_cnt_bps	;//波特率计数开始
wire       end_cnt_bps	;//波特率计数结束

reg [3:0]  cnt_bit      ;//比特计数寄存器
wire       add_cnt_bit  ;//比特计数开始
wire       end_cnt_bit  ;//比特计数结束

reg 			rx_din_r0;//同步
reg 			rx_din_r1;//打拍
wire     	nedge		;//下降沿

reg      	rx_flag;//接受标志

reg [9:0] 	rx_data;//寄存数据包


//波特率计数器设计
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bps <= 13'd0;
	end 
	else if(add_cnt_bps)begin
		if(end_cnt_bps)begin
			cnt_bps <= 13'd0;
		end 
		else begin
			cnt_bps <= cnt_bps + 1'd1;
		end 
	end 
	else begin
		cnt_bps <= cnt_bps;
	end 
end 

assign add_cnt_bps = rx_flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == (`SYS_FRQ / `BAUD_MAX) - 1'd1;

//比特计数器设计
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bit <= 4'd0;
	end 
	else if(add_cnt_bit)begin
		if(end_cnt_bit)begin
			cnt_bit <= 4'd0;
		end
		else begin
			cnt_bit <= cnt_bit + 1'd1;
		end 
	end 
	else begin
		cnt_bit <= cnt_bit;
	end 
end 

assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 4'd10 - 1'd1;

//起始位位置检测
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		rx_din_r0 <= 1'b1;
		rx_din_r1 <= 1'b1;
	end 
	else begin
		rx_din_r0 <= rx_din;
		rx_din_r1 <= rx_din_r0;
	end 
end 

assign nedge = ~rx_din_r0 && rx_din_r1;

//接受标志rx_flag约束
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		rx_flag <= 1'b0;
	end 
	else if(nedge)begin
		rx_flag <= 1'b1;
	end 
	else if(end_cnt_bit)begin
		rx_flag <= 1'b0;
	end
	else begin
		rx_flag <= rx_flag;
	end 

end 

//缓存接受到的数据
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		rx_data <= 10'b0;
	end 
	else if(rx_flag && cnt_bps == (`SYS_FRQ/`BAUD_MAX) >> 1)begin
		rx_data[cnt_bit] = rx_din_r0;
	end 
	else begin
		rx_data <= rx_data;
	end 

end 

assign rx_dout = rx_data[8:1];

//串转并完成标志dout_vld约束
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		dout_vld <= 1'b0;
	end 
	else if(end_cnt_bit)begin
		dout_vld <= 1'b1;
	end 
	else begin
		dout_vld <= 1'b0;
	end 
end 

endmodule 

param.v波特率常量定义

`define SYS_FRQ 50_000_000
`define BAUD_115200

`ifdef BAUD_9600
	`define BAUD_MAX 9600
`elsif BAUD_19200
	`define BAUD_MAX 19200
`elsif BAUD_38400
	`define BAUD_MAX 38400
`elsif BAUD_57600
	`define BAUD_MAX 57600
`elsif BAUD_115200
	`define BAUD_MAX 115200
`else
	`define BAUD_MAX 9600
`endif
	

key_debounce.v按键消抖模块

module key_debounce(
    input clk,
    input rst_n,
    input key,

    output reg temp
);

parameter DELAY = 20'd1000_000;


reg [19:0] delay_cnt;
reg key_reg;//保存上一时刻的键值
reg flag,key_value;

always @(posedge clk or negedge rst_n) begin
    if(!rst_n)begin
        delay_cnt <= 20'd0;
        key_reg   <= 1'b1;
    end
    else begin
        key_reg <= key;
        if(key_reg != key)begin
            delay_cnt <= DELAY;
        end
        else begin
            if(delay_cnt > 20'd0)begin
                delay_cnt <= delay_cnt - 1'd1;
            end
            else begin
                delay_cnt <= 20'd0;
            end
        end
    end
end

always @(posedge clk or negedge rst_n) begin
   if(!rst_n)begin
    flag <= 1'b0;
    key_value <= 1'b1;
   end
   else if(delay_cnt == 1'd1)begin
    flag      <= 1'b1;
    key_value <= key;
   end
   else begin
    flag <= 1'b0;
    key_value <= key_value;
   end
end

always @(posedge clk or negedge rst_n) begin
	if(!rst_n)begin
		temp <= 1'b0;
	end
	else begin
		if(flag&&~key_value)begin
			temp <= 1'b1;
		end
		else
			temp <= 1'b0;
	end
end	
endmodule 

date_send.v数据发送模块

`include "param.v"
module date_send(
	input wire 			clk	,
	input wire 			rst_n	,
	input wire	[1:0]	key,
	output reg          tx_dout//串行数据输出
);
reg 		tx_req;//发送请求
reg [7:0] 	tx_din;//并行数据输入
reg [12:0] cnt_bps		;//波特率计数寄存器	
wire       add_cnt_bps	;//波特率计数开始
wire       end_cnt_bps  ;//波特率计数结束

reg [3:0]  cnt_bit      ;//比特计数寄存器
wire       add_cnt_bit  ;//比特计数开始
wire       end_cnt_bit  ;//比特计数结束

reg        tx_flag      ;//发送标志

reg [9:0]  tx_data      ;

always @(posedge clk or negedge rst_n)begin 
	if(!rst_n)begin
		tx_req <= 0;
		tx_din <= 0;
	end 
	else if(key[0]&&!key[1])begin 
		tx_req <= 1;
		tx_din <= 8'd48;
	end 
	else if(key[1]&&!key[0])begin 
		tx_req <= 1;
		tx_din <= 8'd49;
	end 
	else begin 
		tx_req <= 0;
	end 
end

//波特率计数器设计
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bps <= 13'd0;
	end 
	else if(add_cnt_bps)begin
		if(end_cnt_bps)begin
			cnt_bps <= 13'd0;
		end 
		else begin
			cnt_bps <= cnt_bps + 1'd1;
		end 
	end 
	else begin
		cnt_bps <= cnt_bps;
	end 
end 

assign add_cnt_bps = tx_flag;
assign end_cnt_bps = add_cnt_bps && cnt_bps == (`SYS_FRQ/`BAUD_MAX) - 1'd1;

always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		cnt_bit <= 4'd0;
	end 
	else if(add_cnt_bit)begin
		if(end_cnt_bit)begin
			cnt_bit <= 4'd0;
		end 
		else begin
			cnt_bit <= cnt_bit + 1'd1;
		end 
	end 
	else begin
		cnt_bit <= cnt_bit;
	end 
end 

assign add_cnt_bit = end_cnt_bps;
assign end_cnt_bit = add_cnt_bit && cnt_bit == 9;

//发送标志tx_flag
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_flag <= 1'b0;
	end 
	else if(tx_req)begin
		tx_flag <= 1'b1;
	end 
	else if(end_cnt_bit)begin
		tx_flag <= 1'b0;
	end 
	else begin
		tx_flag <= tx_flag;
	end 
end 


//数据缓存,tx_data
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_data <= 10'b0;
	end 
	else if(tx_req)begin
		tx_data <= {1'b1, tx_din, 1'b0};
	end
	else begin
		tx_data <= tx_data;
	end 
end 

//tx_dout数据串行输出
always @(posedge clk or negedge rst_n)begin
	if(!rst_n)begin
		tx_dout <= 1'b1;
	end 
	else if(tx_flag && cnt_bps == 1)begin
		tx_dout <= tx_data[cnt_bit];
	end 
	else begin
		tx_dout <= tx_dout;
	end 
end 

//dout_vld约束
assign dout_vld = ~tx_flag;

endmodule 

uart.v顶层模块

module uart(
	input wire 	clk	,
	input wire 	rst_n	,
	input	[2:0]	key	,
	input wire 	rx_esp,
	output wire tx_esp,     //串行输出
	input wire 	rx_pc,
	output wire tx_pc     //串行输出	
	);

wire [7:0] rx_byte		;
wire       rx_byte_vld	;
wire [7:0] rx_byte1		;
wire       rx_byte_vld1	;
wire [2:0] temp			;
wire	   tx_AT	 	;
wire	   tx_data	 	;

reg		en;
assign tx_esp=en==1?tx_AT:tx_data;

always @(posedge clk or negedge rst_n)begin 
	if(!rst_n)begin
		en <= 0;
	end 
	else if(temp[0])begin 
		en <= ~en;
	end 
	else begin 
		en <= en;
	end 
end
key_debounce(
.clk(clk),
.rst_n(rst_n),
.key(key[0]),

.temp(temp[0])
);


key_debounce(
.clk(clk),
.rst_n(rst_n),
.key(key[1]),

.temp(temp[1])
);


key_debounce(
.clk(clk),
.rst_n(rst_n),
.key(key[2]),

.temp(temp[2])
);

uart_rx u_uart_rx(
.clk		(clk),
.rst_n	(rst_n),
.rx_din	(rx_pc),//串行数据输入
	
.rx_dout	(rx_byte),//并行数据输出
.dout_vld(rx_byte_vld)//串转并完成标志
);


uart_rx u_uart_rx1(
.clk		(clk),
.rst_n	(rst_n),
.rx_din	(rx_esp),//串行数据输入
	
.rx_dout	(rx_byte1),//并行数据输出
.dout_vld(rx_byte_vld1)//串转并完成标志
);


uart_tx u_uart_tx(
.clk	(clk),
.rst_n	(rst_n),
.tx_req(rx_byte_vld),//发送请求
.tx_din(rx_byte),//并行数据输入
	
.tx_dout(tx_AT)//串行数据输出
//.dout_vld()//并转串完成标志
	

);

date_send u_date_send(
.clk	(clk),
.rst_n	(rst_n),
.key	(temp[2:1]),	
.tx_dout(tx_data)//串行数据输出	

);

uart_tx u_uart_tx1(
.clk	(clk),
.rst_n	(rst_n),
.tx_req(rx_byte_vld1),//发送请求
.tx_din(rx_byte1),//并行数据输入
	
.tx_dout(tx_pc)//串行数据输出
//.dout_vld()//并转串完成标志
	

);
endmodule 

五、具体操作及运行结果。

1.按照管教分配连接ESP8266.
2.连接WiFi
按下key1,将串口tx端切换到PC,此时可接收来自串口调试助手的数据。
在串口调试助手中选择开发板端口,并打开串口。
在这里插入图片描述
输入 AT+RST 重启ESP8266模块。
输入 AT+CWMODE=1 将模块设置为Station模式。(可能会因编码原因返回乱码)
输入 AT+CWJAP=“SSID”,“PWD” 该命令为连接路由器发出的WiFi信号,SSID为此WiFi的用户名,PWD为此PWD的密码。如果返回乱码,可在路由器后台,或电脑热点设置中查看是否连接成功。
在这里插入图片描述
在热点设置中查看到,esp8266连接成功。
在这里插入图片描述
3.创建TCP服务器
打开Socket tool,并创建端口为6666的TCP服务器。
在这里插入图片描述
打开串口调试助手,输入并发送指令:
AT+CIPSTART=“TCP”,“172.16.103.242”,6666(此处可根据自己实际情况修改ip及端口)
在这里插入图片描述
4.发送数据
输入 AT+CIPMODE=1 打开透传模式。
输入 AT+CIPSEND 设置发送数据长度。(AT+CIPSEND=14(等于符号后的数字代表发送数据的长度,此处我们暂不设置数字长度))
按下key1切换输入为按键输入。
按下key2、key3分别发送0、1至TCP服务器。
在这里插入图片描述

六、总结。

本实验主要就是理解串口各个端口的作用,以及串口发送单个字符。

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值