01 波特率是什么
從宏觀理解,波特率表征了串口的 傳輸速度 。
從微觀上,波特率是指在系統(tǒng)中 單位時(shí)間內(nèi)傳輸?shù)拇a元個(gè)數(shù) 。對(duì)于UART而言,碼元是二進(jìn)制的,都是用高低電平傳輸,所以波特率和比特率在數(shù)值上是相等的。例如,當(dāng)波特率為115200時(shí),實(shí)質(zhì)就是UART串口每秒傳輸115200個(gè)bit的數(shù)據(jù)量,傳輸一個(gè)bit的時(shí)間等于1/115200秒。常見(jiàn)的UART串口波特率為300、600、1200、4800、9600、19200、34800等。
串口傳輸中一個(gè)bit數(shù)據(jù)的周期即傳輸一個(gè)bit的時(shí)間,即可以表示為:
在串口傳輸中,一幀數(shù)據(jù)由起始位(1bit)、數(shù)據(jù)位(典型8bit)、校驗(yàn)位(1bit)和停止位(1bit)組成,在通常情況下一幀數(shù)據(jù)有11bit。那么可以算出1幀數(shù)據(jù)傳輸所需的時(shí)間為11x1/bps。
串口通信的雙方需要設(shè)置相同的波特率 ,由波特率約定數(shù)據(jù)傳輸?shù)闹芷凇Q定了應(yīng)該多久讀取一次電平值。
02 模塊接口與描述
- 26MHz功能時(shí)鐘主要用于波特率的產(chǎn)生與計(jì)算,由外部輸入。
- 接收波特率使能信號(hào)由接收數(shù)據(jù)模塊中產(chǎn)生,UART_RX線檢測(cè)到起始位后使能接收波特率。
- 發(fā)送波特率使能信號(hào)由發(fā)送數(shù)據(jù)模塊中產(chǎn)生,需要發(fā)送數(shù)據(jù)時(shí)即可使能。
- 波特率分頻系數(shù)是配置模塊產(chǎn)生,由APB總線配置。
- 接收和發(fā)送波特率時(shí)鐘根據(jù)配置由26MHz時(shí)鐘產(chǎn)生的用接收和發(fā)送數(shù)據(jù)的信號(hào)。
03 功能時(shí)鐘與波特率設(shè)計(jì)
本項(xiàng)目使用的功能時(shí)鐘為26MHz,波特率可通過(guò)波特率分頻系數(shù)BAUD_DIV進(jìn)行配置。波特率分頻系數(shù)BAUD_DIV與波特率之間的關(guān)系為:
為了方便計(jì)算和設(shè)計(jì),我們將N固定為16,只配置BAUD_DIV來(lái)調(diào)整波特率,波特率可配置如下:
波特率計(jì)算公式中,分母即為一個(gè)數(shù)據(jù)周期所需要計(jì)26MHz時(shí)鐘的個(gè)數(shù)。已知波特率和功能時(shí)鐘頻率,即可計(jì)算一個(gè)波特率周期所需的功能時(shí)鐘數(shù)。公式中的乘N操作使用左移實(shí)現(xiàn)(默認(rèn)波特率為9600)。
always@(posedge clk26m ornegedge rst26m_) begin
if(!rst26m_) begin
cnt_value <= 10'd169 < < 4;
end
elsebegin
cnt_value <= (baud_div + 1'b1) < < 4;
end
end
在產(chǎn)生接收數(shù)據(jù)的波特率時(shí)鐘時(shí),需要注意,接收模塊是根據(jù)所產(chǎn)生的這個(gè)波特率時(shí)鐘來(lái)進(jìn)行數(shù)據(jù)接收,數(shù)據(jù)采集如果都在“ 每位數(shù)據(jù)的中間 ”,那么采樣出的數(shù)據(jù)是最穩(wěn)定的。
接收數(shù)據(jù)采樣
所以在產(chǎn)生波特率時(shí)鐘時(shí),RX波特率計(jì)數(shù)器累加到一半時(shí)就應(yīng)使產(chǎn)生接收波特率時(shí)鐘。而發(fā)送數(shù)據(jù)時(shí)則不必這樣,只需保證波特率正確即可。
波特率模塊實(shí)現(xiàn)如下:
`timescale 1ns/1ps
module UART_BAUD(
// inputs
clk26m,
rst26m_,
tx_bps_en,
rx_bps_en,
baud_div,
// outputs
rx_bpsclk,
tx_bpsclk
);
input clk26m; // 26M function clock
input rst26m_; // function clk's rst_
input rx_bps_en; // baud enable signal
input tx_bps_en;
input [9:0] baud_div; // baud frequency divide factor
output rx_bpsclk; // receive bps clk
output tx_bpsclk; // send bps clk
reg [13:0] cnt_value; // bps count value
reg [13:0] cnt_baud_rx; // receive baud counter
reg [13:0] cnt_baud_tx; // send baud counter
// produce receive bpsclk
always@(posedge clk26m ornegedge rst26m_) begin
if(!rst26m_) begin
cnt_baud_rx <= 14'd0;
end
elsebegin
if(rx_bps_en) begin
if(cnt_baud_rx > cnt_value - 1'b1) begin
cnt_baud_rx <= 14'd0;
end
elsebegin
cnt_baud_rx <= cnt_baud_rx + 1'b1;
end
end
elsebegin
cnt_baud_rx <= 14'd0;
end
end
end
assign rx_bpsclk = (cnt_baud_rx == (cnt_value >>1))? 1'b1:1'b0;
// produce send bpsclk
always@(posedge clk26m ornegedge rst26m_) begin
if(!rst26m_) begin
cnt_baud_tx <= 14'd0;
end
elsebegin
if(tx_bps_en) begin
if(cnt_baud_tx > cnt_value - 1'b1) begin
cnt_baud_tx <= 14'd0;
end
elsebegin
cnt_baud_tx <= cnt_baud_tx + 1'b1;
end
end
elsebegin
cnt_baud_tx <= 14'd0;
end
end
end
assign tx_bpsclk = (cnt_baud_tx == (cnt_value >>1))? 1'b1:1'b0;
always@(posedge clk26m ornegedge rst26m_) begin
if(!rst26m_) begin
cnt_value <= 10'd169 < < 4;
end
elsebegin
cnt_value <= (baud_div + 1'b1) < < 4;
end
end
endmodule