iis 網(wǎng)站目錄權(quán)限網(wǎng)站制作維護(hù)
一、UART相關(guān)介紹
UART是我們常用的全雙工異步串行總線,常用TTL電平標(biāo)準(zhǔn),由TXD和RXD兩根收發(fā)數(shù)據(jù)線組成。
那么,利用硬件描述語(yǔ)言實(shí)現(xiàn)UART對(duì)應(yīng)的電路和51單片機(jī)內(nèi)部配合寄存器實(shí)現(xiàn)的電路到底有何區(qū)別呢?接下來(lái)我們對(duì)照看一下。
二、FPGA實(shí)現(xiàn)UART異步串行收發(fā)方式
對(duì)于FPGA而言,利用verilog實(shí)現(xiàn)這個(gè)過(guò)程,其實(shí)最重要的就是安排好對(duì)應(yīng)的計(jì)數(shù)器并配合移位寄存器串并轉(zhuǎn)換即可完成。
FPGA發(fā)送端對(duì)應(yīng)的代碼如下:
module uart_tx(input wire clk ,input wire rst_n ,input wire [7:0] pi_data ,input wire pi_flag ,output reg tx );reg [7:0] pi_data_reg;//用于寄存?zhèn)鬟M(jìn)來(lái)的數(shù)據(jù)reg tx_flag ;reg [12:0] cnt_baud ;reg bit_flag1;reg [3:0] bit_cnt ;//在接收到pi_flag為高電平的時(shí)候寄存輸入數(shù)?always@(posedge clk or negedge rst_n)beginif(!rst_n)pi_data_reg <= 'd0;else if(pi_flag == 1'b1)pi_data_reg <= pi_data ;endalways@(posedge clk or negedge rst_n)beginif(!rst_n)tx_flag <= 1'b0;else if(bit_flag1 == 1'b1 && bit_cnt == 'd8)tx_flag <= 1'b0;else if(pi_flag == 1'b1)tx_flag <= 1'b1;end always@(posedge clk or negedge rst_n)beginif(!rst_n)cnt_baud <= 'd0;else if(tx_flag == 1'b0)cnt_baud <= 'd0;else if(cnt_baud == 'd5207 && tx_flag == 1'b1)cnt_baud <= 'd0;else if(tx_flag == 1'b1)cnt_baud <= cnt_baud + 1'b1;endalways@(posedge clk or negedge rst_n)beginif(!rst_n)bit_flag1 <= 1'b0;else if(cnt_baud == 5206)bit_flag1 <= 1'b1;else bit_flag1 <= 1'b0;endalways@(posedge clk or negedge rst_n)beginif(!rst_n)bit_cnt <= 'd0;else if(bit_cnt == 'd8 && bit_flag1 == 1'b1)bit_cnt <= 'd0;else if(bit_flag1 == 1'b1)bit_cnt <= bit_cnt + 1'b1;end always@(posedge clk or negedge rst_n)beginif(!rst_n)tx <= 1'b1;//空閑狀態(tài)else if(pi_flag == 1'b1)tx <= 1'b0;//起始?else if(bit_flag1 == 1'b1 && bit_cnt <= 'd7)tx <= pi_data_reg[bit_cnt];//8位數(shù)?else if(bit_cnt == 'd8 && bit_flag1 == 1'b1)tx <= 1'b1;//空閑?end
endmodule
FPGA接收端對(duì)應(yīng)的代碼如下:
module uart_rx(input wire clk ,input wire rst_n ,input wire rx ,output reg [7:0] po_data ,output reg po_flag);//用于打拍的寄存器reg rx1;reg rx2;reg rx2_reg ;reg rx_flag ;reg [12:0] cnt_baud ;reg bit_flag ;reg [3:0] bit_cnt ;//對(duì)接收到的外部信號(hào)進(jìn)行打拍寄存always@(posedge clk)beginrx1 <= rx ;rx2 <= rx1 ;rx2_reg <= rx2 ;end//檢測(cè)下降沿,拉高rx_flagalways @(posedge clk or negedge rst_n) beginif (!rst_n) beginrx_flag <= 1'b0;endelse if (rx2 == 1'b0 && rx2_reg == 1'b1) beginrx_flag <= 1'b1;endelse if(bit_flag == 1'b1 && bit_cnt == 'd8)rx_flag <= 1'b0;endalways @(posedge clk or negedge rst_n) beginif (!rst_n) cnt_baud <= 'd0;else if(rx_flag == 1'b0)cnt_baud <= 'd0;else if(cnt_baud == 'd5207 && rx_flag == 1'b1)//5207為波特率是9600時(shí)對(duì)應(yīng)的計(jì)數(shù)值cnt_baud <= 'd0;else if(rx_flag == 1'b1)cnt_baud <= cnt_baud + 1'b1;endalways @(posedge clk or negedge rst_n) beginif (!rst_n) bit_flag <= 1'b0;else if(cnt_baud == 'd2603 && rx_flag == 1'b1)bit_flag <= 1'b1;else bit_flag <= 1'b0;end always @(posedge clk or negedge rst_n) beginif (!rst_n) bit_cnt <= 'd0;else if(bit_cnt == 'd8 && bit_flag == 1'b1)bit_cnt <= 'd0;else if(bit_flag == 1'b1 && rx_flag == 1'b1)bit_cnt <= bit_cnt + 1'b1;endalways @(posedge clk or negedge rst_n) beginif (!rst_n) po_data <= 'd0;else if(bit_flag == 1'b1 && bit_cnt >= 'd1)po_data <= {rx2_reg,po_data[7:1]};end always @(posedge clk or negedge rst_n) beginif (!rst_n) po_flag <= 1'b0 ;else if(bit_flag == 1'b1 && bit_cnt == 'd8)po_flag <= 1'b1 ;else po_flag <= 1'b0;endendmodule
頂層代碼如下:
module top_uart(input wire clk ,input wire rst_n ,input wire rx ,output wire tx);wire [7:0] po_data ;wire po_flag ;uart_rx inst_uart_rx (.clk(clk), .rst_n(rst_n), .rx(rx), .po_data(po_data), .po_flag(po_flag));uart_tx inst_uart_tx (.clk(clk), .rst_n(rst_n), .pi_data(po_data), .pi_flag(po_flag), .tx(tx));endmodule
經(jīng)過(guò)綜合后,生成的對(duì)應(yīng)原理圖如下:
頂層:
tx:可以發(fā)現(xiàn),這里其實(shí)每一位寄存器都對(duì)應(yīng)著一個(gè)D觸發(fā)器,剩余的邏輯由LUT實(shí)現(xiàn)。
rx:接收端同理。
三、單片機(jī)內(nèi)部UART異步串行收發(fā)實(shí)現(xiàn)方式
對(duì)于51單片機(jī)而言,它內(nèi)部是CPU控制一些在物理層面已經(jīng)連接好寄存器,通過(guò)對(duì)寄存器的控制配合電路的改變完成整個(gè)任務(wù)。
對(duì)于串口通信這個(gè)任務(wù)而言,它的整個(gè)實(shí)現(xiàn)過(guò)程總結(jié)如下:
整個(gè)實(shí)現(xiàn)可分為三大部分,定時(shí)器、中斷系統(tǒng)及對(duì)應(yīng)的緩沖寄存器完成,三大部分配合內(nèi)部CPU便可完成收發(fā)任務(wù),具體示意圖如下:
紅色區(qū)域是定時(shí)器部分,它外部連接著晶振,通過(guò)對(duì)TH1和TL1寄存器寫入初始值可實(shí)現(xiàn)具體溢出頻率的控制,假設(shè)晶振頻率位12MHz(12T模式下1us計(jì)數(shù)一次),TH1和TL1填入0xF3(對(duì)應(yīng)十進(jìn)制243),一共256,則每隔256-243=13個(gè)數(shù)就會(huì)溢出一次,則溢出率為1/13us=0.07692MHz,當(dāng)SMOD=1時(shí),頻率只經(jīng)過(guò)?16也就對(duì)應(yīng)4800Hz,就會(huì)對(duì)應(yīng)波特率4800Baud。配合控制器即可完成對(duì)波特率的控制。
藍(lán)色部分是用于發(fā)送和接收數(shù)據(jù)的緩沖區(qū);
黃色部分是串口中斷器,這個(gè)中斷器在接收數(shù)據(jù)的時(shí)候需要使用,TI和RI是中斷標(biāo)志。
在使用方式上,對(duì)涉及的寄存器進(jìn)行初始化后,將數(shù)據(jù)寫入SBUF或通過(guò)中斷讀取SBUF內(nèi)的數(shù)據(jù)即可完成發(fā)送接收任務(wù)。
對(duì)應(yīng)配置代碼如下:
#include <REGX51.H>/*** @brief 串口初始化,4800bps@11.0592MHz* @param 無(wú) * @retval 無(wú)*/
void UART_Init()
{//對(duì)串行寄存器配置SCON=0x50; //串行控制寄存器,涉及模式選擇PCON &= 0x7F; //電源控制寄存器(包括波特率)//對(duì)定時(shí)器0進(jìn)行配置#11.0592MTMOD &= 0x0F; //設(shè)置定時(shí)器模式,低4位保持不變TMOD |= 0x20; //設(shè)置定時(shí)器模式,串口對(duì)應(yīng)的模式需要是雙8位模式TL1 = 0xFA; //設(shè)定定時(shí)初值TH1 = 0xFA; //設(shè)定定時(shí)器重裝值ET1 = 0; //禁止定時(shí)器1中斷TR1 = 1; //啟動(dòng)定定時(shí)器1//串口中斷配置EA=1;//啟動(dòng)所有中斷ES=1;//啟動(dòng)串口中斷
}
/*** @brief 串口發(fā)送1個(gè)字節(jié)數(shù)據(jù),4800bps@11.0592MHz* @param Byte 要發(fā)送的一個(gè)字節(jié)數(shù)據(jù)* @retval 無(wú)*/
void UART_SendByte(unsigned char Byte)
{SBUF=Byte;//將數(shù)據(jù)寫入發(fā)送緩沖器即可while(TI==0);//是否有中斷請(qǐng)求位TI=0;//軟件置0
}//串口中斷函數(shù)的模板,需要用的時(shí)候復(fù)制到主函數(shù)中
/*
//注意:一個(gè)函數(shù)不能既在主函數(shù)中出現(xiàn),又在中斷函數(shù)中出現(xiàn)
void UART_Routine() interrupt 4 //串口中斷對(duì)應(yīng)的中斷號(hào)
{if(RI==1)//接收到了串口中斷{P2=~SBUF;UART_SendByte(SBUF);RI=0;//需要由軟件清0}}
*/
主函數(shù)代碼如下:
#include <REGX51.H>
#include "Delay.h"
#include "UART.h"void main()
{UART_Init();while(1){}
}//注意:一個(gè)函數(shù)不能既在主函數(shù)中出現(xiàn),又在中斷函數(shù)中出現(xiàn)
void UART_Routine() interrupt 4 //串口中斷對(duì)應(yīng)的中斷號(hào)
{if(RI==1)//接收到了串口中斷{P2=~SBUF;UART_SendByte(SBUF);RI=0;//需要由軟件清0}}
四、總結(jié)
均由寄存器加邏輯電路組成,只不過(guò)二者工作模式及靈活性差別很大,單片機(jī)依賴馮諾依曼架構(gòu)需要控制器控制且電路固定(使得定時(shí)器、寄存器等資源有限),FPGA的并行及靈活性在這里體現(xiàn)的淋漓盡致。