首页 > 其他 > 详细

UART接口

时间:2020-06-07 00:17:55      阅读:64      评论:0      收藏:0      [点我收藏+]

一、什么是UART以及UART的运用

 在计算机的数据通信中,外设一般不能与计算机直接相连,它们之间的信息交换主要存在以下问题:

  (1)速度不匹配。外设的工作速度和计算机的工作速度不一样,而且外设之间的工作速度差异也比较大。

  (2)数据格式不匹配。不同的外设在进行信息存储和处理时的数据格式可能不同,例如最基本的数据格式可分为并行数据和串行数据。

  (3)信息类型不匹配。不同的外设可能采用不同类型的型号,有些是模拟信号,有些是数字信号,因此采用的处理方式也不同。

  为了解决外设和计算机之间的信息交换问题,即需要设计一个信息交换的中间环节——接口。UART控制器是最常用的接口。

  通用异步收发器(Universal Asynchronotls Receiv—er/Transmitter,UART)是辅助计算机与串行设备之间的通信,作为RS 232通信接口的一个重要的部分,目前大部分的处理器都集成了UART。

二、UART的通信协议

                            技术分享图片

 

 

 

   

由于数字图像亚像素在计算机中是用8位二进制表示,因此UART传输的有效数据位为8位。(资料位的个数可以是4、5、6、7、8等,构成一个字符。通常采用ASCII码。)传输线在空闲时为高电平,因此有效数据流的开始位设为0。接着传输8位有效数据位,先从最低位开始传送。

  奇偶检验位可以设置为奇检验、偶校验或者不设置校验位,由于本系统使用的传输速率不高,为了加快开发进程,减少电路面积,因此没有设计奇偶检验模块,数据流中不设奇偶检验位。最后停止位为高电平。

由于UART是异步传输,没有传输同步时钟,为了保证数据的正确性,UART采用16倍数据波特率的时钟进行采样。每个数据有16个时钟采样,取中间的采样值,以保证采样不会滑码或误吗。一般UART一帧的数据位数为8,这样即使每个数据有一个时钟的误差,接收端也能正确地采样到数据。
  UART的接收数据时序为:当检测到数据的下降沿时,表明线路上有数据进行传输,这是计数器CNT开始计数,当计数器为24=16+8时,(对24的由来的理解,由于萌新,可能会理解错,忘提醒。16是采样起始位时所用的时钟数,由于采样时采集中间的信号,所以加8)采样的值为第0位数据;当计数器的值为40时,采样的值为第一位数据,依次类推,进行后面6个数据的采样。如果需要进行奇偶校验,则当计数器的值为152时,采样的值即为奇偶位;当计数器的值为168时,采样的值为“1”表示停止位,数据接收完成。

三、Verilog实现UART

技术分享图片

 

 

 实现电路图,参考的小梅哥FPGA的设计理念

module  uart_tx(
        input                   clk                             ,//50M
        input                   rst_n                           ,
        input         [ 7: 0]   data_byte                       ,
        input                   send_en                         ,
        input         [ 3: 0]   baud_set                        ,
        output  reg             rs232_tx                        ,
        output  reg             tx_done                         ,
        output  wire            uart_state 
);
//======================================================================//************** Define Parameter and Internal Signals *****************
//======================================================================/
localparam                      BEGIN_BIT       =   1b0        ;
localparam                      STOP_BIT        =   1b1        ;
localparam                      DATA_BITS       =   10          ;
localparam                      BAUD_RATE_9600  =   5208        ;
localparam                      BAUD_RATE_19200 =   2604        ;
localparam                      BAUD_RATE_38400 =   1302        ;
localparam                      BAUD_RATE_115200=   434         ;

reg     [12: 0]                 BAUD_RATE                       ;

reg                             bps_clk                         ;
reg     [ 7: 0]                 data_byte_reg                   ;

reg                             flag_send                       ;

wire    [10: 0]                 tx_data_temp                    ;

reg     [19: 0]                 cnt0                            ;
wire                            add_cnt0                        ;
wire                            end_cnt0                        ;

reg     [ 3: 0]                 cnt1                            ;
wire                            add_cnt1                        ;
wire                            end_cnt1                        ;



//======================================================================//**************************** Main Code *******************************
//======================================================================/
//data_byte_reg,寄存data_byte
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        data_byte_reg   <=  8d0;
    end
    else if(send_en)begin
        data_byte_reg   <=  data_byte;
    end
end

//BAUD_RATE
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        BAUD_RATE   <= BAUD_RATE_9600; 
    end
    else begin
        case(baud_set)
            4d0:   BAUD_RATE   <= BAUD_RATE_9600;
            4d1:   BAUD_RATE   <= BAUD_RATE_19200;
            4d2:   BAUD_RATE   <= BAUD_RATE_38400;
            4d3:   BAUD_RATE   <= BAUD_RATE_115200;
            default:BAUD_RATE   <= BAUD_RATE_9600;
        endcase
    end
end

//flag_send
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        flag_send   <=  1b0;
    end
    else if(send_en)begin
        flag_send   <=  1b1;
    end
    else if(tx_done)begin
        flag_send   <=  1b0;
    end
end

//cnt0
always @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        cnt0 <= 0;
    end
    else if(add_cnt0)begin
        if(end_cnt0)
            cnt0 <= 0;
        else
            cnt0 <= cnt0 + 1;
    end
    else begin
        cnt0 <= 0;
    end
end

assign  add_cnt0        =       flag_send;
assign  end_cnt0        =       add_cnt0 && cnt0 == BAUD_RATE-1;

//cnt1
always @(posedge clk or negedge rst_n)begin 
    if(!rst_n)begin
        cnt1 <= 0;
    end
    else if(add_cnt1)begin
        if(end_cnt1)
            cnt1 <= 0;
        else
            cnt1 <= cnt1 + 1;
    end
end

assign  add_cnt1        =       end_cnt0;
assign  end_cnt1        =       add_cnt1 && cnt1 == DATA_BITS-1;

//tx_done
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        tx_done <=  1b0;
    end
    else if(end_cnt1)begin
        tx_done <=  1b1;
    end
    else begin
        tx_done <=  1b0;
    end
end

//bps_clk
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        bps_clk <=  1b0;
    end
    else if(cnt0 == 1b1)begin
        bps_clk <=  1b1;
    end
    else begin
        bps_clk <=  1b0;
    end
end

//tx_data_temp
assign  tx_data_temp    =   {STOP_BIT, data_byte_reg, BEGIN_BIT };

//rs232_tx 串行发送数据
always  @(posedge clk or negedge rst_n)begin
    if(!rst_n)begin
        rs232_tx    <=  1b1;
    end
    else if(flag_send && bps_clk)begin
        rs232_tx    <=  tx_data_temp[cnt1]; 
    end
    else if(!flag_send)begin
        rs232_tx    <=  1b1;
    end
end

//uart_state
assign  uart_state  =   flag_send;

endmodule

技术分享图片供参考,如有错误欢迎留言探讨

 

UART接口

原文:https://www.cnblogs.com/darlingsansan/p/13057592.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!