Universal Asynchronous Receiver Transmitter (UART) 通用异步接收发射机

Universal Asynchronous Receiver Transmitter (UART) 通用异步接收发射机

逻辑部分

特征

  • AXI4-Lite 接口,用于寄存器访问和数据传输
  • 全双工
  • 16个字符传输和接收 FIFO
  • 可配置的数据比特数(5-8)每个字符
  • 可配置的奇偶比特(奇数或偶数或无)
  • 可配置的波特率

方框图

在这里插入图片描述

  • AXI Interface: 该模块实现了用于寄存器访问和数据传输的 AXI4-Lite 从接口。
  • UART Lite Registers: 这个块包括内存映射寄存器(如图1-1所示)。它由一个控制寄存器、一个状态寄存器和一对发送/接收 FIFO 组成,它们都有16个字符的深度。
  • Rx Control - 这个块采样接收有关生成波特率的数据,并将其写入接收数据 FIFO。°
  • Tx Control - 该块读取来自传输数据 FIFO 的数据,并在 UART Tx 接口上发送。
  • Interrupt Control - AXI UART Lite 核心提供中断启用/禁用控制。如果启用了中断,则当RX_FIFO 变为非空或当TX_FIFO 变为空时,将产生上升沿敏感中断。如何区别这两种中断?(通过查看状态寄存器查看,但是需要看看官方例程怎么处理的)

寄存器映射

在这里插入图片描述

  • RX FIFO是一个只读寄存器,若设置数据位宽为8时,则其高24位保留,低8位为有效数据位。
  • TX FIFO是一个只写寄存器,若设置数据位宽为8时,则其高24位保留,低8位为有效数据位。
  • CTRL_REG包含用于接收和传输数据 FIFO 的启用中断位和复位引脚。这是一个只写寄存器。其各个bit定义如表2-7所示。
    在这里插入图片描述
  • STAT_REG包含在启用中断和出现错误时接收和传输数据 FIFO 的状态。这是一个只读寄存器
    若是在程序开始就初始化了串口,但是并没有读取串口数据,而在接收了几个数据之后再读取,那读到的是之前接收的数据,还是最新接收到数据?
    在这里插入图片描述
// 设想自己实现UART的运行
1.CTRL_REG开启接收和传输FIFO的启用,以及中断开启。地址:(baseaddr+0x0C),命令:0x0000_0013
	这里可以查看STAT_REG来判断命令是否设置成功了。地址:(baseaddr+0x08),数据:0x0000_0014
2.TX_FIFO写入数据,进行传输。同时通过STAT_REG判断发送FIFO是否已经满了,若是满了就暂停发送,一直等到其为空。
	if(read(baseaddr+0x08) & 0xc == 0x8){}
	else {write((baseaddr+0x04), data);}											// 此处如何判断数据写入FIFO?
3.RX_FIFO可以进行接收数据,进行读取。首先需要判断TX_FIFO是否有数,若是没有数就进行读取,那么读到的数是随机的。
	if(read(baseaddr+0x08) & 0x3 == 0x0){}
	else {data <= read(baseaddr+0x00);}												// 此处如何判断数据读出FIFO?
4.中断的读写控制,当RX_FIFO 变为非空或当TX_FIFO 变为空时,将产生上升沿敏感中断。			// 实际情况如何?

SDK-自己编写部分

在这里插入图片描述
上图为先TX_FIFO中写入数据,由于发送的FIFO深度有限为16,而且uart发送速率很忙,而我们写入的数据量很大(1000)。故而,其很快就被写满,等待其发送完再继续写入FIFO。
在这里插入图片描述其次是中断的尝试,在TX_FIFO中数据全部被发送,TX_FIFO变为空之后,就会触发中断信号。
在这里插入图片描述
对于RX_FIFO的接收,为了防止RX_FIFO满了,就每接收一个字节就进行读取一次。可见每次接收到RX_FIFO的数据是递增的,且每次都可以成功触发中断信号。
在这里插入图片描述
对于uart的接收中断而言,在TX_FIFO接收到第一个数据,从空变为非空时,触发中断信号。
在这里插入图片描述
此处为RX_FIFO每次接收两个字节数据,而读取RX_FIFO一直读到其为空,故而中断触发两次,一次为RX_FIFO非空?还是写入两次就触发两次中断?
在这里插入图片描述
此处为RX_FIFO每次接收三个字节数据,而读取RX_FIFO一直读到其为空,触发中断两次,是因为一次为RX_FIFO非空,一次为读取读到RX_FIFO内部数据为1?
在这里插入图片描述
此图和上图是一个条件下的放大图,可见在读取到RX_FIFO为1时并继续读取时,会触发中断。并且可见,此时还会触发两次中断。(所以,中断并不是判断RX_FIFO非空的充要条件,还是需要读取STAT_REG寄存器进行判断)

SDK-官方例程

polled例程

初始化

在这里插入图片描述

// 此处为初始化,把设备ID、基地址、波特率、奇偶校验、数据位宽信息赋值给对应设备结构体
Status = XUartLite_Initialize(&UartLite, DeviceId);

自我检测

在这里插入图片描述

// 此处为uart串口自我测试,其中先是对TX_FIFO进行复位,再读取状态寄存器,判断TX_FIFO是否为空。
// 若是为空,则自我测试成功;若是不为空,则自我测试失败。
Status = XUartLite_SelfTest(&UartLite);

发送数据

在这里插入图片描述

// 此处为uart串口发送数据,其中先是对控制寄存器中禁止中断,以此停止可能因为调用中断函数而驱动的操作。
// 接着将需要发送数据的字节数,剩余字节数和发送数据的地址给串口结构体
// 接下来回复中断使能信号。这样是为了尽量减少中断被禁用的时间,因为中断被禁止后,接收可能会被填满。
// 接下来便是接收数据的操作,在下图中进行介绍。
SentCount = XUartLite_Send(&UartLite, SendBuffer, TEST_BUFFER_SIZE);

在这里插入图片描述

// 同样先读取状态寄存器,判断TX_FIFO是否为满,并且禁止中断
// 并且若是TX_FIFO并为满,且目前发送的字节数小于串口结构体中需要发送的字节数,则向TX_FIFO寄存器中写入一个字节数据。并对已发送计数加一。
// 重复上述操作,直至TX_FIFO为满或者数据发送完毕(字节数小于16)
// 更新串口结构体中的数据地址和待发送长度
// 重新使能中断部分
BytesSent = XUartLite_SendBuffer(InstancePtr);

因为TX_FIFO深度为16,所以一次最多写入16个字节的数据。

  • 若是想要不断发送数据,就需要采用中断,即TX_FIFO为空再进行发送
  • 采用不断询问的方式,用while循环,每次进行发送,直到发送完成
  • 使用函数中有静态计数变量,计数每次写入TX_FIFO字节数,下次发送从本次后面继续发送
  • 使用xil_printf函数

接收数据

在这里插入图片描述

// 禁止中断
// 将要接收的字节长度和地址保存入串口寄存器
// 打开中断
// 进行数据接收部分

在这里插入图片描述

// 首先是取消中断
// 若是当前已接收数据字节数小于需要此次一共所需接收字节数,进入while循环。
// 获取状态寄存器,查看RX_FIFO是否有数,若是有数则进行读取。一直等到RX_FIFO为空则退出while循环
// 更新目前已接收数据数量和未接收数据数量
// 重新打开中断
ReceivedCount = XUartLite_ReceiveBuffer(InstancePtr);

因为接收字节,RX_FIFO可能会有一些延迟,所以添加while循环。每次都只是读完RX_FIFO中的已有数据

中断例程

待续

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值