Spartan6固定波特率读取JY901P的内容在以下链接:固定波特率读取惯导
这个版本增加了上电自动扫描波特率功能,以及实现修改波特率的功能。
其中JY901P_writer.v,JY901P_reader.v,JY901P_top.v代码并没有任何改变,只修改了JY901P_uart_top.v,uart_send_dynamic.v,uart_receive_dynamic.v

1. JY901P_uart_top.v
上电后 FPGA 会自动按顺序轮询常见波特率(4800~230400),每个波特率尝试一段时间,直到成功解析到 JY901P 的有效数据帧。
一旦正确接收到一帧数据,立即停止扫描,锁定当前波特率进入正常工作模式,保证后续通信稳定。
当发送波特率修改或恢复出厂指令后,状态机会自动回到扫描模式,重新适配新的波特率
cpp
`timescale 1ns / 1ps
module JY901P_Uart_top
(
input clk ,
input rst_n ,
// 串口物理接口
input uart_rxd ,
output uart_txd ,
// JY901指令配置接口
input send_cmd_en ,
input [7:0] cmd_addr ,
input [15:0] cmd_data ,
// JY901解析数据输出
output [15:0] acc_x ,
output [15:0] acc_y ,
output [15:0] acc_z ,
output [15:0] gyro_x ,
output [15:0] gyro_y ,
output [15:0] gyro_z ,
output [15:0] angle_x ,
output [15:0] angle_y ,
output [15:0] angle_z ,
output [15:0] mag_x ,
output [15:0] mag_y ,
output [15:0] mag_z ,
output [63:0] JY901P_data_out ,
output frame_valid
);
// 波特率定义
localparam BAUD_4800 = 32'd4800;
localparam BAUD_9600 = 32'd9600;
localparam BAUD_19200 = 32'd19200;
localparam BAUD_38400 = 32'd38400;
localparam BAUD_57600 = 32'd57600;
localparam BAUD_115200 = 32'd115200;
localparam BAUD_230400 = 32'd230400;
localparam SCAN_TIMEOUT = 32'd30_000_000; // 600ms扫描超时
localparam BAUD_REG_ADDR = 8'h04; // JY901P波特率寄存器地址
localparam RESET_REG_ADDR = 8'h00; //恢复出厂设置
// 状态定义
localparam S_IDLE = 3'd0;
localparam S_SCAN_BAUD = 3'd1;
localparam S_BAUD_LOCK = 3'd2;
localparam S_CHANGE_BAUD = 3'd3;
localparam S_RESET = 3'd4;
// 内部寄存器
reg [2:0] baud_scan_idx;
reg [31:0] scan_timer;
reg [31:0] current_baud;
reg [2:0] state;
reg baud_lock_flag;
reg [15:0] baud_cnt_max;
wire cmd_send_done; // JY901P_top输出的命令完成标志
reg cmd_send_done_d1; // 打拍消抖
// 补充所有缺失的连线(尤其是uart_tx_done)
wire uart_tx_done; // UART单字节发送完成
wire [7:0] uart_rx_data;
wire uart_rx_flag;
wire [7:0] uart_tx_data;
wire uart_tx_flag;
wire frame_valid_int;
// ===================== 主状态机=====================
always @(posedge clk or negedge rst_n) begin
if(!rst_n) begin
state <= S_IDLE;
baud_scan_idx <= 3'd0;
scan_timer <= 32'd0;
current_baud <= BAUD_9600;
baud_lock_flag <= 1'b0;
baud_cnt_max <= (50_000_000 / BAUD_9600) - 1;
cmd_send_done_d1<= 1'b0;
end else begin
cmd_send_done_d1 <= cmd_send_done;
case(state)
S_IDLE: begin
state <= S_SCAN_BAUD;
baud_scan_idx <= 3'd0;
scan_timer <= 32'd0;
baud_lock_flag <= 1'b0;
end
S_SCAN_BAUD: begin
case(baud_scan_idx)
3'd0: begin current_baud <= BAUD_4800; baud_cnt_max <= (50_000_000 / BAUD_4800) - 1; end
3'd1: begin current_baud <= BAUD_9600; baud_cnt_max <= (50_000_000 / BAUD_9600) - 1; end
3'd2: begin current_baud <= BAUD_19200; baud_cnt_max <= (50_000_000 / BAUD_19200) - 1; end
3'd3: begin current_baud <= BAUD_38400; baud_cnt_max <= (50_000_000 / BAUD_38400) - 1; end
3'd4: begin current_baud <= BAUD_57600; baud_cnt_max <= (50_000_000 / BAUD_57600) - 1; end
3'd5: begin current_baud <= BAUD_115200; baud_cnt_max <= (50_000_000 / BAUD_115200) - 1; end
3'd6: begin current_baud <= BAUD_230400; baud_cnt_max <= (50_000_000 / BAUD_230400) - 1; end
default:begin current_baud <= BAUD_9600; baud_cnt_max <= (50_000_000 / BAUD_9600) - 1; end
endcase
if(scan_timer >= SCAN_TIMEOUT) begin
scan_timer <= 32'd0;
baud_scan_idx <= baud_scan_idx + 1'b1;
if(baud_scan_idx >= 3'd6) begin
baud_lock_flag <= 1'b1;
state <= S_BAUD_LOCK;
end
end else begin
scan_timer <= scan_timer + 1'b1;
// 收到有效帧立即锁定波特率
if(frame_valid_int) begin
baud_lock_flag <= 1'b1;
state <= S_BAUD_LOCK;
scan_timer <= 32'd0;
end
end
end
S_BAUD_LOCK: begin
if(send_cmd_en && (cmd_addr == BAUD_REG_ADDR)) begin
state <= S_CHANGE_BAUD;
end
// 恢复出厂设置命令
else if(send_cmd_en && (cmd_addr == RESET_REG_ADDR) && (cmd_data[15:8] == 8'h00)) begin
state <= S_RESET;
end
end
S_CHANGE_BAUD: begin
// 波特率命令发送完成(上升沿触发)
if(cmd_send_done && !cmd_send_done_d1) begin
state <= S_IDLE;
end
end
S_RESET: begin
// 命令发送完成(上升沿触发)
if(cmd_send_done && !cmd_send_done_d1) begin
// 跳回IDLE,触发重新扫描新波特率
state <= S_IDLE;
end
end
default: state <= S_IDLE;
endcase
end
end
// ===================== 模块例化 =====================
uart_recceive_dynamic
#(
.CLK_FREQ(50000000)
)
uart_RX
(
.clk (clk),
.sys_rst_n (rst_n),
.baud_cnt_max (baud_cnt_max),
.rx (uart_rxd),
.po_data (uart_rx_data),
.po_flag (uart_rx_flag)
);
JY901P_top
#(
.CLK_FREQ(50000000)
)
JY901P_top_inst
(
.clk (clk),
.rst_n (rst_n),
.uart_rx_data (uart_rx_data),
.uart_rx_flag (uart_rx_flag),
.uart_tx_data (uart_tx_data),
.uart_tx_flag (uart_tx_flag),
.uart_tx_done (uart_tx_done),
.send_cmd_en (send_cmd_en),
.cmd_addr (cmd_addr),
.cmd_data (cmd_data),
.cmd_send_done (cmd_send_done),
.acc_x (acc_x),
.acc_y (acc_y),
.acc_z (acc_z),
.gyro_x (gyro_x),
.gyro_y (gyro_y),
.gyro_z (gyro_z),
.angle_x (angle_x),
.angle_y (angle_y),
.angle_z (angle_z),
.mag_x (mag_x),
.mag_y (mag_y),
.mag_z (mag_z),
.JY901P_data_out(JY901P_data_out),
.frame_valid (frame_valid_int)
);
uart_send_dynamic
#(
.CLK_FREQ(50000000)
)
uart_TX
(
.clk (clk),
.sys_rst_n (rst_n),
.baud_cnt_max (baud_cnt_max),
.pi_data (uart_tx_data),
.pi_flag (uart_tx_flag),
.tx (uart_txd),
.tx_done (uart_tx_done)
);
// 有效帧输出(波特率锁定+帧接收完成)
assign frame_valid = frame_valid_int & baud_lock_flag;
endmodule
2. uart_send_dynamic.v
新增输入端口:baud_cnt_max
cpp
`timescale 1ns / 1ps
module uart_send_dynamic
#(
parameter CLK_FREQ = 50000000
)
(
input clk ,
input sys_rst_n ,
input [15:0] baud_cnt_max,
input [7:0] pi_data ,
input pi_flag ,
output reg tx ,
output reg tx_done
);
reg [15:0] baud_cnt;
reg [3:0] bit_cnt;
reg [7:0] data_buf;
reg tx_en;
reg pi_flag_d1;
wire pi_flag_posedge = pi_flag & ~pi_flag_d1;
always @(posedge clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
data_buf <= 8'd0;
tx_en <= 1'b0;
pi_flag_d1 <= 1'b0;
end else begin
pi_flag_d1 <= pi_flag;
if (pi_flag_posedge) begin
data_buf <= pi_data;
tx_en <= 1'b1;
end else if (bit_cnt == 4'd9 && baud_cnt == baud_cnt_max - 1) begin
tx_en <= 1'b0;
end
end
end
always @(posedge clk or negedge sys_rst_n) begin
if (!sys_rst_n)
baud_cnt <= 16'd0;
else if (tx_en) begin
if (baud_cnt == baud_cnt_max - 1)
baud_cnt <= 16'd0;
else
baud_cnt <= baud_cnt + 1'b1;
end else
baud_cnt <= 16'd0;
end
always @(posedge clk or negedge sys_rst_n) begin
if (!sys_rst_n)
bit_cnt <= 4'd0;
else if (tx_en) begin
if (baud_cnt == baud_cnt_max - 1) begin
if (bit_cnt == 4'd9)
bit_cnt <= 4'd0;
else
bit_cnt <= bit_cnt + 1'b1;
end
end else
bit_cnt <= 4'd0;
end
always @(posedge clk or negedge sys_rst_n) begin
if (!sys_rst_n)
tx <= 1'b1;
else if (tx_en) begin
case (bit_cnt)
4'd0: tx <= 1'b0;
4'd1: tx <= data_buf[0];
4'd2: tx <= data_buf[1];
4'd3: tx <= data_buf[2];
4'd4: tx <= data_buf[3];
4'd5: tx <= data_buf[4];
4'd6: tx <= data_buf[5];
4'd7: tx <= data_buf[6];
4'd8: tx <= data_buf[7];
4'd9: tx <= 1'b1;
default: tx <= 1'b1;
endcase
end else
tx <= 1'b1;
end
always @(posedge clk or negedge sys_rst_n) begin
if (!sys_rst_n)
tx_done <= 1'b0;
else if (tx_en && (bit_cnt == 4'd9) && (baud_cnt == baud_cnt_max - 1))
tx_done <= 1'b1;
else
tx_done <= 1'b0;
end
endmodule
3. uart_receive_dynamic.v
新增输入端口:baud_cnt_max
cpp
`timescale 1ns / 1ps
module uart_recceive_dynamic
#(
parameter CLK_FREQ = 50_000_000
)
(
input clk ,
input sys_rst_n ,
input [15:0] baud_cnt_max,
input rx ,
output reg [7:0]po_data ,
output reg po_flag
);
reg rx_reg1;
reg rx_reg2;
reg rx_reg3;
reg start_nedge;
reg work_en;
reg [15:0] baud_cnt;
reg bit_flag;
reg [3:0] bit_cnt;
reg [7:0] rx_data;
reg rx_flag;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0) begin
rx_reg1 <= 1'b1;
rx_reg2 <= 1'b1;
rx_reg3 <= 1'b1;
end else begin
rx_reg1 <= rx;
rx_reg2 <= rx_reg1;
rx_reg3 <= rx_reg2;
end
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
start_nedge <= 1'b0;
else if((~rx_reg2) && (rx_reg3))
start_nedge <= 1'b1;
else
start_nedge <= 1'b0;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
work_en <= 1'b0;
else if(start_nedge == 1'b1)
work_en <= 1'b1;
else if((bit_cnt == 4'd8) && (bit_flag == 1'b1))
work_en <= 1'b0;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
baud_cnt <= 16'b0;
else if((baud_cnt == baud_cnt_max - 1) || (work_en == 1'b0))
baud_cnt <= 16'b0;
else if(work_en == 1'b1)
baud_cnt <= baud_cnt + 1'b1;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_flag <= 1'b0;
else if(baud_cnt == baud_cnt_max/2 - 1)
bit_flag <= 1'b1;
else
bit_flag <= 1'b0;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
bit_cnt <= 4'b0;
else if((bit_cnt == 4'd8) && (bit_flag == 1'b1))
bit_cnt <= 4'b0;
else if(bit_flag ==1'b1)
bit_cnt <= bit_cnt + 1'b1;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_data <= 8'b0;
else if((bit_cnt >= 4'd1)&&(bit_cnt <= 4'd8)&&(bit_flag == 1'b1))
rx_data <= {rx_reg3, rx_data[7:1]};
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
rx_flag <= 1'b0;
else if((bit_cnt == 4'd8) && (bit_flag == 1'b1))
rx_flag <= 1'b1;
else
rx_flag <= 1'b0;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_data <= 8'b0;
else if(rx_flag == 1'b1)
po_data <= rx_data;
always@(posedge clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
po_flag <= 1'b0;
else
po_flag <= rx_flag;
endmodule