文章目录
- 1 实验任务
- 2 系统框图
- 3 软件设计
1 实验任务
本实验使用中断方式实现UART串口数据的连续发送。
2 系统框图
参见6.1。
3 软件设计
注意事项:
- 系统上电、程序下载后,此时TX FIFO虽然为空,但是并不会触发空中断;空中断的触发前提是FIFO中的最后一个数据被读出(这个地方调试了好久,明明使能了空中断,但是程序下载后死活都收不到中断;尝试在main函数中加入一些打印信息,反而能触发空中断,思来想去并结合文档关于空中断状态位的描述,发现必须先写入数据);
- 对于XUartPs_Send函数
- (1) 禁用发送相关中断(TXFULL和TXEMPTY)
- (2) 使用XUartPs_SendBuffer函数向TX FIFO中写入数据
- (3) XUartPs_SendBuffer会使能TXEMPTY中断,但是有个前提,必须使能了RX FIFO相关中断(RXFULL、RXEMPTY或RXOVR)(这个地方同样调试了好久,至今仍未明白原因)
- (4) 返回实际写入的个数
- 有个小技巧,在程序下载后,假设上一次数据已发送完毕,SendComplete置1,并将每一轮的首次数据发送放在while循环中,这样TxBuffer中的数据才能一轮一轮的循环发送起来(刚开始把首次数据发送放在while循环外边,在第一轮的最后一次数据发送完毕并触发空中断后,SendComplete置1,然后就没有然后了…)。
/************************** Include Files ***********************************/
#include "xparameters.h"
#include "xuartps.h"
#include "xscugic.h"
#include "xil_exception.h"
#include "stdio.h"
#include "sleep.h"
/************************** Constant Definitions ****************************/
#define UART_DEVICE_ID XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INTR_ID XPAR_XUARTPS_1_INTR
#define BUFFER_SIZE 256 // 发送缓冲区大小
#define FIFO_TRIGGER_LEVEL 32 // FIFO触发阈值
#define RECV_TIMEOUT 4 // 接收超时时间(单位:波特率时钟周期)
/************************** Function Prototypes *****************************/
s32 UartPsInit(XUartPs *UartPsInstPtr, XUartPsFormat* UartFormatPtr);
s32 SetupInterruptSystem(XScuGic *IntcInstPtr, XUartPs *UartPsInstPtr);
void UartIntrHandler(void *CallBackRef);
/************************** Variable Definitions ****************************/
XUartPs UartInst;
XScuGic IntcInst;
u8 TxBuffer[BUFFER_SIZE] = { 0 }; // 接收缓冲区
int RxDataLength = 0; // 接收到的数据长度
XUartPsFormat UartFormat = {
XUARTPS_DFT_BAUDRATE, // 115200
XUARTPS_FORMAT_8_BITS,
XUARTPS_FORMAT_NO_PARITY,
XUARTPS_FORMAT_1_STOP_BIT
};
// 发送状态
u32 TotalBytesSent; // 已发送的字节数
int SendComplete; // 发送完成标志
/************************** Function Implementation *************************/
int main()
{
//
s32 Status;
u32 BytesSent;
//
for (int i = 0; i < BUFFER_SIZE; i++) {
TxBuffer[i] = (u8)i; // 填充从 0 开始的递增数
}
// 初始化UART
Status = UartPsInit(&UartInst, &UartFormat);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// 设置中断系统
Status = SetupInterruptSystem(&IntcInst, &UartInst);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// 主循环
SendComplete = 1;
while(1)
{
if (SendComplete == 1) {
TotalBytesSent = 0;
SendComplete = 0;
sleep(3);
// 启动第一次发送
BytesSent = XUartPs_Send(&UartInst, TxBuffer, BUFFER_SIZE);
TotalBytesSent += BytesSent;
}
}
//
return 0;
}
s32 UartPsInit(XUartPs *UartInstPtr, XUartPsFormat* UartFormatPtr)
{
//
s32 Status;
XUartPs_Config *UartConfigPtr;
// 查找UART配置
UartConfigPtr = XUartPs_LookupConfig(UART_DEVICE_ID);
if(NULL == UartConfigPtr)
{
return XST_FAILURE;
}
// 初始化UART
Status = XUartPs_CfgInitialize(UartInstPtr, UartConfigPtr, UartConfigPtr->BaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
// 设置UART数据格式
XUartPs_SetDataFormat(UartInstPtr, UartFormatPtr);
// 设置UART操作模式
XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL);
// 设置接收FIFO触发阈值
XUartPs_SetFifoThreshold(UartInstPtr, FIFO_TRIGGER_LEVEL);
// 设置接收超时
XUartPs_SetRecvTimeout(UartInstPtr, RECV_TIMEOUT);
// 设置中断掩码,使能发送FIFO空中断
XUartPs_SetInterruptMask(UartInstPtr, XUARTPS_IXR_RXOVR | XUARTPS_IXR_TXEMPTY);
//
return XST_SUCCESS;
}
s32 SetupInterruptSystem(XScuGic *IntcInstPtr, XUartPs *UartInstPtr)
{
//
s32 Status;
XScuGic_Config *IntcConfigPtr;
// 初始化中断控制器GIC
IntcConfigPtr = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfigPtr)
{
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstPtr, IntcConfigPtr, IntcConfigPtr->CpuBaseAddress);
if (Status != XST_SUCCESS)
{
return XST_FAILURE;
}
// 注册异常处理程序
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)XScuGic_InterruptHandler, IntcInstPtr);
Xil_ExceptionEnable();
// 连接UART中断处理程序
XScuGic_Connect(IntcInstPtr, UART_INTR_ID, (Xil_InterruptHandler)UartIntrHandler, (void *)UartInstPtr);
// 使能UART中断
XScuGic_Enable(IntcInstPtr, UART_INTR_ID);
//
return XST_SUCCESS;
}
void UartIntrHandler(void *CallBackRef)
{
//
XUartPs* UartInstPtr = (XUartPs*)CallBackRef;
u32 IsrStatus;
// 读取中断状态
IsrStatus = XUartPs_ReadReg(UartInstPtr->Config.BaseAddress, XUARTPS_IMR_OFFSET);
IsrStatus &= XUartPs_ReadReg(UartInstPtr->Config.BaseAddress, XUARTPS_ISR_OFFSET);
// 处理发送FIFO空中断
if ((IsrStatus & (u32)XUARTPS_IXR_TXEMPTY) != (u32)0) {
XUartPs_WriteReg(UartInstPtr->Config.BaseAddress, XUARTPS_ISR_OFFSET, XUARTPS_IXR_TXEMPTY);
if (TotalBytesSent < BUFFER_SIZE) {
// 继续发送剩余的数据
u32 BytesSent = XUartPs_Send(UartInstPtr, &TxBuffer[TotalBytesSent], BUFFER_SIZE - TotalBytesSent);
TotalBytesSent += BytesSent;
}
else {
// 所有数据已发送完毕
SendComplete = 1;
// xil_printf("Config file sent successfully in polled mode!\n");
}
}
//
return;
}