中断:Zynq Uart中断的流程和例程~UG585的CH.19

news2024/11/16 18:01:58

Zynq里的uart

         UART 控制器是全双工异步接收器和发送器,支持多种可编程波特率和 I/O 信号格式。该控制器可以适应自动奇偶校验生成和多主机检测模式。
        UART 操作由配置和模式寄存器控制。使用状态、中断状态和调制解调器状态寄存器读取 FIFO、调制解调器信号和其他控制器功能的状态。
        该控制器采用独立的 Rx 和 Tx 数据路径构建。每条路径均包含一个 64 字节 FIFO。
        该控制器对 Tx 和 Rx FIFO 中的数据进行串行化和反串行化,并包含一个模式开关以支持 RxD 和 TxD 信号的各种环回配置。 FIFO 中断状态位支持轮询或中断驱动的处理程序。软件使用 Rx 和 Tx 数据端口寄存器读取和写入数据字节。

        (XUARTPS_IXR_RXOVR灯中断敏感事件就是在这里使用的)
        当 UART 用于类似调制解调器的应用时,调制解调器控制模块会检测并生成调制解调器握手信号,并根据握手协议控制接收器和发送器路径。

TxFIFO和RXFIFO

TxFIFO

        (机翻原文,此处涉及到一些UART的触发方法)

        发送 FIFO (TxFIFO) 存储从 APB 接口写入的数据,直到该数据被发送模块移除并加载到其移位寄存器中。 TxFIFO 的最大数据宽度为 8 位。
        通过写入 TxFIFO 寄存器将数据加载到 TxFIFO 中。
        当数据加载到 TxFIFO 中时,TxFIFO 空标志被清除并保持在该低电平状态,直到 TxFIFO 中的最后一个字被移除并加载到发送器移位寄存器中。这意味着主机软件在需要下一个数据之前还有另一个完整的串行字时间,使其能够对设置的空标志做出反应,并在 TxFIFO 中写入另一个字,而不会损失传输时间。
        TxFIFO 满中断状态 (TFULL) 指示 TxFIFO 已完全满,并阻止任何进一步的数据加载到 TxFIFO 中。如果对 TxFIFO 执行另一次 APB 写入,则会触发溢出,并且写入数据不会加载到 TxFIFO 中。发送 FIFO 几乎已满标志 (TNFULL) 表示 FIFO 中没有足够的可用空间,无法再写入一次编程大小(由模式寄存器的 WSIZE 位控制)。
        TxFIFO 近满标志 (TNFULL) 指示 TxFIFO 中仅存在空闲字节。
        可以在 TxFIFO 填充水平上设置阈值触发器 (TTRIG)。发送器触发寄存器可用于设置该值,以便在 TxFIFO 填充水平达到该编程值时设置触发。

RxFIFO

        RxFIFO 存储接收器串行移位寄存器接收到的数据。 RxFIFO 的最大数据宽度为 8 位。
        当数据加载到 RxFIFO 时,RxFIFO 空标志被清除,并且该状态保持低电平,直到 RxFIFO 中的所有数据都已通过 APB 接口传输。从空 RxFIFO 读取返回零。
        RxFIFO 满状态(Chnl_int_sts_reg0 [RFUL] 和 Channel_sts_reg0 [RFUL] 位)指示 RxFIFO 已满,并阻止任何进一步的数据加载到 RxFIFO 中。当 RxFIFO 中出现可用空间时,将加载接收器中存储的任何字符。
        可以在 RxFIFO 填充级别上设置阈值触发器 (RTRIG)。接收器触发电平寄存器 (Rcvr_FIFO_trigger_level0) 可用于设置该值,以便当 RxFIFO 填充电平转变为该编程值时设置触发。范围是 1 到 63。

        当设置了缓冲区的时候,Rcvr_FIFO_trigger_level0的数值将会在缓冲区填满以后才开始计算,这会影响中断:

        例如函数:XUartPs_SetFifoThreshold:

        因为FIFO内的数值会被不断移出,填入缓冲区里。

可参考:

PYNQ UART控制器(二)库函数使用 轮询和中断两种方式使用_xuartps_send-CSDN博客

ZYNQ之UART中断实验软件设计-CSDN博客 

初始化Uart

int  Uart_init(){
    int Status;
    Uart_ConFig = XUartPs_LookupConfig(UART_DEVICE_ID);
    	if (NULL == Uart_ConFig) {
		return XST_FAILURE;
	}

	Status = XUartPs_CfgInitialize(&Uart_instance_point, 
                                   Uart_ConFig, 
                                   Uart_ConFig->BaseAddress);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
    Status = XUartPs_SelfTest(&Uart_instance_point);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}
    Status = XUartPs_SetBaudRate(&Uart_instance_point,
                                  115200);
    if (Status != XST_SUCCESS) {
		return XST_UART_BAUD_ERROR;
	}
}

波特率

        波特率发生器为接收器和发送器提供位周期时钟或波特率时钟。波特率时钟是通过分配基础时钟uart_clk和单周期时钟使能来实现的,以达到适当分频计时的效果。波特率生成的有效逻辑如图 19-3 所示。

        波特率发生器可以使用主时钟信号 uart_ref_clk 或除以 8 的主时钟 uart_ref_clk/8。根据模式寄存器 (uart.mode_reg0) 中 CLKS 位的值选择使用的时钟信号。在下面的描述中,所得到的选定时钟被称为 sel_clk。
        sel_clk 时钟被分频以生成其他三个时钟:baud_sample、baud_tx_rate 和 baud_rx_rate。         baud_tx_rate 是用于传输数据的目标波特率。 baud_rx_rate 名义上具有相同的速率,但会与传入的接收数据重新同步。 baud_sample 以 baud_rx_rate 和 baud_tx_rate 的倍数 ([BDIV] + 1) 运行,用于对接收的数据进行过采样。
        sel_clk 时钟频率除以波特率发生器寄存器中的 CD 字段值,以生成 baud_sample 时钟使能。该寄存器可以编程为 1 到 65535 之间的值。
        baud_sample 时钟除以 [BDIV] 加 1。BDIV 是波特率分频寄存器中的一个可编程字段,可以编程为 4 到 255 之间的值。它的复位值为 15,推断默认比率为 16 baud_sample每个 baud_tx_clock / baud_rx_rate 的时钟。
        因此,baud_sample 时钟使能的频率如公式 19-1 所示。

        baud_rx_rate 和 baud_tx_rate 时钟使能的频率如公式 19-2 所示。

为Uart 配置中断函数相关


int Uart_SetHandler_Event(){
    u32 IntrMask = 0;
    int Index;
    XUartPs_SetHandler(&Uart_instance_point,
                       (XUartPs_Handler)Uart0_IntrHandler,
                       &Uart_instance_point);
	IntrMask =
		XUARTPS_IXR_TOUT | XUARTPS_IXR_PARITY | XUARTPS_IXR_FRAMING |
		XUARTPS_IXR_OVER | XUARTPS_IXR_TXEMPTY | XUARTPS_IXR_RXFULL |
		XUARTPS_IXR_RXOVR;
    XUartPs_SetInterruptMask(&Uart_instance_point, IntrMask);
    XUartPs_SetOperMode(&Uart_instance_point,XUARTPS_OPER_MODE_NORMAL);
    XUartPs_SetRecvTimeout(&Uart_instance_point,8);
    for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {
		// SendBuffer[Index] = (Index % 26) + 'A';
		RecvBuffer[Index] = 0;
	}
    XUartPs_Recv(&Uart_instance_point, RecvBuffer, TEST_BUFFER_SIZE);
    XUartPs_Send(&Uart_instance_point, SendBuffer, TEST_BUFFER_SIZE);
}

包含:

        中断函数设置;

        设置敏感事件列表;

        设置操作模式;

        设置超时(非必须);

        设置收发监视。

 中断函数设置

XUartPs_SetHandler(UartInstPtr, (XUartPs_Handler)Handler, UartInstPtr);
void XUartPs_SetHandler(XUartPs *InstancePtr, 
                        XUartPs_Handler FuncPtr, 
                        void *CallBackRef)

 Uart中断函数的规范

void Handler(void *CallBackRef, u32 Event, EventData)

        这里对于Event:处理程序事件有严格约束。

/******************************************************** *************************/ 
/** * 
* 该函数是执行处理以处理来自设备的数据事件的处理程序。它是从中断上下文中调用的。所以 
* 处理量应该是最小的。
* * 该处理程序提供了如何处理设备数据的示例,并且 
* 是特定于应用程序的。
* * @param CallBackRef 包含来自驱动程序的回调引用, 
* 在本例中它是 XUartPs 驱动程序的实例指针。
* @param Event 包含已发生的特定类型的事件。
* @param EventData 包含发送和接收事件发送或接收的字节数。
* * @返回无。
* * @note 无。
********************************************************* **************************/

 注册Uart处理程序事件

        u32 Event:当触发中断的时候,根据不同事件来决定编程好的操作。

        EventData:不同的事件有不同的数据。大体指的是触发指定事件时,发送和接收事件发送或接收的字节数。

EventData

例如:通过存储这部分字节数并且编程来判断是否出现问题。

    /* 数据全部发送完毕 */
	/* All of the data has been sent */
	if (Event == XUARTPS_EVENT_SENT_DATA) {
		TotalSentCount = EventData;
	}
    /*
     * 收到数据,但不是预期的字节数,
     * 超时仅表示数据停止了 8 个字符时间
     */
	/*
	 * 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;
	}
事件列表:
/** @name Callback events
 *
 * These constants specify the handler events that an application can handle
 * using its specific handler function. Note that these constants are not bit
 * mask, so only one event can be passed to an application at a time.
 * 这些常量指定应用程序可以使用其特定处理程序函数处理的处理程序事件。请注意,这些常量不是位 
 * 掩码,因此一次只能将一个事件传递到应用程序。
 *
 * @{
 */
#define XUARTPS_EVENT_RECV_DATA			1U /**< Data receiving done */
#define XUARTPS_EVENT_RECV_TOUT			2U /**< A receive timeout occurred */
#define XUARTPS_EVENT_SENT_DATA			3U /**< Data transmission done */
#define XUARTPS_EVENT_RECV_ERROR		4U /**< A receive error detected */
#define XUARTPS_EVENT_MODEM				5U /**< Modem status changed */
#define XUARTPS_EVENT_PARE_FRAME_BRKE	6U /**< A receive parity, frame, break
											 *	error detected */
#define XUARTPS_EVENT_RECV_ORERR		7U /**< A receive overrun error detected */

  Uart中断函数范例

/**************************************************************************/
/**
*
* This function is the handler which performs processing to handle data events
* from the device.  It is called from an interrupt context. so the amount of
* processing should be minimal.
*
* This handler provides an example of how to handle data for the device and
* is application specific.
*
* @param	CallBackRef contains a callback reference from the driver,
*		in this case it is the instance pointer for the XUartPs driver.
* @param	Event contains the specific kind of event that has occurred.
* @param	EventData contains the number of bytes sent or received for sent
*		and receive events.
*
* @return	None.
*
* @note		None.
*
***************************************************************************/
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;
	}

    /* 
     * 收到数据,但不是预期的字节数, 
     * 超时仅表示数据停止了 8 个字符时间 
     */
	/*
	 * 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++;
	}

    /* 
     * 收到的数据带有奇偶校验或帧或中断错误,保留数据 
     * 但确定发生了哪种错误。特定于 Zynq     Ultrascale+ * MP。
     */
	/*
	 * 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++;
	}
    
    /* 
     * 收到数据时出现溢出错误,保留数据但确定 
     * 发生了哪种错误。特定于 Zynq Ultrascale+ MP。
     */
	/*
	 * 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++;
	}
}

 为UART 设置触发触发方式掩码(敏感列表):XUartPs_SetInterruptMask

        即中断的敏感列表。

void XUartPs_SetInterruptMask(XUartPs *InstancePtr, u32 Mask) 
该函数设置中断掩码。
参数: 
InstancePtr – 是指向 XUartPs 实例的指针 
Mask – 包含要启用或禁用的中断。 “1”启用中断,“0”禁用中断。
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);

中断方式的介绍:(部分)

        ug585 P595

Receiver Parity Error:XUARTPS_IXR_PARITY

        每次接收到字符时,接收器都会根据 uart.mode_reg0 [PAR] 位字段计算接收到的数据位的奇偶校验。然后将结果与接收到的奇偶校验位进行比较。

        如果检测到差异,则奇偶校验错误位设置为 = 1,uart.Chnl_int_sts_reg0 [PARE]。如果启用,则会生成中断。

Receiver Framing Error:XUARTPS_IXR_FRAMING    

        接收器帧错误 当接收器未能在帧末尾接收到有效停止位时,

        帧错误位设置为 =1,uart.Chnl_int_sts_reg0 [FRAME]。如果启用,则会生成中断。        

Receiver Overflow Error:XUARTPS_IXR_RXFULL     

        当接收到字符时,控制器检查 RxFIFO 是否有空间。

        如果是,则该字符被写入 RxFIFO。

        如果 RxFIFO 已满,则控制器等待。

        如果检测到 RxD 上的后续起始位且 RxFIFO 仍满,则数据会丢失,控制器会设置 Rx 溢出中断位 uart.Chnl_int_sts_reg0 [ROVR] = 1。如果启用,则会生成中断。

Receiver Timeout Mechanism:XUARTPS_IXR_TOUT    

        接收器超时机制:使接收器能够检测非活动 RxD 信号(持续高电平)。超时周期通过写入 uart.Rcvr_timeout_reg0 [RTO] 位字段来编程。超时机制使用10位递减计数器。每当在 RxD 信号上接收到新的起始位,或每当软件将 1 写入 uart.Control_reg0 [RSTTO](无论之前的 [RSTTO] 值如何)时,计数器都会重新加载并开始递减计数。        

        如果在 1,023 位周期内没有发生起始位或复位超时,则发生超时。

        接收器超时错误位[TIMEOUT]将在中断状态寄存器中设置,并且控制寄存器中的[RSTTO]位应写入1以重新启动超时计数器,从而加载新编程的超时值。
        计数器的高 8 位从 [RTO] 位字段中的值重新加载,低 2 位初始化为零。计数器由 UART 位时钟提供时钟。

        例如,如果 [RTO] = 0xFF,则超时周期为 1,023 位时钟(256 x 4 减 1)。如果[RTO]位写入0,则超时机制被禁用。
        当递减计数器达到 0 时,接收器超时发生,控制器设置超时中断状态位 uart.Chnl_int_sts_reg0 [TIMEOUT] = 1。

        如果中断使能(uart.Intrpt_mask_reg0 [TIMEOUT] = 1),则 IRQ 信号PS 中断控制器被置位。
        每当发生超时中断时,都会通过向 Chnl_int_sts_reg0 [TIMEOUT] 位回写 1 来清除该中断。

        软件必须设置 uart.Control_reg0 [RSTTO] = 1 以生成进一步的接收超时中断。

 /*
* @name 中断寄存器 
* 
* 中断控制逻辑使用中断允许寄存器(IER)和 
* 中断禁止寄存器(ID​​R)来设置 
* 中断屏蔽寄存器(IMR)中的位的值。 IMR 确定是否将
* 中断传递给中断状态寄存器(ISR)。
* 向 IER 写入 1 启用中断,向 IDR 写入 1 禁用 
* 中断。 IMR 和 ISR 是只读的,IER 和 IDR 是只写的。
* 读取 IER 或 IDR 返回 0x00。
* * 所有四个寄存器具有相同的位定义。
* * @{ */
*/
#define XUARTPS_IXR_RBRK	0x00002000U /**< Rx FIFO break detect interrupt */
#define XUARTPS_IXR_TOVR	0x00001000U /**< Tx FIFO Overflow interrupt */
#define XUARTPS_IXR_TNFUL	0x00000800U /**< Tx FIFO Nearly Full interrupt */
#define XUARTPS_IXR_TTRIG	0x00000400U /**< Tx Trig interrupt */
#define XUARTPS_IXR_DMS		0x00000200U /**< Modem status change interrupt */
#define XUARTPS_IXR_TOUT	0x00000100U /**< Timeout error interrupt */
#define XUARTPS_IXR_PARITY 	0x00000080U /**< Parity error interrupt */
#define XUARTPS_IXR_FRAMING	0x00000040U /**< Framing error interrupt */
#define XUARTPS_IXR_OVER	0x00000020U /**< Overrun error interrupt */
#define XUARTPS_IXR_TXFULL 	0x00000010U /**< TX FIFO full interrupt. */
#define XUARTPS_IXR_TXEMPTY	0x00000008U /**< TX FIFO empty interrupt. */
#define XUARTPS_IXR_RXFULL 	0x00000004U /**< RX FIFO full interrupt. */
#define XUARTPS_IXR_RXEMPTY	0x00000002U /**< RX FIFO empty interrupt. */
#define XUARTPS_IXR_RXOVR  	0x00000001U /**< RX FIFO trigger interrupt. */
#define XUARTPS_IXR_MASK	0x00003FFFU /**< Valid bit mask */
/* @} */

学会Zynq(27)UART中断驱动模式示例-CSDN博客

 为UART 设置操作模式

        控制逻辑包含控制寄存器和模式寄存器,用于选择UART的各种工作模式。

        控制寄存器启用、禁用接收器和发送器模块并发出软复位。 此外,它还重新启动接收器超时周期,并控制发送器中断逻辑。
        接收断线检测必须在软件中实现。它将由 RxFIFO 中的一个帧错误后跟一个或多个零字节来指示。模式寄存器选择波特率发生器使用的时钟。它还选择发送和接收数据所使用的位长度、奇偶校验位和停止位。此外,它还可以选择 UART 的操作模式,根据需要在正常 UART 模式、自动回显、本地环回或远程环回之间切换。

void XUartPs_SetOperMode(XUartPs *InstancePtr, u8 OperationMode) 
该函数设置 UART 的操作模式。 
UART 可以在四种模式之一下运行:
正常、本地环回、远程环回或自动回显。
参数: InstancePtr – 是指向 XUartPs 实例的指针。
操作模式 – 是 UART 的模式。
Normal, Local Loopback, Remote Loopback, or automatic echo.
#define XUARTPS_OPER_MODE_NORMAL		(u8)0x00U	/**< Normal Mode */
#define XUARTPS_OPER_MODE_AUTO_ECHO		(u8)0x01U	/**< Auto Echo Mode */
#define XUARTPS_OPER_MODE_LOCAL_LOOP	(u8)0x02U	/**< Local Loopback Mode */
#define XUARTPS_OPER_MODE_REMOTE_LOOP	(u8)0x03U	/**< Remote Loopback Mode */

XUartPs_SetOperMode(UartInstPtr, XUARTPS_OPER_MODE_LOCAL_LOOP);

根据设置的敏感事件(触发方式)使用函数

        

上文中可知有许多敏感事件可用。

如果我们使用的是:XUartPs_SetInterruptMask(Uart_Ps, XUARTPS_IXR_RXOVR);

        则可以通过使用:来设置具体的触发等级。

void XUartPs_SetFifoThreshold(XUartPs *InstancePtr, u8 TriggerLevel)

//RxFIFO中的字节数超过TriggerLevel时,会产生一个接收数据中断。不设置的时候默认为8. 

        取值应在1~64,因为RxFIFO最大只能存储64个字节。 

The controller is structured with separate Rx and Tx data paths. Each path includes a 64-byte FIFO. 

        设置 UART 的接收超时

void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout)

RecvTimeout:超时字符时间

        设置允许 UART 检测接收器数据线上的空闲连接。

        超时持续时间 = RecvTimeout x 4 x 位周期。 0 禁用超时功能。

超过RecvTimeout时,视为超时,发生中断。

可以设置其他的,例如:

        XUartPs_SetInterruptMask(Uart_Ps, XUARTPS_IXR_RXOVR);
RxFIFO触发中断:

/** 
* 
* 该函数设置UART的接收超时。
* 
* @param InstancePtr 是指向 XUartPs 实例的指针。
* @param RecvTimeout 设置允许 UART 检测接收器数据线上的空闲连接。
* 超时持续时间 = RecvTimeout x 4 x 位周期。 0 禁用
* 超时功能。
* 
* @返回无。
/* 
* 设置接收器超时。如果不设置,并且数据的最后几个字节
* 没有触发过水或满中断,则不会接收该字节
*。默认情况下它是禁用的。
* 
* 设置为 8 将在 8 x 4 = 32 个字符时间后超时。
* 如果波特率高,则增加超时值;如果 
* 波特率低,则减少超时值。
*/

/****************************************************************************/
/**
*
* This function sets the Receive Timeout of the UART.
*
* @param	InstancePtr is a pointer to the XUartPs instance.
* @param	RecvTimeout setting allows the UART to detect an idle connection
*		on the receiver data line.
*		Timeout duration = RecvTimeout x 4 x Bit Period. 0 disables the
*		timeout function.
*
* @return	None.
*
* @note		None.
*
*****************************************************************************/
void XUartPs_SetRecvTimeout(XUartPs *InstancePtr, u8 RecvTimeout)
{
	u32 RtoRegister;

	/* Assert validates the input arguments */
	Xil_AssertVoid(InstancePtr != NULL);
	Xil_AssertVoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);

	/* Set the correct value by masking the bits */
	RtoRegister = ((u32)RecvTimeout & (u32)XUARTPS_RXTOUT_MASK);

	XUartPs_WriteReg(InstancePtr->Config.BaseAddress,
			   XUARTPS_RXTOUT_OFFSET, RtoRegister);

	/* Configure CR to restart the receiver timeout counter */
	RtoRegister =
		XUartPs_ReadReg(InstancePtr->Config.BaseAddress,
				  XUARTPS_CR_OFFSET);
	XUartPs_WriteReg(InstancePtr->Config.BaseAddress, XUARTPS_CR_OFFSET,
			   (RtoRegister | XUARTPS_CR_TORST));

}

 监听串口数据和初始化缓冲区

/*

* 在发送数据之前开始接收数据,因为存在环回,

* 忽略作为返回值接收到的字节数,因为我们

* 知道它将为零

*/

	/*
	 * 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
	 */
    //Define Buffer
    #define TEST_BUFFER_SIZE 256
    static u8 SendBuffer[TEST_BUFFER_SIZE];	/* Buffer for Transmitting Data */
    static u8 RecvBuffer[TEST_BUFFER_SIZE];	/* Buffer for Receiving Data */
	XUartPs_Recv(UartInstPtr, RecvBuffer, TEST_BUFFER_SIZE);
u32 XUartPs_Recv(XUartPs *InstancePtr, u8 *BufferPtr, u32 NumBytes) 
    该函数尝试从设备接收指定字节数的数据并将其存储到指定的缓冲区中。
    该函数适用于轮询或中断驱动模式。它是非阻塞的。
    在轮询模式下,该函数将仅接收 RX FIFO 中已有的数据。
    应用程序可能需要重复调​​用它才能接收整个缓冲区。
    轮询模式是设备的默认操作模式。
    在中断模式下,该函数将开始接收,如果没有接收到整个缓冲区,
    则中断处理程序将继续接收数据,直到接收到整个缓冲区。
    将调用应用程序指定的回调函数来指示接收完成或错误情况。
参数: 
InstancePtr – 是指向 XUartPs 实例的指针 
BufferPtr – 是指向要接收到数据的缓冲区的指针 
NumBytes – 是要接收的字节数。
零值将停止之前在中断模式下正在进行的接收操作。

 初始化缓冲区:

/*

* 使用模式初始化发送缓冲区字节,

* 并将接收缓冲区字节初始化为零,以允许接收数据被验证

*/

        根据自己的需求选择初始化情况。

	for (Index = 0; Index < TEST_BUFFER_SIZE; Index++) {

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

		RecvBuffer[Index] = 0;
	}

整体例程:

/**************************************************************************/
/**
*
* This function does a minimal test on the UartPS device and driver as a
* design example. The purpose of this function is to illustrate
* how to use the XUartPs driver.
*
* This function sends data and expects to receive the same data through the
* device using the local loopback mode.
*
* This function uses interrupt mode of the device.
*
* @param	IntcInstPtr is a pointer to the instance of the Scu Gic driver.
* @param	UartInstPtr is a pointer to the instance of the UART driver
*		which is going to be connected to the interrupt controller.
* @param	DeviceId is the device Id of the UART device and is typically
*		XPAR_<UARTPS_instance>_DEVICE_ID value from xparameters.h.
* @param	UartIntrId is the interrupt Id and is typically
*		XPAR_<UARTPS_instance>_INTR value from xparameters.h.
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
**************************************************************************/
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;
}
/******************************************************************************
* Copyright (C) 2010 - 2021 Xilinx, Inc.  All rights reserved.
* SPDX-License-Identifier: MIT
******************************************************************************/

/****************************************************************************/
/**
*
* @file		xuartps_intr_example.c
*
* This file contains a design example using the XUartPs driver in interrupt
* mode. It sends data and expects to receive the same data through the device
* using the local loopback mode.
*
*
* @note
* The example contains an infinite loop such that if interrupts are not
* working it may hang.
*
* MODIFICATION HISTORY:
* <pre>
* Ver   Who    Date     Changes
* ----- ------ -------- ----------------------------------------------
* 1.00a  drg/jz 01/13/10 First Release
* 1.00a  sdm    05/25/11 Modified the example for supporting Peripheral tests
*		        in SDK
* 1.03a  sg     07/16/12 Updated the example for CR 666306. Modified
*			the device ID to use the first Device Id
*			and increased the receive timeout to 8
*			Removed the printf at the start of the main
*			Put the device normal mode at the end of the example
* 3.1	kvn		04/10/15 Added code to support Zynq Ultrascale+ MP.
* 3.1   mus     01/14/16 Added support for intc interrupt controller
* 3.8   adk     10/05/19 Don't update the DeviceId variable in peripheral test
*			 app case.
*
* </pre>
****************************************************************************/

/***************************** Include Files *******************************/

#include "xparameters.h"
#include "xplatform_info.h"
#include "xuartps.h"
#include "xil_exception.h"
#include "xil_printf.h"

#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
/*
 * The following constant controls the length of the buffers to be sent
 * and received with the UART,
 */
#define TEST_BUFFER_SIZE	100


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


/************************** Function Prototypes *****************************/

int UartPsIntrExample(INTC *IntcInstPtr, XUartPs *UartInstPtr,
			u16 DeviceId, u16 UartIntrId);


static int SetupInterruptSystem(INTC *IntcInstancePtr,
				XUartPs *UartInstancePtr,
				u16 UartIntrId);

void Handler(void *CallBackRef, u32 Event, unsigned int EventData);


/************************** Variable 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 */

/*
 * The following counters are used to determine when the entire buffer has
 * been sent and received.
 */
volatile int TotalReceivedCount;
volatile int TotalSentCount;
int TotalErrorCount;

/**************************************************************************/
/**
*
* Main function to call the Uart interrupt example.
*
*
* @return	XST_SUCCESS if successful, XST_FAILURE if unsuccessful
*
* @note		None
*
**************************************************************************/
#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

/**************************************************************************/
/**
*
* This function does a minimal test on the UartPS device and driver as a
* design example. The purpose of this function is to illustrate
* how to use the XUartPs driver.
*
* This function sends data and expects to receive the same data through the
* device using the local loopback mode.
*
* This function uses interrupt mode of the device.
*
* @param	IntcInstPtr is a pointer to the instance of the Scu Gic driver.
* @param	UartInstPtr is a pointer to the instance of the UART driver
*		which is going to be connected to the interrupt controller.
* @param	DeviceId is the device Id of the UART device and is typically
*		XPAR_<UARTPS_instance>_DEVICE_ID value from xparameters.h.
* @param	UartIntrId is the interrupt Id and is typically
*		XPAR_<UARTPS_instance>_INTR value from xparameters.h.
*
* @return	XST_SUCCESS if successful, otherwise XST_FAILURE.
*
* @note
*
* This function contains an infinite loop such that if interrupts are not
* working it may never return.
*
**************************************************************************/
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;
}

/**************************************************************************/
/**
*
* This function is the handler which performs processing to handle data events
* from the device.  It is called from an interrupt context. so the amount of
* processing should be minimal.
*
* This handler provides an example of how to handle data for the device and
* is application specific.
*
* @param	CallBackRef contains a callback reference from the driver,
*		in this case it is the instance pointer for the XUartPs driver.
* @param	Event contains the specific kind of event that has occurred.
* @param	EventData contains the number of bytes sent or received for sent
*		and receive events.
*
* @return	None.
*
* @note		None.
*
***************************************************************************/
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_<UARTPS_instance>_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
	/*
	 * Connect the handler that will be called when an interrupt
	 * for the device occurs, the handler defined above performs the
	 * specific interrupt processing for the device.
	 */
	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
#ifndef TESTAPP_GEN
	/* Enable interrupts */
	 Xil_ExceptionEnable();
#endif

	return XST_SUCCESS;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1106681.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

10.18作业

使用手动连接&#xff0c;将登录框中的取消按钮使用qt4版本的连接到自定义的槽函数中&#xff0c;在自定义的槽函数中调用关闭函数 将登录按钮使用qt5版本的连接到自定义的槽函数中&#xff0c;在槽函数中判断ui界面上输入的账号是否为"admin"&#xff0c;密码是否为…

在ts中val is Map是什么意思呢?

最近在学习vue3的源码&#xff0c;顺便也在学习ts&#xff0c;就记录一下自己学习中的困惑吧 export const isArray Array.isArray export const isMap (val: unknown): val is Map<any, any> >toTypeString(val) [object Map] export const isSet (val: unknow…

【极速发表】2-4区SCI (含CCF),平均录用周期仅2个月,最快11天见刊!

一、计算机科学类SCI (11.30截稿) 【期刊概况】IF:4.0-5.0, JCR2区&#xff0c;中科院3区&#xff1b; 【检索情况】SCI在检&#xff0c;正刊&#xff1b; 【国人占比】10.58%&#xff1b; 【自引率】7.50%&#xff1b; 【年发文量】100篇以下&#xff1b; 【预警情况】无…

微服务负载均衡实践

概述 本文介绍微服务的服务调用和负载均衡&#xff0c;使用spring cloud的loadbalancer及openfeign两种技术来实现。 本文的操作是在微服务的初步使用的基础上进行。 环境说明 jdk1.8 maven3.6.3 mysql8 spring cloud2021.0.8 spring boot2.7.12 idea2022 步骤 改造Eu…

华为Atlas 200I DK A2开发者套件--基础使用配置

文章目录 前言一、快速开始二、通过路由器联网三、USB相机总结 前言 Atlas 200I DK A2基础使用配置方法。准备好键鼠、显示器、网线、USB拓展器。 一、快速开始 下载最新官方Windows版本昇腾开发者套件一键制卡工具&#xff1a; https://ascend-repo.obs.cn-east-2.myhuaweic…

消除隐患 防患未然|AIRIOT智慧消防管理解决方案

随着科技的飞速发展和城市化进程的不断推进&#xff0c;消防安全问题逐渐凸显。传统消防手段在应对现代复杂多变的火灾事故时显得力不从心&#xff0c;面临着许多挑战和弊端&#xff1a; 监控能力不足&#xff1a;传统消防手段通常依赖于人力监控和报警系统&#xff0c;如消防员…

SpringBoot前后端分离jar包nginx配置https访问

背景&#xff1a;做微信支付回调需要用到https域名&#xff0c;服务器是linux系统&#xff0c;用nginx做反向代理 准备&#xff1a;阿里云、腾讯云或者自己生成的SSL证书&#xff0c;java是8086端口 一&#xff1a;安装nginx&#xff0c;以前博客有记录 二&#xff1a;安装SS…

MySQL学习路线

1 学习路线图 2 参考的文档&#xff1a; 民工哥技术之路菜鸟教程

ScaleButton缩放按钮的实现基于javascript,typescript的代码-复制即用

调用方法 newChestInstance(sp:cc.SpriteFrame,pos:cc.Vec3){var node = new cc.Node("New Sprite");var sprite = node.addComponent(cc.Sprite);node.parent = this.canvasRoot;sprite.spriteFrame = sp;sprite.node.position = pos;node.addComponent(ChestView);…

极客笔记-消息队列

rocketMq 如果nameserver都挂了&#xff0c;sdk缓存了topic信息&#xff0c;依旧可用&#xff0c;所有它是AP,即保证可用性跟分区容错性 Bzhan https://www.bilibili.com/video/BV1cf4y157sz?p30&spm_id_frompageDriver&vd_sourceb2ecb56ea9b8dabcf65d10396ff…

WPF实现签名拍照功能

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…

低代码:时代的选择

低代码&#xff0c;作为一种快速开发应用的软件&#xff0c;将通用、可重复利用的代码形成组件化的模块&#xff0c;通过图形化的界面来拖拽组件并形成应用。低代码能够实现只写少量代码或不写代码&#xff0c;类似用“乐高积木”的方式来开发。 既减少了不必要的工作量&#x…

【硬件+软件】示波器的自动化控制

有没有这样一种情况&#xff0c;就是通过脚本控制你的测量设备&#xff0c;比如示波器&#xff0c;那是不是就可以不用人为的去分析数据&#xff0c;直接由脚本就可以完成整个操作了。 是的&#xff0c;有这样一种方式就可以&#xff0c;就是利用python中的pyvisa库&#xff0c…

TODO Vue typescript forEach的bug,需要再核實

forEach 一個string[]&#xff0c;只有最後一個匹配條件有效&#xff0c;其它條件無效。 所以&#xff0c;只能替換成普通的for循環。 console.log(taskList)// for (const _task of taskList.value) {// if (_task invoiceSendEmail) {// form.value.invoiceSendEmail…

license授权方案

文章目录 概要license文件内容架构流程图实现 概要 当我们的商业软件售卖给客户后&#xff0c;往往需要对分发出去的软件进行限制&#xff0c;比如指定使用者&#xff0c;限制软件使用有效时间&#xff0c;声明版权信息、限制软件使用磁盘大小等。很多场景又是离线使用&#x…

JMeter 随机数生成器简介:使用 Random 和 UUID 算法

在压力测试中&#xff0c;经常需要生成随机值来模拟用户行为。JMeter 提供了多种方式来生成随机值&#xff0c;本文来具体介绍一下。 随机数函数 JMeter 提供了多个用于生成随机数的函数&#xff0c;其中最常用的是 __Random 函数。该函数可以生成一个指定范围内的随机整数或…

Python名侦探柯南

文章目录 系列文章前言Turtle入门名侦探柯南尾声 系列文章 序号文章目录直达链接1浪漫520表白代码https://want595.blog.csdn.net/article/details/1306668812满屏表白代码https://want595.blog.csdn.net/article/details/1297945183跳动的爱心https://want595.blog.csdn.net/…

Java中的日期类整理

文章目录 第一代日期Date类第二代日期Calendar类第三代日期LocalDateTime类4. Instant类 时间戳 第一代日期Date类 jdk1.0引入 1.第一代日期类 包含两个构造器&#xff0c;Date()和Date(long)&#xff1b; new Date()&#xff1b;精确到毫秒 Date(time)如果time是Long类型的会将…

数据库安全运维是什么意思?数据库安全运维系统用哪家好?

我们大家都直到数据在某些情况下容易丢失或被破坏&#xff0c;攻击者可能通过对数据库进行破坏或勒索等手段获取利益。所以保障数据库安全至关重要。今天我们就来聊聊数据库安全运维是什么意思&#xff1f;数据库安全运维系统用哪家好&#xff1f; 数据库安全运维是什么意思&…

如何使用Python实现发送邮件功能

目录 代码示例&#xff1a; 代码解释 注意事项&#xff1a; 总结&#xff1a; 在Python中&#xff0c;可以使用内置的smtplib库和email库来发送电子邮件。 代码示例&#xff1a; 下面是一个使用smtplib和email库来发送电子邮件的示例&#xff1a; import smtplib from …