精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

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

如何實現(xiàn)串口數(shù)據(jù)的接收呢?

冬至子 ? 來源:兩猿社 ? 作者:IC猿 ? 2023-06-05 15:24 ? 次閱讀

00 簡介

UART接收數(shù)據(jù)部分是接收另一個串口設(shè)備發(fā)送的數(shù)據(jù),緩存到接收FIFO中。FIFO快要寫滿時,產(chǎn)生中斷通知CPU拿取數(shù)據(jù),實現(xiàn)串口數(shù)據(jù)的接收。

模塊涉及到兩個時鐘域,ARM時鐘和26MHz功能時鐘。其中 接收FIFO讀寫邏輯是ARM時鐘域,接收數(shù)據(jù)狀態(tài)機和同步邏輯等是功能時鐘域

01 模塊接口與描述

1.jpg

2.jpg

02 實現(xiàn)

UART_RX模塊主要由三部分組成: 配置信息同步接收狀態(tài)機接收數(shù)據(jù)FIFO控制

配置信息是reg_if模塊由APB總線配置寄存器產(chǎn)生,功能時鐘域做兩級同步處理。

接收狀態(tài)機是根據(jù)串口協(xié)議劃分,分為IDLE、START、RX_DATA、CHECK_DATA、STOP和SEND六種狀態(tài)。

接收數(shù)據(jù)FIFO控制部分將接收完成的數(shù)據(jù)寫入到FIFO,在CPU讀取RX_FIFO寄存器時將FIFO數(shù)據(jù)讀出送到RX_FIFO寄存器。

  • 配置信息同步

由于配置信息是由ARM時鐘產(chǎn)生,到接收模塊的功能時鐘域需要做同步處理。配置信息是電平信號,通常不會像數(shù)據(jù)一樣變化快,所以只需要兩級同步。

  • 接收狀態(tài)產(chǎn)生

接收數(shù)據(jù)停止位狀態(tài)指示st_error和接收數(shù)據(jù)校驗位狀態(tài)指示p_error是串口校驗位和停止位檢測狀態(tài)指示。前者為1表示停止位錯誤;后者為1表示校驗位錯誤。兩個狀態(tài)位都會傳到reg_if模塊,指示URAT當前狀態(tài),供CPU查詢。當CPU發(fā)現(xiàn)停止位或者校驗位錯誤時,會決定當前數(shù)據(jù)的處理方式(丟棄或者接受),清除狀態(tài)位(即寫1清0)。reg_if模塊發(fā)現(xiàn)該狀態(tài)位清除后,會回送一個ack到接收模塊,即st_error_ack和p_error_ack。接收模塊接收到ack后釋放狀態(tài)指示st_error和p_error,繼續(xù)接收數(shù)據(jù)。

這個過程就是狀態(tài)位的握手,本模塊設(shè)計方式是握手期間,即發(fā)現(xiàn)校驗位或者停止位錯誤后停止接收數(shù)據(jù),直到CPU清除狀態(tài)后才開始正常接收。讀者可以根據(jù)自己的需要判斷錯誤后是否繼續(xù)接收數(shù)據(jù)。

  • 接收狀態(tài)機

使用典型的三段式狀態(tài)機設(shè)計,包含六種狀態(tài),IDLE、START、RX_DATA、CHECK_DATA、STOP和SEND。

圖片

uart接收狀態(tài)轉(zhuǎn)移圖

IDLE:狀態(tài)機從IDLE狀態(tài)開始,檢測到uart_i的下降沿,進入START狀態(tài)。

START:START狀態(tài)起始位是否為低(避免毛刺觸發(fā)狀態(tài)機),起始位正常即進入RX_DATA開始接收數(shù)據(jù)。RX_DATA:接收滿8bit后判斷是否使能校驗位,如使能,進入CHECK_DATA狀態(tài)進行奇偶校驗的判斷;如不使能,直接進入停止狀態(tài)STOP。

CHECK_DATA:CHECK_DATA狀態(tài)判斷奇偶校驗是否正確,不正確則發(fā)出p_error信號,在狀態(tài)寄存器指示校驗錯誤,待CPU處理返回p_error_ack后回到IDLE狀態(tài)。如果正確,判斷是否使能停止位檢查;使能停止位檢查則跳轉(zhuǎn)到STOP狀態(tài);不使能則跳轉(zhuǎn)到SEND狀態(tài)。

STOP:同樣的,在STOP狀態(tài)檢測停止位是否是高電平。如果是,表示停止位正確,跳轉(zhuǎn)到SEND狀態(tài);如果不是,則發(fā)出st_error信號,在狀態(tài)寄存器指示停止位錯誤,待CPU處理返回st_error_ack后回到IDLE狀態(tài)。

SEND:SEND狀態(tài)主要是產(chǎn)生rx_start信號表示8bits數(shù)據(jù)接收正確,可以將數(shù)據(jù)寫到接收FIFO。

前兩段狀態(tài)機,狀態(tài)跳轉(zhuǎn):

// state to nextstate with clk in this block.
always@(posedge clk26m ornegedge rst26m_)begin
    if(!rst26m_) begin
        state <= IDLE;
    end
    elsebegin
        state <= nextstate;
    end
end

// nextstate transform
always@(*) begin
    case(state)
    IDLE: begin
        if(neg_urxd_i) begin
            nextstate = START;
        end
        elsebegin
            nextstate = IDLE;
        end
    end
    START: begin
        if(start_right) begin// start bit is right,then reserve data
            nextstate = RX_DATA;
        end
        elsebegin
            nextstate = IDLE;
        end
    end
    RX_DATA: begin
        if(data_cnt < 4'd8) begin// reserve 8 datas
            nextstate = RX_DATA;
        end
        elsebegin
            if(rx_bpsclk) begin
                if(check_syn2) begin
                    nextstate = CHECK_DATA;
                end
                elsebegin
                    nextstate = STOP;
                end
            end
            elsebegin
                nextstate = RX_DATA;
            end
        end
    end
    CHECK_DATA: begin
        if(p_error_ack_delay2) begin
            nextstate = IDLE;
        end
        elsebegin
            if(rx_bpsclk) begin
		            // p_error:1:parity bit error,0:parity bit error
		            if(p_error) begin
		                nextstate = CHECK_DATA;
		            end
		            elsebegin
		                // st_check:1:check stop bit,0:don't check stop bit
		                if(st_check_syn2) begin
		                    nextstate = STOP;
		                end
		                elsebegin
		                    nextstate = SEND;
		                end
		            end
		        end
		        elsebegin
		            nextstate = CHECK_DATA;
		        end
        end
    end
    STOP: begin
        if(st_error_ack_delay2) begin
            nextstate = IDLE;
        end
        elsebegin
            if(rx_bpsclk) begin
		            // st_error:1:stop bit error,0:stop bit error
		            if(st_error) begin
		                nextstate = STOP;
		            end
		            elsebegin
		                nextstate = SEND;
		            end
		        end
		        elsebegin
		            nextstate = STOP;
		        end
        end
    end
    SEND: begin
        if(rx_ack_delay2) begin
            nextstate = IDLE;
        end
        elsebegin
            nextstate = SEND;
        end
    end
    default: begin
        nextstate = IDLE;
    end
    endcase
end

第三段狀態(tài)機,信號賦值:

// output signal state
always@(posedge clk26m ornegedge rst26m_) begin
    if(!rst26m_) begin
        rx_bpsen <= 1'b0;
        data_rx  <= 8'd0;
        data_cnt <= 4'd0;
        p_error  <= 1'b0;
        st_error <= 1'b0;
        rx_start <= 1'b0;
        start_right <= 1'b0;
    end
    elsebegin
        case(nextstate)
        IDLE: begin
            rx_bpsen    <= 1'b0;
            data_cnt    <= 4'd0;
            st_error    <= 1'b0;
            p_error     <= 1'b0;
            rx_start    <= 1'b0;
            start_right <= 1'b0;
        end
        START: begin
            rx_bpsen    <= 1'b1;
            if(rx_bpsclk) begin
                if(urxd_i == 1'b0) begin
                    start_right <= 1'b1;
                end
                elsebegin
                    start_right <= 1'b0;
                end
            end
        end
        RX_DATA: begin
            if(rx_bpsclk) begin
                data_rx[data_cnt] <= urxd_i;
                data_cnt <= data_cnt + 1'b1;
            end
        end
        CHECK_DATA: begin
            if(rx_bpsclk) begin
                // odd check
                if(parity_syn2) begin
                    if(^data_rx == urxd_i) begin// odd check is wrong
                        p_error  <= 1'b1;
                        rx_bpsen <= 1'b0;
                    end
                end
                // even check
                elsebegin
                    if(^data_rx == !urxd_i) begin// even check is wrong
                        p_error  <= 1'b1;
                        rx_bpsen <= 1'b0;
                    end
                end
            end
        end
        STOP: begin
            if(rx_bpsclk) begin
                if(urxd_i == 1'b0) begin// stop bit is wrong
                    st_error <= 1'b1;
                    rx_bpsen <= 1'b0;
                end
            end
        end
        SEND: begin
            rx_start <= 1'b1;
        end
        endcase
    end
end
  • 接收數(shù)據(jù)FIFO控制

接收狀態(tài)機的SEND狀態(tài)表示1Byte數(shù)據(jù)接收完成,此狀態(tài)會產(chǎn)生一個rx_start信號。

FIFO寫控制部分通過監(jiān)控此信號產(chǎn)生寫使能rx_fifo_winc(1個ARM時鐘周期)和接收響應(yīng)rx_ack,SEND狀態(tài)發(fā)現(xiàn)rx_ack后釋放rx_start,回到IDLE狀態(tài)。由于FIFO寫控制是在ARM時鐘域進行,握手的時間很短,不會對接收下一Byte數(shù)據(jù)產(chǎn)生影響。

// this state machine to send data to RX FIFO
always@(posedge clk ornegedge rst_) begin
    if(!rst_) begin
        rx_ack       <= 1'b0;
        rx_fifo_winc <= 1'b0;
        wdata_state  <= 2'b0;
    end
    elsebegin
        case(wdata_state)
        2'b00: begin
            if(!rx_fifo_wfull && rx_start_delay2) begin
                rx_ack       <= 1'b1;
                rx_fifo_winc <= 1'b1;
                wdata_state  <= 2'b01;
            end
        end
        2'b01: begin
            rx_fifo_winc    <= 1'b0;
            if(!rx_start_delay2) begin
                rx_ack      <= 1'b0;
                wdata_state <= 2'b10;
            end
        end
        2'b10: begin
            wdata_state <= 2'b0;
        end
        endcase
    end
end

FIFO讀邏輯放在reg_if模塊,APB讀RX_DATA寄存器時,產(chǎn)生讀使能信號,F(xiàn)IFO將數(shù)據(jù)放到寄存器中。

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

    關(guān)注

    2

    文章

    492

    瀏覽量

    27478
  • FIFO存儲
    +關(guān)注

    關(guān)注

    0

    文章

    103

    瀏覽量

    5963
  • UART接口
    +關(guān)注

    關(guān)注

    0

    文章

    124

    瀏覽量

    15268
  • 時鐘域
    +關(guān)注

    關(guān)注

    0

    文章

    52

    瀏覽量

    9529
  • 狀態(tài)寄存器
    +關(guān)注

    關(guān)注

    0

    文章

    38

    瀏覽量

    7073
收藏 人收藏

    評論

    相關(guān)推薦

    stm32串口是如何實現(xiàn)接收不定長度數(shù)據(jù)

    1.不定長度數(shù)據(jù)為什么會存在串口接收不定長度數(shù)據(jù)?首先,在通信雙方進行數(shù)據(jù)傳輸?shù)臅r候,由于不同
    發(fā)表于 08-11 08:18

    如何去實現(xiàn)STM32串口發(fā)送數(shù)據(jù)接收數(shù)據(jù)

    串口發(fā)送數(shù)據(jù)最直接的方式是什么?如何去實現(xiàn)STM32串口發(fā)送數(shù)據(jù)接收
    發(fā)表于 12-07 06:03

    如何去實現(xiàn)STM32的USART串口接收數(shù)據(jù)處理

    如何去實現(xiàn)STM32的USART串口接收數(shù)據(jù)處理?其代碼程序該如何去實現(xiàn)
    發(fā)表于 12-09 07:30

    如何實現(xiàn)串口USART2的發(fā)送和接收功能

    如何實現(xiàn)串口USART2的發(fā)送和接收功能?如何實現(xiàn)USART2中斷接收任意長度和任意格式的
    發(fā)表于 01-20 06:16

    net2.0實現(xiàn)串口GPS數(shù)據(jù)接收設(shè)計應(yīng)用

    net2.0實現(xiàn)串口GPS數(shù)據(jù)接收設(shè)計應(yīng)用
    發(fā)表于 02-08 16:42 ?25次下載

    python串口接收數(shù)據(jù)

    本文主要介紹了python串口接收數(shù)據(jù)。其中涉及了Python使用線程來接收串口數(shù)據(jù),以及pyt
    發(fā)表于 01-15 09:52 ?4.6w次閱讀
    python<b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>

    labview串口接收數(shù)據(jù)_labview串口被動接收數(shù)據(jù)

    字節(jié)的數(shù)據(jù)。最后,用一個狀態(tài)機來實現(xiàn)相鄰兩個字符串的判斷。如果串口在相鄰兩個字符串之間接收時間大于50ms,則判斷為兩個獨立的字符串;如果小于50ms,則自動拼接前后兩個字符串。
    發(fā)表于 01-15 15:49 ?6.6w次閱讀
    labview<b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>_labview<b class='flag-5'>串口</b>被動<b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>

    MCU-串口接收實現(xiàn)

    MCU-串口接收實現(xiàn)例程倉庫:https://gitee.com/ll0_0ll/MCU-UART1.串口接收中斷+空閑中斷空閑中斷是接受
    發(fā)表于 10-25 10:36 ?12次下載
    MCU-<b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>實現(xiàn)</b>

    stm32 串口接收不定長度數(shù)據(jù)及黏包處理 + 串口DMA接收

    1.不定長度數(shù)據(jù) 為什么會存在串口接收不定長度數(shù)據(jù)?首先,在通信雙方進行數(shù)據(jù)傳輸?shù)臅r候,由于不
    發(fā)表于 12-23 19:09 ?27次下載
    stm32 <b class='flag-5'>串口</b><b class='flag-5'>接收</b>不定長度<b class='flag-5'>數(shù)據(jù)</b>及黏包處理 + <b class='flag-5'>串口</b>DMA<b class='flag-5'>接收</b>

    STM32—無需中斷來實現(xiàn)使用DMA接收串口數(shù)據(jù)

    如何來優(yōu)化?比如四軸飛行器,當在不停地獲取姿態(tài)控制方向時,又要去接收串口數(shù)據(jù).答:使用DMA,無需CPU中斷便能實現(xiàn)接收
    發(fā)表于 12-24 19:01 ?8次下載
    STM32—無需中斷來<b class='flag-5'>實現(xiàn)</b>使用DMA<b class='flag-5'>接收</b><b class='flag-5'>串口</b><b class='flag-5'>數(shù)據(jù)</b>

    STM32之串口DMA接收不定長數(shù)據(jù)

    目錄STM32之串口DMA接收不定長數(shù)據(jù)引言DMA簡介什么是DMA在STM32的DMA資源DMA接收數(shù)據(jù)判斷
    發(fā)表于 12-24 19:03 ?30次下載
    STM32之<b class='flag-5'>串口</b>DMA<b class='flag-5'>接收</b>不定長<b class='flag-5'>數(shù)據(jù)</b>

    stm32 發(fā)送完數(shù)據(jù)串口繼續(xù)發(fā)送_STM32之串口DMA接收不定長數(shù)據(jù)

    引言在使用stm32或者其他單片機的時候,會經(jīng)常使用到串口通訊,那么如何有效地接收數(shù)據(jù)?假如這段數(shù)據(jù)是不定長的有如何高效
    發(fā)表于 12-24 19:17 ?8次下載
    stm32 發(fā)送完<b class='flag-5'>數(shù)據(jù)</b>后 <b class='flag-5'>串口</b>繼續(xù)發(fā)送_STM32之<b class='flag-5'>串口</b>DMA<b class='flag-5'>接收</b>不定長<b class='flag-5'>數(shù)據(jù)</b>

    如何有效地使用串口通訊接收數(shù)據(jù)

    在使用stm32或者其他單片機的時候,會經(jīng)常使用到串口通訊,那么如何有效地接收數(shù)據(jù)?假如這段數(shù)據(jù)是不定長的有如何高效
    的頭像 發(fā)表于 02-14 09:50 ?2637次閱讀
    如何有效地使用<b class='flag-5'>串口</b>通訊<b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>

    串口接收數(shù)據(jù)的兩種方式是什么

    上方是發(fā)送數(shù)據(jù)的例子,那么串口接收又該如何配置,又要在串口發(fā)送的例子上做哪些更改? 這里我們可以通過查詢或者中斷的方式來進行
    的頭像 發(fā)表于 11-10 16:20 ?2224次閱讀
    <b class='flag-5'>串口</b><b class='flag-5'>接收</b><b class='flag-5'>數(shù)據(jù)</b>的兩種方式是什么

    基于RA2L1實現(xiàn)串口DTC數(shù)據(jù)接收

    基于RA2L1實現(xiàn)串口DTC數(shù)據(jù)接收
    的頭像 發(fā)表于 10-10 09:34 ?490次閱讀
    基于RA2L1<b class='flag-5'>實現(xiàn)</b><b class='flag-5'>串口</b>DTC<b class='flag-5'>數(shù)據(jù)</b><b class='flag-5'>接收</b>