单字节收发
uartps是xilinx为PS端提供的串口收发库,其最简单的收发函数为
void XUartPs_SendByte(u32 BaseAddress, u8 Data)
u8 XUartPs_RecvByte(u32 BaseAddress)
【XUartPs_SendByte】用于数据发送,其中Data即为发送的字节,【XUartPs_RecvByte】的返回值为接收到的字节。参数BaseAddress为串口地址,可在xparameters.h中找到。
一个简单的示例如下
#define UART XPAR_XUARTPS_0_BASEADDR
void uartByteTest(){
int i = 0;
char ch;
char buf[32];
while (1) {
ch = XUartPs_RecvByte(UART);
if (ch == '.' || i == 32){
i = 0;
continue;
}
buf[i++] = ch;
XUartPs_SendByte(UART, ch); // Echo back
}
}
其功能很简单,就是把接收到的数据重新发回去,如果该数据以点号结尾,则不发送这个点号。通过串口调试助手测试如下
[2025-08-18 09:14:43.122]# SEND ASCII/6 >>>
hello.
[2025-08-18 09:14:43.175]# RECV ASCII/5 <<<
hello
数组收发
uartps中提供了两个相对复杂的数组收发函数,原型如下
u32 XUartPs_Send(XUartPs * InstancePtr, u8 * BufferPtr, u32 NumBytes)
u32 XUartPs_Recv(XUartPs * InstancePtr, u8 * BufferPtr, u32 NumBytes)
这两个函数的输入参数相同,均为串口指针、数据指针和数据长度。需要注意的是,其第一个参数为XuartPS的指针,而非单字节收发函数的串口地址。对于这两组收发函数,一个简单的示例如下
void uartTest(){
char cBuf[10];
XUartPs Uart_PS;
int nRecv;
// 初始化UART
XUartPs_Config *Uart_Config = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID);
XUartPs_CfgInitialize(&Uart_PS, Uart_Config, Uart_Config->BaseAddress);
while(1){
usleep(10000);
nRecv = XUartPs_Recv(&Uart_PS, (u8 *)cBuf, 10);
if(nRecv > 0)
XUartPs_Send(&Uart_PS, (u8 *)cBuf, 10);
}
}
其中,【XUartPs_Config】是串口的配置参数,【XUartPs_CfgInitialize】用于初始化串口。
【XUartPs_Recv】的原理是,直接从Uart_PS所在地址读取数据,不管这些数据是否为上位机传来的数据,都会立即返回。如果上位机没有传来数据,那么其返回值就是0个数据。正因如此,需要对其返回值进行判断,只有大于0时,才视作有效的数据。另一方面,为了让上位机传来的数据充分占据UART所在地址,在每次接收之前,需要等待10ms。
接收结构体
在工程应用中,串口通信需要在严格的协议下进行,协议中不同的位置代表不同的数据,例如,我们希望计算除法,那么可以定义如下结构体,包括一个帧头和校验位,中间是除数和被除数。
#pragma pack(push, 1)
typedef struct {
u8 head;
u32 dividend;
u32 divisor;
u8 check;
} DivData;
#pragma pack(pop)
其中pack语句用于取消结构体的字节对齐,从而让其成员之间不存在缝隙,能够与数组之间无缝转换。其验证程序如下
void uartTest(){
DivData * dv;
XUartPs Uart_PS;
int nRecv, a, b;
float res;
XUartPs_Config *Uart_Config = XUartPs_LookupConfig(XPAR_XUARTPS_0_DEVICE_ID);
XUartPs_CfgInitialize(&Uart_PS, Uart_Config, Uart_Config->BaseAddress);
while(1){
usleep(10000);
nRecv = XUartPs_Recv(&Uart_PS, (u8 *)dv, 10);
if(nRecv > 0){
res = 1.0*dv->dividend/dv->divisor;
a = (int)res;
b = (int)((res-a)*1000);
xil_printf("%d/%d=%d.%d", dv->dividend, dv->divisor, a, b);
}
}
}
测试如下
# SEND HEX/10 >>>
AA FF 00 00 00 02 00 00 00 00
# RECV ASCII/13 <<<
255/2=127.500
1万+

被折叠的 条评论
为什么被折叠?



