这几天刚开始做驱动开发,要写一个串口中断的程序。看了几天也没写出来
使用的是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标志,判断完成后在主函数或者中断函数中执行你规划实现的部分。