当前位置: 首页 > news >正文

Diving into the STM32 HAL-----Clock Tree笔记

        几乎每个数字电路都需要一种方法来同步其内部电路或与其他电路同步。时钟是一种产生周期性信号的设备,它是数字电子学中最普遍的心跳源形式。

        然而,相同的时钟信号不能用于馈送现代微控制器(如 STM32 微控制器)提供的所有组件和外设。此外,功耗是与给定外设的时钟速度直接相关的一个关键方面。能够选择性地禁用或降低某些 MCU 部件的时钟速度,可以优化整体器件功耗。这要求时钟以层次组织,使开发人员可以选择不同的速度的时钟源。

        本章简要介绍了 STM32 MCU 的复杂时钟分配网络。其目的是为读者提供必要的工具来理解和管理 clock tree,展示 HAL_RCC 模块的主要功能。后面进一步专门介绍电源管理。

1、时钟分配

        

        时钟是一种通常产生方波信号的器件,占空比为 50%,如上图所示。(这里的方波是“理想的”,实际的波形具有梯形形式。)时钟信号在 VL 和 VH 电压电平之间振荡,对于 STM32 微控制器,该电压电平仅为 VDD 电源电压的一小部分。时钟最基本的参数是频率,它表示它在一秒钟内从 VL 切换到 VH 的次数。频率以赫兹表示。

        大多数STM32 MCU可以交替由两个不同的时钟源提供时钟:内部RC振荡器(称为高速内部(HSI))或外部专用晶体振荡器(称为高速外部(HSE))。选择外部晶体而不是内部 RC 振荡器有几个原因:

        与内部 RC 网络相比,外部晶体提供更高的精度,内部 RC 网络的额定精度为 1%,特别是当 PCB 工作温度远离 25°C 的环境温度时。(1% 的精度似乎是一个不错的折衷方案,特别是如果您考虑到可以节省 PCB 空间和专用晶体的成本,而专用晶体是一种价格不可忽视的器件。但是,对于时间受限的应用程序,1% 可能是一个巨大的变化。例如,一天由 86,400 秒组成。等于 1% 的误差意味着在最坏的情况下,我们可以损失(或赚取)长达 864 秒,即 14.4 分钟!如果温度升高,情况可能会变得更糟。这就是为什么如果您要使用 RTC,则必须使用外部低速晶体的原因。)

        某些外设,尤其是高速外设,只能由以给定频率运行的专用外部晶振进行计时。

        与高速振荡器一起,另一个时钟源可用于偏置低速振荡器,而低速振荡器又可以由外部晶体(称为 Low Speed External (LSE))或内部专用 RC 振荡器(称为 Low Speed Internal (LSI))提供时钟。低速振荡器用于驱动实时时钟 (RTC) 和独立看门狗 (IWDT) 外设。

        高速振荡器的频率并不构成 Cortex-M 内核和其他外设的实际频率。复杂的分配网络(也称为时钟树)负责 STM32 MCU 内部时钟信号的传播。使用多个可编程锁相环 (PLL) 和预分频器,可以根据需要增加/减少源频率(参见下图),具体取决于我们想要达到的性能、给定外设或总线的最大速度以及整体全局功耗。(MCU 的功耗与其频率大致呈线性关系;频率越高,消耗的功率就越大)

1.1、STM32 时钟树概述

        STM32 MCU 的时钟树可以具有真正的铰接结构。即使在“更简单”的 STM32F0 MCU 中,内部时钟网络也可以有多达四个 PLL/预分频器级,并且系统时钟多路复用器(也称为系统时钟开关 (SW))可以由多个备用源馈送。

        此外,深入解释每个 STM32 系列的时钟树是一项复杂的任务,这也需要我们将注意力集中在特定的零件编号上。这是因为时钟树结构主要受以下关键方面的影响:

         微控制器的 STM32 主系列。例如,所有 STM32F0 MCU 都只提供一条外设总线 (APB1),该总线可以以相同的 Cortex-M 内核最大频率进行计时。其他 STM32 微控制器通常提供两条外设总线,其中只有一个 (APB2) 可以达到最大 CPU 时钟速度。相反,STM32F7 微控制器中可用的外设总线都无法达到最大内核频率,而 STM32G4 MCU 中的 APB1 和 ABP2 都可以达到最大内核时钟速度。可以注意到,对于“旧”STM32F103,仅使用外部 HSE 振荡器即可达到最大时钟速度。

        MCU 提供的外设类型和数量。时钟树的复杂性随着可用外设的数量而增加。此外,一些外设需要专用的时钟源和速度,这会影响 PLL 级的数量。

        MCU 的销售类型和封装,决定了提供外设的有效类型和数量。

        上图显示了最简单的 STM32 微控制器之一 STM32F030R8 的时钟树。对于 STM32 平台的许多新手来说,这个数字完全没有意义并且很难解码,特别是如果他们也是嵌入式微控制器的新手。最相关的路径以红色标出:从 HSI 振荡器到 Cortex-M0 内核、AHB 总线和 DMA 的路径。这就是我们从那时起一直默默地 “使用” 的路径,而没有过多地处理其可能的配置。让我们介绍该路径中最相关的部分。

        该路径从内部 8MHz 振荡器开始。如前所述,它是由 ST 在工厂校准的 RC 振荡器,在 25 °C 的环境温度下具有 1% 的精度。 然后,HSI clock 可以按原样用于馈送 System Clock Switch (SW) (图中以蓝色突出显示的 path),或者由于中间预分频器,它可以用于在 PLL 乘法器被 2 除以后馈送 PLL 乘法器。因此,主 PLL 可以将 4MHz 时钟乘以 12 倍,以获得 48MHz 的最大系统时钟频率 (SYSCLK)。SYSCLK 源头可用于馈送 I2C1 外设(替代 HSI)和另一个中间预分频器 AHB 预分频器,后者可用于降低高(速度)时钟 (HCLK),进而偏置 AHB 总线、内核和 SysTimer。

        为什么有这么多中间 PLL/Prescaler 级?如前所述,时钟速度决定了整体性能,但它也会影响 MCU 的总功耗。能够选择性地打开/关闭 MCU 的某些部分 - 或降低时钟速度 - 可以根据所需的有效计算能力降低功耗。L0/1/4/5 MCU 引入了更多的 PLL/预分频器阶段,为开发人员提供了对整体 MCU 消耗的更多控制。结合专用的硬件设计,这使得创建电池供电的设备,甚至可以使用相同的电池运行数年。

        时钟树配置通过名为 Reset and Clock Control (RCC) 的专用外设执行,该过程主要由三个步骤组成: 1. 如果使用 HSE,则选择高速振荡器源(HSI 或 HSE)并正确配置。2. 如果我们想以高于高速振荡器提供的频率馈送 SYSCLK,那么我们需要配置主 PLL (提供 PLLCLK 信号)。否则,我们可以跳过此步骤。3. 系统时钟开关 (SW) 配置,选择正确的时钟源 (HSI、HSE 或 PLLCLK)。然后,我们选择正确的 AHB、APB1 和 APB2(如果可用)预分频器设置,以达到高速时钟(HCLK - 即馈送内核、DMA 和 AHB 总线的时钟)的所需频率,以及高级外设总线 1 (APB1) 和 APB2(如果可用)总线的频率。

        了解 PLL 和 prescaler 的允许值可能是一场噩梦,尤其是对于更复杂的 STM32 MCU。只有某些组合对给定的 STM32 微控制器有效,其不当配置可能会损坏 MCU 或至少导致故障错误的 clock configuration 可能会导致异常行为、奇怪和不可预测的 resets 等。幸运的是,STM32 工程师提供了一个很棒的工具来简化时钟配置:CubeMX。

1.1.1、STM32L/U 系列中的多速内部 RC 振荡器

        时钟源及其分配网络对 MCU 的整体功耗有不可忽视的影响。如果我们需要一个高于或低于内部 HSI 时钟源的 SYSCLK 频率(大多数 STM32 MCU 为 8MHz,其他一些为 16MHz),我们必须通过使用 PLL Source Mux 和中间预分频器来增加/减少它。不幸的是,这些组件会消耗能量,这可能会对电池供电的设备产生巨大影响。

        STM32L/U MCU 专为低功耗应用而设计,它们通过提供名为 MultiSpeed Internal (MSI) RC 振荡器的专用内部时钟源来解决这一特定问题。MSI 是一款低功耗 RC 振荡器,具有 ±1%@25°C 的工厂预校准精度,在 0-85°C 范围内可提高高达 ±3%。MSI 的主要特点是它提供多达 12 种不同的频率,而无需添加任何外部组件。例如,STM32L476中的 MSI 提供 100kHz 至 48MHz 的内部时钟源。MSI 时钟在从 Reset、Standby 和 Shutdown 低功耗模式重启后用作 SYSCLK。从 Reset 重新启动后,MSI 频率设置为默认值(例如,STM32L476中的默认 MSI 频率为 4MHz)。

        上表总结了 STM32L476 MCU 中所有可能的 clock sources 的最相关特性。如您所见,当 MCU 由 MSI 计时时(不使用 PLL 多路复用器),可实现最佳功耗。此外,与 HSI 相比,这个 clock source 保证了最短的 start time 。有趣的是,稳定 LSE 时钟最多需要 2 秒:如果启动速度对您的应用程序真的很重要,那么使用单独的线程来启动 LSE 是一个可以考虑的选项。

        除了与低功耗相关的优势外,当 MSI 用作 PLL Source Mux 的源时,它提供了一个非常精确的时钟源,USB OTG FS 设备可以使用该源,而无需使用外部专用晶体,同时馈送主 PLL 以最大速度运行系统。

1.2、使用 CubeMX 配置 Clock Tree

        上图显示了到目前为止看到的相同 F0 MCU 的 clock tree。clock tree 最相关的 paths 也以红色和蓝色突出显示。这应该简化了与前图的比较。创建新项目时,默认情况下,CubeMX 选择 HSI 振荡器作为默认时钟源。HSI 也被选为 System Clock Mux(蓝色路径) 的默认时钟源,如图所示。这意味着,对于我们在这里考虑的 MCU,Cortex-M 内核频率将等于 8MHz。

        CubeMX 还建议我们两件事:在此 MCU 中,高速(高速)时钟 (HCLK) 和 APB1 总线的最大频率等于 48MHz(蓝色标签)。为了提高 CPU 内核频率,我们首先需要选择 PLLCLK 作为 System Clock Switch 的源时钟,然后选择正确的 PLL multiplier factor。但是,CubeMX 提供了一种快速的方法:您只需在 HCLK 字段中输入“48”,然后按 Enter 键即可。CubeMX 将自动安排设置,选择正确的时钟树路径(图中的红色路径)。

        如果您的电路板依赖于外部 HSE/LSE 晶体,则必须先在 RCC 外设中启用它,然后才能将其用作相应振荡器的主时钟源。一旦启用外部振荡器,就可以指定其频率(在标有 “input frequency” 的蓝色框内)并配置主 PLL 以达到所需的 SYSCLK 速度(参见上图)。否则,外部振荡器 input frequency 可以直接用作 System Clock Switch 的源 clock。我们需要相应地配置 RCC 外设以启用外部时钟源。这可以从 CubeMX 的 Pinout 视图中完成,如下图所示。

        对于 HSE 和 LSE 振荡器,CubeMX 提供三个配置选项:

        Disable:外部振荡器不可用/未使用,而使用相应的内部振荡器。

        Crystal/Ceramic Resonator:使用外部晶体/陶瓷谐振器,并从中得出相应的主频率。这意味着 RCC_OSC_IN 和 RCC_OSC_OUT 引脚用于连接 HSE,并且相应的信号 I/O 不可用于其他用途(如果我们使用外部低速晶体,则也使用相应的 RCC_OSC32_IN 和 RCC_OSC32_OUT I/O)。

        BYPASS Clock Source:使用外部 clock source。clock source 由另一个活动器件生成。这意味着 RCC_OSC_OUT 未使用,可以将其用作常规 GPIO。在 ST 的几乎所有开发板中,ST-LINK 接口的主时钟输出 (MCO) 引脚用作目标 STM32 MCU 的外部时钟源。启用此选项允许将 ST-LINK MCO 用作 HSE。

        RCC 外设还允许启用主时钟输出 (MCO),这是一个可用于为另一个外部设备提供时钟的引脚,允许为另一个 IC 节省外部晶体。一旦 MCO 被启用,就可以使用 Clock Configuration 视图选择它的 clock source,如下图所示。

2、HAL_RCC 模块概述

        到目前为止,我们已经看到 Reset and Clock Control (RCC) 外设负责 STM32 MCU 的整个 clock tree 的配置。HAL_RCC 模块包含 CubeHAL 的相应描述符和例程,以便从特定的 RCC 实现中抽象出来。我们现在将简要概述它的主要功能以及配置 clock tree 期间涉及的步骤。

        配置 clock tree 最相关的 C 结构是 RCC_OscInitTypeDef 和 RCC_ClkInitTypeDef。第一个用于配置 RCC 内部/外部振荡器源(HSE、HSI、LSE、LSI),以及一些额外的时钟源(如果由 MCU 提供)。例如,F0 系列的一些 STM32 MCU(STM32F07x、STM32F0x2 和 STM32F09x 的)提供 USB 2.0 支持,此外还有一个内部专用且经过工厂校准的高速振荡器,运行频率为 48MHz,用于偏置 USB 外设。如果是这种情况,则 RCC_OscInitTypeDef 结构也用于配置这些额外的 clock sources。RCC_OscInitTypeDef 结构体还有一个字段,该字段是 RCC_PLLInitTypeDef 结构体的实例,该字段配置用于提高源时钟速度的主 PLL。它反映了主 PLL 的硬件结构,可以根据 STM32 系列由多个字段组成(在 STM32F2/4/7 MCU 中,它可以具有相当复杂的结构)。相反,RCC_ClkInitTypeDef 结构用于配置系统时钟开关 (SWCLK)、AHB 总线和 APB1/2 总线的源时钟。

        CubeMX 旨在为 MCU 的时钟树生成正确的代码初始化。所有必要的代码都打包在 SystemClock_Config() 例程中,到目前为止我们在生成的项目中遇到过。例如,以下 SystemClock_Config() 的实现反映了运行频率为 48MHz 的 STM32F030R8 MCU 的 clock tree 配置:

void SystemClock_Config(void) {RCC_OscInitTypeDef RCC_OscInitStruct;RCC_ClkInitTypeDef RCC_ClkInitStruct;RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;RCC_OscInitStruct.HSIState = RCC_HSI_ON;RCC_OscInitStruct.HSICalibrationValue = 16;RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL12;RCC_OscInitStruct.PLL.PREDIV = RCC_PREDIV_DIV1;HAL_RCC_OscConfig(&RCC_OscInitStruct);RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_SYSCLK;RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_1);HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000);HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK);/* SysTick_IRQn interrupt configuration */HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
}

        首先选择 HSI 作为源振荡器并启用主 PLL,通过 PLL 多路复用器将 HSI 设置为其时钟源。然后 clock frequency 增加 12 倍(设置 PLLMUL 字段)。设置 SYSCLK 频率。PLLCLK 被选为 clock source 。同样,SYSCLK 频率被选为 AHB 总线的源,相同的 HCLK 频率 (RCC_HCLK_DIV1) 被选为 APB1 总线的源。其他代码行设置 SysTick 计时器,这是 Cortex-M 内核中提供的一个特殊计时器,用于同步一些内部 HAL 活动(或驱动 RTOS 的调度器)。HAL 基于 SysTick 计时器每 1 毫秒生成一次中断的约定。由于我们正在配置 SysTick 时钟,使其以 48MHz 的最大内核频率运行(这意味着 SYSCLK 每秒执行 48000000 个时钟周期),我们可以设置 SysTick 定时器,使其每 48000000 个周期/1000ms = 48000 个时钟周期生成一个中断。

        SysTick 计时器是一个 24 位 downcounter 计时器,也就是说,它从配置的最大值(在本例中为 48000)计数到零,然后再次自动重新启动。timer 的 source clock 确定此 timer 的计数速度。由于这里我们指定 SysTick 定时器的 clock source 是 HCLK,那么计数器将每 1ms 达到零。

2.1、计算运行时的时钟频率

        有时,了解 CPU 内核的运行速度非常重要。如果我们的固件设计为始终以既定频率运行,那么我们可以使用符号常量轻松地在固件中对该值进行硬编码。然而,这始终是一种糟糕的编程风格,如果我们动态地管理 CPU 频率,它是完全不适用的。CubeHAL 提供了一个可用于计算 SYSCLK 频率的函数:HAL_RCC_GetSysClockFreq()。但是,必须特别小心地处理此功能。让我们看看为什么。

        HAL_RCC_GetSysClockFreq() 不返回实际的 SYSCLK 频率 (如果没有已知且精确的外部参考,它永远无法以可靠的方式执行此操作),但它的结果基于以下算法:

        如果 SYSCLK 源是 HSI 振荡器,则返回基于 HSI_VALUE 宏的值;

        如果 SYSCLK 源是 HSE 振荡器,则根据 HSE_VALUE 宏返回值;

         如果 SYSCLK 源是 PLLCLK,则根据特定的 STM32 MCU 实现,返回一个基于 HSI_VALUE/HSE_VALUE 乘以 PLL 因子的值。

        HSI_VALUE 和 HSE_VALUE 宏在 stm32xxx_hal_conf.h 文件中定义,它们是硬编码值。HSI_VALUE 由 ST 在芯片设计期间定义,我们可以信任相应宏的值(除了那 1% 的准确率)。相反,如果我们使用外部振荡器作为 HSE 源,我们必须提供 HSE_VALUE 宏的实际值,否则 HAL_RCC_GetSysClockFreq() 函数返回的值是错误的。这也会影响 SysTick 定时器的 tick 频率 (即生成 timer 中断需要多长时间)。

        我们还可以使用 SystemCoreClock CMSIS 全局变量来检索 core frequency。

        如果我们决定在不使用 CubeHAL 例程的情况下手动操作 clock tree 配置,我们必须记住,每次更改 SYSCLK 频率时,都需要调用 CMSIS 函数 SystemCoreClockUpdate(),否则某些 CMSIS 例程可能会给出错误的结果。此函数由 HAL_RCC_ClockConfig() 例程自动调用。

        请注意,Cortex-M 内核不是由 SYSCLK 频率计时的,而是由 HCLK 频率计时的,HCLK 频率可以通过 AHB 预分频器降低。所以,回顾一下,core frequency 等于 HAL_RCC_GetSysClockFreq()/AHB-prescaler。

2.2、启用主时钟输出

        如前所述,根据所使用的 IC 封装,STM32 MCU 允许将时钟信号路由到一个或两个输出 I/O,称为主时钟输出 (MCO)。这是通过使用函数

void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv);

例如,要将 PLLCLK 路由到 STM32F401RE MCU 中的 MCO1 引脚(对应 PA8 引脚),我们必须按以下方式调用上述函数:

HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_PLLCLK, RCC_MCODIV_1);

        请注意,当将 MCO 引脚配置为输出 GPIO 时,其速度(即转换速率)会影响输出时钟的质量。此外,对于更高的时钟频率,必须按以下方式启用补偿单元:

HAL_EnableCompensationCell();

2.3、启用时钟安全系统

        时钟安全系统(CSS)是 RCC 外设的一项功能,用于检测外部 HSE 的故障。CSS 是一些关键应用中的重要功能,其中 HSE 的故障可能会对用户造成伤害。通过 NMI 异常(无法禁用的 Cortex-M 异常)注意到故障检测这一事实证明了它的重要性。

        当检测到 HSE 故障时,MCU 会自动切换到 HSI 时钟,该时钟被选为 SYSCLK 时钟的源。因此,如果需要更高的内核频率,我们需要在 NMI 异常处理程序中执行适当的初始化。

        为了启用 CSS,我们使用 HAL_RCC_EnableCSS() 例程,我们需要按以下方式定义 NMI 异常的处理程序:

void NMI_Handler(void) {HAL_RCC_NMI_IRQHandler();
}

        捕获 HSE 时钟故障的正确方法是定义回调:无需启用 NMI 异常,因为它是自动启用的,不能禁用。

void HAL_RCC_CSSCallback(void) {//Catch the HSE failure and take proper actions
}

3、HSI 校准

        我们在前面看到的 SystemClock_Config() 例程中保留了一行代码,没有注释。它用于执行 HSI 振荡器的微调校准。但它到底有什么作用呢?

        如前所述,由于制造工艺的不同,内部 RC 振荡器的频率可能因芯片而异。因此,HSI 振荡器由 ST 进行工厂校准,在室温下的精度为 1%。复位后,出厂校准值自动加载到 RCC 配置寄存器 (RCC_CR) 的第二个字节 (HSICAL) 中(下图显示了该寄存器在 STM32F401RE中的实现)。

        内部 RC 振荡器的频率可以微调,以便在更宽的温度和电源电压范围内实现更高的精度。修剪位用于此目的。五个微调位 RCC_CR->HSITRIM[4:0] 用于微调。默认剪裁值为 16。此修剪值的增加/减少会导致 HSI 频率的增加/减少。HSI 振荡器以 HSI 时钟速度的 0.5% 为步长进行微调:         写入 17 到 31 范围内的微调值会增加 HSI 频率。

        写入 0 到 15 范围内的修整值会降低 HSI 频率。

        写入等于 16 的修剪值将导致 HSI 频率保持其默认值。

 HSI 可以按照以下步骤进行校准:

        1. 设置内部高速 RC 振荡器 System clock;

        2. 测量每个微调值的内部 RC 振荡器频率;

        3. 计算每个 trimming 值的频率误差(根据已知的参考);

        4. 最后,将 Trimming Bits 设置为最佳值 (对应于最低频率误差)。

        内部振荡器频率不是直接测量的,而是根据使用 timer 计数的 clock pulse 数与典型值进行比较计算得出的。为此,必须提供非常精确的参考频率,例如外部 32.768 kHz 晶体提供的 LSE 频率或电源的 50 Hz/60 Hz。

        ST 提供了几个应用说明,更好地描述了这一程序(例如,AN4067是关于 STM32F0 系列中的校准程序https://bit.ly/1R8kEbf)。

相关文章:

Diving into the STM32 HAL-----Clock Tree笔记

几乎每个数字电路都需要一种方法来同步其内部电路或与其他电路同步。时钟是一种产生周期性信号的设备,它是数字电子学中最普遍的心跳源形式。 然而,相同的时钟信号不能用于馈送现代微控制器(如 STM32 微控制器)提供的所有组件和外…...

【AIGC】如何充分利用ChatGPT:有效提示框架与基本规则

概述 在使用ChatGPT进行内容创作时,遵循结构化的提示框架和基本规则可以显著提升AI响应的质量。本文探讨了五种结构化的提示框架,并详细介绍了基本规则和进阶技巧,帮助您更有效地与ChatGPT互动。 基础规则 规则1:指令放在开头&…...

【1个月速成Java】基于Android平台开发个人记账app学习日记——第7天,申请阿里云SMS短信服务SDK

系列专栏链接如下,方便跟进: https://blog.csdn.net/weixin_62588253/category_12821860.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12821860&sharereferPC&sharesourceweixin_62588253&sharefromfrom_link 同时篇幅…...

视频怎么去除杂音保留人声?教你如何实现视频降噪

在视频录制的过程中,可能会产生很多杂音和噪音,这可能时因为录制环境不理想、录制设备故障等多方面造成的。视频怎么去除杂音保留人声?今天我们就来谈谈如何实现视频降噪。 视频中常见的杂音类型 自然环境音:如风声、水流声、鸟叫…...

数学建模学习(136):使用Python基于Fuzzy WSM、Fuzzy WPM、Fuzzy WASPAS的多准则决策分析

1. 算法介绍 1.1 Fuzzy WSM、Fuzzy WPM、Fuzzy WASPAS 的基本概念和背景 模糊多属性决策(MADM)方法是解决复杂决策问题的重要工具,尤其是在信息不确定且难以量化的情况下。Fuzzy WSM(Fuzzy Weighted Sum Model)、Fuzzy WPM(Fuzzy Weighted Product Model)、以及 Fuzzy…...

Python小游戏21——拼图小游戏

使用了Pygame库来创建图形界面。请确保你已经安装了Pygame库(可以使用pip install pygame来安装)。 运行结果展示 代码展示 python import pygame import sys import random # 初始化Pygame pygame.init() # 设置屏幕尺寸 screen_width, screen_height …...

C# 常用的测试框架合集

在 C# 开发中,拥有强大的测试框架是确保代码质量和稳定性的关键。本文将介绍一些 C# 中常用的测试框架,帮助你更好地进行单元测试、集成测试等各类测试工作。 一、NUnit 简介 NUnit 是一个广泛使用的开源测试框架,专为.NET 平台设计。它提供…...

Android——从相机/相册获取图片

从相机获取图片 设置权限 <uses-permission android:name"android.permission.CAMERA" />点击跳转 private static final int REQUEST_CODE_TAKE 1;public void takePhoto(View view) {if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAM…...

MySQL 数据库基准测试报告

MySQL 数据库基准测试报告 1. 引言 数据库基准测试是一项重要的性能评估活动&#xff0c;旨在通过模拟实际的工作负载&#xff0c;测试数据库在不同条件下的表现。这些测试有助于发现性能瓶颈并提供优化的依据。在本报告中&#xff0c;我们将基于 sysbench 工具对 MySQL 数据…...

计算机毕业设计Python+大模型神经网络电影推荐 知识图谱图神经网络电影推荐可视化系统 注意力机制 秒杀同类电影推荐项目 GNN GAT

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

Python | Leetcode Python题解之第543题二叉树的直径

题目&#xff1a; 题解&#xff1a; class Solution:def diameterOfBinaryTree(self, root: TreeNode) -> int:self.ans 1def depth(node):# 访问到空节点了&#xff0c;返回0if not node:return 0# 左儿子为根的子树的深度L depth(node.left)# 右儿子为根的子树的深度R …...

【浪潮商城-注册安全分析报告-无验证方式导致安全隐患】

前言 由于网站注册入口容易被黑客攻击&#xff0c;存在如下安全问题&#xff1a; 1. 暴力破解密码&#xff0c;造成用户信息泄露 2. 短信盗刷的安全问题&#xff0c;影响业务及导致用户投诉 3. 带来经济损失&#xff0c;尤其是后付费客户&#xff0c;风险巨大&#xff0c;造…...

如何设置VSCODE快捷键光标移到行首和行尾

{ "key": "cmdhome", "command": "cursorTop", },{ "key": "cmdend", "command": "cursorBottom", }...

Android——多线程、线程通信、handler机制

Android——多线程、线程通信、handler机制 模拟网络请求&#xff0c;会阻塞主线程 private String getStringForNet() {StringBuilder stringBuilder new StringBuilder();for (int i 0; i < 100; i) {stringBuilder.append("字符串" i);}try {Thread.sleep(…...

Java | Leetcode Java题解之第542题01矩阵

题目&#xff1a; 题解&#xff1a; class Solution {static int[][] dirs {{-1, 0}, {1, 0}, {0, -1}, {0, 1}};public int[][] updateMatrix(int[][] matrix) {int m matrix.length, n matrix[0].length;// 初始化动态规划的数组&#xff0c;所有的距离值都设置为一个很大…...

docker安装低版本的jenkins-2.346.3,在线安装对应版本插件失败的解决方法

提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、网上最多的默认解决方法1、jenkins界面配置清华源2、替换default.json文件 二、解决低版本Jenkins在线安装插件问题1.手动下载插件并导入2.低版本jenkins在…...

CSS3新增渐变(线性渐变、径向渐变、重复渐变)

1.线性渐变 代码&#xff1a; 效果图&#xff1a; 使文字填充背景颜色&#xff1a; 效果图&#xff1a; 2.径向渐变 代码&#xff1a; 效果图&#xff1a; 代码图&#xff1a; 效果图&#xff1a; 3.重复渐变 代码&#xff1a; 效果图&#xff1a;...

汽车免拆诊断案例 | 2017款凯迪拉克XT5车组合仪表上的指针均失灵

故障现象 一辆2017款凯迪拉克XT5车&#xff0c;搭载LTG 发动机&#xff0c;累计行驶里程约为17.2万km。车主反映&#xff0c;组合仪表上的发动机转速表、车速表、燃油表及发动机冷却液温度表的指针均不指示&#xff0c;但发动机起动及运转正常&#xff0c;且车辆行驶正常。 故…...

Cloudera Hue深度解析:安装、配置到高级用法

Hue的介绍 HUE 是一个开源的 Apache Hadoop UI 系统&#xff0c;早期由 Cloudera 开发&#xff0c;它是基于 Python Web 框架 Django 实现&#xff0c;后来贡献给开源社区。它包括 3 个部分 hue ui&#xff0c;hue server&#xff0c; hue db。通过使用 Hue 我们可以通过浏览…...

17、论文阅读:VMamba:视觉状态空间模型

前言 设计计算效率高的网络架构在计算机视觉领域仍然是一个持续的需求。在本文中&#xff0c;我们将一种状态空间语言模型 Mamba 移植到 VMamba 中&#xff0c;构建出一个具有线性时间复杂度的视觉主干网络。VMamba 的核心是一组视觉状态空间 (VSS) 块&#xff0c;搭配 2D 选择…...

GPT-5 一年后发布?对此你有何期待?

GPT-5 一年后发布&#xff1f;对此你有何期待&#xff1f; 在最新技术的洪流中&#xff0c;GPT-5即将登场。你是否在思考&#xff0c;它将为我们的生活和工作带来哪些变革&#xff1f;接下来的探索&#xff0c;或许可以启发你对未来的想象。让我们一起深入这场关于未来AI语言模…...

2024中国国际数字经济博览会:图为科技携明星产品引领数智化潮流

10月24日&#xff0c;全球数智化领域的目光齐聚于中国石家庄正定&#xff0c;一场关于数字经济未来的盛会—2024中国国际数字经济博览会在此拉开帷幕。 云边端算力底座的领航者&#xff0c;图为科技携其明星产品惊艳亮相&#xff0c;期待与您共赴一场数智化的非凡之旅&#xff…...

大模型面试题:常见的微调方法有哪些说下原理并对比

更多实时面试题总结请关注我的公众号"算法狗" 或移步至 https://pica.zhimg.com/80/v2-7fd6e77f69aa02c34ca8c334870b3bcd_720w.webp?sourced16d100b 这里说的微调主要是指参数微调&#xff0c;参数微调的方法主要有以下几种&#xff1a; Adapter 在预训练模型每一层…...

CentOS 9 Stream 上安装 PostgreSQL 16

CentOS 9 Stream 上安装 PostgreSQL 16 CentOS 9 Stream 上安装 PostgreSQL 16设置密码并且远程连接 CentOS 9 Stream 上安装 PostgreSQL 16 在 CentOS 9 Stream 上安装 PostgreSQL 16 可以通过以下步骤完成&#xff1a; 添加 PostgreSQL 官方仓库&#xff1a; PostgreSQL 提…...

【数据分享】1901-2023年我国省市县镇四级的逐年最高气温数据(免费获取/Shp/Excel格式)

之前我们分享过1901-2023年1km分辨率逐月最高气温栅格数据和Excel和Shp格式的省市县镇四级逐月最高气温数据&#xff0c;原始的逐月最高气温栅格数据来源于彭守璋学者在国家青藏高原科学数据中心平台上分享的数据&#xff01;基于逐月数据我们采用求年平均值的方法得到逐年最高…...

使用C++和QT开发应用程序入门以及开发实例分享

目录 1、搭建开发环境&#xff08;VS2010和QT4.8.2&#xff09; 2、创建一个QT窗口 3、在QT窗口中添加子窗口 4、QT界面布局 5、QT信号&#xff08;SIGNAL&#xff09;和槽&#xff08;SLOT&#xff09; 6、最后 C软件异常排查从入门到精通系列教程&#xff08;专栏文章列…...

Openlayers高级交互(20/20):超级数据聚合,页面不再混乱

本示例在vue+openlayers中使用cluster生成聚合数据的效果。在OpenLayers中实现点聚合(clustering)是一个常见的需求,特别是在处理大量地理数据点时。聚合可以提高地图的性能并减少视觉上的混乱。 一、示例效果图 专栏名称内容介绍Openlayers基础实战 (72篇)专栏提供73篇文…...

qt QStandardItemModel详解

1、概述 QStandardItemModel是Qt框架中提供的一个基于项的模型类&#xff0c;用于存储和管理数据&#xff0c;这些数据可以以表格的形式展示在视图控件&#xff08;如QTableView、QTreeView等&#xff09;中。QStandardItemModel支持丰富的数据操作&#xff0c;包括添加、删除…...

光伏设计软件如何快速上手?

光伏设计软件是现代光伏系统设计不可或缺的工具&#xff0c;它们大大简化了设计流程&#xff0c;提高了设计效率。对于新手来说&#xff0c;快速上手一款光伏设计软件可能会显得有些困难&#xff0c;但只要掌握了一些基础操作&#xff0c;就能迅速提升设计技能。 1、导入CAD图片…...

Mac下安装Apache JMeter并启动

一、下载JMeter https://jmeter.apache.org/download_jmeter.cgi 下载好对应的压缩包&#xff0c;解压后即可&#xff0c;并将解压后的文件夹放至自己想要存放的位置。 二、启动JMeter 进入解压后的文件夹下的bin目录cd /usr/local/apache-jmeter-5.6.3/bin配置语言vim jmet…...