FPGA 串口与HC05蓝牙模块通信

server/2025/1/17 14:42:16/

介绍

  关于接线: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;    //模块全局时钟输入,50Minput 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)beginuart_rx_sync1 <= 1'b0;uart_rx_sync2 <= 1'b0;	endelse beginuart_rx_sync1 <= uart_rx;uart_rx_sync2 <= uart_rx_sync1;	end//数据寄存器always@(posedge clk or posedge reset)if(reset)beginuart_rx_reg1 <= 1'b0;uart_rx_reg2 <= 1'b0;	endelse beginuart_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 begincase(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;			endcaseend//counteralways@(posedge clk or posedge reset)if(reset)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;// bps_clk genalways@(posedge clk or posedge reset)if(reset)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;//bps counteralways@(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;elsebps_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;elserx_done <= 1'b0;		always@(posedge clk or posedge reset)if(reset)beginSTART_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;endelse if(bps_clk)begincase(bps_cnt)0:beginSTART_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;			end6 ,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:beginSTART_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;endendcaseendalways@(posedge clk or posedge reset)if(reset)data_byte <= 8'd0;else if(bps_cnt == 8'd159)begindata_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;elseuart_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 ;    //模块全局时钟输入,50Minput 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;elseuart_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;elsedata_byte_reg <= data_byte_reg;always@(posedge clk or posedge reset)if(reset)bps_DR <= 16'd5207;else begincase(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;			endcaseend	//counteralways@(posedge clk or posedge reset)if(reset)div_cnt <= 16'd0;else if(uart_state)beginif(div_cnt == bps_DR)div_cnt <= 16'd0;elsediv_cnt <= div_cnt + 1'b1;endelsediv_cnt <= 16'd0;// bps_clk genalways@(posedge clk or posedge reset)if(reset)bps_clk <= 1'b0;else if(div_cnt == 16'd1)bps_clk <= 1'b1;elsebps_clk <= 1'b0;//bps counteralways@(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;elsebps_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;elsetx_done <= 1'b0;always@(posedge clk or posedge reset)if(reset)uart_tx <= 1'b1;else begincase(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;endcaseend	endmodule
module top(input					clk				,input					reset_n			,input key_in,input					hc05_rx			,input					uart_rx			,output				hc05_tx			,output				uart_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。

可以看到串口接收到蓝牙助手发过来的数据,蓝牙助手也就接收到串口发过来的数据


http://www.ppmy.cn/server/159112.html

相关文章

科研总结系列|2-GPT学术写作提示词集锦手册

科研总结系列&#xff5c;2-GPT学术写作提示词集锦手册 一、前言 随着生成式人工智能&#xff08;如 ChatGPT&#xff09;的迅速发展&#xff0c;学术写作正变得更加智能和高效。高质量的学术论文不仅能够准确传达研究成果&#xff0c;也会在学术圈内带来更广泛的影响力。借助…

Linux安装Docker教程(详解)

如果想要系统学习docker,建议进入官方文档中学习&#xff1a;docker官方文档 一. 基本概念 Docker Desktop 和 Docker Engine 有什么区别&#xff1f; Docker Desktop for Linux 提供用户友好的图形界面&#xff0c;可简化容器和服务的管理。它包括 Docker Engine&#xff0c…

Electron 开发者的 Tauri 2.0 实战指南:文件系统操作

作为 Electron 开发者&#xff0c;我们习惯了使用 Node.js 的 fs 模块来处理文件操作。在 Tauri 2.0 中&#xff0c;文件系统操作被重新设计&#xff0c;采用了 Rust 的安全特性和权限系统。本文将帮助你理解和重构这部分功能。 文件操作对比 Electron 的文件操作 在 Electr…

Self-RAG

Self-RAG&#xff08;Self-Referencing Augmented Generation&#xff09; 是一种结合了 自我增强生成 和 检索增强生成&#xff08;RAG&#xff09;的技术方法。其主要目的是在自然语言生成&#xff08;NLG&#xff09;任务中&#xff0c;利用模型自身生成的信息来增强回答质量…

基于Netty+InfluxDB+MQTT+Spring Boot的物联网(IoT)项目实现方案

基于NettyInfluxDBMQTTSpring Boot的物联网&#xff08;IoT&#xff09;项目实现方案 引言 物联网&#xff08;IoT&#xff09;技术近年来发展迅速&#xff0c;广泛应用于智能城市、工业物联网、农业物联网等领域。本文将详细介绍如何使用Netty、InfluxDB、MQTT和Spring Boot…

LLM(大语言模型)支撑下的传统工作流转型发展为AI工作流

传统工作流 工作流入门这篇就够了 BPMN.JS中文教程 BPMN 工作流引擎解析 AI工作流是指一系列将人工智能技术应用于业务流程的有序步骤&#xff0c;目的是高效地完成特定任务或实现目标。以下是对AI工作流的详细解释&#xff1a; AI工作流 RAGAI工作流Agent&#xff1a;LLM框…

SpringAOP前置——代理模式

代理模式是SpringAOP&#xff08;面向切面编程&#xff09;的底层原理 代理模式的分类 静态代理动态代理 静态代理 角色分析&#xff1a; 抽象角色&#xff1a;一般使用抽象类或接口来解决 代理角色&#xff1a;代理真实角色&#xff0c;在代理真实角色后&#xff0c;一般会…

【深度学习】关键技术-正则化(Regularization)

正则化&#xff08;Regularization&#xff09; 是一种用于防止模型过拟合的技术。它通过在损失函数中添加额外的约束项&#xff0c;限制模型的复杂度&#xff0c;从而提高模型的泛化能力。 正则化的主要作用 防止过拟合&#xff1a;通过抑制模型对训练数据的过度拟合&#xf…