UART串口实验(第一个实用模块)

本文详细解释了UART串口的工作原理,涉及电气接口标准、数据发送流程、逻辑设计要点,以及如何实现一个发送模块,包括波特率控制、数据缓存和LED状态控制。还展示了逻辑优化后的设计策略。
摘要由CSDN通过智能技术生成

什么是UART串口

全称通用异步收发器,是一种串行异步的通信协议,该协议规定了传输数据时数据的传输方式及其所使用的信号。
RS232标准:+3~+15低电平  -3~-15高电平
RS485标准:差分信号D+D-,D+ - D- +2~+6低电平 -2~-6高电平

在这里插入图片描述
TTL电平信号:工作在5v电压下,输出>2.4v高电平,<0.5v低电平,输入>2.0v高电平,<0.8v低电平。2.4v与5v有较大差距
LVTTL:工作在3.3v电压下,输出>2.4v高电平,<0.5v低电平,输入>2.0v高电平,<0.8v低电平。2.4v与5v有较大差距

串口细节梳理

UART:串口协议
UART控制器:实现UART协议收发数据的逻辑电路
RS232/RS485:电气接口标准,规定了电气标准和接线顺序
DB9接口:用于RS232电气接口通信的物理接线连接器
USB转TLL串口:将UART协议数据转换为USB接口信号进行传输的桥接芯片

我们是遵循,使用协议;电气接口属于硬件电路设计范畴;我们要做的是实现UART逻辑控制器

UART发数据

在这里插入图片描述
若UART发送器没有数据发送,处于空闲态,此时TX保持高电平,需要发送数据时,先将TX信号拉低,保持一个位时间。一位起始位时间标志着数据开始传输,紧接着传输数据,每一位bit数据传输时间和起始位位时间相同,当最后一位数据发送完成后,TX拉高并保持一个位时间的长度,标志着一轮数据发送完。发送一个8位数据,包括起始位和结束位,则一轮数据加两位标志位是10个bit,即10个码元。
波特率:每秒中传输的码元个数,每个码元占用时间为(1/波特率)秒
奇偶检验:通过在数据位后接一位校验位来确保数据+校验位中的”1“的个数位奇偶个。

UART串口发送逻辑设计要点分析

设计任务

设计一个串口发送模块,发送用户输入的数据给电脑,要求:

  • 波特率位9600
  • 8位数据位
  • 1位停止位
  • 无校验位
  • 每1秒发送一次当前8位拨码开关的值
  • 每次发送完成后将led0的状态翻转

模块端口

在这里插入图片描述
uart_tx:用来发送的数据信号
led:发送一次让led翻转
data[7:0]:8位拨码开关的值,由用户输入
波特率:9600,每一码元发送的最小时间单位是1/9600 秒,需要计数一轮耗费时间为 1/9600 的计数器
在这里插入图片描述
发送的数据8位:先发一位起始位,再发送8位数据,再发送一个停止位

  • 要求1:串口每1秒发送一次数据:

在这里插入图片描述
思路:设计一个1秒的计数器,此计数器不会停止,每计数到1秒,让串口发送一次数据,再回到初始0继续计数。

  • 要求2:串口发送内容为启动发送时,8位拨码开关的值
    启动信号发送时,此时八位开关的状态被寄存下来,不会因输入改变而改变。
    思路:使用8位的D触发器对拨码开关的值进行缓存
    在这里插入图片描述

  • 要求3:串口每发送完一次,翻转led状态

  • 思路:通过线性序列机,当串口发送完成时,翻转led

UART发数模块主要功能点

//最小位时间,波特率计数器

//最小位时间,波特率计数器 1/9600 * 1_000_000_000 /20 -1
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		en_counter_bit <= 0;
	else if(counter1 == maxcnt1 - 1'd1) //计满1s,发送开始时刻
		en_counter_bit <= 1;
	else if((counter_10 == 9) && (counter_bit == maxcntbit - 1))  //发送结束时刻
		en_counter_bit <= 0;
	else
		en_counter_bit <= en_counter_bit;
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter_bit <= 0;
	else if(en_counter_bit) begin
	if(counter_bit == 13'd5208 - 1'd1)
		counter_bit <= 0;
	else	
		counter_bit <= counter_bit + 1'd1;
		end
	else 
		counter_bit <= 0;

添加使能信号,en_counter_bit,使能信号为0时,标志还未发送数据,发送处于空闲态。
//位计数器,发送哪十位中的哪一位数据由该计数器确定

//延时计数器,1秒钟不停止

//延时计数器,1秒钟不停止
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter1 <= 0;
	else if(counter1 == maxcnt1 - 1'd1)
		counter1 <= 0;
	else	
		counter1 <= counter1 + 1'd1;

//位计数器,记到10

//位计数器,发送哪十位中的哪一位数据由该计数器确定
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		counter_10 <= 0;
	else if(counter_bit == 13'd5208 -1'd1) begin
		if(counter_10 == 10 - 1'd1)
		counter_10 <= 0;
		else
		counter_10 <= counter_10 + 1'd1;
	end
	else 
		counter_10 <= counter_10;

//位 发送/选择 逻辑

//位发送逻辑
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		r_data <= 0;
	else if(counter1 == maxcnt1 - 1)
		r_data <= data;
		
		
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		uart_tx <= 1;  //空闲态为高电平
	else if(en_counter_bit == 0)
		uart_tx <= 1;
	else begin
		case(counter_10)
			0:uart_tx <= 0;
			1:uart_tx <=r_data[0];
			2:uart_tx <=r_data[1];
			3:uart_tx <=r_data[2];
			4:uart_tx <=r_data[3];
			5:uart_tx <=r_data[4];
			6:uart_tx <=r_data[5];
			7:uart_tx <=r_data[6];
			8:uart_tx <=r_data[7];
			9:uart_tx <= 1;
			default:uart_tx <= uart_tx;
		endcase
		end

//led翻转逻辑

//led翻转逻辑
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		led <= 0;
	else if((counter_10 == 9) && (counter_bit == 5207))
		led <= ~led;

仿真截图

在这里插入图片描述
在en_counter_bit使能有效,即开始发数据的时刻,r_data中存储的数据8‘d0101_0101,由低到高依次传输,起始位低电平,结束位高电平

逻辑优化

发送信号由外部逻辑提供
定义一个输入端口 input send_go;
定义一个输出端口 tx_done; 当counter109 && counter_bit5208时,拉高该信号,标志当前发数完成。
位发送逻辑中 else if(counter1 == maxcnt1 - 1) r_data <= data;
表示延时计数器计数到1秒,即发数开始时刻,锁存data到r_data。修改逻辑为
else if(send_go)

assign tx_done = (counter109 && counter_bit5208);

  • 42
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值