当前位置: 首页 > article >正文

6.3 - UART串口数据发送之中断

文章目录

  • 1 实验任务
  • 2 系统框图
  • 3 软件设计

1 实验任务

本实验使用中断方式实现UART串口数据的连续发送。

2 系统框图

参见6.1。

3 软件设计

注意事项:

  1. 系统上电、程序下载后,此时TX FIFO虽然为空,但并不会触发空中断;空中断的触发前提是FIFO中有数据且被读空,即FIFO中的最后一个数据被读出(This event is triggered whenever the final word is removed from the transmit FIFO);
  2. XUartPs_Send函数:
    • (1)函数功能:发送数据到TX FIFO
    • (2)函数实现:
      • 1)禁用TX FIFO空中断和TX FIFO满中断
      • 2)设置缓冲区参数,包括请求发送的字节数、剩余待发送的字节数和指向下一个要发送的字节的指针
      • 3)调用XUartPs_SendBuffer函数,该函数完成数据发送功能并返回实际发送的字节数
      • 4)接收XUartPs_SendBuffer函数的返回值并返回
  3. XUartPs_SendBuffer函数:
    • (1)函数功能:以轮询或中断驱动模式将缓冲区数据发送到TX FIFO
    • (2)函数实现:
      • 1)发送数据到TX FIFO,如果TX FIFO未满且缓冲区中还有数据未发送,则将数据写入TX FIFO(Otherwise put bytes into the TX FIFO unil it is full, or all of the data has been put into the FIFO
      • 2)更新缓冲区指针和剩余字节数
      • 3)使能TX FIFO空中断:注意,如果接收中断已启用,则启用TX FIFO空中断(这也是为何在UartInit函数中使能看似无关的XUARTPS_IXR_RXOVR中断的原因)
        • 疑问1:为什么在启用接收中断的前提下才能启用TX FIFO空中断
        • 疑问2:为什么仅启用了TX FIFO空中断,TX FIFO满中断在XUartPs_Send也被禁用了,为何未被重新启用
      • 4)返回实际发送的字节数
  4. 程序设计思路:
    • (1)在程序下载后,假设上一次数据已发送完毕,SendComplete置1;
    • (2)将每一轮的首次数据发送放在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  c(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;
}

http://www.kler.cn/a/562596.html

相关文章:

  • Snapshot Compressed Imaging:打破传统成像的新视界
  • 接口测试-计算机网络基础扫盲
  • Linux | man 手册使用详解
  • 关于远程连接工具不能用hostname而只能用ip连接上的问题
  • flowable-ui 的会签功能实现
  • Hutool - Http:基于 HttpUrlConnection 的 Http 客户端封装
  • Vscode编辑器获取更新远程最新分支
  • DeepSeek 开源周:DeepEP 项目详解,GPU 压榨计划启动!
  • DeepSeek开源周首日:发布大模型加速核心技术可变长度高效FlashMLA 加持H800算力解码性能狂飙升至3000GB/s
  • 扩增子测序|R包microeco妙用之零模型计算群落确定性和随机性过程(NST,pNST,βNTI,RCbray生态过程计算)
  • 基于springboot的学习社区博客
  • DeepSeek回答:AI时代Go语言学习路线
  • 在 C++23 中使用智能指针进行现代内存管理 — 第 2 部分:共享指针
  • Windows 上源码安装 FastGPT
  • Java 数学函数库
  • 精美登录注册UI,登录页面设计模板
  • SOME/IP-SD -- 协议英文原文讲解2
  • 解决后端跨域问题
  • 未来技术的边界:机器学习如何塑造我们的世界
  • elementPlus 中表单验证方法(手机号、正整数、邮箱)