国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

FPGA與STM32之間的UART通信實(shí)驗(yàn)

這篇具有很好參考價(jià)值的文章主要介紹了FPGA與STM32之間的UART通信實(shí)驗(yàn)。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

目錄

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)處于高電平。

fpga與stm32通信,fpga開(kāi)發(fā),stm32,arm,單片機(jī),c語(yǔ)言

????????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ī)。

fpga與stm32通信,fpga開(kāi)發(fā),stm32,arm,單片機(jī),c語(yǔ)言

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ù)。

  • 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)!

本文來(lái)自互聯(lián)網(wǎng)用戶(hù)投稿,該文觀(guān)點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 基于SPI實(shí)現(xiàn)stm32與fpga通信(一)

    SPI通信協(xié)議有以下4種模式: 模式0:時(shí)鐘極性為0,時(shí)鐘相位為0,數(shù)據(jù)在時(shí)鐘下降沿捕獲,數(shù)據(jù)在時(shí)鐘上升沿改變。 模式1:時(shí)鐘極性為0,時(shí)鐘相位為1,數(shù)據(jù)在時(shí)鐘上升沿捕獲,數(shù)據(jù)在時(shí)鐘下降沿改變。 模式2:時(shí)鐘極性為1,時(shí)鐘相位為0,數(shù)據(jù)在時(shí)鐘上升沿捕獲,數(shù)據(jù)在時(shí)鐘

    2024年04月16日
    瀏覽(43)
  • FPGA主SPI與STM32從機(jī)通信

    FPGA主SPI與STM32從機(jī)通信

    目錄 概述 FPGA的SPI主機(jī)代碼 STM32從機(jī) SPI模式配置 SPI參數(shù)設(shè)置 ?SPI的DMA傳輸配置 STM32從機(jī)SPI接收代碼 ? ? ? ? 不說(shuō)一些SPI原理之類(lèi)的廢話(huà),浪費(fèi)空間。我使用的硬件環(huán)境為STM32F407VET6和DE0-nano,長(zhǎng)什么樣子如下圖。 ?使用cubemx配置工程,F(xiàn)PGA使用Quartus軟件,時(shí)序仿真圖如下 ? ?

    2024年02月02日
    瀏覽(31)
  • ARM開(kāi)發(fā),stm32mp157a-A7核(UART總線(xiàn)實(shí)驗(yàn))

    ARM開(kāi)發(fā),stm32mp157a-A7核(UART總線(xiàn)實(shí)驗(yàn))

    ---.h頭文件--- ---.c功能實(shí)現(xiàn)文件--- ---.c主函數(shù)測(cè)試文件--- 結(jié)果: 字符:? 字符串:?

    2024年02月11日
    瀏覽(25)
  • K210 UART串口通信介紹與 STM32通信

    目錄 K210-UART串口通信相關(guān)函數(shù): 使用K210串口的時(shí)候需要映射引腳: K210與STM32串口通信? 發(fā)送單字節(jié): K210端 STM32端 發(fā)送數(shù)據(jù)包 K210端 STM32端? K210的UART模塊支持全雙工通信,可以同時(shí)進(jìn)行數(shù)據(jù)的發(fā)送和接收。在K210上使用UART串口通信,你可以連接外部設(shè)備,如傳感器、顯示器

    2024年03月23日
    瀏覽(39)
  • 【單片機(jī)】基于STM32的UART串口通信

    【單片機(jī)】基于STM32的UART串口通信

    簡(jiǎn)單講解一下UART通信協(xié)議,以及UART能夠?qū)崿F(xiàn)的一些功能,還有有關(guān)使用STM32CubeMX來(lái)配置芯片的一些操作。實(shí)驗(yàn)內(nèi)容基于 正點(diǎn)原子精英板 開(kāi)發(fā)板,單片機(jī)芯片為 STM32F103ZET6 。 在后面我會(huì)以我使用的STM32F429開(kāi)發(fā)板來(lái)舉例講解(其他STM32系列芯片大多數(shù)都可以按照這些步驟來(lái)操作

    2024年01月17日
    瀏覽(96)
  • STM32CubeMX教程9 USART/UART 異步通信

    開(kāi)發(fā)板(正點(diǎn)原子stm32f407探索者開(kāi)發(fā)板V2.4) STM32CubeMX軟件(Version 6.10.0) keil μVision5 IDE(MDK-Arm) ST-LINK/V2驅(qū)動(dòng) 邏輯分析儀nanoDLA 野火DAP仿真器 XCOM V2.6串口助手 使用STM32CubeMX軟件配置STM32F407開(kāi)發(fā)板 USART1與PC進(jìn)行異步通信(阻塞傳輸方式、中斷傳輸方式) ,具體為 使用WK_UP按鍵

    2024年02月03日
    瀏覽(25)
  • 學(xué)習(xí)筆記一:樹(shù)莓派與STM32的UART通信

    學(xué)習(xí)筆記一:樹(shù)莓派與STM32的UART通信

    樹(shù)莓派4B一共包含兩個(gè)串口,一個(gè)是硬件串口(/dev/ttyAMA0),一個(gè)是mini串口(/dev/ttyS0)。硬件串口因?yàn)槭褂闷鋯为?dú)的時(shí)鐘源,性能高,穩(wěn)定可靠,成為使用較為廣泛的串口;另一個(gè)mini串口性能低,功能簡(jiǎn)單,但是沒(méi)有單獨(dú)的時(shí)鐘源,會(huì)受到內(nèi)部時(shí)鐘的影響,樹(shù)莓派本身運(yùn)行

    2023年04月18日
    瀏覽(29)
  • STM32 UART串口通信IDLE空閑中斷的使用步驟

    參考了各路大神的資料,蒙蔽了半天,終于學(xué)會(huì)了,記錄一下,以后忘了可以回來(lái)復(fù)習(xí)參考。 一、首先在stm32cube中配置打開(kāi)對(duì)應(yīng)uart串口的中斷 二、工程main函數(shù)調(diào)用 __HAL_UART_ENABLE_IT(huart1,UART_IT_IDLE);//hal庫(kù)宏定義,使能串口空閑中斷 ?? ?HAL_UART_Receive_DMA(huart1,data,sizeof(data));//使

    2024年02月12日
    瀏覽(15)
  • STM32CubeMx+MATLAB Simulink串口輸出實(shí)驗(yàn),UART/USART串口測(cè)試實(shí)驗(yàn)

    STM32CubeMx+MATLAB Simulink串口輸出實(shí)驗(yàn),UART/USART串口測(cè)試實(shí)驗(yàn)

    STM32CubeMx+MATLAB Simulink串口輸出實(shí)驗(yàn)

    2024年02月21日
    瀏覽(27)
  • OpenMV與STM32之間的通信

    OpenMV與STM32之間使用串口進(jìn)行通信。 詳細(xì)解釋可以看代碼里面的注釋。 注意:轉(zhuǎn)換成字節(jié)型傳輸時(shí),負(fù)數(shù)會(huì)以補(bǔ)碼形式傳輸,比如:-1在單片機(jī)接受時(shí)變成255. 先在項(xiàng)目中加入串口通信包,PA2為T(mén)XD,PA3為RXD??梢蚤_(kāi)一個(gè)串口通過(guò)串口助手打印接收到的數(shù)據(jù)。 注意:OpenMV的TXD和

    2024年02月16日
    瀏覽(18)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包