您的位置 首页 发布

浅谈UART通信协议 UART接纳数据时序规划

浅谈UART通信协议 UART接收数据时序设计-UART通信的一帧一般由11到12位数据组成。1bit的起始位,检测为低电平表示数据开始传输;紧接着8bits的数据;然后是1bit的奇偶校验位,可以是奇校验或者偶校验;最后是1bit或2bits的停止位,必须为高电平,表示一个字符数据的传输结束。

串口通讯也是一个根底试验,是FPGA与电脑、单片机、DSP通讯的一种最简略的计划,对通讯速率要求不高时能够挑选UART通讯。您或许现已知道UART时序的操控、波特率的装备等方面的内容,但在实际运用时仍是会遇到一些问题,比方怎么才干恰当的和其它模块进行联接?为什么时序分明没问题,却无法和其它操控单元成功通讯?本文致力于全面解析在规划UART通讯时的思路办法。

UART通讯协议

UART通讯的一帧一般由11到12位数据组成。1bit的开端位,检测为低电平表明数据开端传输;紧接着8bits的数据;然后是1bit的奇偶校验位,能够是奇校验或许偶校验;最终是1bit或2bits的中止位,有必要为高电平,表明一个字符数据的传输完毕。

浅谈UART通讯协议 UART接纳数据时序规划

其间校验位是可选的,用来查验数据是否传输正确。假如有校验位,则需求保证收发两边挑选相同的一种查验办法。奇校验便是保证数据中的1是奇数,比方假如8bit数据中有3bits的1,校验方位0;假如有4bits的1,校验方位1。偶校验便是保证数据中的1是偶数。

浅谈UART通讯协议 UART接纳数据时序规划

波特率的装备

  波特率表明数据传输的速率,单位bps,表明位每秒。比方9600bps就表明1s能够传输9600bits的数据。异步收发没有时钟打拍来操控数据的传输,就需求保证收发两边在波特率设置上的共同。保证接纳数据的完好性。

  程序中一般运用16倍速率对UART通讯时序进行采样,则UART通讯所需的时钟便是16*bps,如9600bps通讯所需的驱动时钟巨细便是16*9600=153.6kHz。程序中能够运用一个计数器对体系时钟分频发生UART通讯时钟。

  // 分频生成UART通讯时钟

  always @(posedge clk50 or negedge rst_n)

  if (!rst_n) begin

  clkout 《=1‘b0;

  cnt《=0;

  end

  else if(cnt == 16’d162) begin //近似50%占空比

  clkout 《= 1‘b1;

  cnt 《= cnt + 16’d1;

  end

  else if(cnt == 16‘d325) begin //50M/(16*9600)

  clkout 《= 1’b0;

  cnt 《= 16‘d0;

  end

  else cnt 《= cnt + 16’d1;

UART发送数据时序规划

  一般咱们程序中都会规划一个UART发送数据的开端信号,对这个开端信号的处理办法和“FPGA根底规划(二):PS2键盘操控及短按、长按”这篇文章对按键有用信号处理的办法相同,选用一级存放,然后进行逻辑判别,然后发生一个时钟宽度的有用信号。那么当检测到有用信号时便能够发动UART发送数据的进程。

  // 检测发送指令wrsig的上升沿

  always @(posedge clk)

  begin

  wrsigbuf 《= wrsig;

  wrsigrise 《= (~wrsigbuf) & wrsig;

  end

  // 发动串口发送程序

  always @(posedge clk)

  if (wrsigrise && (~idle)) //当发送指令有用且线路为闲暇时,发动新的数据发送进程

  send 《= 1‘b1;

  else if(cnt == 8’d168) //一帧数据发送完毕

  send 《= 1‘b0;

  UART是按单bit发送的,因而在操控时序时能够运用一个计数器操控,在对应的计数位送出对应的数据。因为咱们运用的是16倍时钟采样,因而每个数据位之间的计数距离便是16,一次完好的发送进程如下所示:

  // 串口发送程序, 16个时钟发送一个bit

  always @(posedge clk or negedge rst_n)

  begin

  if (!rst_n) begin

  tx 《= 1’b0;

  idle 《= 1‘b0;

  cnt《=8’d0;

  presult《=1‘b0;

  end

  else if(send == 1’b1) begin

  case(cnt) //发生开端位

  8‘d0: begin

  tx 《= 1’b0;

  idle 《= 1‘b1;

  cnt 《= cnt + 8’d1;

  end

  8‘d16: begin

  tx 《= datain[0]; //发送数据0位

  presult 《= datain[0]^paritymode;

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d32: begin

  tx 《= datain[1]; //发送数据1位

  presult 《= datain[1]^presult;

  idle 《= 1‘b1;

  cnt 《= cnt + 8’d1;

  end

  8‘d48: begin

  tx 《= datain[2]; //发送数据2位

  presult 《= datain[2]^presult;

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d64: begin

  tx 《= datain[3]; //发送数据3位

  presult 《= datain[3]^presult;

  idle 《= 1‘b1;

  cnt 《= cnt + 8’d1;

  end

  8‘d80: begin

  tx 《= datain[4]; //发送数据4位

  presult 《= datain[4]^presult;

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d96: begin

  tx 《= datain[5]; //发送数据5位

  presult 《= datain[5]^presult;

  idle 《= 1‘b1;

  cnt 《= cnt + 8’d1;

  end

  8‘d112: begin

  tx 《= datain[6]; //发送数据6位

  presult 《= datain[6]^presult;

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d128: begin

  tx 《= datain[7]; //发送数据7位

  presult 《= datain[7]^presult;

  idle 《= 1‘b1;

  cnt 《= cnt + 8’d1;

  end

  8‘d144: begin

  tx 《= presult; //发送奇偶校验位

  presult 《= datain[0]^paritymode;

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d160: begin

  tx 《= 1‘b1; //发送中止位

  idle 《= 1’b1;

  cnt 《= cnt + 8‘d1;

  end

  8’d168: begin

  tx 《= 1‘b1;

  idle 《= 1’b0; //一帧数据发送完毕

  cnt 《= cnt + 8‘d1;

  end

  default: begin

  cnt 《= cnt + 8’d1;

  end

  endcase

  end

  else begin

  tx 《= 1‘b1;

  cnt 《= 8’d0;

  idle 《= 1‘b0;

  end

  end

UART接纳数据时序规划

  UART接纳数据的进程和发送数据的进程是恰好相反的。区别只在于UART发送的开端信号和发送数据端tx是从FPGA内部的其它模块发生的;而UART接纳的开端信号和接纳数据段rx送来的数据来自其它设备,因而需求对外部送来的信号进行监测。

  一帧数据的开端位是低电平有用,因而当检测到rx线上的下降沿时就表明数据通讯的开端:

  always @(posedge clk) //检测线路的下降沿

  begin

  rxbuf 《= rx;

  rxfall 《= rxbuf & (~rx);

  end

  // 发动串口接纳程序

  always @(posedge clk)

  if (rxfall && (~idle)) //检测到线路的下降沿而且原先线路为闲暇,发动接纳数据进程

  receive 《= 1‘b1;

  else if(cnt == 8’d168) //接纳数据完结

  receive 《= 1‘b0;

  接纳数据的进程和发送相同,用一个计数器来操控,这儿不再赘述。

发送与接纳数据的打包

  UART一次通讯只能完结一帧,即传输一个8bits的数据,但是咱们一般需求许多帧来组成一次完好的通讯。如一种简略常用的气候收集站通讯格局为:“FF(开端帧)+雨量+温度+湿度+气压+风速+风向+CRC校验+FE(完毕帧)”。这种情况下能够树立一组存放器专门存储发送或接纳的数据。比方发送时能够做如下处理:

  /********************************************/

  //存储待发送的串口信息

  /********************************************/

  reg [7:0] uart_ad [7:0]; //存储发送字符

  always @(clk)

  begin //界说发送的字符

  if(uart_stat==3‘b000) begin

  uart_ad[0]《=8’hFF;

  uart_ad[1]《=rain;

  uart_ad[2]《=temp;

  uart_ad[3]《=humi;

  uart_ad[4]《=winddir;

  uart_ad[5]《=windspeed;

  uart_ad[6]《=CRC16;

  uart_ad[7]《=8‘hFE;

  end

  end

  接纳的原理相似,只不过接纳是在通讯进程中接纳。这样咱们运用一个计数器操控,并检测串口通讯的状况,顺次将这组存放器中的值按发送次序传入UART发送数据模块即可。

  别的需求做好的一件事便是串口模块与其它模块的联接。咱们在树立好上述的存放器组之后,只要把数据来历填充到存放器组中对应的方位即可。但假如数据是从RAM、FIFO等模块中来的,在串口通讯时就应该对使能信号、FIFO空满信号等做出合理的判别和操控,就像“FPGA数据收集-传输-显现体系(一):1.2/50μs冲击电压丈量与显现”和“FPGA数据收集-传输-显现体系(二):根据FPGA的温度收集和以太网传输”两篇文章中做的相同。

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/fabu/339600.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部