ZYNQ进阶之路14--PS端uart串口接收不定长数据

ZYNQ进阶之路14--PS端uart串口接收不定长数据

导语

繁忙的博主又来了,本节我们实现一个比较简单的东西:串口。之前的章节中我们也有使用PS端的串口进行收发数据,但是都是接收固定长度的数据包,在实际的项目工程中是很不方便和不实用的。本章节我们来详细讲解ZYNQ中PS端串口接收的机制和实现接收不定长数据的原理。
本章节对应工程源码: ZYNQ进阶之路14工程 对应软件版本vivado2018.3

ZYNQ串口简介

ZYNQ PS端有两个串口,uart0和uart1。两个串口基本一样,只要学会了其中一个串口的配置,另一个串口也就照搬程序了。串口的硬件框图大致如下图所示:
在这里插入图片描述
如上图所展示的,一个串口有两个FIFO,接收和发送各用一个,FIFO的缓存能大大的提高串口的工作效率,并且减少CPU的干预。两个FIFO的宽度都为8bit,深度为64字节。当串口发送数据时,CPU/DMA通过总线将需要发送的数据写入TxFIFO中,硬件检测到FIFO中有数据或者数据到达一定数量就会往外发送数据直到TxFIFO为空。当串口接收数据时,硬件将数据缓存如RxFIFO中,当软件检测到RxFIFO有数据时,CPU/DMA就通过总线去读取RxFIFO直到RxFIFO为空。对于串口发送,我们一个字节一个字节发送便可,已经足够我们日常使用。本节我们主要讲解串口接收的原理,本节中我们使用两种中断实现串口接收不定长数据,第一种为RxFIFO阈值触发中断:这种中断首先是要给FIFO设置一个阈值,当RxFIFO中有效数据量大于等于阈值时,产生中断;第二种是接收数据超时(timeout)中断,使用过STM32的同学可能比较熟悉STM32中有一个串口的空闲中断,这里的接收数据超时中断和这个类似,如果在设定时间周期内没有接收到串口数据则产生超时中断。
同时使能以上两种中断便可以实现任意长度的串口数据接收了,接下来我们来看一下具体是如何实现的吧!

实现步骤

首先我们创建一个新的ZYNQ工程,具体工程创建流程参照 ZYNQ进阶之路5中的工程创建流程。工程创建后如下所示:
在这里插入图片描述
然后导入到SDK中,创建helloworld工程,输入如下代码实现本节功能:
在这里插入图片描述
在这里插入图片描述
上图中红框1为串口中断服务函数,
红框2读取中断类型
红框3中是读取FIFO数据代码,500为设置的读取数据长度,该值无论设置多大都无所谓,因为读取到FIFO为空后就不会再读数据了,而返回数值为实际读取到的数据数量。所以这里我们设置为500也是可以的。
红框4中为数据发送程序,将接收到的数据全部发送出去,并且只有接收到最后一个数据后发生超时中断才会触发数据发送。
红框5为串口初始化函数
红框6为设置超时中断的超时时间,超时时间=16个波特率时钟周期。其计算公式为:超时时间=n*4个波特率周期,本程序中n=4.
然后编译程序后,下载但芯片中,便可实现不定长数据接收了,其实际运行效果如下所示:
在这里插入图片描述
一次发送130个字节,发送一段时间后也不会出现丢数据的状况,还是相当稳定可靠的!好了本节内容就到此为止了,在下一节的内容中我们将讲解在ZYNQ中通过AXI stream接口+AXI DMA实现PS和PL的高速数据传输,有兴趣的博友可以持续关注本博主哦!博主邮箱:wanpengwork@163.com 博主微信技术公众号:鹏哥DIY。

### Zynq PS UART 数据收发教程 #### 初始化设置 为了使能Zynq PSUART功能,需先配置UART模块的相关参数。这包括设定波特率、停止位数量以及校验方式等基本属性[^1]。 ```c XUartPs_Config *Config; int Status; // 获取设备配置信息 Config = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID); if (NULL == Config) { return XST_FAILURE; } Status = XUartPs_CfgInitialize(&Uart, Config, Config->BaseAddress); if (Status != XST_SUCCESS) { return XST_FAILURE; } ``` #### 设置UART模式与数据格式 接着定义通信的具体形式,比如字符宽度可以设为8比特无奇偶检验并采用单个停止位的形式。 ```c XUartPs_SetOptions(&Uart, XUARTPS_OPTION_PARITY_even | XUARTPS_OPTION_STOP_BITS_1); ``` #### 中断处理程序安装 通过注册中断服务例程来响应外部输入事件,从而高效地管理I/O操作而不必轮询查询状态变化情况。 ```c XScuGic_Connect(IntcInstancePtr, XPAR_FABRIC_AXI_UARTLITE_0_INTERRUPT_INTR, (Xil_ExceptionHandler)XUartLiteInterruptHandler, &Uart); Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstancePtr); Xil_ExceptionEnable(); ``` #### 发送UART数据流程 当准备向另一方传输消息时,调用特定函数写入待发送字符串至缓冲区直至完成整个过程;期间还需确认是否有新到达的信息存在以便即时回复之。 ```c char SendBuffer[] = "Hello from Zynq!"; XUartPs_Send(&Uart, (u8*)SendBuffer, strlen(SendBuffer)); while (!XUartPs_IsTransmitEmpty(&Uart)) {} ``` 对于接收到的数据,则可以通过读取API获取最新内容,并判断其是否存在有效负载以决定后续动作——即刻回应还是稍后再试一次发送尝试[^2]。 ```c char RecvBuffer[64]; unsigned int ReceivedBytes; ReceivedBytes = XUartPs_Recv(&Uart, (u8 *)RecvBuffer, sizeof(RecvBuffer)); if (ReceivedBytes > 0){ // Process received data here... } else { usleep(1000); // Wait for one second before retrying. } ```
评论 26
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值