UART原理
UART原理
? ? ? ?通用異步收發傳輸器(Universal Asynchronous Receiver / Transmitter),通常稱作UART,是一種異步收發傳輸器,是電腦硬件的一部分。將資料由串行通信與并行通信間作傳輸轉換,作為并行輸入成為串行輸出的芯片,通常集成于其他通訊接口的連結上。
1、UART發送
? ? ? ?數據的發送實際上就是按照幀格式將寄存器中的并行數據轉為串行數據,為其加上起始位和停止位,以一定的波特率進行傳輸。波特率可以有多種選擇,如9600bits/s,14400bits/s,19200bits/s,38400bits/s等
2、UART接收
? ? ? ?由于傳輸中有可能會產生毛刺,接收端極有可能將毛刺誤認為是起始位,所以要對檢測到的下降沿進行判別。一般采用如下的方法:取接收端的時鐘頻率是發送頻率的16倍頻,當檢測到一個下降沿后,在接下來的16個周期內檢測數據線上“0”的個數,若“0”的個數超過8個或者10(根據具體情況設置),則認為是起始位到來,否則認為起始位沒有到來,繼續檢測傳輸線,等待起始位。
3、發送主要代碼
//============================================================================== //開始發送使能 //============================================================================== reg start_trig_reg1 ;//延遲一拍觸發信號 reg start_en ;//開始發送使能信號 always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)start_trig_reg1 <=1'b0;elsestart_trig_reg1 <= i_start_trig ;always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)start_en <= 1'b0 ;else if(!start_trig_reg1&&i_start_trig)//檢測觸發信號上升沿start_en <= 1'b1 ;elsestart_en <= 1'b0 ;//============================================================================== //波特率計算 //==============================================================================always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)time_cnt <= 10'h0 ;else if(crt_state==IDLE)time_cnt <= 10'b0 ;else if(time_cnt==10'd867) // 波特率率為115200 ,每一位的周期是8.68us=868個周期time_cnt <= 10'b0 ;elsetime_cnt <=time_cnt + 1'b1 ;//=============================================================================== //并串轉換,數據移位 //=============================================================================== always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)shift_data <= 10'h3ff;else if((time_cnt == 9'h0) && (next_state == SEND_START))shift_data <= {1'b1,i_tx_data[7:0],1'b0}; //time_cnt 每一次為0時,就需要移出一位數據到TX線上else if(time_cnt == 9'h0)shift_data <= {1'b1,shift_data[9:1]};elseshift_data <= shift_data;//============================================================================== // 奇偶校驗 //============================================================================== // 奇偶校驗位的產生,parity_cnt 為1 時,數據中1的個數為奇數,該位將在發送校驗位時 // 發送出去。計算過程是獨立的,屬于并行的流水線架構。 always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)parity_cnt <= 1'h0;else if(crt_state == IDLE)parity_cnt <= 1'h0;else if((time_cnt == 9'd10) && (crt_state == SEND_DATA))parity_cnt <= parity_cnt + shift_data[0];elseparity_cnt = parity_cnt; //=============================================================================== //檢測發送的位順序,位計數器 //=============================================================================== always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)bit_cnt <= 4'h0;else if(crt_state != next_state)bit_cnt<= 4'h0 ;else if(time_cnt == 10'd867)bit_cnt<= bit_cnt + 4'h1;elsebit_cnt <=bit_cnt;//------------------------------------------------------------------------------ //發送控制狀態機 //------------------------------------------------------------------------------ always @ (posedge i_100m_clk or negedge i_rst_n) beginif(!i_rst_n)crt_state <= IDLE;elsecrt_state <= next_state; endalways @ ( *)case(crt_state)IDLE :if( start_en )next_state = SEND_START;//進入發送起始位elsenext_state = crt_state;SEND_START :if((bit_cnt == 4'h0) && (time_cnt == 10'd867))//發送狀態必須保持完整的計數周期,每一位的時間嚴格保證next_state = SEND_DATA ;elsenext_state = crt_state; SEND_DATA :if((bit_cnt == 4'h7) && (time_cnt == 10'd867))//發送8位數據next_state = SEND_PARITY;elsenext_state = crt_state;SEND_PARITY :if((bit_cnt == 4'h0) && (time_cnt == 10'd867))//奇偶校驗位next_state = SEND_STOP;elsenext_state = crt_state;SEND_STOP :if((bit_cnt == 4'h0) && (time_cnt == 10'd400))//結束位的持續時間不是867個周期next_state = IDLE;elsenext_state = crt_state;default : next_state = IDLE;endcase//========================================================================== //數據發送 //============================================================================ always @ (posedge i_100m_clk or negedge i_rst_n)if(!i_rst_n)o_uart_tx_bit <= 1'b1;else if(crt_state[1] || crt_state[2]) //發送數據位和起始位o_uart_tx_bit <= shift_data[0]; else if(crt_state == SEND_PARITY) //發送奇偶校驗位o_uart_tx_bit <= parity_cnt; else o_uart_tx_bit <= 1'b1; //============================================================================== //發送完指示 //==============================================================================always @ (posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) o_tx_done<= 1'b0 ;else if(crt_state [4]) o_tx_done<= 1'b1 ; elseo_tx_done<= 1'b0 ; endmodule4、接收主要代碼
// 計時 //=============================================================== // 波特率為115200,每一位串行數據持續的周期數=1/115200s=8.68us=868*10ns,因此計數868個周期 reg [9:0] time_cnt ; reg [3:0] bit_cnt ;always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) time_cnt <= 10'b0 ;else if(crt_state==idle)time_cnt <= 10'b0 ;else if(time_cnt==10'd867) time_cnt <=10'b0 ;elsetime_cnt <=time_cnt+1'b1 ; always@(posedge i_100m_clk or negedge i_rst_n)//位計數器 if(!i_rst_n) bit_cnt <= 4'b0 ;else if(crt_state==idle)bit_cnt <=4'b0 ;else if(time_cnt==10'd867)bit_cnt <=bit_cnt+1'b1 ;elsebit_cnt <=bit_cnt ;//================================================================ //狀態機 //================================================================ always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) crt_state <= idle ;elsecrt_state <=next_state ;always@( * ) begincase(crt_state)idle : if( fall_edge ) next_state = start ;elsenext_state = crt_state ;start: if(bit_cnt==0&&time_cnt==10'd867) //起始位 next_state =data ;elsenext_state = crt_state ;data: if(bit_cnt==4'd9) //八位數據位next_state = stop ;elsenext_state =crt_state ; // parity: if(time_cnt==10'd867)next_state = stop ;elsenext_state = crt_state ;stop : if(time_cnt==10'd867)next_state = idle ;elsenext_state =crt_state ; default: next_state = idle ;endcaseend //====================================================================//串并轉換,移位輸出//==================================================================== reg [7:0] rx_data_reg1 ;always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n)rx_data_reg1 <= 8'b0 ;else if(crt_state[2]&&time_cnt==10'd435) rx_data_reg1 <= {serial_data_r2,rx_data_reg1[7:1]} ;else rx_data_reg1 <=rx_data_reg1 ;always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) o_rx_data <=8'b 0 ;else if(bit_cnt==4'd8&&time_cnt==10'd700) o_rx_data <=rx_data_reg1 ;elseo_rx_data <=o_rx_data ; ///=======數據輸出指示always@(posedge i_100m_clk or negedge i_rst_n) if(!i_rst_n) o_rx_finish <=1'b0 ;else if(bit_cnt==4'd9&&time_cnt==10'd700) o_rx_finish <=1'b1 ;elseo_rx_finish <=1'b0 ; endmodule總結
- 上一篇: FPGA硬件学习基础知识点总结(1)
- 下一篇: 二类医疗器械备案目录(二类医疗器械备案表