FPGA 串口与HC05蓝牙模块通信
介绍
关于接线:HC-05蓝牙模块一共有6个引脚,但经过我查阅资料以及自己的实操,实际上只需要用到中间的4个引脚即可(即RXD,TXD,GND,VCC)。需要注意的是,蓝牙模块的RXD引脚需要接单片机的TXD引脚,同样,蓝牙模块的TXD引脚需要接单片机的RXD引脚!也就是RXD--TXD,TXD--RXD,VCC--5V,GND--GND(注:HC-05模块的TX对于FPGA来说是 RX)
FPGA代码
//
// Company: 武汉芯路恒科技有限公司
// Engineer: 小梅哥团队
// Web: www.corecourse.cn
//
// Create Date: 2020/07/20 00:00:00
// Design Name: uart_rx
// Module Name: uart_byte_rx
// Project Name: uart_rx
// Description: 串口接收模块
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_byte_rx(
clk,
reset_n,
baud_set,
uart_rx,
data_byte,
rx_done
);
wire reset=~reset_n;
input clk; //模块全局时钟输入,50M
input reset_n; //复位信号输入,低有效
input [2:0]baud_set; //波特率设置
input uart_rx; //串口输入信号
output [7:0]data_byte; //串口接收的1byte数据
output rx_done; //1byte数据接收完成标志
reg [7:0]data_byte;
reg rx_done;
reg uart_rx_sync1; //同步寄存器
reg uart_rx_sync2; //同步寄存器
reg uart_rx_reg1; //数据寄存器
reg uart_rx_reg2; //数据寄存器
reg [15:0]bps_DR; //分频计数最大值
reg [15:0]div_cnt; //分频计数器
reg bps_clk; //波特率时钟
reg [7:0] bps_cnt; //波特率时钟计数器
reg uart_state;//接收数据状态
wire uart_rx_nedge;
reg [2:0]START_BIT;
reg [2:0]STOP_BIT;
reg [2:0]data_byte_pre [7:0];
//同步串行输入信号,消除亚稳态
always@(posedge clk or posedge reset)
if(reset)begin
uart_rx_sync1 <= 1'b0;
uart_rx_sync2 <= 1'b0;
end
else begin
uart_rx_sync1 <= uart_rx;
uart_rx_sync2 <= uart_rx_sync1;
end
//数据寄存器
always@(posedge clk or posedge reset)
if(reset)begin
uart_rx_reg1 <= 1'b0;
uart_rx_reg2 <= 1'b0;
end
else begin
uart_rx_reg1 <= uart_rx_sync2;
uart_rx_reg2 <= uart_rx_reg1;
end
//下降沿检测
assign uart_rx_nedge = !uart_rx_reg1 & uart_rx_reg2;
always@(posedge clk or posedge reset)
if(reset)
bps_DR <= 16'd324;
else begin
case(baud_set)
0:bps_DR <= 16'd324;
1:bps_DR <= 16'd162;
2:bps_DR <= 16'd80;
3:bps_DR <= 16'd53;
4:bps_DR <= 16'd26;
default:bps_DR <= 16'd324;
endcase
end
//counter
always@(posedge clk or posedge reset)
if(reset)
div_cnt <= 16'd0;
else if(uart_state)begin
if(div_cnt == bps_DR)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 16'd0;
// bps_clk gen
always@(posedge clk or posedge reset)
if(reset)
bps_clk <= 1'b0;
else if(div_cnt == 16'd1)
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
//bps counter
always@(posedge clk or posedge reset)
if(reset)
bps_cnt <= 8'd0;
else if(bps_cnt == 8'd159 | (bps_cnt == 8'd12 && (START_BIT > 2)))
bps_cnt <= 8'd0;
else if(bps_clk)
bps_cnt <= bps_cnt + 1'b1;
else
bps_cnt <= bps_cnt;
always@(posedge clk or posedge reset)
if(reset)
rx_done <= 1'b0;
else if(bps_cnt == 8'd159)
rx_done <= 1'b1;
else
rx_done <= 1'b0;
always@(posedge clk or posedge reset)
if(reset)begin
START_BIT <= 3'd0;
data_byte_pre[0] <= 3'd0;
data_byte_pre[1] <= 3'd0;
data_byte_pre[2] <= 3'd0;
data_byte_pre[3] <= 3'd0;
data_byte_pre[4] <= 3'd0;
data_byte_pre[5] <= 3'd0;
data_byte_pre[6] <= 3'd0;
data_byte_pre[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
else if(bps_clk)begin
case(bps_cnt)
0:begin
START_BIT <= 3'd0;
data_byte_pre[0] <= 3'd0;
data_byte_pre[1] <= 3'd0;
data_byte_pre[2] <= 3'd0;
data_byte_pre[3] <= 3'd0;
data_byte_pre[4] <= 3'd0;
data_byte_pre[5] <= 3'd0;
data_byte_pre[6] <= 3'd0;
data_byte_pre[7] <= 3'd0;
STOP_BIT <= 3'd0;
end
6 ,7 ,8 ,9 ,10,11:START_BIT <= START_BIT + uart_rx_sync2;
22,23,24,25,26,27:data_byte_pre[0] <= data_byte_pre[0] + uart_rx_sync2;
38,39,40,41,42,43:data_byte_pre[1] <= data_byte_pre[1] + uart_rx_sync2;
54,55,56,57,58,59:data_byte_pre[2] <= data_byte_pre[2] + uart_rx_sync2;
70,71,72,73,74,75:data_byte_pre[3] <= data_byte_pre[3] + uart_rx_sync2;
86,87,88,89,90,91:data_byte_pre[4] <= data_byte_pre[4] + uart_rx_sync2;
102,103,104,105,106,107:data_byte_pre[5] <= data_byte_pre[5] + uart_rx_sync2;
118,119,120,121,122,123:data_byte_pre[6] <= data_byte_pre[6] + uart_rx_sync2;
134,135,136,137,138,139:data_byte_pre[7] <= data_byte_pre[7] + uart_rx_sync2;
150,151,152,153,154,155:STOP_BIT <= STOP_BIT + uart_rx_sync2;
default:
begin
START_BIT <= START_BIT;
data_byte_pre[0] <= data_byte_pre[0];
data_byte_pre[1] <= data_byte_pre[1];
data_byte_pre[2] <= data_byte_pre[2];
data_byte_pre[3] <= data_byte_pre[3];
data_byte_pre[4] <= data_byte_pre[4];
data_byte_pre[5] <= data_byte_pre[5];
data_byte_pre[6] <= data_byte_pre[6];
data_byte_pre[7] <= data_byte_pre[7];
STOP_BIT <= STOP_BIT;
end
endcase
end
always@(posedge clk or posedge reset)
if(reset)
data_byte <= 8'd0;
else if(bps_cnt == 8'd159)begin
data_byte[0] <= data_byte_pre[0][2];
data_byte[1] <= data_byte_pre[1][2];
data_byte[2] <= data_byte_pre[2][2];
data_byte[3] <= data_byte_pre[3][2];
data_byte[4] <= data_byte_pre[4][2];
data_byte[5] <= data_byte_pre[5][2];
data_byte[6] <= data_byte_pre[6][2];
data_byte[7] <= data_byte_pre[7][2];
end
always@(posedge clk or posedge reset)
if(reset)
uart_state <= 1'b0;
else if(uart_rx_nedge)
uart_state <= 1'b1;
else if(rx_done || (bps_cnt == 8'd12 && (START_BIT > 2)) || (bps_cnt == 8'd155 && (STOP_BIT < 3)))
uart_state <= 1'b0;
else
uart_state <= uart_state;
endmodule
//
// Company: 武汉芯路恒科技有限公司
// Engineer: 小梅哥团队
// Web: www.corecourse.cn
//
// Create Date: 2020/07/20 00:00:00
// Design Name: uart_tx
// Module Name: uart_byte_tx
// Project Name: uart_tx
// Description: 串口发送模块
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module uart_byte_tx(
clk,
reset_n,
data_byte,
send_en,
baud_set,
uart_tx,
tx_done,
uart_state
);
input clk ; //模块全局时钟输入,50M
input reset_n; //复位信号输入,低有效
input [7:0]data_byte; //待传输8bit数据
input send_en; //发送使能
input [2:0]baud_set; //波特率设置
output reg uart_tx; //串口输出信号
output reg tx_done; //1byte数据发送完成标志
output reg uart_state; //发送数据状态
wire reset=~reset_n;
localparam START_BIT = 1'b0;
localparam STOP_BIT = 1'b1;
reg bps_clk; //波特率时钟
reg [15:0]div_cnt; //分频计数器
reg [15:0]bps_DR; //分频计数最大值
reg [3:0]bps_cnt; //波特率时钟计数器
reg [7:0]data_byte_reg;//data_byte寄存后数据
always@(posedge clk or posedge reset)
if(reset)
uart_state <= 1'b0;
else if(send_en)
uart_state <= 1'b1;
else if(bps_cnt == 4'd11)
uart_state <= 1'b0;
else
uart_state <= uart_state;
always@(posedge clk or posedge reset)
if(reset)
data_byte_reg <= 8'd0;
else if(send_en)
data_byte_reg <= data_byte;
else
data_byte_reg <= data_byte_reg;
always@(posedge clk or posedge reset)
if(reset)
bps_DR <= 16'd5207;
else begin
case(baud_set)
0:bps_DR <= 16'd5207;
1:bps_DR <= 16'd2603;
2:bps_DR <= 16'd1301;
3:bps_DR <= 16'd867;
4:bps_DR <= 16'd433;
default:bps_DR <= 16'd5207;
endcase
end
//counter
always@(posedge clk or posedge reset)
if(reset)
div_cnt <= 16'd0;
else if(uart_state)begin
if(div_cnt == bps_DR)
div_cnt <= 16'd0;
else
div_cnt <= div_cnt + 1'b1;
end
else
div_cnt <= 16'd0;
// bps_clk gen
always@(posedge clk or posedge reset)
if(reset)
bps_clk <= 1'b0;
else if(div_cnt == 16'd1)
bps_clk <= 1'b1;
else
bps_clk <= 1'b0;
//bps counter
always@(posedge clk or posedge reset)
if(reset)
bps_cnt <= 4'd0;
else if(bps_cnt == 4'd11)
bps_cnt <= 4'd0;
else if(bps_clk)
bps_cnt <= bps_cnt + 1'b1;
else
bps_cnt <= bps_cnt;
always@(posedge clk or posedge reset)
if(reset)
tx_done <= 1'b0;
else if(bps_cnt == 4'd11)
tx_done <= 1'b1;
else
tx_done <= 1'b0;
always@(posedge clk or posedge reset)
if(reset)
uart_tx <= 1'b1;
else begin
case(bps_cnt)
0:uart_tx <= 1'b1;
1:uart_tx <= START_BIT;
2:uart_tx <= data_byte_reg[0];
3:uart_tx <= data_byte_reg[1];
4:uart_tx <= data_byte_reg[2];
5:uart_tx <= data_byte_reg[3];
6:uart_tx <= data_byte_reg[4];
7:uart_tx <= data_byte_reg[5];
8:uart_tx <= data_byte_reg[6];
9:uart_tx <= data_byte_reg[7];
10:uart_tx <= STOP_BIT;
default:uart_tx <= 1'b1;
endcase
end
endmodule
module top(
inputclk,
inputreset_n,
input key_in,
inputhc05_rx,
inputuart_rx,
outputhc05_tx,
outputuart_tx
);
wire [7:0]data;
wire [7:0]rx_data;
reg send_en;
wire key_flag;
wire key_state;
key_filter key_filter(
.clk(clk),
.reset_n(reset_n),
.key_in(key_in),
.key_flag(key_flag),
.key_state(key_state)
);
always @ (posedge clk or negedge reset_n)
if (!reset_n)
send_en <= 0;
else if (key_flag && (!key_state))
send_en <= ~send_en;
else
send_en <= 0;
uart_byte_tx tx_inst_hc05(
.clk(clk),
.reset_n(reset_n),
.data_byte(data),
.send_en(send_en),
.baud_set(0),
.uart_tx(hc05_tx),
.tx_done(),
.uart_state ()
);
uart_byte_tx tx_inst_uart(
.clk(clk),
.reset_n(reset_n),
.data_byte(rx_data),
.send_en(send_en),
.baud_set(0),
.uart_tx(uart_tx),
.tx_done(),
.uart_state ()
);
uart_byte_rx rx_inst_hc05(
.clk(clk),
.reset_n(reset_n),
.baud_set(0),
.uart_rx(hc05_rx),
.data_byte(rx_data),
.rx_done()
);
uart_byte_rx rx_inst_uart(
.clk(clk),
.reset_n(reset_n),
.baud_set(0),
.uart_rx(uart_rx),
.data_byte(data),
.rx_done()
);
endmodule
实验现象
通过蓝牙助手发送了一个16进制的数据66.
同时通过串口助手发送了一个16进制的数据55。接着按下按键S0。
可以看到串口接收到蓝牙助手发过来的数据,蓝牙助手也就接收到串口发过来的数据
原文地址:https://blog.csdn.net/weixin_62953178/article/details/145166970
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!