嵌入式开发串口中断读写的程序要怎么写

这几天刚开始做驱动开发,要写一个串口中断的程序。看了几天也没写出来
使用的是VITIS 2021,zynq7000系列的开发板,只要写一个串口和电脑端通过中断能收发读写信息的程序就可以。然而看了几天也不会写,不知从何下手...官方给的文档和程序也看了,没太明白。
下面这个程序是个官方example,我要怎么编写中断,调用编写哪个函数来让串口能够通过输入的字执行流程。比如输入w就中断进入一个程序,输入r是另一个。再去读取对应值,这部分程序已经写好了,唯独串口中断没写过,也不知道该怎么用库函数呢?
#ifdef XPAR_INTC_0_DEVICE_ID
#include "xintc.h"
#else
#include "xscugic.h"
#endif
/************************** Constant Definitions **************************/
/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#ifdef XPAR_INTC_0_DEVICE_ID
#define INTC        XIntc
#define UART_DEVICE_ID        XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID        XPAR_INTC_0_DEVICE_ID
#define UART_INT_IRQ_ID        XPAR_INTC_0_UARTPS_0_VEC_ID
#else
#define INTC        XScuGic
#define UART_DEVICE_ID        XPAR_XUARTPS_0_DEVICE_ID
#define INTC_DEVICE_ID        XPAR_SCUGIC_SINGLE_DEVICE_ID
#define UART_INT_IRQ_ID        XPAR_XUARTPS_1_INTR
#endif
#define TEST_BUFFER_SIZE    100


/**************************** Type Definitions ******************************/

XUartPs UartPs    ;        /* Instance of the UART Device */
INTC InterruptController;    /* Instance of the Interrupt Controller */

/*
 * The following buffers are used in this example to send and receive data
 * with the UART.
 */
static u8 SendBuffer[TEST_BUFFER_SIZE];    /* Buffer for Transmitting Data */
static u8 RecvBuffer[TEST_BUFFER_SIZE];    /* Buffer for Receiving Data */

volatile int TotalReceivedCount;
volatile int TotalSentCount;
int TotalErrorCount;

#ifndef TESTAPP_GEN
int main(void)
{
    int Status;

    /* Run the UartPs Interrupt example, specify the the Device ID */
    Status = UartPsIntrExample(&InterruptController, &UartPs,
                UART_DEVICE_ID, UART_INT_IRQ_ID);
    if (Status != XST_SUCCESS) {
        xil_printf("UART Interrupt Example Test Failed\r\n");
        return XST_FAILURE;
    }

    xil_printf("Successfully ran UART Interrupt Example Test\r\n");
    return XST_SUCCESS;
}
#endif

int UartPsIntrExample(INTC *IntcInstPtr, XUartPs *UartInstPtr,
            u16 DeviceId, u16 UartIntrId)
{
    int Status;
    XUartPs_Config *Config;
    int Index;
    u32 IntrMask;
    int BadByteCount = 0;

#ifndef TESTAPP_GEN
    if (XGetPlatform_Info() == XPLAT_ZYNQ_ULTRA_MP) {
#ifdef XPAR_XUARTPS_1_DEVICE_ID
        DeviceId = XPAR_XUARTPS_1_DEVICE_ID;
#endif
    }
#endif

    /*
     * Initialize the UART driver so that it's ready to use
     * Look up the configuration in the config table, then initialize it.
     */
    Config = XUartPs_LookupConfig(DeviceId);
    if (NULL == Config) {
        return XST_FAILURE;
    }

    Status = XUartPs_CfgInitialize(UartInstPtr, Config, Config->BaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /* Check hardware build */
    Status = XUartPs_SelfTest(UartInstPtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Connect the UART to the interrupt subsystem such that interrupts
     * can occur. This function is application specific.
     */
    Status = SetupInterruptSystem(IntcInstPtr, UartInstPtr, UartIntrId);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Setup the handlers for the UART that will be called from the
     * interrupt context when data has been sent and received, specify
     * a pointer to the UART driver instance as the callback reference
     * so the handlers are able to access the instance data
     */
    XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)Handler, UartInstPtr);

    /*
     * Enable the interrupt of the UART so interrupts will occur, setup
     * a local loopback so data that is sent will be received.
     */
    IntrMask =
        XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
        XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
        XUARTPS_IXR_RXOVR;

    if (UartInstPtr->Platform == XPLAT_ZYNQ_ULTRA_MP) {
        IntrMask |= XUARTPS_IXR_RBRK;
    }

    XUartPs_SetInterruptMask(UartInstPtr, IntrMask);

    XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_LOCAL_LOOP);

    /*
     * Set the receiver timeout. If it is not set, and the last few bytes
     * of data do not trigger the over-water or full interrupt, the bytes
     * will not be received. By default it is disabled.
     *
     * The setting of 8 will timeout after 8 x 4 = 32 character times.
     * Increase the time out value if baud rate is high, decrease it if
     * baud rate is low.
     */
    XUartPs_SetRecvTimeout(UartInstPtr, 8);


    /*
     * Initialize the send buffer bytes with a pattern and the
     * the receive buffer bytes to zero to allow the receive data to be
     * verified
     */
    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {

        SendBuffer[Index] = (Index % 26) + 'A';

        RecvBuffer[Index] = 0;
    }

    /*
     * Start receiving data before sending it since there is a loopback,
     * ignoring the number of bytes received as the return value since we
     * know it will be zero
     */
    XUartPs_Recv(UartInstPtr, RecvBuffer, TEST_BUFFER_SIZE);

    /*
     * Send the buffer using the UART and ignore the number of bytes sent
     * as the return value since we are using it in interrupt mode.
     */
    XUartPs_Send(UartInstPtr, SendBuffer, TEST_BUFFER_SIZE);

    /*
     * Wait for the entire buffer to be received, letting the interrupt
     * processing work in the background, this function may get locked
     * up in this loop if the interrupts are not working correctly.
     */
    while (1) {
        if ((TotalSentCount == TEST_BUFFER_SIZE) &&
            (TotalReceivedCount == TEST_BUFFER_SIZE)) {
            break;
        }
    }

    /* Verify the entire receive buffer was successfully received */
    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
        if (RecvBuffer[Index] != SendBuffer[Index]) {
            BadByteCount++;
        }
    }



    /* Set the UART in Normal Mode */
    XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_NORMAL);


    /* If any bytes were not correct, return an error */
    if (BadByteCount != 0) {
        return XST_FAILURE;
    }

    return XST_SUCCESS;
}

void Handler(void *CallBackRef, u32 Event, unsigned int EventData)
{
    /* All of the data has been sent */
    if (Event == XUARTPS_EVENT_SENT_DATA) {
        TotalSentCount = EventData;
    }

    /* All of the data has been received */
    if (Event == XUARTPS_EVENT_RECV_DATA) {
        TotalReceivedCount = EventData;
    }

    /*
     * Data was received, but not the expected number of bytes, a
     * timeout just indicates the data stopped for 8 character times
     */
    if (Event == XUARTPS_EVENT_RECV_TOUT) {
        TotalReceivedCount = EventData;
    }

    /*
     * Data was received with an error, keep the data but determine
     * what kind of errors occurred
     */
    if (Event == XUARTPS_EVENT_RECV_ERROR) {
        TotalReceivedCount = EventData;
        TotalErrorCount++;
    }

    /*
     * Data was received with an parity or frame or break error, keep the data
     * but determine what kind of errors occurred. Specific to Zynq Ultrascale+
     * MP.
     */
    if (Event == XUARTPS_EVENT_PARE_FRAME_BRKE) {
        TotalReceivedCount = EventData;
        TotalErrorCount++;
    }

    /*
     * Data was received with an overrun error, keep the data but determine
     * what kind of errors occurred. Specific to Zynq Ultrascale+ MP.
     */
    if (Event == XUARTPS_EVENT_RECV_ORERR) {
        TotalReceivedCount = EventData;
        TotalErrorCount++;
    }
}

/*****************************************************************************/
/**
*
* This function sets up the interrupt system so interrupts can occur for the
* Uart. This function is application-specific. The user should modify this
* function to fit the application.
*
* @param    IntcInstancePtr is a pointer to the instance of the INTC.
* @param    UartInstancePtr contains a pointer to the instance of the UART
*        driver which is going to be connected to the interrupt
*        controller.
* @param    UartIntrId is the interrupt Id and is typically
*        XPAR__INTR value from xparameters.h.
*
* @return    XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note        None.
*
****************************************************************************/
static int SetupInterruptSystem(INTC *IntcInstancePtr,
                XUartPs *UartInstancePtr,
                u16 UartIntrId)
{
    int Status;

#ifdef XPAR_INTC_0_DEVICE_ID
#ifndef TESTAPP_GEN
    /*
     * Initialize the interrupt controller driver so that it's ready to
     * use.
     */
    Status = XIntc_Initialize(IntcInstancePtr, INTC_DEVICE_ID);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
#endif
    Status = XIntc_Connect(IntcInstancePtr, UartIntrId,
        (XInterruptHandler) XUartPs_InterruptHandler, UartInstancePtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

#ifndef TESTAPP_GEN
    /*
     * Start the interrupt controller so interrupts are enabled for all
     * devices that cause interrupts.
     */
    Status = XIntc_Start(IntcInstancePtr, XIN_REAL_MODE);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }
#endif
    /*
     * Enable the interrupt for uart
     */
    XIntc_Enable(IntcInstancePtr, UartIntrId);

    #ifndef TESTAPP_GEN
    /*
     * Initialize the exception table.
     */
    Xil_ExceptionInit();

    /*
     * Register the interrupt controller handler with the exception table.
     */
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                (Xil_ExceptionHandler) XIntc_InterruptHandler,
                IntcInstancePtr);
    #endif
#else
#ifndef TESTAPP_GEN
    XScuGic_Config *IntcConfig; /* Config for interrupt controller */

    /* Initialize the interrupt controller driver */
    IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
    if (NULL == IntcConfig) {
        return XST_FAILURE;
    }

    Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
                    IntcConfig->CpuBaseAddress);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Connect the interrupt controller interrupt handler to the
     * hardware interrupt handling logic in the processor.
     */
    Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
                (Xil_ExceptionHandler) XScuGic_InterruptHandler,
                IntcInstancePtr);
#endif

    /*
     * Connect a device driver handler that will be called when an
     * interrupt for the device occurs, the device driver handler
     * performs the specific interrupt processing for the device
     */
    Status = XScuGic_Connect(IntcInstancePtr, UartIntrId,
                  (Xil_ExceptionHandler) XUartPs_InterruptHandler,
                  (void *) UartInstancePtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /* Enable the interrupt for the device */
    XScuGic_Enable(IntcInstancePtr, UartIntrId);

#endif
    return XST_SUCCESS;
}
测试可以运行,但 我应该怎么加入自己的程序呢?

在嵌入式开发中,串口通信常常使用中断机制来进行读写操作。

假设你的程序运行在一个具有串口的嵌入式系统上,并且已经在系统中配置好了串口的硬件,你可以使用以下步骤来实现串口中断读写:

在程序中定义一个结构体,用于保存串口读写时需要使用的变量。例如,可以在结构体中定义一个缓冲区,用于存储从串口读入的数据。

在程序中设置串口的中断服务程序 (ISR, Interrupt Service Routine)。这个程序会在串口收到数据时自动被调用,你可以在这个程序中实现串口数据的读写操作。

在程序的主循环中,使用循环语句不断检查缓冲区中是否有新的数据。如果有,则进行相应的处理。

以上是实现串口中断读写的大致步骤。实际的代码实现可能会因硬件平台和编程语言的不同而有所差异。

可以参考这个:https://blog.csdn.net/qq_45614178/article/details/122523330

你好!

为了使用串口中断,你需要在程序中进行以下步骤:

1.初始化中断控制器:

// 初始化中断控制器
INTC_DEVICE_ID = XPAR_SCUGIC_SINGLE_DEVICE_ID; // 中断控制器的设备ID
Status = XScuGic_Initialize(&InterruptController, INTC_DEVICE_ID);
if (Status != XST_SUCCESS) {
    return XST_FAILURE;
}


2.设置串口的中断服务程序:


// 设置串口的中断服务程序
Status = XScuGic_Connect(&InterruptController, UART_INT_IRQ_ID,
    (Xil_ExceptionHandler)XUartPs_InterruptHandler, (void *)&UartPs);
if (Status != XST_SUCCESS) {
    return XST_FAILURE;
}

3.使能串口中断:


// 使能串口中断
XUartPs_SetInterruptMask(&UartPs, XUARTPS_IXR_RXOVR | XUARTPS_IXR_RXFULL |
    XUARTPS_IXR_TOUT | XUARTPS_IXR_TXEMPTY);
XScuGic_Enable(&InterruptController, UART_INT_IRQ_ID);

4.在中断服务程序中,处理串口的接收和发送:

void XUartPs_InterruptHandler(void *CallBackRef)
{
    // 处理接收和发送
    // ...
}


串口发用不用中断都好解决,主要是串口收,中断处理包括初始化中断配置、中断程序接收状态判断、获取数据、队列管理等,要尽量短小精悍。

可以参考我的文章串口中断的测试,也是基于zynq7000的芯片开发的:https://vuko-wxh.blog.csdn.net/article/details/116953496%E3%80%82
对于你的需求可以在中断服务函数中进行增加对于字符判断的flag标志,判断完成后在主函数或者中断函数中执行你规划实现的部分。