PS_UART.h
#ifndef PS_UART_PS_UART_H_
#define PS_UART_PS_UART_H_
#include "COMMON.h"
#include "xuartps.h"
#define PS_UART0_IRQ_ID XPAR_XUARTPS_0_INTR
#define PS_UART1_IRQ_ID XPAR_XUARTPS_1_INTR
extern XUartPs UartPs1; //UART�豸ʵ��
void PS_UART_Init(XUartPs *UartInstPtr,uint16_t DeviceId, uint8_t UART_Mode, uint32_t BaudRate);
void PS_UART_Intr_Init(XUartPs *UartInstPtr,uint16_t UartIntrId, uint8_t RecvTimeout, Xil_InterruptHandler Handler);
void PS_Uart_SendData(XUartPs *UartInstPtr,uint32_t data);
void PS_Uart_SendString(XUartPs *UartInstPtr, char *str);
void PS_Uart_RecvData(XUartPs *UartInstPtr, uint8_t *Buffer,uint32_t Len);
typedef struct{
u8 rec_buff[1024*1024];
u32 recv_length;
} rec_buff_t;
void PS_UART_RX(rec_buff_t *pbuf);
void PS_UART_TX(rec_buff_t *pbuf);
#endif /* PS_UART_PS_UART_H_ */
PS_UART.c
/**
*****************************************************************************
* PS部分UART相关库
*****************************************************************************
*
* @File : PS_UART.c
* @By : Sun
* @Version: V1.3
* @Date : 2021 / 11 / 04
* @Shop : https://xiaomeige.taobao.com/
*
*****************************************************************************
**/
#include "PS_UART.h"
XUartPs UartPs1; //UART设备实例
/***********************************************************************************************************
* @brief: 初始化PS_UART设备
* @param: UartInstPtr UART对象
* @param: DeviceId UART设备ID
* @param: UART_Mode UART模式选择
* @param: BaudRate 设置波特率
* 模式有以下几种: XUARTPS_OPER_MODE_NORMAL 标准模式
* XUARTPS_OPER_MODE_AUTO_ECHO 自动回显模式
* XUARTPS_OPER_MODE_LOCAL_LOOP 本地环回模式
* XUARTPS_OPER_MODE_REMOTE_LOOP 远程环回模式
* //初始化UART设备UartPs1,设为标准模式,波特率115200
* Sample: PS_UART_Init(&UartPs1,XPAR_PS7_UART_1_DEVICE_ID, XUARTPS_OPER_MODE_NORMAL, 115200);
***********************************************************************************************************/
void PS_UART_Init(XUartPs *UartInstPtr,uint16_t DeviceId, uint8_t UART_Mode, uint32_t BaudRate)
{
XUartPs_Config *Config;
Config = XUartPs_LookupConfig(DeviceId);
XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
//设置波特率
XUartPs_SetBaudRate(UartInstPtr, BaudRate);
//设置UART模式
XUartPs_SetOperMode(UartInstPtr, UART_Mode);
}
/***********************************************************************************************************
* @brief: 初始化PS UART中断(初始化PS UART中断前,需先初始化PS UART)
* @param: UartInstPtr UART对象
* @param: UartIntrId UART中断ID
* @param: RecvTimeout 接收超时设置(设置为n时,如果超过nx4个字符时间仍未接收到数据,则进入超时中断;
* 设置为0时禁用该功能)
* @return: 无
* Sample: PS_UART_Intr_Init(&UartPs1, PS_UART1_IRQ_ID, 8, (void *)PS_UART1_IRQ_Handler);
* //初始化PS UART中断,UART对象为UartPs,中断ID为UART1_IRQ_ID,接收超时32字符
***********************************************************************************************************/
void PS_UART_Intr_Init(XUartPs *UartInstPtr,uint16_t UartIntrId, uint8_t RecvTimeout, Xil_InterruptHandler Handler)
{
uint32_t IntrMask;
Set_ScuGic_Link(UartIntrId, 0xA8, HIGH_Level_Sensitive,
(Xil_ExceptionHandler)XUartPs_InterruptHandler, (void *)UartInstPtr);
//为 UART 设置处理程序,当数据发送和接收时,该处理程序将从中断上下文中调用,
//指定一个指向 UART 驱动程序实例的指针作为回调引用,以便处理程序能够访问实例数据
XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)PS_UART0_IRQ_Handler, UartInstPtr);
//配置UART的中断模式
IntrMask = XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL | XUARTPS_IXR_RXOVR;
XUartPs_SetInterruptMask(UartInstPtr, IntrMask);
//Fifo阈值设置为1
XUartPs_SetFifoThreshold(&UartPs1, 1);
//接收超时设置
XUartPs_SetRecvTimeout(UartInstPtr, RecvTimeout);
}
/***********************************************************************************************************
* @brief: 使用PS UART发送数据,数据需在0~65535之间
* @param: UartInstPtr UART对象
* @param: data 数据
* @return: 无
* Sample: PS_Uart_SendData(&UartPs,12345); //发送数据12345
***********************************************************************************************************/
void PS_Uart_SendData(XUartPs *UartInstPtr,uint32_t data)
{
uint8_t SendData[2];
int data_H,data_L;
data_H = data>>8;
data_L = data&0x00ff;
if(data_H == 0)//如果高位为0
{
SendData[0] = data;
XUartPs_Send(UartInstPtr, SendData, 1);
}
else
{
SendData[0] = data_H;
SendData[1] = data_L;
XUartPs_Send(UartInstPtr, SendData, 2);
}
}
/***********************************************************************************************************
* @brief: 使用PS UART发送字符串
* @param: UartInstPtr UART对象
* @param: str 字符串地址
* @return: 无
* Sample: PS_Uart_SendString(&UartPs,"1234567"); //发送了7个字节
***********************************************************************************************************/
void PS_Uart_SendString(XUartPs *UartInstPtr, char *str)
{
XUartPs_Send(UartInstPtr, (uint8_t *)str, strlen(str));
}
/***********************************************************************************************************
* @brief: 使用PS UART接收数据
* @param: UartInstPtr UART对象
* @param: Buffer 接收数据存储区
* @param: Len 接收数据的长度
* @return: 无
* Sample: PS_Uart_RecvData(&UartPs, RecvBuffer,2);接收两个数据,并将数据存入RecvBuffer数组
***********************************************************************************************************/
void PS_Uart_RecvData(XUartPs *UartInstPtr, uint8_t *Buffer,uint32_t Len)
{
XUartPs_Recv(UartInstPtr, Buffer, Len);
}
/***********************************************************************************************************
* 不定长度接收与发送
***********************************************************************************************************/
void PS_UART_RX(rec_buff_t *pbuf)
{
PS_UART_Init(&UartPs1,XPAR_PS7_UART_0_DEVICE_ID, XUARTPS_OPER_MODE_NORMAL, 115200);
u32 max_length=sizeof(pbuf->rec_buff);
u32 ReceivedCount=0;
u32 loop_cnt=0;
while (ReceivedCount<=max_length) {
u32 OneTimeCount=XUartPs_Recv(&UartPs1, &pbuf->rec_buff[ReceivedCount],
(max_length- ReceivedCount));
ReceivedCount+=OneTimeCount;
if(ReceivedCount>0){ /*只有当接收到数据后,才开始计数。最初没有接收到数据,不计数。*/
if(OneTimeCount==0){/*当接收停顿后,开始计时*/
usleep(10);
loop_cnt++;
if(loop_cnt>10000){ /*这个计数长度要大于sscom每发送256bytes后的停顿时间*/
pbuf->recv_length=ReceivedCount;
break;
}
}
else{
loop_cnt=0; /*一旦接收到数量不为零,那么计数值就清零*/
}
}
}
}
void PS_UART_TX(rec_buff_t *pbuf)
{
u32 TransmitCount = 0;
u32 remainBytes=pbuf->recv_length;
while (remainBytes >= 32) {
TransmitCount+=XUartPs_Send(&UartPs1, &pbuf->rec_buff[TransmitCount],32);
while (XUartPs_IsSending(&UartPs1)) {}
remainBytes-=32;
}
if(remainBytes){
TransmitCount+=XUartPs_Send(&UartPs1, &pbuf->rec_buff[TransmitCount],remainBytes);
while (XUartPs_IsSending(&UartPs1)) {}
}
}