欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 科技 > 能源 > UART双向通信实现(序列机)

UART双向通信实现(序列机)

2025/4/12 20:25:33 来源:https://blog.csdn.net/m0_66619666/article/details/146988244  浏览:    关键词:UART双向通信实现(序列机)

前言        

        UART(通用异步收发传输器)是一种串行通信协议,用于在电子设备之间进行数据传输。RS232是UART协议的一种常见实现标准,广泛应用于计算机和外围设备之间的通信。它定义了串行数据的传输格式和电气特性,以确保不同设备之间的兼容性和可靠性。RS232协议采用异步串行通信方式,通过数据线将并行数据转换为串行数据进行传输,接收端再将串行数据恢复为并行数据。RS232的标准包括信号电平、连接器类型和数据格式等规范,确保了设备之间的正确通信。它的常见应用包括计算机串口、调制解调器、打印机等设备的连接。

        UART通信实现与验证(RS232)

正文

一、UART双向通信实现(序列机)的设计验证

        1.项目需求

        完成9600波特率串口的数据收发实验

        2.技术介绍

        采用序列机架构,使用锁相环产生一个16倍9600波特率的时钟,当该时钟计数到16时,表示串口数据发送的1bit数据传输完成(即1bit数据在计数0时放置与txd数据线上,在16时完成该数据传输,下次计数0时传输下1bit数据)。为保证数据接收正常,数据接收需要在9600波特率的时钟的周期中心接收,对应16倍时钟,在计数器到7或8的时刻进行数据接收。

        为完成数据收发实验,将接收的数据在发送出去,完成数据回环,可以通过上位机去观察接收的数据是否完整以此验证实验成功。

        涉及到数据传递,虽然时钟相同但是正常情况需要进行数据缓存(建议,如果是异步时钟,必须进行数据缓存),常用的数据缓存有异步fifo,双口ram(本实验实验异步fifo)

        3.顶层架构

        

        4.端口描述

clk时钟接口(50Mhz)
rst_n复位按键(低电平有效)
rxd数据接收接口
txd数据发送接口

二、代码验证

顶层连线

module uart_tx_rx(input			clk	,input			rst_n	,input 		rxd	,output 		txd	
);wire clk_01536;wire rst_en;clk_uart	clk_uart_inst (.areset 	( ~rst_n ),.inclk0 	( clk ),.c0 		( clk_01536 ),.locked 	( rst_en ));wire[7:0]data,q_sig;wire rdempty,rdreq,down;uart_rx rx(.clk	(clk_01536	),.rst_n	(rst_en		),.rxd	(rxd			),//数据接收.data	(data			),//接收数据打包.down	(down			) //输出有效);fifo	fifo_inst (.data 	(data	),.rdclk 	(clk_01536  ),.rdreq 	(rdreq  ),.wrclk 	(clk_01536  ),.wrreq 	(down  ),.q 		(q_sig  ),.rdempty (rdempty 	),.wrfull 	(  ));uart_txd_v1 tx(.clk		(clk_01536	),.rst_n	(rst_en		),.data		(q_sig		),.done		(rdempty		),.txd		(txd			),.rd_en	(rdreq		));
endmodule

收数据模块

module uart_rx(input				clk	,input				rst_n	,input				rxd	,//数据接收output reg[7:0]data	,//接收数据打包output reg 		down	 //输出有效
);reg state;reg [7:0]temp;reg [7:0]cnt;always@(posedge clk,negedge rst_n)//cnt在工作状态计数beginif(!rst_n)cnt <= 0;else if(state == 1)cnt <= cnt + 1;elsecnt <= 0;endalways@(posedge clk,negedge rst_n)beginif(!rst_n)state <= 0;elsecase(state)0:	if(rxd == 0)//等待起始信号state <= 1;elsestate <= 0;1: if(cnt == 153)//完成一包数据接收state <= 0;elsestate <= 1;default:state <= 0;endcaseendalways@(posedge clk,negedge rst_n)beginif(!rst_n)begintemp <= 0;down <= 0;data <= 0;endelsecase(cnt)0:begintemp <= 0;down <= 0;data <= data;end1*16+7:temp[0] <= rxd;//在每个时序的中间收数据,数据在N*16时放在rxd上,保证数据稳定,在N*16 + 7时读2*16+7:temp[1] <= rxd;3*16+7:temp[2] <= rxd;4*16+7:temp[3] <= rxd;5*16+7:temp[4] <= rxd;6*16+7:temp[5] <= rxd;7*16+7:temp[6] <= rxd;8*16+7:temp[7] <= rxd;9*16+7:begindown <= 1;data <= temp;end9*16+7+1:down <= 0;endcaseendendmodule

发数据模块

module uart_txd(//fifo不为空时发input			clk	,//0.1536 = 9600 * 16 = 153600hz = 0.1536Mhz input			rst_n	,input	[7:0]	data	,input			done	,output reg	txd	,output reg 	rd_en	
);reg [7:0]temp;reg [7:0]cnt;reg state;always@(posedge clk,negedge rst_n)//计数器在工作时进行计数beginif(!rst_n)cnt <= 0;else if(state == 1)//fifo不空,开始发送if(cnt < 10*16)cnt <= cnt + 1;elsecnt <= 0;elsecnt <= 0;endalways@(posedge clk,negedge rst_n)beginif(!rst_n)state <= 0;else case(state)0:	if(done == 0)state <= 1;elsestate <= 0;1: if(cnt == 10*16)state <= 0;elsestate <= 1;default:state <= 0;endcaseendalways@(posedge clk,negedge rst_n)beginif(!rst_n)rd_en <= 0;elsecase(cnt)0:rd_en <= 0;1:rd_en <= 1;2:rd_en <= 0;endcaseendalways@(posedge clk,negedge rst_n)beginif(!rst_n)txd <= 1;elsecase(cnt)0:txd <= 1;1:txd <= 0;//起始位3:temp <= data;1*16:txd <= temp[0];//数据在时序开始时放在txd,2*16:txd <= temp[1];3*16:txd <= temp[2];4*16:txd <= temp[3];5*16:txd <= temp[4];6*16:txd <= temp[5];7*16:txd <= temp[6];8*16:txd <= temp[7];9*16:txd <= 1;endcaseendendmodule

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词