目錄
1.UART串口介紹
2.實(shí)驗(yàn)任務(wù)
3.FPGA代碼
4.STM32代碼
5.總結(jié)
1.UART串口介紹
????????UART是一種采用異步串行方式的通用異步收發(fā)傳輸器,在發(fā)送數(shù)據(jù)時(shí)將并行數(shù)據(jù)轉(zhuǎn)換成串行數(shù)據(jù)來(lái)傳輸,在接收數(shù)據(jù)時(shí)將接收到的串行數(shù)據(jù)轉(zhuǎn)換成并行數(shù)據(jù)。
????????UART串口通信需要兩根信號(hào)線(xiàn)來(lái)實(shí)現(xiàn),一根用于串口發(fā)送,另一根負(fù)責(zé)串口接收。
????????UART的一幀數(shù)據(jù)由4部分組成:起始位、數(shù)據(jù)位、奇偶校驗(yàn)位和停止位。起始位標(biāo)志著一幀數(shù)據(jù)的開(kāi)始,低電平有效;數(shù)據(jù)位代表一幀數(shù)據(jù)中的有效數(shù)據(jù);校驗(yàn)位分為奇校驗(yàn)和偶校驗(yàn)檢測(cè)數(shù)據(jù)是否出錯(cuò);在空閑狀態(tài)下總線(xiàn)處于高電平。
????????UART通信過(guò)程中更多數(shù)據(jù)格式及傳輸速率時(shí)刻設(shè)置的,并且要求雙方遵循同樣的設(shè)置。其中起始位;數(shù)據(jù)位可選5-8位,一般選擇8位;校驗(yàn)位一般選擇無(wú)校驗(yàn)位;停止位一般選擇1位。傳輸速率用波特率表示,波特率表示每秒傳輸二進(jìn)制數(shù)據(jù)的位數(shù),單位時(shí)bps(位/秒),常用的波特率有9600、115200等
2.實(shí)驗(yàn)任務(wù)
-
上位機(jī)通過(guò)串口調(diào)試工具將數(shù)據(jù)發(fā)送給MCU的UART2,MCU的UART2接收到的數(shù)據(jù)通MCU的UART1發(fā)送給FPGA的UART1,F(xiàn)PGA的UART1接收到的數(shù)據(jù)通過(guò)FPGA的UART2發(fā)送給上位機(jī)。
-
上位機(jī)通過(guò)串口調(diào)試工具將數(shù)據(jù)發(fā)送給FPGA的UART2,F(xiàn)PGA的UART2接收到的數(shù)據(jù)通FPGA的UART1發(fā)送給MCU的UART1,MCU的UART1接收到的數(shù)據(jù)通過(guò)MCU的UART2發(fā)送給上位機(jī)。
3.FPGA代碼
????????FPGA主控芯片是EP4CE10F17C8。
????????在頂層模塊上,對(duì)uart1和uart2接收到的數(shù)據(jù)和發(fā)送數(shù)據(jù)進(jìn)行控制和操作。
????????頂層模塊代碼:
module test(
input sys_clk, //外部50M時(shí)鐘
input sys_rst_n, //外部復(fù)位信號(hào),低有效
//uart1接口
input wire uart1_rxd, //UART接收端口
output wire uart1_txd, //UART發(fā)送端口
//uart2接口
input wire uart2_rxd, //UART接收端口
output wire uart2_txd //UART發(fā)送端口
);
wire clk_1m_w;
//parameter define
parameter CLK_FREQ = 50000000; //定義系統(tǒng)時(shí)鐘頻率
parameter UART_BPS = 256000; //定義串口波特率
parameter CMD_PKGEND = 8'h65; //數(shù)據(jù)包尾
//uart1接口
wire uart1_recv_en; //UART1接收完成使能
wire [7:0] uart1_recv_data; //UART1接收到的數(shù)據(jù)
reg uart1_send_en; //UART1發(fā)送使能
wire uart1_txd_busy; //UART1發(fā)送忙標(biāo)志
//uart2接口
wire uart2_recv_en; //UART2接收完成使能
wire [7:0] uart2_recv_data; //UART2接收到的數(shù)據(jù)
reg uart2_send_en; //UART2發(fā)送使能
wire uart2_txd_busy; //UART2發(fā)送忙標(biāo)志
//邊沿檢測(cè)接口
reg uart2_en_d0;
reg uart2_en_d1;
wire uart2_en_flag;
//邊沿檢測(cè)接口
reg uart1_en_d0;
reg uart1_en_d1;
wire uart1_en_flag;
//uart2_uart1 fifo寫(xiě)接口
reg uart2_wrreq;
wire [7:0] uart2_data_in;
wire uart2_wrfull;
//uart2_uart1 fifo讀接口
reg uart2_fifo_flag; //uart2_uart1開(kāi)始讀fifo標(biāo)志
reg uart2_rdreq;
wire [7:0] uart2_data_out;
wire uart2_rdempty;
//uart1_uart2 fifo寫(xiě)接口
reg uart1_wrreq;
wire [7:0] uart1_data_in;
wire uart1_wrfull;
//uart1_uart2 fifo讀接口
reg uart1_fifo_flag; //uart1_uart2開(kāi)始讀fifo標(biāo)
reg uart1_rdreq;
wire [7:0] uart1_data_out;
wire uart1_rdempty;
//*****************************************************
//** main code
//*****************************************************
//捕獲uart2_recv_en上升沿,得到一個(gè)時(shí)鐘周期的脈沖信號(hào)
assign uart2_en_flag = (~uart2_en_d1) & uart2_en_d0;
//捕獲uart1_recv_en上升沿,得到一個(gè)時(shí)鐘周期的脈沖信號(hào)
assign uart1_en_flag = (~uart1_en_d1) & uart1_en_d0;
//UART2和UART1邊沿檢測(cè)
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart2_en_d0 <= 1'b0;
uart2_en_d1 <= 1'b0;
uart1_en_d0 <= 1'b0;
uart1_en_d1 <= 1'b0;
end
else begin
uart2_en_d0 <= uart2_recv_en;
uart2_en_d1 <= uart2_en_d0;
uart1_en_d0 <= uart1_recv_en;
uart1_en_d1 <= uart1_en_d0;
end
end
//UART2寫(xiě)進(jìn)uart2_uart1 FIFO中
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart2_wrreq <= 0;
uart2_fifo_flag <= 0;
end
else begin
if(uart2_en_flag && !uart2_wrfull) begin
uart2_wrreq <= 1;
end
else begin
uart2_wrreq <= 0;
end
if(uart2_en_flag && uart2_recv_data == CMD_PKGEND)begin //檢測(cè)到數(shù)據(jù)包尾,uart2_uart1 fifo開(kāi)始讀
uart2_fifo_flag <= 1;
end
if(!uart2_en_flag && uart2_rdempty) begin //uart2_uart1 fifo為空時(shí),將uart2_fifo_flag標(biāo)志置零
uart2_fifo_flag <= 0;
end
end
end
//uart2_uart1 fifo讀 uart1發(fā)送
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart2_rdreq <= 0;
uart1_send_en <= 0;
end
else begin
if(uart2_fifo_flag) begin
//讀到數(shù)據(jù)的下一個(gè)周期uart1_txd_busy依舊為0,所以需要增加!uart2_rdreq來(lái)延遲一個(gè)周期,在第二個(gè)周期到來(lái)時(shí),uart1_txd_busy為1
if(!uart2_rdempty && !uart1_txd_busy && !uart2_rdreq)begin
uart2_rdreq <= 1;
uart1_send_en <= 1;
end
else begin
uart2_rdreq <= 0;
uart1_send_en <= 0;
end
end
else begin
uart2_rdreq <= 0;
uart1_send_en <= 0;
end
end
end
//UART1寫(xiě)進(jìn)uart1_uart2 FIFO中
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart1_wrreq <= 0;
uart1_fifo_flag <= 0;
end
else begin
if(uart1_en_flag && !uart1_wrfull) begin
uart1_wrreq <= 1;
end
else begin
uart1_wrreq <= 0;
end
if(uart1_en_flag && uart1_recv_data == CMD_PKGEND)begin //檢測(cè)到數(shù)據(jù)包尾,uart2_uart1 fifo開(kāi)始讀
uart1_fifo_flag <= 1;
end
if(!uart1_en_flag && uart1_rdempty) begin //uart2_uart1 fifo為空時(shí),將uart2_fifo_flag標(biāo)志置零
uart1_fifo_flag <= 0;
end
end
end
//fifo讀 uart1_uart2 uart2發(fā)送
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart1_rdreq <= 0;
uart2_send_en <= 0;
end
else begin
if(uart1_fifo_flag) begin
//讀到數(shù)據(jù)的下一個(gè)周期uart2_txd_busy依舊為0,所以需要增加!uart1_rdreq來(lái)延遲一個(gè)周期,在第二個(gè)周期到來(lái)時(shí),uart2_txd_busy為1
if(!uart1_rdempty && !uart2_txd_busy && !uart1_rdreq)begin
uart1_rdreq <= 1;
uart2_send_en <= 1;
end
else begin
uart1_rdreq <= 0;
uart2_send_en <= 0;
end
end
else begin
uart1_rdreq <= 0;
end
end
end
//例化鎖相環(huán)
pll_clk u_pll_clk( //時(shí)鐘分頻模塊,用于調(diào)試
.inclk0 (sys_clk),
.c0 (clk_1m_w)
);
//例化uart1接收模塊
uart_recv #( //串口接收模塊
.CLK_FREQ (CLK_FREQ), //設(shè)置系統(tǒng)時(shí)鐘頻率
.UART_BPS (UART_BPS)) //設(shè)置串口接收波特率
u_uart1_recv(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_rxd (uart1_rxd),
.uart_done (uart1_recv_en),
.uart_data (uart1_recv_data)
);
//例化uart1發(fā)送模塊
uart_send #( //串口發(fā)送模塊
.CLK_FREQ (CLK_FREQ), //設(shè)置系統(tǒng)時(shí)鐘頻率
.UART_BPS (UART_BPS)) //設(shè)置串口發(fā)送波特率
u_uart1_send(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_en (uart1_send_en),
.uart_din (uart2_data_out),
.uart_txd (uart1_txd),
.uart_txd_busy (uart1_txd_busy)
);
//例化uart2接收模塊
uart_recv #( //串口接收模塊
.CLK_FREQ (CLK_FREQ), //設(shè)置系統(tǒng)時(shí)鐘頻率
.UART_BPS (UART_BPS)) //設(shè)置串口接收波特率
u_uart2_recv(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_rxd (uart2_rxd),
.uart_done (uart2_recv_en),
.uart_data (uart2_recv_data)
);
//例化uart2發(fā)送模塊
uart_send #( //串口發(fā)送模塊
.CLK_FREQ (CLK_FREQ), //設(shè)置系統(tǒng)時(shí)鐘頻率
.UART_BPS (UART_BPS)) //設(shè)置串口發(fā)送波特率
u_uart2_send(
.sys_clk (sys_clk),
.sys_rst_n (sys_rst_n),
.uart_en (uart2_send_en),
.uart_din (uart1_data_out),
.uart_txd (uart2_txd),
.uart_txd_busy (uart2_txd_busy)
);
//例化uart2_uart1 fifo
uart2_uart1 u_uart2_uart1(
.wrclk (sys_clk),
.wrreq (uart2_wrreq),
.data (uart2_recv_data),
.wrfull (uart2_wrfull),
.rdclk (sys_clk),
.rdreq (uart2_rdreq),
.q (uart2_data_out),
.rdempty (uart2_rdempty)
);
//例化uart1_uart2 fifo
uart1_uart2 u_uart1_uart2(
.wrclk (sys_clk),
.wrreq (uart1_wrreq),
.data (uart1_recv_data),
.wrfull (uart1_wrfull),
.rdclk (sys_clk),
.rdreq (uart1_rdreq),
.q (uart1_data_out),
.rdempty (uart1_rdempty)
);
endmodule
?????????uart接收模塊代碼:
module uart_recv(
input sys_clk, //系統(tǒng)時(shí)鐘
input sys_rst_n, //系統(tǒng)復(fù)位,低電平有效
input uart_rxd, //UART接收端口
output reg uart_done, //接收一幀數(shù)據(jù)完成標(biāo)志信號(hào)
output reg [7:0] uart_data //接收的數(shù)據(jù)
);
//parameter define
parameter CLK_FREQ = 50000000; //系統(tǒng)時(shí)鐘頻率
parameter UART_BPS = 115200; //串口波特率
localparam BPS_CNT = CLK_FREQ/UART_BPS; //為得到指定波特率,
//需要對(duì)系統(tǒng)時(shí)鐘計(jì)數(shù)BPS_CNT次
//reg define
reg uart_rxd_d0;
reg uart_rxd_d1;
reg [15:0] clk_cnt; //系統(tǒng)時(shí)鐘計(jì)數(shù)器
reg [ 3:0] rx_cnt; //接收數(shù)據(jù)計(jì)數(shù)器
reg rx_flag; //接收過(guò)程標(biāo)志信號(hào)
reg [ 7:0] rxdata; //接收數(shù)據(jù)寄存器
//wire define
wire start_flag;
//*****************************************************
//** main code
//*****************************************************
//捕獲接收端口下降沿(起始位),得到一個(gè)時(shí)鐘周期的脈沖信號(hào)
assign start_flag = uart_rxd_d1 & (~uart_rxd_d0);
//對(duì)UART接收端口的數(shù)據(jù)延遲兩個(gè)時(shí)鐘周期
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_rxd_d0 <= 1'b0;
uart_rxd_d1 <= 1'b0;
end
else begin
uart_rxd_d0 <= uart_rxd;
uart_rxd_d1 <= uart_rxd_d0;
end
end
//當(dāng)脈沖信號(hào)start_flag到達(dá)時(shí),進(jìn)入接收過(guò)程
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
rx_flag <= 1'b0;
else begin
if(start_flag) //檢測(cè)到起始位
rx_flag <= 1'b1; //進(jìn)入接收過(guò)程,標(biāo)志位rx_flag拉高
else if((rx_cnt == 4'd9)&&(clk_cnt == BPS_CNT/2))
rx_flag <= 1'b0; //計(jì)數(shù)到停止位中間時(shí),停止接收過(guò)程
else
rx_flag <= rx_flag;
end
end
//進(jìn)入接收過(guò)程后,啟動(dòng)系統(tǒng)時(shí)鐘計(jì)數(shù)器與接收數(shù)據(jù)計(jì)數(shù)器
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
else if ( rx_flag ) begin //處于接收過(guò)程
if (clk_cnt < BPS_CNT - 1) begin
clk_cnt <= clk_cnt + 1'b1;
rx_cnt <= rx_cnt;
end
else begin
clk_cnt <= 16'd0; //對(duì)系統(tǒng)時(shí)鐘計(jì)數(shù)達(dá)一個(gè)波特率周期后清零
rx_cnt <= rx_cnt + 1'b1; //此時(shí)接收數(shù)據(jù)計(jì)數(shù)器加1
end
end
else begin //接收過(guò)程結(jié)束,計(jì)數(shù)器清零
clk_cnt <= 16'd0;
rx_cnt <= 4'd0;
end
end
//根據(jù)接收數(shù)據(jù)計(jì)數(shù)器來(lái)寄存uart接收端口數(shù)據(jù)
always @(posedge sys_clk or negedge sys_rst_n) begin
if ( !sys_rst_n)
rxdata <= 8'd0;
else if(rx_flag) //系統(tǒng)處于接收過(guò)程
if (clk_cnt == BPS_CNT/2) begin //判斷系統(tǒng)時(shí)鐘計(jì)數(shù)器計(jì)數(shù)到數(shù)據(jù)位中間
case ( rx_cnt )
4'd1 : rxdata[0] <= uart_rxd_d1; //寄存數(shù)據(jù)位最低位
4'd2 : rxdata[1] <= uart_rxd_d1;
4'd3 : rxdata[2] <= uart_rxd_d1;
4'd4 : rxdata[3] <= uart_rxd_d1;
4'd5 : rxdata[4] <= uart_rxd_d1;
4'd6 : rxdata[5] <= uart_rxd_d1;
4'd7 : rxdata[6] <= uart_rxd_d1;
4'd8 : rxdata[7] <= uart_rxd_d1; //寄存數(shù)據(jù)位最高位
default:;
endcase
end
else
rxdata <= rxdata;
else
rxdata <= 8'd0;
end
//數(shù)據(jù)接收完畢后給出標(biāo)志信號(hào)并寄存輸出接收到的數(shù)據(jù)
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
else if(rx_cnt == 4'd9) begin //接收數(shù)據(jù)計(jì)數(shù)器計(jì)數(shù)到停止位時(shí)
uart_data <= rxdata; //寄存輸出接收到的數(shù)據(jù)
uart_done <= 1'b1; //并將接收完成標(biāo)志位拉高
end
else begin
uart_data <= 8'd0;
uart_done <= 1'b0;
end
end
endmodule
????????uart發(fā)送模塊代碼:
module uart_send(
input sys_clk, //系統(tǒng)時(shí)鐘
input sys_rst_n, //系統(tǒng)復(fù)位,低電平有效
input uart_en, //發(fā)送使能信號(hào)
input [7:0] uart_din, //待發(fā)送數(shù)據(jù)
output reg uart_txd, //UART發(fā)送端口
output reg uart_txd_busy
);
//parameter define
parameter CLK_FREQ = 50000000; //系統(tǒng)時(shí)鐘頻率
parameter UART_BPS = 115200; //串口波特率
localparam BPS_CNT = CLK_FREQ/UART_BPS; //為得到指定波特率,對(duì)系統(tǒng)時(shí)鐘計(jì)數(shù)BPS_CNT次
//reg define
reg uart_en_d0;
reg uart_en_d1;
reg [15:0] clk_cnt; //系統(tǒng)時(shí)鐘計(jì)數(shù)器
reg [ 3:0] tx_cnt; //發(fā)送數(shù)據(jù)計(jì)數(shù)器
reg tx_flag; //發(fā)送過(guò)程標(biāo)志信號(hào)
reg [ 7:0] tx_data; //寄存發(fā)送數(shù)據(jù)
//wire define
wire en_flag;
//*****************************************************
//** main code
//*****************************************************
//捕獲uart_en上升沿,得到一個(gè)時(shí)鐘周期的脈沖信號(hào)
assign en_flag = (~uart_en_d1) & uart_en_d0;
//對(duì)發(fā)送使能信號(hào)uart_en延遲兩個(gè)時(shí)鐘周期
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
uart_en_d0 <= 1'b0;
uart_en_d1 <= 1'b0;
end
else begin
uart_en_d0 <= uart_en;
uart_en_d1 <= uart_en_d0;
end
end
//當(dāng)脈沖信號(hào)en_flag到達(dá)時(shí),寄存待發(fā)送的數(shù)據(jù),并進(jìn)入發(fā)送過(guò)程
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
tx_flag <= 1'b0;
tx_data <= 8'd0;
uart_txd_busy <= 1'b0;
end
else begin
if(uart_en) uart_txd_busy <= 1'b1;
if (en_flag) begin //檢測(cè)到發(fā)送使能上升沿
tx_flag <= 1'b1; //進(jìn)入發(fā)送過(guò)程,標(biāo)志位tx_flag拉高
tx_data <= uart_din; //寄存待發(fā)送的數(shù)據(jù)
end
else if ((tx_cnt == 4'd9)&&(clk_cnt == BPS_CNT - 1))begin //計(jì)數(shù)到停止位中間時(shí),停止發(fā)送過(guò)程
tx_flag <= 1'b0; //發(fā)送過(guò)程結(jié)束,標(biāo)志位tx_flag拉低
tx_data <= 8'd0;
uart_txd_busy <= 1'b0;
end
else begin
tx_flag <= tx_flag;
tx_data <= tx_data;
end
end
end
//進(jìn)入發(fā)送過(guò)程后,啟動(dòng)系統(tǒng)時(shí)鐘計(jì)數(shù)器與發(fā)送數(shù)據(jù)計(jì)數(shù)器
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n) begin
clk_cnt <= 16'd0;
tx_cnt <= 4'd0;
end
else if (tx_flag) begin //處于發(fā)送過(guò)程
if (clk_cnt < BPS_CNT - 1) begin
clk_cnt <= clk_cnt + 1'b1;
tx_cnt <= tx_cnt;
end
else begin
clk_cnt <= 16'd0; //對(duì)系統(tǒng)時(shí)鐘計(jì)數(shù)達(dá)一個(gè)波特率周期后清零
tx_cnt <= tx_cnt + 1'b1; //此時(shí)發(fā)送數(shù)據(jù)計(jì)數(shù)器加1
end
end
else begin //發(fā)送過(guò)程結(jié)束
clk_cnt <= 16'd0;
tx_cnt <= 4'd0;
end
end
//根據(jù)發(fā)送數(shù)據(jù)計(jì)數(shù)器來(lái)給uart發(fā)送端口賦值
always @(posedge sys_clk or negedge sys_rst_n) begin
if (!sys_rst_n)
uart_txd <= 1'b1;
else if (tx_flag)
case(tx_cnt)
4'd0: uart_txd <= 1'b0; //起始位
4'd1: uart_txd <= tx_data[0]; //數(shù)據(jù)位最低位
4'd2: uart_txd <= tx_data[1];
4'd3: uart_txd <= tx_data[2];
4'd4: uart_txd <= tx_data[3];
4'd5: uart_txd <= tx_data[4];
4'd6: uart_txd <= tx_data[5];
4'd7: uart_txd <= tx_data[6];
4'd8: uart_txd <= tx_data[7]; //數(shù)據(jù)位最高位
4'd9: uart_txd <= 1'b1; //停止位
default: ;
endcase
else
uart_txd <= 1'b1; //空閑時(shí)發(fā)送端口為高電平
end
endmodule
4.STM32代碼
????????STM32的主控芯片是STM32F103RCT6。
????????main.c代碼:
#include "sys.h"
#include "usart.h"
int main(void)
{
u8 t;
u8 len;
delay_init(); //延時(shí)函數(shù)初始化
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 設(shè)置中斷優(yōu)先級(jí)分組2
uart1_init(256000); //串口初始化為25600
uart2_init(256000);
printf("初始化成功\r\n");
while(1)
{
if(USART2_RX_STA&0x8000)
{
len=USART2_RX_STA&0x3fff;//得到此次接收到的數(shù)據(jù)長(zhǎng)度
for(t=0;t<len;t++)
{
USART1->DR=USART2_RX_BUF[t];
while((USART1->SR&0X40)==0);//等待發(fā)送結(jié)束
}
USART2_RX_STA=0;
}
else if(USART1_RX_STA&0x8000)
{
len=USART1_RX_STA&0x3fff;//得到此次接收到的數(shù)據(jù)長(zhǎng)度
for(t=0;t<len;t++)
{
USART2->DR=USART1_RX_BUF[t];
while((USART2->SR&0X40)==0);//等待發(fā)送結(jié)束
}
USART1_RX_STA=0;
}
else
{
delay_ms(10);
}
}
}
????????usart.c文件代碼:
#include "sys.h"
#include "usart.h"
u8 USART1_RX_BUF[USART1_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).
u16 USART1_RX_STA=0; //接收狀態(tài)標(biāo)記
u8 USART2_RX_BUF[USART2_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).
u16 USART2_RX_STA=0; //接收狀態(tài)標(biāo)記
void uart1_init(u32 bound){
//GPIO端口設(shè)置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1|RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時(shí)鐘
//USART1_TX GPIOA.9
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.9
//USART1_RX GPIOA.10初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.10
//Usart1 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //子優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長(zhǎng)為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無(wú)奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無(wú)硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART1, &USART_InitStructure); //初始化串口1
USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//開(kāi)啟串口接受中斷
USART_Cmd(USART1, ENABLE); //使能串口1
}
void uart2_init(u32 bound){
//GPIO端口設(shè)置
GPIO_InitTypeDef GPIO_InitStructure;
USART_InitTypeDef USART_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //使能USART1,GPIOA時(shí)鐘
RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
//USART2_TX GPIOA.2
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; //PA.2
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //復(fù)用推挽輸出
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.2
//USART2_RX GPIOA.3初始化
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;//PA3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入
GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化GPIOA.3
//Usart2 NVIC 配置
NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=3 ;//搶占優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2; //子優(yōu)先級(jí)3
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ通道使能
NVIC_Init(&NVIC_InitStructure); //根據(jù)指定的參數(shù)初始化VIC寄存器
//USART 初始化設(shè)置
USART_InitStructure.USART_BaudRate = bound;//串口波特率
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字長(zhǎng)為8位數(shù)據(jù)格式
USART_InitStructure.USART_StopBits = USART_StopBits_1;//一個(gè)停止位
USART_InitStructure.USART_Parity = USART_Parity_No;//無(wú)奇偶校驗(yàn)位
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//無(wú)硬件數(shù)據(jù)流控制
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //收發(fā)模式
USART_Init(USART2, &USART_InitStructure); //初始化串口2
USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//開(kāi)啟串口2接受中斷
USART_Cmd(USART2, ENABLE); //使能串口2
}
void USART1_IRQHandler(void) //串口1中斷服務(wù)程序
{
u8 Res;
if(USART_GetITStatus(USART1, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是0x65結(jié)尾)
{
Res =USART_ReceiveData(USART1); //讀取接收到的數(shù)據(jù)
if((USART1_RX_STA&0x8000)==0)//接收未完成
{
USART1_RX_BUF[USART1_RX_STA&0X3FFF]=Res ;
USART1_RX_STA++;
if(Res==0x65) USART1_RX_STA|=0x8000; //接收完成了
else if(USART1_RX_STA>(USART1_REC_LEN-1))USART1_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開(kāi)始接收
}
}
}
void USART2_IRQHandler(void)
{
u8 Res;
if(USART_GetITStatus(USART2, USART_IT_RXNE) != RESET) //接收中斷(接收到的數(shù)據(jù)必須是65結(jié)尾)
{
Res =USART_ReceiveData(USART2); //讀取接收到的數(shù)據(jù)
if((USART2_RX_STA&0x8000)==0)//接收未完成
{
USART2_RX_BUF[USART2_RX_STA&0X3FFF]=Res ;
USART2_RX_STA++;
if(Res==0x65) USART2_RX_STA|=0x8000; //接收完成了
else if(USART2_RX_STA>(USART2_REC_LEN-1))USART2_RX_STA=0;//接收數(shù)據(jù)錯(cuò)誤,重新開(kāi)始接收
}
}
}
//重定向c庫(kù)函數(shù)printf到串口,重定向后可使用printf函數(shù)
int fputc(int ch, FILE *f)
{
/* 發(fā)送一個(gè)字節(jié)數(shù)據(jù)到串口 */
USART_SendData(USART2, (uint8_t) ch);
/* 等待發(fā)送完畢 */
while (USART_GetFlagStatus(USART2, USART_FLAG_TXE) == RESET);
return (ch);
}
????????usart.h文件代碼:
#ifndef __USART_H
#define __USART_H
#include "stdio.h"
#include "sys.h"
#define USART1_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
#define USART2_REC_LEN 200 //定義最大接收字節(jié)數(shù) 200
extern u8 USART1_RX_BUF[USART1_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符
extern u16 USART1_RX_STA; //接收狀態(tài)標(biāo)記
extern u8 USART2_RX_BUF[USART2_REC_LEN]; //接收緩沖,最大USART_REC_LEN個(gè)字節(jié).末字節(jié)為換行符
extern u16 USART2_RX_STA; //接收狀態(tài)標(biāo)記
void uart1_init(u32 bound);
void uart2_init(u32 bound);
#endif
5.總結(jié)
-
波特率不宜選太高,會(huì)導(dǎo)致通信不了;
-
FPGA方面注意FIFO讀請(qǐng)求置1后,在下一個(gè)時(shí)鐘周期讀的數(shù)據(jù)才會(huì)更新,所以u(píng)ar待t發(fā)送的數(shù)據(jù)要延時(shí)一周期后再接收f(shuō)ifo讀到的數(shù)據(jù)。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-640588.html
-
FPGA方面的uart發(fā)送模塊需要注意FIFO每讀取一次數(shù)據(jù)uart發(fā)送一次,所以增加了uart_txd_busy,防止fifo連續(xù)讀數(shù)據(jù)。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-640588.html
到了這里,關(guān)于FPGA與STM32之間的UART通信實(shí)驗(yàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!