从0开始的STM32学习之旅:使用中断完成等待型任务(理论部分)

目录

中断

NVIC

中断优先级

先说说一般我们聊到的中断优先级

STM32中的NVIC中断优先级表示

API

CubeMx配置说明


很好,我们在之前的学习中已经完成了简单的GPIO输入输出驱动的控制,我们的下一步就是仔细了解一下中断这个事情。

中断

中断这个事情字如其名:程序流好好的运转,来一个事件通知要求处理器放下手头的活来处理,流水线被挂起打断:这就是中断了!

中断可以认为是一种信号,通知处理器发生了某种事件,要求处理器暂停当前正在执行的任务,转而执行相应的中断处理程序(Interrupt Service Routine, ISR)(STM32在初始化的时候就布置好了传统的经典的中断向量表了)。中断的主要目的在于提高系统的响应速度和资源利用率。中断处理通常是异步的,这意味着中断可以在任何时刻发生。

中断的主要目的包括提高效率、响应外部事件以及实现多任务处理。通过中断机制,处理器可以在不需要主动查询设备状态的情况下处理设备请求。一般的,一个外部的中断(内部类似,不过设备变成了处理器本身罢了)几个步骤:

  • 当设备发出中断请求时,处理器在执行指令时定期检测中断信号。

  • 一旦检测到中断,处理器将保存当前的执行状态(上下文),

  • 然后跳转到中断处理程序的入口地址,执行相关的中断处理逻辑。

  • 最后,在中断处理完成后,处理器恢复之前保存的上下文,继续执行被中断的任务。

中断可以根据不同的标准进行分类。根据来源,中断可以分为外部中断和内部中断。外部中断由外部设备发起,如I/O设备和定时器;内部中断则由程序内部产生,如除零错误和非法操作。根据优先级,中断可以分为高优先级中断和低优先级中断。高优先级中断可以打断低优先级的中断处理程序,确保重要事件的及时响应。按照响应方式,中断可分为掩蔽中断和非掩蔽中断。掩蔽中断可以被处理器屏蔽,而非掩蔽中断则必须立即响应。

中断的实现原理涉及硬件和软件两个层面。在硬件方面,中断控制器是中断管理的核心组件,负责接收中断请求、处理优先级并将中断信号发送给处理器。中断向量表是一个存储中断处理程序地址的表格,处理器通过中断号查找中断向量表,从而找到相应的ISR地址。中断屏蔽寄存器则用于设置哪些中断可以被处理器响应,哪些可以被屏蔽。在软件层面,中断处理程序是响应中断请求的代码,通常是系统级别的函数。中断处理程序的设计需要尽量简洁快速,以减少对其他任务的影响。当中断发生时,处理器需要保存当前的执行上下文,以便在中断处理完成后恢复。操作系统还会根据中断的优先级设计调度策略,以确保高优先级中断能及时得到处理。

中断自身在计算机系统中的应用非常广泛,尤其在I/O设备管理、定时器中断、错误处理和实时系统中都发挥着重要作用。对于外设,如键盘、鼠标和打印机,中断机制使得设备能够在准备好数据时向处理器发送信号,处理器随即执行相应的处理程序,确保高效的数据传输。在操作系统中,定时器中断用于实现时间片轮转调度,定期唤醒调度程序,以确保各个进程能够公平地获得处理器使用权。

在程序执行过程中,发生的错误(如除零或无效指令)会产生内部中断,操作系统可以捕捉这些异常并进行相应的错误处理,以确保系统的稳定性。在实时系统中,快速响应外部事件至关重要,而中断机制则能够确保系统对实时事件的及时处理,提供高效的实时调度。

当然,我们这里打算了解的更多的是外部中断。让我们继续了解一下STM32的中断是如何做的。

NVIC

Nested Vectored Interrupt Controller。嵌套中断向量控制器。嵌套,是为了说明当我们的中断发生了嵌套叠叠乐的时候,处理器仍然能保持最大限度的受理所有的向量,按照我们指定的方式进行事件的处理。向量,这个事情在我们前面分析启动文件的时候就差不多说过了:可以看到我们将中断排了号,成为了一个向量。当然控制器就是我们下面要说的,他是如何控制的事情了。

(不难看出确实是一个表,不是吗)

中断名称中断向量地址描述
NMI_Handler0x00000004非屏蔽中断处理程序
HardFault_Handler0x00000008硬故障中断处理程序
MemManage_Handler0x0000000C内存管理故障中断处理程序
BusFault_Handler0x00000010总线故障中断处理程序
UsageFault_Handler0x00000014使用故障中断处理程序
SVC_Handler0x00000018服务调用中断处理程序
DebugMon_Handler0x0000001C调试监视中断处理程序
PendSV_Handler0x00000020延迟服务请求中断处理程序
SysTick_Handler0x00000024系统滴答定时器中断处理程序
WWDG_IRQHandler0x00000028看门狗定时器中断处理程序
PVD_IRQHandler0x0000002C电压侦测中断处理程序
TAMP_STAMP_IRQHandler0x00000030时间戳/回调中断处理程序
RTC_WKUP_IRQHandler0x00000034实时钟唤醒中断处理程序
FLASH_IRQHandler0x00000038闪存控制器中断处理程序
RCC_IRQHandler0x0000003C时钟控制器中断处理程序

当然,NVIC在C语言程序中的表达就显得十分的直接了:

typedef struct
{__IOM uint32_t ISER[8U];               /*!< Offset: 0x000 (R/W)  Interrupt Set Enable Register */uint32_t RESERVED0[24U];__IOM uint32_t ICER[8U];               /*!< Offset: 0x080 (R/W)  Interrupt Clear Enable Register */uint32_t RSERVED1[24U];__IOM uint32_t ISPR[8U];               /*!< Offset: 0x100 (R/W)  Interrupt Set Pending Register */uint32_t RESERVED2[24U];__IOM uint32_t ICPR[8U];               /*!< Offset: 0x180 (R/W)  Interrupt Clear Pending Register */uint32_t RESERVED3[24U];__IOM uint32_t IABR[8U];               /*!< Offset: 0x200 (R/W)  Interrupt Active bit Register */uint32_t RESERVED4[56U];__IOM uint8_t  IP[240U];               /*!< Offset: 0x300 (R/W)  Interrupt Priority Register (8Bit wide) */uint32_t RESERVED5[644U];__OM  uint32_t STIR;                   /*!< Offset: 0xE00 ( /W)  Software Trigger Interrupt Register */
}  NVIC_Type;

ISER[8]:ISER 全称是:Interrupt Set Enable Registers,这是一个中断使能寄存器组。上面 说了 CM3 内核支持 256 个中断,这里用 8 个 32 位寄存器来控制,每个位控制一个中断。但是STM32F103 的可屏蔽中断最多只有60 个,所以对我们来说,有用的就是两个(ISER[0]和ISER[1]),总共可以表示 64 个中断。而 STM32F103 只用了其中的 60 个。ISER[0]的 bit0~31 分别对应中断 0~31;ISER[1]的 bit0~27 对应中断 32~59,这样总共 60 个中断就可以分别对应上了。你要使能某个中断,必须设置相应的 ISER 位为 1,使该中断被使能(这里仅仅是使能,还要配合中断分组、屏蔽、IO 口映射等设置才算是一个完整的中断设置)。具体每一位对应哪个中断,请参考stm32f103xe.h 里面的第 69 行,笔者这里给出

/*!< Interrupt Number Definition */
typedef enum
{
/******  Cortex-M3 Processor Exceptions Numbers ***************************************************/NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                             */HardFault_IRQn              = -13,    /*!< 3 Cortex-M3 Hard Fault Interrupt                     */MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M3 Memory Management Interrupt              */BusFault_IRQn               = -11,    /*!< 5 Cortex-M3 Bus Fault Interrupt                      */UsageFault_IRQn             = -10,    /*!< 6 Cortex-M3 Usage Fault Interrupt                    */SVCall_IRQn                 = -5,     /*!< 11 Cortex-M3 SV Call Interrupt                       */DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M3 Debug Monitor Interrupt                 */PendSV_IRQn                 = -2,     /*!< 14 Cortex-M3 Pend SV Interrupt                       */SysTick_IRQn                = -1,     /*!< 15 Cortex-M3 System Tick Interrupt                   */
​
/******  STM32 specific Interrupt Numbers *********************************************************/WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                            */PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt            */TAMPER_IRQn                 = 2,      /*!< Tamper Interrupt                                     */RTC_IRQn                    = 3,      /*!< RTC global Interrupt                                 */FLASH_IRQn                  = 4,      /*!< FLASH global Interrupt                               */RCC_IRQn                    = 5,      /*!< RCC global Interrupt          ...

ICER[8]:全称是:Interrupt Clear Enable Registers,是一个中断除能寄存器组。该寄存器组与 ISER 的作用恰好相反,是用来清除某个中断的使能的。其对应位的功能,也和 ICER 一样。这里要专门设置一个ICER 来清除中断位,而不是向 ISER 写0 来清除,是因为 NVIC 的这些寄存器都是写1 有效的,写 0 是无效的。

ISPR[8]:全称是:Interrupt Set Pending Registers,是一个中断使能挂起控制寄存器组。每个位对应的中断和ISER 是一样的。通过置 1,可以将正在进行的中断挂起,而执行同级或更高级别的中断。写 0 是无效的。

ICPR[8]:全称是:Interrupt Clear Pending Registers,是一个中断解挂控制寄存器组。其作用与 ISPR 相反,对应位也和 ISER 是一样的。通过设置 1,可以将挂起的中断解挂。写 0 无效。

IABR[8]:全称是:Interrupt Active Bit Registers,是一个中断激活标志位寄存器组。对应位所代表的中断和 ISER 一样,如果为 1,则表示该位所对应的中断正在被执行。这是一个只读寄存器,通过它可以知道当前在执行的中断是哪一个。在中断执行完了由硬件自动清零。

IP[240]:全称是:Interrupt Priority Registers,是一个中断优先级控制的寄存器组。这个寄存器组相当重要!STM32F103 的中断分组与这个寄存器组密切相关。IP 寄存器组由 240 个 8bit的寄存器组成,每个可屏蔽中断占用8bit,这样总共可以表示 240 个可屏蔽中断。而 STM32F103只用到了其中的 60 个。IP[59]~IP[0]分别对应中断 59~0。而每个可屏蔽中断占用的 8bit 并没有全部使用,而是只用了高 4 位。这 4 位,又分为抢占优先级和子优先级。抢占优先级在前,子优先级在后。而这两个优先级各占几个位又要根据 SCB->AIRCR 中的中断分组设置来决定。

中断优先级

这个事情是笔者之前遇到过的,你先想下为什么。

笔者决定写一个简单的Demo,我配置好中断 + 开启之后,写了一个如下的简单程序:

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin){HAL_GPIO_TogglePin(LED0_GPIO_Port, LED0_Pin);
}
int main(void)
{HAL_Init();SystemClock_Config();MX_GPIO_Init();while (1){HAL_Delay(100);}
}

但是程序仍然直接挂了,无论我怎么施加以外部信号,程序不闻不顾。这是怎么回事呢?答案是:优先级配置错误,导致Systicks没法正常更新,时钟系统乱套了。

那怎么办呢?答案是正确的配置中断优先级。

先说说一般我们聊到的中断优先级

中断优先级是指在多个中断请求同时到达处理器时,处理器根据预设的优先级规则决定哪个中断请求先被响应和处理。优先级通常由系统设计者在编程时设定,反映了不同事件的重要性。例如,在某些应用中,紧急的硬件故障中断可能被设定为高优先级,而不太重要的传感器读取中断可能被设定为低优先级。

中断优先级的管理可以采用多种策略,其中包括固定优先级、动态优先级以及优先级反转处理。固定优先级意味着中断的优先级在系统运行期间保持不变,而动态优先级允许系统根据实时需求调整中断的优先级。优先级反转是指低优先级任务持有高优先级任务所需的资源,从而导致高优先级任务无法执行。

中断优先级通常可以分为硬件优先级和软件优先级。硬件优先级由中断控制器在硬件层面决定,处理器在收到中断信号时,会根据中断信号的优先级进行处理。软件优先级则是在操作系统或应用程序中定义的,允许开发者根据具体需求调整中断的响应行为。在一些系统中,中断优先级采用分级管理的方式。高优先级中断可以打断低优先级中断的处理,这种方式允许系统在高优先级事件发生时迅速做出响应。例如,在嵌入式系统中,定时器中断可能具有高优先级,而数据传输中断的优先级可能较低。

中断优先级的实现通常涉及中断控制器和中断向量表。中断控制器负责管理所有中断请求,判断各个中断的优先级并将最高优先级的中断信号发送给处理器。在STM32等微控制器中,开发者可以通过编程设置各个中断的优先级,以满足系统的需求。中断向量表则是一个包含所有中断处理程序入口地址的表格。当中断发生时,处理器通过中断向量表找到相应的中断处理程序,执行特定的逻辑。中断优先级在这个过程中起到决定哪个中断处理程序被调用的作用。在某些情况下,中断优先级可能会被动态调整。通过实时监控系统的运行状态,操作系统可以根据当前的任务需求和资源利用情况调整中断的优先级。这种动态调整的机制通常用于复杂的实时系统,以确保关键任务的优先级始终高于非关键任务。

在配置中断优先级时,开发者需要综合考虑系统的整体架构、实时性要求、任务特性等因素。合理的中断优先级设置能够显著提高系统的响应速度和稳定性。以下是一些优化中断优先级配置的建议。开发者应该评估每个中断的响应时间要求,并根据事件的重要性分配优先级。高优先级中断应优先处理响应时间敏感的任务,而低优先级中断则可以在系统空闲时处理。其次,应尽量减少中断处理程序的执行时间。中断处理程序应该尽可能简洁,避免在ISR中执行复杂的计算或阻塞操作。可以通过设置标志位或使用消息队列等方式,将较为复杂的处理逻辑放到主程序中进行,以减小ISR的负担。最后,定期评估和调整中断优先级设置。在系统运行过程中,可能会出现新的需求或问题,开发者应根据实际情况对中断优先级进行动态调整,以确保系统的稳定性和响应性。

STM32中的NVIC中断优先级表示

STM32 中的中断优先级可以分为:抢占式优先级和响应优先级,响应优先级也称子优先级,每个中断源都需要被指定这两种优先级。抢占式优先级和响应优先级的区别:

  • 抢占优先级:抢占优先级高的中断可以打断正在执行的抢占优先级低的中断。

  • 响应优先级:抢占优先级相同,响应优先级高的中断不能打断响应优先级低的中断。

还有一种情况就是当两个或者多个中断的抢占式优先级和响应优先级相同时,那么就遵循自然优先级,看中断向量表的中断排序,数值越小,优先级越高。

在 NVIC 中由寄存器 NVIC_IPR0-NVIC_IPR59 共 60 个寄存器控制中断优先级,每个寄存器的 8 位,所以就有了 240 个宽度为 8bit 的中断优先级控制寄存器,原则上每个外部中断配置的优先级为 0~255,数值越小,优先级越高。但是实际上 M3 芯片为了精简设计,只使用了高四位[7:4],低四位取零,这样以至于最多只有 16 级中断嵌套,即 2^4=16。

优先级分组AIRCR[10:8]抢占优先级位数响应优先级位数
011104
111013
210122
310031
401140

当然,数字越小,越优先!在强调一次。拿正点原子的举例:假定设置中断优先级分组为 2,然后设置中断 3(RTC_WKUP 中断)的抢占优先级为 2,响应优先级为 1。中断6(外部中断 0)的抢占优先级为 3,响应优先级为0。中断 7(外部中断 1)的抢占优先级为 2,响应优先级为 0。那么这 3 个中断的优先级顺序为:中断 7>中断 3>中断 6。

API

HAL_NVIC_SetPriorityGrouping 函数用于设置中断优先级分组。它的声明为 void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)。该函数允许开发者选择不同的中断优先级分组,范围从 NVIC_PRIORITYGROUP_0NVIC_PRIORITYGROUP_4。通常情况下,这个函数在一个项目中只需调用一次,通常是在程序的 HAL 库初始化阶段调用。后续如果再调用该函数更改优先级分组,可能会导致之前设置的抢占优先级和响应优先级不匹配。

HAL_NVIC_SetPriority 函数,声明为 void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)。该函数用于设置特定中断的抢占优先级和响应优先级。函数的第一个参数是中断号,范围由 IRQn_Type 定义的枚举类型决定;第二个参数是抢占优先级,范围为 0 到 15;第三个参数是响应优先级,同样范围为 0 到 15。此函数允许开发者灵活配置中断优先级,以满足不同应用的需求。

HAL_NVIC_EnableIRQ,其声明为 void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)。该函数用于使能指定的中断。参数为中断号,开发者可以通过这个函数启用特定的中断,使其可以被处理。

HAL_NVIC_DisableIRQ 函数用于中断的除能,其声明为 void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)。通过这个函数,开发者可以禁用某个特定中断,防止其在未准备好时被处理。

HAL_NVIC_SystemReset 函数的声明为 void HAL_NVIC_SystemReset(void),它用于执行软件复位。调用该函数后,系统将立即复位,所有外设和寄存器状态将被重置。

函数名函数描述声明参数返回值注意事项
HAL_NVIC_SetPriorityGrouping设置中断优先级分组void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup);PriorityGroup: NVIC_PRIORITYGROUP_0 到 NVIC_PRIORITYGROUP_4该函数在一个工程里通常只调用一次,后续调用可能导致优先级不匹配。
HAL_NVIC_SetPriority设置中断的抢占优先级和响应优先级void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority);IRQn: 中断号 PreemptPriority: 0 到 15 SubPriority: 0 到 15抢占优先级和响应优先级的范围均为0到15。
HAL_NVIC_EnableIRQ使能中断void HAL_NVIC_EnableIRQ(IRQn_Type IRQn);IRQn: 中断号使能后对应的中断可以被处理。
HAL_NVIC_DisableIRQ中断除能void HAL_NVIC_DisableIRQ(IRQn_Type IRQn);IRQn: 中断号除能后对应的中断将不会被处理。
HAL_NVIC_SystemReset软件复位系统void HAL_NVIC_SystemReset(void);调用后系统会立即复位,所有的外设和寄存器将重置。

CubeMx配置说明

可以在NVIC一栏中看到,当我们给一个检测的目标GPIO上中断配置的时候,这里会出现,以及需要配置优先级。可以看到外面需要给优先级配成如图所示的样子(防止中断死锁)

  • 开启下降沿触发中断:即在 按下按键时 电平由高变为低时触发,则在 GPIO mode 中选择 External Interrupt Mode with Falling edge trigger detection

  • 开启上升沿触发中断:即在 按下按键后松开时 电平由低变为高时触发,则在 GPIO mode 中选择 External Interrupt Mode with Rising edge trigger detection

  • 开启下降沿上升沿都触发中断:即在 按下时触发,松开时再次触发,则在 GPIO mode 中选择 External Interrupt Mode with Rising/Falling edge trigger detection

  • External Event Mode with Rising Edge Trigger Detection(外部事件上升沿触发检测):在此模式下,当引脚检测到上升沿(即信号从低电平变为高电平)时,会生成一个外部事件。这种配置适用于需要响应信号开始变化的场合,例如按钮按下时。

  • External Event Mode with Falling Edge Trigger Detection(外部事件下降沿触发检测):此模式下,当引脚检测到下降沿(即信号从高电平变为低电平)时,会生成一个外部事件。适合用于监测信号关闭或变低的情况,例如按钮释放时。

  • External Event Mode with Rising/Falling Edge Trigger Detection(外部事件上升/下降沿触发检测):在这个模式下,引脚可以同时响应上升沿和下降沿的信号变化,任何边沿的变化都会生成一个外部事件。这提供了更高的灵活性,适合需要对信号变化全面响应的应用。

分为两组看的话,一个就是事件驱动,一个是中断驱动。后面的区别外面详细再说!

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

使用Python进行数据分析入门

文章目录 Python环境搭建安装Anaconda验证安装 必备库介绍NumPyPandasMatplotlibSciPy 数据导入与清洗导入数据清洗数据 数据探索与分析描述性统计相关性分析 数据可视化绘制直方图 高级主题机器学习深度学习 总结 随着大数据时代的到来&#xff0c;数据分析变得越来越重要。Py…

RabbitMQ + JMeter组合,优化你的中间件处理方式!

RabbitMQ是实现了高级消息队列协议&#xff08;AMQP&#xff09;的开源消息中间件&#xff0c;它是基于Erlang语言编写的&#xff0c;并发能力强&#xff0c;性能好&#xff0c;是目前主流的消息队列中间件之一。 RabbitMQ的安装可参照官网&#xff08; https://www.rabbitmq.c…

python 爬虫 入门 五、抓取图片、视频

目录 一、图片、音频 二、下载视频&#xff1a; 一、图片、音频 抓取图片的手法在上一篇python 爬虫 入门 四、线程&#xff0c;进程&#xff0c;协程-CSDN博客里面其实有&#xff0c;就是文章中的图片部分&#xff0c;在那一篇文章&#xff0c;初始代码的28&#xff0c;29行…

Vulnhub靶机——DC-1

#环境 本次环境是利用VMware15搭建 靶机DC-1( https://download.vulnhub.com/dc/DC-1.zip) --192.168.200.131 Kali2021.1--192.168.200 将以上两个操作系统启动&#xff0c;并设置网卡为NAT模式 #信息收集 使用arp-scan对网段进行扫描&#xff0c;探测存活主机 使用nmap…

吴恩达深度学习笔记(10)12.

多任务学习 什么时候多任务学习有意义&#xff1a; 能从共享低级特征中获益&#xff1b;每个任务拥有的数据相当相似&#xff1b;训练一个足够大的神经网络用于所有任务。 目标定位&#xff1a; 分类定位&#xff08;单个对象&#xff09;与检测不同&#xff08;多个对象&…

Android 音量调节流程分析

音量调节流程分析 按下音量键 音量键被按下后&#xff0c;按键事件会一路派发给Acitivity&#xff0c;如果无人拦截并处理&#xff0c;承载当前Activity的显示PhoneWindow类的onKeyDown()以及onKeyUp()函数将会被处理&#xff0c;从而开始通过音量键调整音量的处理流程&#x…

LLMs在股票投资组合崩溃中的时间关系推理

1. 引言 想象一下&#xff0c;你是一位投资经理&#xff0c;管理着一个多元化的股票投资组合。突然&#xff0c;一场前所未有的全球性事件发生了&#xff0c;比如2007年的金融危机或2020年的新冠疫情&#xff0c;这可能会对你的投资组合造成重大影响。传统的投资组合崩溃检测方…

o1驾驶无人机后空翻,OpenAI开发者日惊掉下巴!2分钟爆改代码写App

【导读】OpenAI伦敦开发者日上&#xff0c;首次曝出了o1五大核心能力&#xff0c;还有图像理解。o1两分钟构建应用驾驶无人机、电话订餐、讲解太阳系&#xff0c;现场演示让所有开发者沸腾。 完整版o1的解禁&#xff0c;离我们不远了&#xff01; 就在刚刚举办的OpenAI伦敦开…

利用AWS服务轻松迁移数据上云

在数字化转型的浪潮中&#xff0c;越来越多的企业意识到将数据迁移至云端的重要性。云服务不仅能够提供更高的灵活性和可扩展性&#xff0c;还能显著降低IT成本。AWS&#xff08;Amazon Web Services&#xff09;作为全球领先的云服务提供商&#xff0c;为企业提供了一系列高效…

期货跟单、量化交易模拟演示系统

演示版可直接下载本文绑定资源。 一、跟单下单 在“排行榜”中选择要跟单的用户&#xff0c;合约可以跟全部&#xff0c;也可以指定跟该用户的某一合约操作&#xff0c;选定跟单的倍数&#xff08;操作手数的倍数&#xff09;/手数&#xff08;指定手数&#xff0c;可以不是对…

界面控件DevExpress WPF中文教程:Data Grid——卡片视图概述

DevExpress WPF拥有120个控件和库&#xff0c;将帮助您交付满足甚至超出企业需求的高性能业务应用程序。通过DevExpress WPF能创建有着强大互动功能的XAML基础应用程序&#xff0c;这些应用程序专注于当代客户的需求和构建未来新一代支持触摸的解决方案。 无论是Office办公软件…

【数据结构二叉树】补充:C实现二叉树的层次遍历

1、层次遍历 按层次遍历二叉树的方式&#xff1a;按照“从上到下&#xff0c;从左到右”的顺序遍历二叉树&#xff0c;即先遍历二叉树的第一层的结点&#xff0c;然后是第二层的结点&#xff0c;直到最底层的结点&#xff0c;对每一层的遍历按照从左到右的次序进行。 2、层次…

供应商图纸外发:如何做到既安全又高效?

供应商跟合作伙伴、客户之间会涉及到图纸外发的场景&#xff0c;这是一个涉及数据安全、效率及合规性的重要环节。供应商图纸发送流程一般如下&#xff1a; 1.申请与审批 采购人员根据需要提出发放图纸的申请并提交审批&#xff1b; 采购部负责人审批发放申请&#xff0c;确…

MySQL 9从入门到性能优化-系统信息函数

【图书推荐】《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;》-CSDN博客 《MySQL 9从入门到性能优化&#xff08;视频教学版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) MySQL9数据库技术_夏天又到了…

【第一个qt项目的实现和介绍以及程序分析】【正点原子】嵌入式Qt5 C++开发视频

qt项目的实现和介绍 1.第一个qt项目  &#xff08;1).创建qt工程    [1].创建一个存放qt的目录    [2].新建一个qt工程    [3].编译第一个工程    发生错误时的解决方式 二.QT文件介绍  (1).工程中文件简单介绍  (2).项目文件代码流程介绍    [1].添…

推荐一款开源的免费PDF编辑工具:CubePDF Utility

CubePDF Utility是一款功能强大的开源免费PDF编辑器&#xff0c;它采用了基于缩略图的界面设计&#xff0c;为用户提供了直观且高效的PDF编辑体验。该软件特别针对那些希望以简单直观方式编辑 PDF 文件的用户而设计&#xff0c;支持多种操作&#xff0c;如合并、提取、拆分、更…

shodan7,shodan参数使用,常用端口,Google语法

参数使用 alert shodan alert -h(查看帮助文档 这个就是怎么去配置ip监控)我们能在web页面上面去做&#xff0c;而且更加方便&#xff0c;所以就不多讲了 info shodan info(查看你查询的扫描的一些次数每个账户都是每个月有限制次数的)domain shodan domain(查询域名信息…

不是她所期待的那个人

今天那&#xff0c;我又来写用AI小说辣。 从最初的喜欢到最后的讨厌&#xff0c;她对他的感觉经历了一段奇妙的变化。一开始&#xff0c;当她第一次看到他时&#xff0c;她被他的外表所吸引。他高大英俊&#xff0c;阳光活泼的笑容总是让她心生好感。她喜欢和他在一起的感觉&am…

智能合约分享

智能合约练习 一、solidity初学者经典示例代码&#xff1a; 1.存储和检索数据&#xff1a; // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; // 声明 Solidity 编译器版本// 定义一个名为 SimpleStorage 的合约 contract SimpleStorage {// 声明一个公共状态变量 d…

硬件在环仿真建模之电路拓扑建模与数学建模

我们需要先明确一个问题&#xff0c;什么是电路拓扑式建模&#xff08;后面简称拓扑建模&#xff09;和数学建模&#xff1f; 电力电子系统的拓扑建模&#xff0c;从大类上都可以归入为物理式建模&#xff08;Physics-Based Modeling&#xff09;,物理式建模的最大特点就是用户…