步进电机中断函数解释

STM32 motor111.cHAL_TIM_PeriodElapsedCallback 函数逐行解释

下面我们对 STM32 项目中 motor111.c 文件里的 HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) 函数进行逐行解析,帮助初学者理解每一行代码的作用。此函数是在定时器产生更新中断时被调用的回调函数,用于控制两个步进电机的运动。解析过程中,我们还将解释 TIM5 定时器的作用、如何判断哪个电机在运行、GPIO 如何驱动电机步进,以及 HAL_TIM_PWM_StopHAL_TIM_Base_Stop_IT 的作用,最后说明整个流程在系统控制逻辑中的作用。

1. 每一行代码的含义

以下是 HAL_TIM_PeriodElapsedCallback 函数的代码,并在每行添加中文注释说明其含义:

void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {if (htim->Instance == TIM5) {                    // 如果触发中断的定时器实例是 TIM5,则处理电机逻辑uint8_t needStop = 1;                        // 标志是否需要停止定时器,初始值为1(假设需要停止)// 处理电机0 (如X轴电机)if (motor0_Running && stepCount[0] < targetSteps[0]) {HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);   // 翻转PA2引脚电平(给电机0的步进引脚产生一个脉冲)stepCount[0]++;                          // 电机0的已执行步数加一needStop = 0;                            // 还有剩余步数,暂时不停止定时器} else if (motor0_Running) {HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3); // 停止TIM5通道3的PWM输出(停止电机0的脉冲信号)HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET); // 将PE5引脚置高(关闭电机0的使能或刹车信号)motor0_Running = 0;                      // 标记电机0已停止运行}// 处理电机1 (如Y轴电机)if (motor1_Running && stepCount[1] < targetSteps[1]) {HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);   // 翻转PA3引脚电平(给电机1的步进引脚产生一个脉冲)stepCount[1]++;                          // 电机1的已执行步数加一needStop = 0;                            // 还有剩余步数,暂时不停止定时器} else if (motor1_Running) {HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL _4); // 停止TIM5通道4的PWM输出(停止电机1的脉冲信号)HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET); // 将PE3引脚置高(关闭电机1的使能或刹车信号)motor1_Running = 0;                      // 标记电机1已停止运行}// 如果两个电机都已停止运行,则停止定时器中断if (needStop) {HAL_TIM_Base_Stop_IT(&htim5);            // 停止TIM5基础定时器及其中断触发}}
}

逐行说明:

  • 第1行: void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) {
    定义了一个回调函数,当定时器更新事件发生时(定时器溢出或达到设定周期),HAL库会调用此函数。参数 htim 指向触发这个中断的定时器句柄。

  • 第2行: if (htim->Instance == TIM5) {
    检查触发该回调的定时器是否为 TIM5。如果是 TIM5 更新中断,才执行后续电机控制代码。这样可以防止其他定时器的中断误触发此段逻辑(因为 HAL 的这个回调对所有定时器通用,需要自行判断来源)。

  • 第3行: uint8_t needStop = 1;
    定义并初始化一个 8 位无符号变量 needStop 为 1。needStop 用作标志位,指示是否需要停止定时器。初始假定需要停止(置1),如果发现任一电机仍需继续运行,则会将其置0,表示不停止。

  • 第5行(注释): // 处理电机0 (如X轴电机)
    这是一个注释,说明接下来要处理电机0的逻辑(假设电机0对应 X 轴)。

  • 第6行: if (motor0_Running && stepCount[0] < targetSteps[0]) {
    判断条件:如果电机0的“运行标志”motor0_Running为真(表示电机0目前设定为在运行状态),电机0已走的步数 stepCount[0] 小于目标步数 targetSteps[0](还没走完设定的总步数),则进入该分支,执行电机0的步进操作。

  • 第7行: HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2);
    使用 HAL 库提供的函数翻转(Toggle)GPIOA端口的2号引脚的电平状态。由于 PA2 引脚连接到电机0的步进脉冲控制信号,每次翻转该引脚电平就产生一个上升沿或下降沿的脉冲。这相当于给步进电机的驱动器发送一个脉冲信号,让电机转动 一步(步进电机每接收一个脉冲信号就转动一个固定角度或前进一步 (STM32之步进电机 - Sakura_Ji - 博客园))。

  • 第8行: stepCount[0]++;
    将电机0的步进计数值加一。stepCount[0] 用于记录电机0已经执行了多少步,每产生一次脉冲就累加1。这样可以跟踪电机是否已经走到目标步数。

  • 第9行: needStop = 0;
    needStop 置为0,表示目前不应停止定时器。之所以设置为0,是因为在这个定时器中断周期内,发现电机0还有剩余步数要走(刚执行了一步且未达到目标),因此需要继续让定时器触发后续中断来完成剩下的步数。

  • 第10行: } else if (motor0_Running) {
    如果上一条 if 不满足,但是 motor0_Running 为真(表示电机0标记为正在运行)——也就是说电机0 正在运行但已没有剩余步数需要执行 (stepCount[0] 已达到或超过 targetSteps[0]),则进入此分支。这种情况表示电机0的运动已经完成目标步数。

  • 第11行: HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3);
    调用了 HAL 库函数停止 TIM5 定时器的通道3上的 PWM输出。根据代码逻辑,TIM5通道3被用于电机0的脉冲产生。因此这行代码停止电机0的PWM信号输出,不再发出步进脉冲。换句话说,停止对电机0继续发脉冲,让它停下。

    提示:Start_Motors 函数中,曾经通过 HAL_TIM_PWM_Start(&htim5, TIM_CHANNEL_3) 启动了 TIM5 通道3 的 PWM,用于电机0脉冲输出。这里对应地将其关闭。

  • 第12行: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_5, GPIO_PIN_SET);
    将 GPIOE 端口的 5 号引脚拉高(设置为高电平)。从上文 Start_Motors 函数可知,在启动电机时曾经把 PE5 拉低(RESET)以使能电机0驱动。因此推测 PE5 引脚可能是电机0驱动器的“使能”(Enable)控制或制动信号(比如一些驱动模块需要拉低使能引脚才能运行)。在完成运动后,将该引脚置高,意味着关闭电机0的驱动输出(禁用电机或上电刹车),确保电机停止转动或锁定。

  • 第13行: motor0_Running = 0;
    将电机0的运行标志置0,表示电机0不再运行。这样做不仅在内部记录电机状态,也会被主循环察觉,用于后续逻辑(例如主程序可能正等待该标志变为0,以判断运动完成)。

  • 第14行: }
    结束电机0的处理分支。

  • 第16行(注释): // 处理电机1 (如Y轴电机)
    注释:说明下面的代码块是处理电机1的逻辑(假设电机1对应 Y 轴)。

  • 第17行: if (motor1_Running && stepCount[1] < targetSteps[1]) {
    判断电机1是否需要执行一步:条件与电机0类似,如果电机1标记为正在运行且尚未完成目标步数 (stepCount[1] < targetSteps[1]),则进入该分支。

  • 第18行: HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_3);
    翻转 GPIOA 端口3号引脚的电平。PA3 引脚连接电机1的步进控制信号,因此每次翻转 PA3 电平,会给电机1发送一个脉冲信号,让电机1前进一步。

  • 第19行: stepCount[1]++;
    电机1的步数计数加一,记录已经执行了一个步进脉冲。

  • 第20行: needStop = 0;
    needStop 置0,表示由于电机1仍有未完成的步数,定时器不应停止,还需继续中断以完成后续步数。

  • 第21行: } else if (motor1_Running) {
    如果电机1正在运行但已没有剩余步数需要走(即目标步数已达到),则进入此分支,执行电机1停止运行的收尾工作。

  • 第22行: HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_4);
    停止 TIM5 定时器通道4的 PWM输出。TIM5通道4对应电机1的脉冲输出通道,所以这将停止电机1的步进脉冲信号,终止电机1的运动。

  • 第23行: HAL_GPIO_WritePin(GPIOE, GPIO_PIN_3, GPIO_PIN_SET);
    将 GPIOE 端口3号引脚置高电平。类似电机0的情况,PE3 在启动时被拉低使能电机1驱动,在运动结束时拉高以关闭电机1驱动输出。

  • 第24行: motor1_Running = 0;
    清零电机1的运行标志,表示电机1已停止运行。

  • 第25行: }
    结束电机1处理的分支。

  • 第27行: if (needStop) {
    检查 needStop 标志。如果仍然为1,表示在此次中断处理中并没有执行任何一步(即两个电机都没有进入运行步进的分支)。换言之,要么两个电机都不需要再运行(都已完成目标步数或根本未启动),要么定时器在一个周期内没有检测到需要继续的步数。

  • 第28行: HAL_TIM_Base_Stop_IT(&htim5);
    调用 HAL 函数停止 TIM5 基础定时器的运行,并关闭其更新中断 (_IT 表示中断模式下停止)。当 needStop == 1 时意味着两个电机都已经停止,因此可以安全地停止定时器,不再产生中断。一旦停止TIM5,中断回调将不再被调用,电机控制循环结束。这样做也避免了 CPU 继续进入中断浪费资源。

  • 第29行: }
    结束 if (needStop) 分支。

  • 第30行: }
    结束 if (htim->Instance == TIM5) 主分支。至此,TIM5定时器中断的处理逻辑结束。如果有其他定时器使用了这个回调函数,它们将被忽略(因为不在 TIM5 分支内)。

  • 第31行: }
    回调函数结束。

通过上述逐行解释,可以看出该回调函数的主要作用是在 TIM5 定时器中断时,为两个步进电机(电机0和电机1)生成步进脉冲并计数步数,当达到目标步数时停止相应电机的脉冲输出,并在两个电机都停止后停止定时器中断。

接下来,我们针对题目要求的具体问题进行说明和拓展。

2. TIM5 定时器的作用及为何用它触发中断

TIM5 定时器的作用: 在这个项目中,TIM5 被用作步进电机控制的基础定时器。它的主要作用是按照设定的时间间隔周期性地产生中断(更新事件),从而触发上面的回调函数。在每次中断中,系统对电机的步数进行更新和脉冲输出。这实现了对步进电机运动速度和步数的精确控制。通过调节 TIM5 的定时周期,可以控制步进电机脉冲的频率,从而控制电机的转速。

具体来说,TIM5 配合其 PWM 通道一起使用:在 Start_Motors 函数中,调用了 HAL_TIM_Base_Start_IT(&htim5) 开启 TIM5 的基础定时器中断,并通过 HAL_TIM_PWM_Start 启动 TIM5 的通道3和通道4 PWM输出。这样TIM5就开始按照预先配置的频率计数,并在每次计数周期溢出时(即达到自动重装值ARR)触发更新中断,由回调函数输出一步脉冲。

为什么使用 TIM5 来触发中断:

  • 精确定时与稳定脉冲: 硬件定时器能够提供精确且稳定的定时基准,比纯软件延时可靠得多。TIM5 定时器触发中断的周期决定了步进脉冲的频率,从而决定电机转动速度。使用 TIM5 硬件定时,可以确保每一步的时间间隔均匀,一致地控制电机运动。

  • 多通道支持双电机: TIM5 在许多 STM32 微控制器上是一个拥有多通道的通用定时器。例如在 STM32F4 系列中,TIM5 有4个通道(并且是32位定时器)。在本代码中利用了通道3和通道4分别输出两个电机的PWM脉冲,一个定时器同时管理两个电机的步进信号,保证两电机脉冲同步在同一个时基下。这对于需要协调运动的轴来说很方便(虽然本例中未实现插补算法,但共用一个定时源可简化控制)。

  • 资源独立且优先级控制: 使用单独的TIM5定时器来控制电机,不会干扰主CPU执行其他任务。定时器中断可以设置优先级,确保电机控制的实时性。当TIM5中断触发时,由回调函数执行关键的步数更新和GPIO切换,而主循环可以并行处理其他逻辑或等待完成信号。

  • 触发中断的原因: 总结来说,TIM5用于触发中断是为了在硬件定时的基础上执行电机步进控制代码。每次 TIM5 溢出产生中断,就相当于“时钟敲一下”,驱动电机前进一小步,并检查是否达到目标。相比在主循环中用延时或轮询产生脉冲,中断方式更加精准和高效。

简而言之,TIM5 定时器充当了电机的“节拍器”,每一次节拍(中断)让电机迈出一步,并最终在完成指定步数时停止节拍。

3. 如何判断哪个电机在运行

在该系统中,通过状态标志变量来判断电机的运行状态。具体而言,有两个全局变量:motor0_Runningmotor1_Running,分别对应电机0和电机1的运行状态。它们的用法如下:

  • 在启动电机运动时,这两个标志会被置为1。例如,在 Start_Motors 函数中,启动双电机运动之前,代码执行:motor0_Running = 1; motor1_Running = 1; 这表示电机0和电机1的运行标志均被设为“正在运行”。

  • HAL_TIM_PeriodElapsedCallback 回调函数中,根据这些标志决定是否产生脉冲并执行步进。当 motorX_Running 为真且步数未完成时,代码对相应电机执行 HAL_GPIO_TogglePin 产生脉冲并累加步数(如代码第6-9行所示)。如果 motorX_Running 为假,则意味着该电机当前没有运动需求,回调中也不会对其产生脉冲。

  • 当电机完成其目标步数时(即 stepCount[x] 达到 targetSteps[x]),回调函数会执行对应的 “停止” 分支:调用 HAL_TIM_PWM_Stop 停止PWM输出,拉高控制引脚,并将 motorX_Running 标志置0。将标志清零表示该电机的运动已结束。

  • 主程序或其他任务可以通过检查 motor0_Runningmotor1_Running 来判断电机是否还在运行。例如,在 MovePathWithCenterReturn 等上层逻辑中,代码使用 while (motor0_Running || motor1_Running); 来等待,直到两个电机的运行标志都变为0,才说明此次运动已经全部完成.

总结: 哪个电机在运行取决于对应的 motorX_Running 标志是否为1。标志为1表示电机正处于运动过程中;标志为0表示该电机已停止(要么尚未启动,要么已经完成运动)。此外,还可以结合步数计数判断:当 stepCount[x] 尚未达到 targetSteps[x] 时且 motorX_Running 为1,则该电机正在执行运动;一旦步数达到目标并标志被清零,即表示该电机运动结束。

4. GPIO 控制如何驱动步进电机

本项目中,步进电机采用脉冲+方向的控制方式,也就是常见的步进电机驱动控制:由一个引脚提供脉冲信号控制步进,另一个引脚提供方向信号控制电机转动方向。GPIO 的控制具体体现在以下方面:

  • 方向控制(Direction): 在开始运动时,通过GPIO设置电机转动方向。代码中 Start_Motors 函数对几个引脚进行了初始化:

    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_6, dirX ? GPIO_PIN_RESET : GPIO_PIN_SET);
    HAL_GPIO_WritePin(GPIOE, GPIO_PIN_4, dirY ? GPIO_PIN_SET : GPIO_PIN_RESET);
    

    这里推测 GPIOE_Pin_6 控制电机0的方向、GPIOE_Pin_4 控制电机1的方向。dirX/dirY 是传入的方向参数,根据其值决定将方向引脚拉高还是拉低,从而设定电机朝正转或反转方向运动。在步进电机驱动器中,方向引脚电平高低通常对应顺时针或逆时针旋转。

  • 步进脉冲控制(Step Pulse): 正是通过定时器中断里的 GPIO 翻转来实现的。比如电机0使用 PA2 引脚作为步进脉冲引脚,每次在中断中执行 HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_2) 就会使 PA2 从低电平变高,或从高电平变低。这个电平的跳变沿即构成了一个脉冲信号,被步进驱动器识别为一步指令。通常,步进驱动器会在检测到引脚从低->高的上升沿时让电机走一步(也有的驱动对下降沿敏感,但无论哪种,每次 Toggle 产生一个完整的脉冲周期)。因此每进入一次定时中断翻转引脚,电机就前进一“步距角”。正如步进电机的特性所述:每输入一个脉冲信号,电机转子就转过一个固定角度(前进一步) (STM32之步进电机 - Sakura_Ji - 博客园)。

  • 使能控制(Enable/Disable): 从代码看,GPIOE_Pin_5 和 GPIOE_Pin_3 似乎用作电机驱动器的使能或相关控制信号。在启动电机时,这两个引脚被拉低 (GPIO_PIN_RESET),而在停止电机时被拉高 (GPIO_PIN_SET) 来关闭驱动。许多步进电机驱动模块(如常见的TB6600、A4988模块)都有使能引脚使能(ENABLE)或睡眠引脚等,通常低电平激活驱动,高电平关闭输出。由此推断:

    • 当开始运动时,将使能引脚拉低,使能驱动器输出,使电机准备接收脉冲。
    • 当运动结束或需要停机时,将使能引脚拉高,禁用驱动器输出,防止电机继续受到脉冲(也减少电机功耗或锁定位置)。
  • GPIO 引脚配置: 为了可靠驱动步进电机,这些引脚一般配置为输出模式,推挽输出,高速,以确保能够产生清晰的方波脉冲。另外,最好在硬件上这些引脚连接到驱动器时有共地,驱动器根据脉冲信号变化驱动电机线圈。

简要流程: 初始化时设定方向,引脚使能驱动器;运动过程中定时翻转步进引脚产生持续的脉冲序列;结束时停止脉冲并禁用驱动。GPIO 的这种控制方式实现了步进电机的典型开环控制:脉冲数决定转动角度,脉冲频率决定转动速度 (STM32之步进电机 - Sakura_Ji - 博客园)。整个过程中GPIO输出的高低电平序列就是电机动作的直接指令。

5. HAL_TIM_PWM_StopHAL_TIM_Base_Stop_IT 的作用

在代码中,我们看到了这两个停止函数:

  • HAL_TIM_PWM_Stop(TIM_HandleTypeDef *htim, uint32_t Channel): 停止指定定时器通道的 PWM 输出。调用此函数会关闭对应通道的比较输出,使其不再产生PWM波形。在本项目中,TIM5的通道3和通道4被用于产生电机步进脉冲信号(对应PA2和PA3引脚)。当调用 HAL_TIM_PWM_Stop(&htim5, TIM_CHANNEL_3) 时,通道3的PWM输出被关闭,不再自动翻转PA2引脚电平;同理,TIM_CHANNEL_4 停止后不再输出脉冲。作用: 终止特定电机的脉冲信号输出。从电机驱动的角度看,这意味着不再给该电机发送步进指令脉冲,电机将停止继续转动。

    值得注意的是,PWM输出停止后,如果需要的话,我们仍然可以通过软件手动控制GPIO引脚电平(正如代码中紧接着通过 HAL_GPIO_WritePin 拉高引脚来锁定电机状态)。HAL_TIM_PWM_Stop 单纯停止硬件定时器对引脚的控制。

  • HAL_TIM_Base_Stop_IT(TIM_HandleTypeDef *htim): 停止基础定时器的计数,并且停用其更新中断。当调用 HAL_TIM_Base_Stop_IT(&htim5) 时,会停止 TIM5 定时器的运行,也就是停止计数。这样TIM5就不会再触发中断了(对应的 HAL_TIM_PeriodElapsedCallback 不会再被调用)。作用: 在确定无需再产生任何步进脉冲时,关闭定时器以结束整个定时中断过程。停止定时器中断有助于节省CPU资源(不再无谓地进入中断处理),也表明当前一次运动控制流程正式结束。

结合本例,HAL_TIM_PWM_Stop 用于单个电机的停止,而 HAL_TIM_Base_Stop_IT 用于整个定时器的停止。当两个电机都已经达到目标步数时,needStop 仍为1,触发执行 HAL_TIM_Base_Stop_IT(&htim5),从而完全停止TIM5。这相当于:“两个电机都走完了,该停表了。” 如果只有一个电机走完,另一个还在跑,则仅停止走完的那一路PWM,定时器仍继续跑以服务另一个电机。

小结: HAL_TIM_PWM_Stop 针对定时器的某一通道关闭PWM信号输出;HAL_TIM_Base_Stop_IT 则关闭整个定时器和中断。当使用定时器+PWM组合控制电机时,经常会在任务完成时先停PWM再停定时器,确保不多发脉冲也不多占用中断。

6. 整体流程在系统控制逻辑中的作用

综合来看,这套基于 TIM5 定时器中断的电机控制流程在系统中扮演了步进运动控制核心逻辑的角色,确保电机按照指令完成指定的移动。下面从系统层面说明其工作流程及作用:

  • 启动阶段: 上层代码(例如控制逻辑函数 MovePathWithCenterReturn)在需要电机移动时会调用 Start_Motors(stepsX, dirX, stepsY, dirY) 等函数,传入X、Y轴各自需要移动的步数和方向。Start_Motors 将目标步数保存到 targetSteps[0/1],将已走步数 stepCount[0/1] 清零,并设置方向引脚和使能引脚的初始状态,然后开启 TIM5 定时器中断和PWM输出 。这一步相当于发出了“让两个电机按照给定方向各走 N 步”的命令,并启动了驱动装置。

  • 运行阶段: TIM5 定时器开始计时,并按照设定频率周期性中断。每一次 TIM5 更新中断都会调用电机控制回调 HAL_TIM_PeriodElapsedCallback。在回调中,根据每个电机的运行标志和剩余步数:

    • 如果电机需要继续运行(标志为1且步数未完),就翻转对应步进引脚,产生一个脉冲,电机走一步,同时步数计数加一。
    • 如果电机不需要再运行了(标志为1但步数已完),则停止其PWM输出、拉高停止引脚、清除运行标志。
    • 如此循环,定时器持续触发中断,“喂”给电机一个接一个脉冲,两个电机各自推进各自的步数。当某个电机先完成目标时,其标志会被清零,但定时器不中止,另一个电机继续运行。
  • 停止阶段: 当且仅当检测到两个电机都无需再运行时(即本次中断中没有任何一个电机产生脉冲,needStop 保持为1),系统调用 HAL_TIM_Base_Stop_IT 停止定时器。这终止了进一步的中断调用,意味着预定的运动已全部完成。此时两个电机的运行标志都已清零,上层代码通过检测这些标志即可知道运动结束。

  • 后续处理: 主控制逻辑往往在发出运动命令后,会等待运动完成再进行下一步。例如代码里 while (motor0_Running || motor1_Running); 就是忙等待两个电机完成。完成后,主逻辑可能记录当前位置(如更新 currentX, currentY)或者执行其他动作(如控制其它执行器)。整个过程保证了运动的确定性:不会多走少走步数,且结束时电机状态明确。

控制逻辑作用总结: 该流程相当于实现了一个定长步进运动控制器。上层只需指定方向和步数,启动运动后,底层通过定时器中断精确输出对应数量的脉冲给电机,达到步数后自动停止。一方面,它解放了主CPU(利用硬件定时+中断来产生精确定时脉冲,而非软件延时),另一方面,它确保了运动达到预期的位置:由于记录了 targetSteps 和逐步比较 stepCount,不会遗漏或多发脉冲。通过标志变量的设置和清除,上层代码也能方便地与此异步过程交互(如等待完成或提前停止等)。

在整个系统中,这段控制逻辑扮演着驱动底层执行机构(步进电机)的任务调度者角色:依据目标,对电机发出一系列脉冲“指令”,严格按计划数量执行,然后在任务完成时善后(停止定时器、清标志)。对于双电机同时运动的情况,它还能基本同步地驱动两轴(在相同的时间基准下脉冲输出),满足简单的直线运动要求。总之,该流程保证了步进电机按指令运动到位,是运动控制系统可靠运行的关键。

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

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

相关文章

什么是Linux中的systemd?

写在前面 为什么要回过头来复习linux的system的&#xff0c;最近在研究DELL EMC的PowerStore存储系统&#xff0c;其底层是基于CoreOS开发的&#xff0c;这套操作系统是基于Systemd来设计的。所以要深入了解PowerStore就必须对systemd做详细了解。 systemd 是一个用于 Linux …

Linux 环境下 Mysql 5.7 数据定期备份

目录 一、创建数据备份脚本二、查看备份日志三、数据库数据恢复 备份策略&#xff1a; 系统环境 openEuler 22.03 (LTS-SP4) 单机备份 每天凌晨2点&#xff0c;指定数据库表全量备份&#xff0c;只保留近7次备份数据 每次的脚本执行&#xff0c;将会记录执行结果到日志&#xf…

C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ C 语言字符输入:掌握 getchar 和 scanf 的用法与陷阱 你好!在 C 语言编程中,与用户进行交互最基本的方式就是通过标准输入和标准输出。我们之前探讨了如何使用 ​​printf​​ 和 ​​putchar​​ 进行…

【React】 Hooks useTransition 解析与性能优化实践

1.背景 useTransition 是 React 18 引入的一个并发模式下的 Hook&#xff0c;用于区分紧急和非紧急的状态更新&#xff0c;提升应用的响应性和用户体验;它可以管理 UI 中的过渡状态&#xff0c;特别是在处理长时间运行的状态更新时。它允许你将某些更新标记为“过渡”状态&…

蘑菇管理——AI与思维模型【94】

一、定义 蘑菇管理思维模型是一种形象地描述组织对待新员工或初入职场者的管理方式及相关现象的思维模型。它将新员工或初入职场者比作蘑菇&#xff0c;这些人在初期往往被置于阴暗的角落&#xff08;不受重视的部门&#xff0c;或打杂跑腿的工作&#xff09;&#xff0c;浇上…

c++STL——set和map的使用

文章目录 set和map的使用set系列声名和定义默认成员函数迭代器set的增删查lower_bound和upper_boundInsert接口pair类 对于查找的另一种使用 set和multiset的区别 map系列声名和定义pair类的进一步介绍默认成员函数map的增删查map的数据修改map和multimap的差异 set和map的使用…

什么是DGI数据治理框架?

DGI数据治理框架是由数据治理研究所&#xff08;Data Governance Institute, DGI&#xff09;提出的一套系统性方法论&#xff0c;旨在帮助企业或组织建立有效的数据治理体系&#xff0c;确保数据资产的高质量管理、合规使用和价值释放。以下是关于DGI数据治理框架的核心内容&a…

chrome 浏览器怎么不自动提示是否翻译网站

每次访问外国语网页都会弹出这个对话框&#xff0c;很是麻烦&#xff0c;每次都得手动关闭一下。 不让他弹出来方法&#xff1a; 设置》语言》首选语言》添加语言&#xff0c;搜索英语添加上 如果需要使用翻译&#xff0c;就点击三个点&#xff0c;然后选择翻译

LeetCode 热题 100 54. 螺旋矩阵

LeetCode 热题 100 | 54. 螺旋矩阵 大家好&#xff0c;今天我们来解决一道经典的算法题——螺旋矩阵。这道题在LeetCode上被标记为中等难度&#xff0c;要求我们按照顺时针螺旋顺序返回矩阵中的所有元素。下面我将详细讲解解题思路&#xff0c;并附上Python代码实现。 问题描述…

生成式AI将重塑的未来工作

在人类文明的长河中,技术革命始终是推动社会进步的核心动力。从蒸汽机的轰鸣到互联网的浪潮,每一次技术跃迁都在重塑着人类的工作方式与生存形态。而今,生成式人工智能(Generative AI)的崛起,正以超越以往任何时代的速度与深度,叩响未来工作范式变革的大门。这场变革并非…

【2025软考高级架构师】——2024年05月份真题与解析

摘要 本文内容是关于2025年软考高级架构师考试的相关资料&#xff0c;包含2024年05月份真题与解析。其中涉及体系结构演化的步骤、OSI协议中能提供安全服务的层次、数据库设计阶段中进行关系反规范化的环节等知识点&#xff0c;还提及了软考高级架构师考试的多个模块&#xff…

KAG:通过知识增强生成提升专业领域的大型语言模型(三)

目录 摘要 Abstract 1 Schema 2 Prompt 3 KAG-Builder 3.1 reader 3.2 splitter 3.3 extractor 3.4 vectorizer 3.5 writer 3.6 可选组件 4 示例 总结 摘要 本周深入学习了 KAG 项目中的 Schema、Prompt 以及 KAG-Builder 相关代码知识&#xff0c;涵盖了其定义、…

Gitea windows服务注册,服务启动、停止、重启脚本

修改配置文件 查看COMPUTERNAME echo %COMPUTERNAME%进入配置文件D:\gitea\custom\conf\app.ini&#xff0c;将 Gitea 设置为以本地系统用户运行 如果结果是 USER-PC&#xff0c;那么 RUN_USER USER-PC$ RUN_USER COMPUTERNAME$SQLite3 PATH配置&#xff0c;更改为包含完整…

矿泉水瓶的绘制

1.制作中心矩形&#xff0c;大小为60&#xff0c;注意设置矩形的两条边相等 2.点击拉伸&#xff0c;高度为150mm 3.使用圆角命令&#xff0c;点击连接到开始面&#xff0c;同时选中4条边&#xff0c;进行圆角转化&#xff0c;圆角大小为10mm&#xff0c;点击多半径圆角&#xf…

【程序+论文】大规模新能源并网下的火电机组深度调峰经济调度

目录 1 主要内容 讲解重点 2 讲解视频及代码 1 主要内容 该视频为《大规模新能源并网下的火电机组深度调峰经济调度》代码讲解内容&#xff0c;该程序有完全对照的论文&#xff0c;以改进IEEE30节点作为研究对象&#xff0c;系统包括5个火电机组和2个新能源机组&#xff0c;…

​​工业机器人智能编程:从示教器到AI自主决策​​

工业机器人智能编程:从示教器到AI自主决策 引言 工业机器人作为智能制造的核心装备,其编程方式正经历革命性变革。传统示教器编程效率低下,平均每个路径点需要30秒人工示教,而复杂轨迹编程可能耗时数周。随着AI技术的发展,工业机器人编程正朝着"所见即所得"的…

n8n 构建一个 ReAct AI Agent 示例

n8n 构建一个 ReAct AI Agent 示例 0. 引言1. 详细步骤创建一个 "When Executed by Another Workflow"创建一个 "Edit Fields (Set)"再创建一个 "Edit Fields (Set)"创建一个 HTTP Request创建一个 If 节点在 true 分支创建一个 "Edit Fiel…

Monorepo项目多项目一次性启动工具对比与实践

Monorepo项目多项目一次性启动工具对比与实践 在现代软件开发中&#xff0c;Monorepo&#xff08;单一仓库&#xff09;模式越来越受到开发者的青睐。Monorepo将多个相关的项目或包集中在一个仓库中进行管理&#xff0c;方便依赖共享、代码复用和统一发布。在Monorepo项目开发…

笔记整理六----OSPF协议

OSPF 动态路由的分类&#xff1a; 1.基于网络范围进行划分--将网络本身划分为一个个AS&#xff08;自治系统---方便管理和维护&#xff09; 内部网关协议---负责AS内部用户之间互相访问使用的协议 IGP--RIP EIGRP ISIS OSPF 外部网关协议--负责AS之间&#xff08;整个互联网&…

网络编程,使用select()进行简单服务端与客户端通信

这里在Ubuntu环境下演示 一般流程 服务端常用函数&#xff1a; socket()&#xff1a;创建一个新的套接字。bind()&#xff1a;将套接字与特定的IP地址和端口绑定。listen()&#xff1a;使套接字开始监听传入的连接请求。accept()&#xff1a;接受一个传入的连接请求&#xff…