1.接收原理和思路

初步思路:除发送位和停止位外,在数据位的每一位数据的中间时刻进行采样,读取到高电平或者低电平,如图所示:图中读取到的数据位为0110(左至右)

但是,倘若有外界干扰,忽然将某数据位的电平拉低了一瞬间,如图:此时再在各个数据位的中间时刻检测会检测到:0010(从左至右)很显然是错误的。

解决办法:在每一位的数据位上进行多次采样,然后比较0和1的概率。1的概率大就为高电平,0的概率大就为低电平。

然后还需要检测起始位,怎么检测起始位呢?边缘检测电路!边缘检测电路原理如下:

当波形2的第一个上升沿检测到波形 1的的值为1,第二个上升沿检测到波形1的值为0时,就说明其产生了下降沿。边缘检测电路由两个触发器构成,如图所示:

接下来就可以开始代码编写啦!

源文件代码:

module uart_tx(input clk,input uart_rx, //从外部接收到的数据input rst,//复位input [2:0] Baud_set,//选择接收数据的波特率,要和发送数据的波特率一致output reg [7:0] Rx_Data, //最后我们看到的数据output reg Rx_Done);reg Rx_En;//开始接收数据 //设置波特率
reg [17:0] Baud;
always@(Baud_set)
case(Baud_set)3'd0:Baud=18'd166666;//波特率为3003'd1:Baud=18'd41666;//波特率为12003'd2:Baud=18'd20833;//波特率为24003'd3:Baud=18'd5208;//波特率为96003'd4:Baud=18'd2604;//波特率为192003'd5:Baud=18'd1302;//波特率为384003'd6:Baud=18'd868;//波特率为576003'd7:Baud=18'd434;//波特率为115200
endcase //波特率分频
reg [17:0] counter_Baud;
always@(posedge clk or negedge rst)if(!rst) counter_Baud<=0;else if(Rx_En)beginif(counter_Baud==Baud-1) counter_Baud<=0;else counter_Baud<=counter_Baud+1;endelse counter_Baud<=0;//检测起始位
reg [1:0] Detect;
always@(posedge clk or negedge rst)if(!rst) Detect<=2'b00;else if(!Rx_En)beginDetect[0] <= uart_rx;Detect[1] <= Detect[0];endelse Detect<=2'b00;//控制En
always@(posedge clk or negedge rst) if(!rst)  Rx_En<=0;else if(Detect==2'b10) Rx_En<=1;else if(Rx_Done) Rx_En<=0;else Rx_En<=Rx_En;    //设置采样时钟
//每位数据为分成16段,舍弃前5段后4段,取中间7段进行采样
reg [7:0] counter_1;   //对采样次数进行计数
reg [4:0] counter_time; //counter_time计时到24时(1s/115200/16/20=24),为一个时间间隔
wire [14:0] caiyang;  // 每位数据为分成16段,每一小段的时间为1s/115200/16,故每一小段的计数值为1s/115200/20/16=Baud/16;
assign caiyang = Baud/16;
always@(posedge clk or negedge rst) if(!rst) counter_time<=0;else if(Rx_En==1 )beginif(counter_time==caiyang-1)  counter_time<=0;else counter_time<=counter_time+1;endelse if(Rx_Done)  counter_time<=0;else counter_time<=0;
always@(posedge clk or negedge rst) if(!rst) counter_1<=0;else if(Rx_En==1)beginif(counter_1==160 && counter_time==18)  counter_1<=0;else if(counter_time==caiyang-1) counter_1<=counter_1+1;else counter_1<=counter_1;endelse if(Rx_Done)  counter_1<=0;   else counter_1<=0;  wire clk_16_caiyang;assign clk_16_caiyang = (counter_time==caiyang/2);//开始采样reg [3:0] x_bit [7:0]; //定义一个二维数组,该二维数组里面有7个元素,分别表示8个数据位,每个元素位宽三位 reg [3:0] start;//起始位reg [3:0] stop;//停止位always@(posedge clk or negedge rst)if(!rst) beginstart<=0;stop<=0;x_bit[0]<=0;x_bit[1]<=0;x_bit[2]<=0;x_bit[3]<=0;x_bit[4]<=0;x_bit[5]<=0;x_bit[6]<=0;x_bit[7]<=0;endelse if(clk_16_caiyang)begincase(counter_1)0: beginstart<=0;stop<=0;x_bit[0]<=0;x_bit[1]<=0;x_bit[2]<=0;x_bit[3]<=0;x_bit[4]<=0;x_bit[5]<=0;x_bit[6]<=0;x_bit[7]<=0;end5,6,7,8,9,10,11:start<=start+uart_rx;21,22,23,24,25,26,27:x_bit[0]<=x_bit[0]+uart_rx;37,38,39,40,41,42,43:x_bit[1]<=x_bit[1]+uart_rx;53,54,55,56,57,58,59:x_bit[2]<=x_bit[2]+uart_rx;69,70,71,72,73,74,75:x_bit[3]<=x_bit[3]+uart_rx;85,86,87,88,89,90,91:x_bit[4]<=x_bit[4]+uart_rx;101,102,103,104,105,106,107:x_bit[5]<=x_bit[5]+uart_rx;117,118,119,120,121,122,123:x_bit[6]<=x_bit[6]+uart_rx;133,134,135,136,137,138,139:x_bit[7]<=x_bit[7]+uart_rx;149,150,151,152,153,154,155:stop<=stop+uart_rx;default: beginstart<=start;x_bit[0]<=x_bit[0];x_bit[1]<=x_bit[1];x_bit[2]<=x_bit[2];x_bit[3]<=x_bit[3];x_bit[4]<=x_bit[4];x_bit[5]<=x_bit[5];x_bit[6]<=x_bit[6];x_bit[7]<=x_bit[7]; stop<=stop;endendcaseendelse beginstart<=start;x_bit[0]<=x_bit[0];x_bit[1]<=x_bit[1];x_bit[2]<=x_bit[2];x_bit[3]<=x_bit[3];x_bit[4]<=x_bit[4];x_bit[5]<=x_bit[5];x_bit[6]<=x_bit[6];x_bit[7]<=x_bit[7]; stop<=stop;end//控制Rx_Donealways@(posedge clk or negedge rst)  if(!rst) Rx_Done<=0;else if(counter_1==160&&counter_time==18) Rx_Done<=1;else Rx_Done<=0; //判断采样得到的数据并且进行赋值reg Data_start;reg Data_stop;always@(posedge clk or negedge rst)if(!rst) Rx_Data<=0;else if(counter_1==159)beginData_start<=(start>=3'd4)?1'b1:1'd0;Data_stop<=(stop>=3'd4)?1'b1:1'd0;Rx_Data[0]<=(x_bit[0]>=3'd4)?1'b1:1'd0;Rx_Data[1]<=(x_bit[1]>=3'd4)?1'b1:1'd0;Rx_Data[2]<=(x_bit[2]>=3'd4)?1'b1:1'd0;Rx_Data[3]<=(x_bit[3]>=3'd4)?1'b1:1'd0;Rx_Data[4]<=(x_bit[4]>=3'd4)?1'b1:1'd0;Rx_Data[5]<=(x_bit[5]>=3'd4)?1'b1:1'd0;Rx_Data[6]<=(x_bit[6]>=3'd4)?1'b1:1'd0; Rx_Data[7]<=(x_bit[7]>=3'd4)?1'b1:1'd0;           endelse Rx_Data<=Rx_Data;
endmodule

激励文件代码:

module uart_rx_tb();reg clk;reg uart_rx; //从外部接收到的数据reg rst;//复位reg [2:0] Baud_set;//选择接收数据的波特率,要和发送数据的波特率一致wire [7:0] Rx_Data; //最后我们看到的数据wire Rx_Done;uart_tx uart_tx_Inst(.clk(clk),.uart_rx(uart_rx),.rst(rst),.Baud_set(Baud_set),.Rx_Data(Rx_Data),.Rx_Done(Rx_Done)
);
initial clk=1;
initial Baud_set=3'd7;
always #10 clk=~clk;
initialbeginrst=0;uart_rx=1;#200;rst=1;uart_tx_byte(8'b11011011);@(posedge Rx_Done) #5000;uart_tx_byte(8'b10011010);@(posedge Rx_Done) #6000;uart_tx_byte(8'b10011110);    endtask uart_tx_byte;  //发送一个字节input [7:0] tx_data;beginuart_rx=1;#200;uart_rx=0;#8680;uart_rx=tx_data[0];#8680;uart_rx=tx_data[1];#8680;uart_rx=tx_data[2];#8680;uart_rx=tx_data[3];#8680;uart_rx=tx_data[4];#8680;uart_rx=tx_data[5];#8680;uart_rx=tx_data[6];#8680;uart_rx=tx_data[7];#8680;uart_rx=1;#8680;end
endtask
endmodule

代码已测试可以使用!

FPGA串口接收学习相关推荐

  1. FPGA 串口接收不准确,有误码

    FPGA 串口接收不准确,有误码 FPGA 的Uart接收时,出现接收不正确的分析 波特率计数值= 时钟频率/波特率 FPGA 的Uart接收时,出现接收不正确的分析 波特率计数值= 时钟频率/波特率 ...

  2. FPGA串口接收与发送详解( part 3 )

    之前的part1~2已经详解完了单个数据的串口接收与发送,链接如下: FPGA串口接收与发送 详解 (part 1 )_居安士的博客-CSDN博客 FPGA串口接收与发送详解( part 2 )_居安 ...

  3. HAL库的串口基础学习(包含串口接收不定长数据的实现)

    HAL库的串口基础学习(1) HAL库有一个特点就是对于许多外设的初始化以及功能操作,都提供有一个weak版本的函数,这是充分的展现出库名字的含义(Hardware Abstraction Layer ...

  4. FPGA串口收发(四):接收数据并转发,间隔时间发送

    FPGA串口收发(四):接收数据并转发,间隔时间发送 // Description: 串口收发:串口接收数据,内部生成数据,串口间隔特定时间发送数据 // 串口接收数据:串行信号线 1101_1000 ...

  5. FPGA串口多字节接收、解码和仿真

    序 本项目采用Altera的FPGA,串口多字节接收,并解码以及采用ModelSim进行仿真.串口接收程序源自正点原子的例程. 程序基本框架 程序分为两个部分,单字节接收部分和多字节接收及解码部分,其 ...

  6. FPGA 串口中断_一个严谨的STM32串口DMA发送amp;接收(1.5Mbps波特率)机制

    昨天分享的<嵌入式大杂烩读者福利:第一期>大家有去抽奖吗,没抽的可参与抽奖,碰碰运气.我最喜欢抽奖了,还记得前几个月疫情严重时期连抽中了3包口罩,真刺激,哈哈.之后多多安排抽奖,敬请期待. ...

  7. 【STM32入门100步--学习笔记】USART串口接收程序(含教学视频)

    STM32串口接收的程序和8051单片机一样,有2种接收方式:中断处理和查询方式. 试过两种方式之后发现,中断处理方式更方便,可以扩展多个数据的接收.推荐中断方式. 我已经将本资料内容整理后录制了视频 ...

  8. C#串口通信学习笔记

    因为参加一个小项目,需要对继电器进行串口控制,所以这两天学习了基本的串口编程.同事那边有JAVA的串口通信包,不过是从网上下载的,比较零乱,难以准确掌握串口通信的流程和内含.因此,个人通过学习网上大牛 ...

  9. FPGA串口(UART)通信协议制定与设计思路详解示例

    串口(UART)通信协议制定与设计思路详解 1 概述 本文用于描述规定的串口通信协议,以及传输内容. 2 项目关于串口的要求 a) 支持BIT自检,1路UART上报BIT信息: b) 1路UART接口 ...

最新文章

  1. 电商系统如何做搜索引擎?
  2. Web 前端,易学难精,没有拿手的实战项目,怎么办?
  3. java数组编译后_Java中数组和集合的foreach操作编译后究竟是啥
  4. Linux 内核的文件 Cache 管理机制介绍
  5. 大量多风格多功能后台管理模板
  6. Azure SQL 数据库:服务级别与性能问答
  7. ubuntu19 安装git_在Ubuntu 18.04上安装Git
  8. Asp.Net回车键触发Button的OnClick事件解决方案
  9. Java中的自增操作符与中间缓存变量机制
  10. android webview 3d,Unity3d Android的web视图没有显示_webview_开发99编程知识库
  11. c# 操作redisclient 设置过期时间_C# Redis分布式锁 单节点
  12. 2.3 Hadoop安装与体验
  13. 项目中的设计模式【适配器模式】
  14. Linux系统中安装Nginx
  15. font-family 各字体一览表
  16. 金蝶标准版7.0计算机快捷,掌握金蝶KIS基本的技巧,快速操作金蝶软件!
  17. 看看十二星座哪个更适合当程序员
  18. ubuntu18.04 使用scp命令
  19. eclipse中的图片路径 image
  20. matlab坐标轴加粗

热门文章

  1. 解决谷歌的but your computer or network may be sending automated queries
  2. 一堂难忘的计算机课作文,一节电脑课作文600字
  3. No current assignment for partition 解决
  4. 查询分析器默认代码颜色
  5. 转图精灵算法分析!!
  6. 微信小程序招聘管理系统+后台管理系统
  7. 同元软控助力复杂系统数字孪生落地应用
  8. 【网络】计算机网络-数据链路层 Data Link Layer
  9. 是否可以从一个静态(static)方法内部发出对非静态(non-static)方法的调用?
  10. 简单的快递管理系统(c语言版)--大一下的总结