串口RS232

news/2024/12/29 19:12:15/

串口RS232

  • 1. 串口简介
  • 2. 串口RS232接口
  • 3. 代码实现
    • UART接收模块
    • UART发送模块
    • 顶层模块
  • 4. 下板验证

1. 串口简介

通用异步收发传输器,英文全称Universal Asynchronous Receiver/Transmitter,简称UART
UART
UART是一种通用的数据通信协议,也是异步串行通信口(串口)的总称,它在发送数据时将并行数据转换成串行数据来传输,在接收数据时将接收到的数据转换成并行数据
UART是异步串行通信口,SPI是同步的,双方约定好使用频率一致的时钟,主机发送时钟
UART中,数据的收发都有独立的端口,所以它可以实现全双工通信

RS232传输距离比较近,传输速率也比较慢,数据线只有两条,可以节省IO口

2. 串口RS232接口

是UART串口的一种,没有时钟线只有两个数据线
在这里插入图片描述
在这里插入图片描述
注意:两个设备间的TXD和RXD应交叉相连

串口数据的发送和接收都是基于帧结构的,起始位+数据位+停止位,共10bit,空闲状态下rx和tx都保持高电平
在这里插入图片描述
波特率:来波特率指数据信号对载波的调制速率,它用单位时间内载波调制状态改变次数来表示,其单位为波特(Baud),Bps

比特率:比特率是每秒传输的比特数。单位为比特(bps位/秒)

波特率源与比特率的关系为:比特率=波特率 * 单个调制状态对应的二进制位数

串口常用波特率有4800、9600、115200
9600Bps的串口比特率就是9600*1bps,串口发送或接收1bit数据的时间称为1个波特,也就是1/9600s。clk = 50MHz,T = 20ns,9600Bps下,传输一个波特需要的时钟个数,cnt = (1 * 10^9)ns / 9600 / 20ns 约等于5208,相当于每个bit的传输间隔需要50MHz时钟下的5208个clk

3. 代码实现

实现50MHz下9600波特率传输

波特率为9600Baud
一秒传输9600个波特
每个波特10bit数据,1bit起始位 + 8bit数据位 + 1bit结束位

每个码元传输需要的clk数 = ((1/9600)*10^9ns) / 20ns≈ 5208
串口传输,每个码元也就是一个bit,也可以理解为传递每个bit需要的clk数

在这里插入图片描述

UART接收模块

将上位机发送过来的串行数据进行接收,转换成并行数据

在这里插入图片描述
在这里插入图片描述

module uart_rx 
#(parameter	UART_BPS	=	'd9600			,parameter	CLK_FREQ	=	'd50_000_000	
)
(input	wire			sys_clk		,input	wire			sys_rst_n	,input	wire			rx			,output	reg		[ 7: 0]	po_data		,output	reg				po_flag
);//	parameter	BAUD_CNT_MAX	=	5208;	// 9600Bps		(1/9600s)/(1/50M) = F/Bps = 50M / 9600localparam	BAUD_CNT_MAX	=	CLK_FREQ / UART_BPS;reg				rx_reg1		;	// 同步到系统时钟下reg				rx_reg2		;reg				rx_reg3		;	// 打两拍,减小亚稳态危害reg				start_flag	;	// 开始一个数据帧的传输标志信号reg				work_en		;	// 标识数据采集范围,接收数据工作使能信号reg		[15: 0]	baud_cnt	;	// 计数1个码元需要的clk,0~8207reg				bit_flag	;	// 每bit数据稳定点拉高一拍reg		[ 3: 0]	bit_cnt		;	// 10bit数据计数器reg		[ 7: 0]	rx_data		;reg				rx_flag		;always @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)beginrx_reg1	<=	1'b1;	// 空闲状态为高rx_reg2	<=	1'b1;rx_reg3	<=	1'b1;endelsebeginrx_reg1	<=	rx;rx_reg2	<=	rx_reg1;rx_reg3	<=	rx_reg2;end// start_flag:检测下降沿always @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)start_flag	<=	1'b0;else	if (~rx_reg2 && rx_reg3 && work_en == 1'b0)	// 检测下降沿,并且现在不在数据采集范围内start_flag	<=	1'b1;elsestart_flag	<=	1'b0;// work_enalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)work_en	<=	1'b0;else	if (start_flag == 1'b1)work_en	<=	1'b1;else	if (bit_cnt == 4'd8 && bit_flag == 1'b1)work_en	<=	1'b0;elsework_en	<=	work_en;// baud_cntalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)baud_cnt	<=	16'd0;else	if ((baud_cnt == BAUD_CNT_MAX - 1'b1) ||(work_en == 1'b0) )baud_cnt	<=	160'd0;elsebaud_cnt	<=	baud_cnt + 1'b1;	// bit_flag:当baud_cnt计数器计数到中间数时采样的数据最稳定,拉高一个标志信号表示数据可以被采样always @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)bit_flag	<=	1'b0;else	if  (baud_cnt == BAUD_CNT_MAX / 2 - 1'b1)	// 数据稳定的最中间位置bit_flag	<=	1'b1;elsebit_flag	<=	1'b0;// bit_cntalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)bit_cnt	<=	4'd0;else	if ((bit_cnt == 4'd8) && (bit_flag == 1'b1))bit_cnt	<=	4'd0;else	if (bit_flag == 1'b1)bit_cnt	<=	bit_cnt + 1'b1;elsebit_cnt	<=	bit_cnt;// rx_dataalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)rx_data	<=	8'b0;else	if (((bit_cnt >= 4'd1) && (bit_cnt <= 4'd8)) && (bit_flag == 1'b1))rx_data	<=	{rx_reg3, rx_data[7:1]};elserx_data	<=	rx_data;// rx_flagalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)rx_flag	<=	1'b0;else	if ((bit_flag == 1'b1) && (bit_cnt == 4'd8))rx_flag	<=	1'b1;elserx_flag	<=	1'b0;// po_dataalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)po_data	<=	8'b0;else	if (rx_flag == 1'b1)po_data	<=	rx_data;// po_flagalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)po_flag	<=	1'b0;elsepo_flag	<=	rx_flag;endmodule
`timescale	1ns/1nsmodule uart_rx_tb ();reg		sys_clk		;reg		sys_rst_n	;reg		rx			;wire	[ 7: 0]	po_data	;wire			po_flag	;uart_rx#(.UART_BPS	('d9600		),.CLK_FREQ	('d50_000_000	))uart_rx_inst(.sys_clk	(sys_clk	),.sys_rst_n	(sys_rst_n	),.rx			(rx			),.po_data	(po_data	),.po_flag	(po_flag	));always # 10	sys_clk = ~sys_clk;initial	beginsys_clk		=	1;sys_rst_n	=	0;rx	=	1;#10sys_rst_n	=	1;end// 模拟发送数据帧initial	begin#200rx_bit(8'd0);rx_bit(8'd1);rx_bit(8'd2);rx_bit(8'd3);rx_bit(8'd4);rx_bit(8'd5);rx_bit(8'd6);rx_bit(8'd7);rx_bit(8'b1100_1010);end// 任务函数
task	rx_bit ;input			[ 7: 0]	data;integer	i;beginfor (i = 0; i < 10 ; i = i + 1)	begin		// 这个begin不可缺少,不然设置的延时起不到循环内的延迟作用case (i)0:	rx	<=	1'b0;		// 起始位1:	rx	<=	data[0];	// 数据位2:	rx	<=	data[1];3:	rx	<=	data[2];4:	rx	<=	data[3];5:	rx	<=	data[4];6:	rx	<=	data[5];7:	rx	<=	data[6];8:	rx	<=	data[7];9:	rx	<=	1'b1;		// 结束位endcase#(5208 * 20);endend
endtaskendmodule

在这里插入图片描述

UART发送模块

将FPGA内部的数据以固定的波特率,并转串,包装成数据帧,发送给上位机

module uart_tx 
#(parameter	UART_BPS	=	'd9600			,parameter	CLK_FREQ	=	'd50_000_000	
)
(input	wire			sys_clk		,input	wire			sys_rst_n	,input	wire	[ 7: 0]	pi_data		,input	wire			pi_flag		,output	reg				tx
);localparam	BAUD_CNT_MAX	=	CLK_FREQ / UART_BPS;reg				work_en		;reg		[15: 0]	baud_cnt	;reg				bit_flag	;reg		[ 3: 0]	bit_cnt		;// work_enalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)work_en	<=	1'b0;else	if ((bit_cnt == 4'd9) && (bit_flag == 1'b1))work_en	<=	1'b0;else	if (pi_flag == 1'b1)work_en	<=	1'b1;elsework_en	<=	work_en;// baud_cntalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)	baud_cnt	<=	16'd0;else	if ((work_en == 1'b0) || (baud_cnt == BAUD_CNT_MAX - 1'b1))baud_cnt	<=	16'd0;else	if (work_en == 1'b1)baud_cnt	<=	baud_cnt + 1'b1;// bit_flagalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)bit_flag	<=	1'b0;else	if (baud_cnt == 16'd1)	// 每一个波特计数周期,拉高一个bit_flag周期,相邻脉冲间隔为一个波特bit_flag	<=	1'b1;elsebit_flag	<=	1'b0;// bit_cntalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)bit_cnt	<=	4'd0;else	if ((bit_cnt == 4'd9) && (bit_flag == 1'b1))bit_cnt	<=	4'd0;else	if ((work_en == 1'b1) && (bit_flag == 1'b1))bit_cnt	<=	bit_cnt + 1'b1;elsebit_cnt	<=	bit_cnt;// txalways @ (posedge sys_clk or negedge sys_rst_n)if (sys_rst_n == 1'b0)tx	<=	1'b1;else	if (bit_flag == 1'b1)case (bit_cnt)0:	tx	<=	1'b0;1:	tx	<=	pi_data[0];2:	tx	<=	pi_data[1];3:	tx	<=	pi_data[2];4:	tx	<=	pi_data[3];5:	tx	<=	pi_data[4];6:	tx	<=	pi_data[5];7:	tx	<=	pi_data[6];8:	tx	<=	pi_data[7];9:	tx	<=	1'b1;default:	tx	<=	1'b1;endcaseendmodule

在这里插入图片描述

顶层模块

在这里插入图片描述
模拟接收串行数据8’b1100_1010,随后逐比特发送
在这里插入图片描述

4. 下板验证

在这里插入图片描述


http://www.ppmy.cn/news/174868.html

相关文章

RS-422接口定义

RS-422接口定义 RS-422接口定义 什么是RS-422 接口&#xff1f; RS-422 的电气性能与RS-485完全一样。主要的区别在于&#xff1a; RS-422 有4 根信号线&#xff1a;两根发送&#xff08;Y、Z&#xff09;、两根接收&#xff08;A、B&#xff09;。由于RS-422 的收与发 …

什么是rs232?

转载&#xff1a;https://www.usr.cn/News/1626.html 什么是RS232协议?   RS232协议是一种流行的串行接口&#xff0c;用于将计算机连接到诸如串口服务器之类的联网设备。我们将了解用于实现RS232的串口引脚以及有关该协议的一些其他参考信息。   RS232协议使用不同于标准…

RS-232/RS-485/RS-422通信协议介绍

1、RS-232 (1) 基本概念 RS-232接口符合美国电子工业联盟(EIA)制定的串行数据通信的接口标准&#xff0c;被广泛用于计算机串行接口外设连接&#xff0c;像有些老式PC机上就配置有RS232接口。RS232的工作方式是单端工作方式&#xff0c;这是一种不平衡的传输方式&#xff0c;收…

RS232_RS422_RS485简介

1. RS232 通讯数据线是2线&#xff08;RX,TX)&#xff0c;支持全双工通讯电平值&#xff0c;高电平&#xff1a;-3v ~ -15v&#xff1b;低电平&#xff1a;3v ~ 15v。所以和单片机的通信通常需要用232转ttl电平的芯片。接收&#xff0c;发送&#xff0c;地&#xff1b;三线形成…

RS-232详解

RS-232是美国电子工业联盟制定的串行数据通信接口标准&#xff0c;原始编号全称是EIA-RS-232&#xff08;简称RS232&#xff09;&#xff0c;它被广泛用于DCE&#xff08;Data Communication Equipment &#xff09; 和 DTE&#xff08;Data Terminal Equipment&#xff09; 之…

ESP32-PICO-D4的串口使用

默认串口1的IO为9&#xff0c;10&#xff1b; 若使用arduino并任选择ESP32-S为开发板&#xff0c;在使用第三方库示例时注意不要使用串口1默认IO&#xff0c;否则读不出数据&#xff0c;而自己写的程序默认IO可以使用&#xff0c;原因是第三方库为ESP32-S编写&#xff0c;而ESP…

k8s重新生成token

1、查看token kubeadm token list 2、重新生成token kubeadm token create 3、master节点获取ca证书sha256编码hash值 openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed s/^.* /…

D4S发布在即 尼康D4将停产

尼康预计于明天&#xff0c;也就是2月11日正式发布新旗舰单反D4S。该相机在D4基础上强化了对焦性能&#xff0c;并采用全新图像处理器&#xff08;EXPEED 4&#xff1f;&#xff09;。然而就像当年D3S取代D3一样&#xff0c;D4也面临着停产的命运。 尼康D4将停产 根据NR最新报…