0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

UART的回環(huán)實(shí)例代碼設(shè)計(jì)

FPGA之家 ? 來源:FPGA之家 ? 作者:FPGA之家 ? 2022-07-10 09:20 ? 次閱讀

1.UART

UART是異步串行通信口的總稱。它所包含的RS232RS449RS423等等是對(duì)應(yīng)各種異步串行通信口的接口標(biāo)準(zhǔn)和總線標(biāo)準(zhǔn)。他們規(guī)定了通信口的電氣特性、傳輸速率、連接特性和機(jī)械特性等一系列內(nèi)容,實(shí)際上屬于通信網(wǎng)絡(luò)的底層概念,與通信協(xié)議沒有直接關(guān)系。

幾個(gè)相關(guān)名詞的解釋:

·波特率:每秒鐘傳送的bit的個(gè)數(shù)。

·起始位:先發(fā)出一個(gè)邏輯0的信號(hào),表示傳輸數(shù)據(jù)的開始。

·數(shù)據(jù)位:衡量通信中實(shí)際數(shù)據(jù)位的參數(shù),標(biāo)準(zhǔn)數(shù)據(jù)位可以是5、7、8位,從最低位開始傳輸。

·奇偶校驗(yàn)位:UART發(fā)送時(shí),檢查發(fā)送數(shù)據(jù)中“1”的個(gè)數(shù),自動(dòng)在奇偶校驗(yàn)位添加1/0,用于發(fā)送數(shù)據(jù)的校驗(yàn)。

·停止位:一個(gè)數(shù)據(jù)的結(jié)束標(biāo)志,可以為1位、1.5位、2位的高電平。

·空閑位:處于邏輯1狀態(tài),表示當(dāng)前線路上無數(shù)據(jù)傳輸。

·時(shí)序圖:

033fe9e2-ff1c-11ec-ba43-dac502259ad0.png

·發(fā)送數(shù)據(jù)過程:空閑狀態(tài),線路處于高電平,當(dāng)收到發(fā)送數(shù)據(jù)指令后,拉低電平一個(gè)數(shù)據(jù)位的時(shí)間,接著數(shù)據(jù)按從低位到高位依次發(fā)送,數(shù)據(jù)發(fā)送完畢,接著發(fā)送奇偶校驗(yàn)位和停止位(停止位為高電平),一幀數(shù)據(jù)發(fā)送結(jié)束。

·接收數(shù)據(jù)過程:空閑狀態(tài),線路處于高電平,當(dāng)檢測(cè)到線路的下降沿,說明線路有數(shù)據(jù)傳輸,按照約定的波特率從低位到高位接收數(shù)據(jù),數(shù)據(jù)接收完畢,接著接收并比較奇偶校驗(yàn)位是否正確,如果正確則通知接收端設(shè)備準(zhǔn)備接收數(shù)據(jù)或存入緩存。

由于UART是異步傳輸,沒有同步傳輸時(shí)鐘。為保證數(shù)據(jù)傳輸?shù)恼_性,每個(gè)數(shù)據(jù)有16個(gè)時(shí)鐘采樣,取中間的采樣值,以保證不會(huì)誤碼或滑碼。

·設(shè)計(jì)實(shí)例:

下面是一個(gè)UART的回環(huán)實(shí)例代碼設(shè)計(jì):

接收模塊uart_rx:

module uart_rx(    input rxd,    input clk,    output receive_ack,    output reg [7:0] data_i    );        parameter IDLE = 0;    parameter RECEIVE = 1;    parameter RECEIVE_END = 2;        reg [3:0] CS,NS;    reg [4:0] count;    reg [7:0] data_o_tmp;        always@(posedge clk)        CS <= NS;        always@(*) begin        NS <= CS;        case(CS)            IDLE:       if(!rxd) NS = RECEIVE;            RECEIVE:    if(count == 7) NS = RECEIVE_END;else NS = NS;            RECEIVE_END:NS = IDLE;            default:    NS = IDLE;        endcase    end        always@(posedge clk)        if(CS == RECEIVE)            count <= count + 1;        else if(CS == IDLE | CS == RECEIVE_END)            count <= 0;        always @(posedge clk)        if(CS == RECEIVE)begin            data_i[6:0] <= data_i[7:1];            data_i[7] <= rxd;        end            assign receive_ack = (CS == RECEIVE_END) ? 1 : 0;             endmodule
發(fā)送模塊uart_tx:

module uart_tx(    input [7:0] data_o,    input       clk,    input       receive_ack,    output reg  txd    );    parameter IDLE          = 0;    parameter SEND_START    = 1;    parameter SEND_DATA     = 2;    parameter SEND_END      = 3;        reg [3:0] CS,NS;    reg [4:0] count;    reg [7:0] data_o_tmp;        always @ (posedge clk)        CS <= NS;        always @ (*) begin        NS <= CS;        case(CS)            IDLE:       begin if(receive_ack) NS = SEND_START;  end            SEND_START: begin NS = SEND_DATA;                   end            SEND_DATA:  begin if(count == 7) NS = SEND_END;     end            SEND_END:   begin if(receive_ack) NS = SEND_START;  end            default:    NS = IDLE;        endcase    end        always @(posedge clk)        if(CS == SEND_START)            count <= count + 1;        else if(CS == IDLE | CS == SEND_END)            count <= 0;        else            count <= count;        always @(posedge clk)        if(CS == SEND_START)            data_o_tmp <= data_o;        else if(CS == SEND_DATA)            data_o_tmp[6:0] <= data_o_tmp[7:1];        always @(posedge clk)        if(CS == SEND_START)            txd <= 0;        else if(CS == SEND_DATA)            txd <= data_o_tmp;        else if(CS == SEND_END)            txd <= 1;            endmodulemodule uart_tx(    input [7:0] data_o,    input       clk,    input       receive_ack,    output reg  txd    );    parameter IDLE          = 0;    parameter SEND_START    = 1;    parameter SEND_DATA     = 2;    parameter SEND_END      = 3;        reg [3:0] CS,NS;    reg [4:0] count;    reg [7:0] data_o_tmp;        always @ (posedge clk)        CS <= NS;        always @ (*) begin        NS <= CS;        case(CS)            IDLE:       begin if(receive_ack) NS = SEND_START;  end            SEND_START: begin NS = SEND_DATA;                   end            SEND_DATA:  begin if(count == 7) NS = SEND_END;     end            SEND_END:   begin if(receive_ack) NS = SEND_START;  end            default:    NS = IDLE;        endcase    end        always @(posedge clk)        if(CS == SEND_START)            count <= count + 1;        else if(CS == IDLE | CS == SEND_END)            count <= 0;        else            count <= count;        always @(posedge clk)        if(CS == SEND_START)            data_o_tmp <= data_o;        else if(CS == SEND_DATA)            data_o_tmp[6:0] <= data_o_tmp[7:1];        always @(posedge clk)        if(CS == SEND_START)            txd <= 0;        else if(CS == SEND_DATA)            txd <= data_o_tmp;        else if(CS == SEND_END)            txd <= 1;            endmodule
特定波特率產(chǎn)生模塊clk_div:

module clk_div(    input clk,    output reg clk_out    );
    parameter baud_rata = 9600;parameterdiv_num='d125_000_000/baud_rata;//分頻數(shù)等于時(shí)鐘頻率除以想要得到的波特率    reg [15:0] num;
    always @(posedge clk) begin        if(num == div_num) begin            num <= 0;            clk_out <= 1;        end        else begin            num <= num + 1;            clk_out <= 0;        end    end
endmodule

頂層文件uart_top:

module uart_top(    input clk,inputrxd,outputtxd    );
    wire clk_9600;    wire receive_ack;    wire [7:0] data;
    uart_tx uart_tx    (        .clk        (clk_9600),        .txd        (txd),        .data_o     (data),        .receive_ack(receive_ack)    );
    uart_rx uart_rx    (        .clk        (clk_9600),        .rxd        (rxd),        .data_i     (data),        .receive_ack(receive_ack)    );
    clk_div clk_div    (        .clk        (clk),        .clk_out    (clk_9600)    );
endmodule

2.PS/2 PS/2是一種雙向同步串行通信協(xié)議。接口是一種6針的連接口,但只有四個(gè)引腳是有意義的,分別是Clock(時(shí)鐘)、Data(數(shù)據(jù))、VCC和GND。其中時(shí)鐘和數(shù)據(jù)引腳是雙向的。PS/2常用于連接某些輸入設(shè)備,例如鼠標(biāo)、鍵盤等。通信的兩端通過時(shí)鐘來同步,通過數(shù)據(jù)引腳來交換數(shù)據(jù)。任何一方想要抑制另外一方的通信,只需要將時(shí)鐘引腳拉低即可。 如果是PC和PS/2鍵盤之間通信,PC必須做主機(jī),即PC可以抑制鍵盤發(fā)送數(shù)據(jù),而鍵盤不能抑制PC發(fā)送數(shù)據(jù)。 PS/2的每一位數(shù)據(jù)幀包含11-12位,具體含義如下:

數(shù)據(jù)位名稱 說明
1個(gè)起始位 總是邏輯0
8個(gè)數(shù)據(jù)位 低位在前
1個(gè)奇偶校驗(yàn)位 奇校驗(yàn)
1個(gè)停止位 總是邏輯1
1個(gè)應(yīng)答位 僅用在主機(jī)對(duì)設(shè)備的通信中

·PS/2的時(shí)序圖:

03bf9700-ff1c-11ec-ba43-dac502259ad0.png

由設(shè)備產(chǎn)生時(shí)鐘和數(shù)據(jù),主機(jī)根據(jù)時(shí)鐘來讀取數(shù)據(jù)。以FPGA和PS/2鍵盤為例,鍵盤產(chǎn)生時(shí)鐘和數(shù)據(jù),F(xiàn)PGA只需要讀數(shù)據(jù)。當(dāng)時(shí)鐘下降沿時(shí),F(xiàn)PGA記錄數(shù)據(jù)信號(hào)。 ·設(shè)計(jì)實(shí)例: 主機(jī)為FPGA,根據(jù)PS/2的時(shí)序,得到鍵盤的按鍵值。雖然在時(shí)序圖中,主機(jī)是在時(shí)鐘下降沿讀取數(shù)據(jù),但實(shí)際上要為了排除噪聲干擾,需要在FPGA端對(duì)信號(hào)進(jìn)行濾波。下面給出設(shè)計(jì)代碼。

module ps2_keyboard(    input clk,    input clr,    input PS2C,       //ps2 clk in    input PS2D,       //ps2 data in        output [15:0] xkey);reg         PS2CF;reg         PS2DF;reg [7:0]   ps2c_filter;reg [7:0]   ps2d_filter;reg [10:0]  shift1;reg [10:0]  shift2;
assign xkey = { shift2[8:1], shift1[8:1] };always @(posedge clk or posedge clr) begin    if (clr) begin        ps2c_filter <= 11'b0;        ps2d_filter <= 11'b0;        PS2CF <= 1;        PS2DF <= 1;    end    else begin        ps2c_filter[7] <= PS2C;        ps2c_filter[6:0] <= ps2c_filter[7:1];        ps2d_filter[7] <= PS2D;        ps2d_filter[6:0] <= ps2d_filter[7:1];        if(ps2c_filter == 8'b1111_1111)            PS2CF <= 1;                         //去時(shí)鐘毛刺        else if(ps2c_filter == 8'b0000_0000)            PS2CF <= 0;        if(ps2d_filter == 8'b1111_1111)            PS2DF <= 1;                         //去數(shù)據(jù)毛刺        else if(ps2d_filter == 8'b0000_0000)            PS2DF <= 0;    endend
always @(negedge PS2CF or posedge clr) begin    if (clr) begin        shift1 <= 11'b0;        shift2 <= 11'b0;    end    else begin        shift1 <= {PS2DF, shift1[10:1]};        shift2 <= {shift1[0], shift2[10:1]};     endend
endmodule

原文標(biāo)題:常用通信協(xié)議總結(jié)及FPGA實(shí)現(xiàn)(上)

文章出處:【微信公眾號(hào):FPGA之家】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

審核編輯:彭靜

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • uart
    +關(guān)注

    關(guān)注

    22

    文章

    1219

    瀏覽量

    101121
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4723

    瀏覽量

    68236
  • 異步串行通信
    +關(guān)注

    關(guān)注

    0

    文章

    16

    瀏覽量

    8406
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    如何對(duì)RK代碼添加回環(huán)測(cè)試呢

    怎樣去解決RK系列出現(xiàn)網(wǎng)口丟包的問題呢?如何對(duì)RK代碼添加回環(huán)測(cè)試呢?
    發(fā)表于 03-02 06:36

    UART應(yīng)用中的實(shí)例代碼程序-UART In-Applic

    UART應(yīng)用中的實(shí)例代碼程序:A UART code loader provides in-system reprogrammability of program code spac
    發(fā)表于 01-23 23:04 ?66次下載

    UART 4 UART參考設(shè)計(jì),Xilinx提供VHDL代碼

    UART 4 UART參考設(shè)計(jì),Xilinx提供VHDL代碼 uart_vhdl This zip file contains the following folders
    發(fā)表于 06-14 08:57 ?114次下載

    UART參考設(shè)計(jì),帶16byte緩沖 VHDL代碼 xapp

    UART參考設(shè)計(jì),帶16byte緩沖 VHDL代碼 xapp223 These small UART transmitter and receiver macros of just 7 and 8
    發(fā)表于 06-14 09:00 ?33次下載

    Verilog 入門的實(shí)例代碼

    Verilog 入門的實(shí)例代碼,有需要的下來看看
    發(fā)表于 05-24 10:03 ?20次下載

    1768_UART_Test源代碼

    1768_UART_Test源代碼,下來看看
    發(fā)表于 06-07 10:41 ?13次下載

    LPC2368_UART代碼

    LPC2368_UART代碼,又需要的下來看看
    發(fā)表于 08-15 17:55 ?19次下載

    vhdl基礎(chǔ)實(shí)例代碼

    vhdl基礎(chǔ)實(shí)例代碼,感興趣的小伙伴們可以瞧一瞧。
    發(fā)表于 11-11 17:17 ?5次下載

    CAN—回環(huán)測(cè)試

    程序簡(jiǎn)介 -工程名稱:CAN回環(huán)測(cè)試 -實(shí)驗(yàn)平臺(tái): 秉火STM32 F429 開發(fā)板 -MDK版本:5.16 -ST固件庫(kù)版本:1.5.1 【 !】功能簡(jiǎn)介: 使用CAN回環(huán)模式進(jìn)行通訊實(shí)驗(yàn)。 學(xué)習(xí)
    發(fā)表于 12-13 15:35 ?31次下載

    python代碼示例之基于Python的日歷api調(diào)用代碼實(shí)例

    本文檔的主要內(nèi)容詳細(xì)介紹的是python代碼示例之基于Python的日歷api調(diào)用代碼實(shí)例。
    發(fā)表于 09-06 14:25 ?42次下載
    python<b class='flag-5'>代碼</b>示例之基于Python的日歷api調(diào)用<b class='flag-5'>代碼</b><b class='flag-5'>實(shí)例</b>

    RTC LCD UART的源代碼和工程文件免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是RTC LCD UART的源代碼和工程文件免費(fèi)下載
    發(fā)表于 01-03 16:22 ?4次下載
    RTC LCD <b class='flag-5'>UART</b>的源<b class='flag-5'>代碼</b>和工程文件免費(fèi)下載

    linux spi應(yīng)用層驅(qū)動(dòng)以及回環(huán)測(cè)試代碼

    linux spi應(yīng)用層驅(qū)動(dòng)以及回環(huán)測(cè)試代碼
    發(fā)表于 10-22 15:47 ?2次下載

    MPC82G516 MCU的串行UART示例代碼

    MPC82G516 MCU的串行UART示例代碼
    發(fā)表于 06-30 17:24 ?0次下載
    MPC82G516 MCU的串行<b class='flag-5'>UART</b>示例<b class='flag-5'>代碼</b>

    鴻蒙應(yīng)用實(shí)例代碼

    鴻蒙應(yīng)用實(shí)例代碼,僅供參考。
    發(fā)表于 09-27 14:56 ?12次下載

    代碼生成器配置和軟件UART的實(shí)現(xiàn)

    (RL78)上的具體的實(shí)現(xiàn)方法,這里略去工程的建立過程,相應(yīng)的驅(qū)動(dòng)程序細(xì)節(jié)可以參考代碼生成器生成的代碼,這里只重點(diǎn)講述代碼生成器配置和軟件UART的實(shí)現(xiàn)。
    的頭像 發(fā)表于 05-09 09:25 ?1469次閱讀
    <b class='flag-5'>代碼</b>生成器配置和軟件<b class='flag-5'>UART</b>的實(shí)現(xiàn)