前言:为什么SysTick是嵌入式开发的"瑞士军刀"?

在STM32开发中,我们经常需要精确的延时功能(如毫秒级延时控制LED闪烁)或周期性任务调度(如定时采集传感器数据)。实现这些功能的方式有很多,比如使用外设定时器(TIM2-TIM5),但这类定时器往往需要占用GPIO引脚和外设资源。

而Cortex-M内核自带的SysTick(系统定时器) 完美解决了这一问题——它是内核集成的16位定时器,无需占用外设资源,可直接用于系统延时、RTOS任务调度等核心功能。无论是裸机开发还是RTOS环境,SysTick都是不可或缺的"基础组件"。

本文将从SysTick的硬件结构讲起,详细解析其工作原理、配置方法、实战应用(如精确延时函数、RTOS调度),并结合代码示例,帮助你彻底掌握这一"轻量级定时器"的使用技巧。

一、SysTick系统定时器概述

1.1 SysTick的核心特性

SysTick(System Tick Timer)是Cortex-M0/M3/M4/M7等内核标配的定时器,其核心特性如下:

特性说明
位数16位递减计数器,最大计数值为65535(0xFFFF)
计数模式仅支持递减计数(从装载值减到0后自动重装载)
时钟源可选两种时钟源:
- 内核时钟(HCLK)
- 内核时钟/8(HCLK/8)
中断支持计数到0时可触发中断(SysTick_IRQn)
资源占用内核集成,不占用外设定时器资源(如TIM2-TIM5)
典型应用系统延时函数(delay_ms/delay_us)、RTOS任务调度、周期性任务触发

为什么选择SysTick?

  • 无需配置GPIO引脚,简化硬件设计;
  • 内核级定时器,响应速度比外设定时器更快;
  • 跨平台兼容(所有Cortex-M内核通用),代码可移植性强;
  • 适合作为系统级定时器(如RTOS的时基)。

1.2 SysTick与外设定时器的区别

STM32的外设定时器(如TIM2-TIM5)功能强大,但与SysTick相比有明显差异:

对比项SysTick外设定时器(如TIM3)
所属模块Cortex-M内核STM32外设
功能复杂度简单(仅定时中断)复杂(PWM、输入捕获、编码器接口等)
资源占用无外设资源占用占用定时器外设和GPIO引脚
适用场景系统延时、RTOS时基复杂定时任务(如PWM输出、频率测量)
移植性跨Cortex-M平台兼容仅限特定STM32型号

总结:SysTick适合做"系统基石"(如延时、调度),外设定时器适合做"专项任务"(如电机控制、传感器数据采集)。

二、SysTick硬件结构与寄存器解析

2.1 核心寄存器

SysTick通过3个寄存器实现全部功能,所有寄存器都是32位,但实际有效位根据功能有所不同:

寄存器名称地址范围功能描述
SYST_CSR0xE000E010控制与状态寄存器,负责使能定时器、选择时钟源、查看计数状态
SYST_RVR0xE000E014重装载值寄存器,存储计数最大值(递减到0后自动装载此值)
SYST_CVR0xE000E018当前值寄存器,存储当前计数数值,写入任意值可清零
SYST_CALIB0xE000E01C校准值寄存器,存储出厂校准信息(一般不使用)
(1)控制与状态寄存器(SYST_CSR)
位段功能描述
0位(ENABLE)定时器使能位:0=关闭,1=开启
1位(TICKINT)中断使能位:0=计数到0不触发中断,1=计数到0触发中断
2位(CLKSOURCE)时钟源选择:0=HCLK/8,1=HCLK(内核时钟)
16位(COUNTFLAG)计数标志位:1=已计数到0(读寄存器后自动清零)

示例:配置SysTick为HCLK/8时钟源,使能中断并启动定时器:

SYST_CSR = (1 << 0) | (1 << 1) | (0 << 2);  // ENABLE=1, TICKINT=1, CLKSOURCE=0
(2)重装载值寄存器(SYST_RVR)
  • 低16位有效(16位定时器),高16位保留;
  • 存储递减计数的最大值,计数到0后自动重新装载此值;
  • 若设置为0,则定时器不工作(每次计数到0后停止)。

最大计数范围:0~65535(16位),若时钟源为72MHz/8=9MHz,则最大定时时间为:65535 / 9MHz ≈ 7.28ms(超过此值会溢出)。

(3)当前值寄存器(SYST_CVR)
  • 低16位有效,存储当前计数数值;
  • 读取时返回当前计数值,写入任意值会将计数器清零;
  • 计数到0时,COUNTFLAG(SYST_CSR的16位)置1。

清零计数器示例

SYST_CVR = 0;  // 写入任意值(如0),计数器清零

2.2 工作原理

SysTick的工作流程如下:

  1. 配置SYST_RVR寄存器,设置重装载值(如9000);
  2. 配置SYST_CSR寄存器,选择时钟源(如HCLK/8)并使能定时器;
  3. 计数器从SYST_RVR的值开始递减计数(9000→8999→…→0);
  4. 计数到0时:
    • 若TICKINT=1(使能中断),则触发SysTick_IRQn中断;
    • COUNTFLAG(SYST_CSR.16)置1;
    • 自动重新装载SYST_RVR的值,重复计数。

定时时间计算公式

定时时间(秒)= 重装载值 / 时钟源频率(Hz)

例如:时钟源=9MHz(72MHz/8),重装载值=9000 → 定时时间=9000/9e6=0.001秒=1ms。

三、SysTick配置步骤(HAL库与寄存器两种方式)

3.1 HAL库配置(适合新手)

STM32Cube HAL库提供了SysTick的封装函数,无需直接操作寄存器,适合快速开发。

步骤1:CubeMX配置SysTick
  1. 新建工程,选择STM32型号(如F103C8T6);
  2. 配置系统时钟(HCLK=72MHz);
  3. SysTick无需额外配置(默认用于HAL_Delay函数),若需自定义,需在代码中重配置。
步骤2:HAL库函数解析

HAL库中与SysTick相关的核心函数:

函数名功能描述
HAL_InitTick()初始化SysTick,用于HAL_Delay函数(默认配置)
HAL_SYSTICK_Config()配置SysTick定时器(设置重装载值和中断)
HAL_Delay()基于SysTick的毫秒级延时函数

自定义SysTick中断示例

// 初始化SysTick,配置为1ms中断
void SysTick_Init(void)
{// 时钟源=HCLK/8=72MHz/8=9MHz,1ms需计数9000次if (HAL_SYSTICK_Config(SystemCoreClock / 8 / 1000) != 0){Error_Handler();  // 配置失败}// 设置SysTick中断优先级(最低优先级)HAL_NVIC_SetPriority(SysTick_IRQn, 15, 0);
}// SysTick中断服务函数(在stm32f1xx_it.c中)
void SysTick_Handler(void)
{HAL_IncTick();  // HAL库的系统滴答计数(用于HAL_Delay)User_SysTick_Callback();  // 用户自定义回调函数
}// 用户自定义回调(如定时执行任务)
void User_SysTick_Callback(void)
{static uint32_t cnt = 0;if (++cnt >= 1000)  // 1ms中断,1000次=1秒{cnt = 0;HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);  // 翻转LED}
}

3.2 寄存器直接配置(适合进阶)

直接操作寄存器可跳过HAL库的封装,提高效率,适合对实时性要求高的场景。

步骤1:初始化SysTick定时器
// 初始化SysTick,时钟源=HCLK/8,定时1ms中断
void SysTick_Init(void)
{// 1. 关闭定时器SYST_CSR &= ~(1 << 0);  // ENABLE=0// 2. 清零计数器SYST_CVR = 0;// 3. 设置重装载值(9000 = 9MHz * 1ms)SYST_RVR = 9000;// 4. 配置时钟源(HCLK/8)和中断SYST_CSR |= (1 << 1) | (0 << 2);  // TICKINT=1(使能中断),CLKSOURCE=0(HCLK/8)// 5. 设置中断优先级(最低优先级)NVIC_SetPriority(SysTick_IRQn, 15);NVIC_EnableIRQ(SysTick_IRQn);// 6. 使能定时器SYST_CSR |= (1 << 0);  // ENABLE=1
}
步骤2:实现中断服务函数
// SysTick中断服务函数
void SysTick_Handler(void)
{static uint32_t ms_cnt = 0;// 1ms中断一次,每1秒翻转LEDif (++ms_cnt >= 1000){ms_cnt = 0;GPIOC->ODR ^= GPIO_PIN_13;  // 翻转PC13(LED)}
}

3.3 两种配置方式的对比

配置方式优点缺点适用场景
HAL库简单易用,无需了解寄存器细节代码冗余,效率稍低快速开发、新手入门
寄存器直接操作代码精简,执行效率高需了解寄存器结构,移植性稍差对实时性要求高的场景、底层优化

四、实战案例:SysTick的典型应用

4.1 案例1:实现精确延时函数(delay_us/delay_ms)

SysTick最常用的功能是实现微秒级和毫秒级延时,替代低效的for循环延时。

实现思路
  • delay_us:根据微秒数计算需要的计数次数,等待计数器减到0;
  • delay_ms:基于delay_us实现,循环调用微秒延时(注意16位定时器的最大延时限制);
  • 关闭中断(避免中断干扰延时精度)。
代码实现
// 时钟源:HCLK/8=9MHz(1us≈9个计数周期)
#define SYSTICK_CLK 9000000  // 9MHz// 微秒级延时(最大约7280us,超过会溢出)
void delay_us(uint32_t us)
{uint32_t ticks;uint32_t start;// 计算需要的计数值(向上取整)ticks = us * (SYSTICK_CLK / 1000000);// 关闭SysTick中断(避免干扰)SYST_CSR &= ~(1 << 1);  // TICKINT=0// 设置重装载值SYST_RVR = ticks - 1;  // 计数从ticks-1到0,共ticks次// 清零计数器并启动SYST_CVR = 0;SYST_CSR |= (1 << 0);  // ENABLE=1// 等待计数完成(COUNTFLAG置1)do{start = SYST_CSR;} while (!(start & (1 << 16)));  // 等待COUNTFLAG=1// 停止定时器并恢复中断SYST_CSR &= ~(1 << 0);  // ENABLE=0SYST_CSR |= (1 << 1);   // 恢复TICKINT=1
}// 毫秒级延时(通过多次调用delay_us实现)
void delay_ms(uint32_t ms)
{while (ms--){delay_us(1000);  // 每次延时1000us=1ms}
}
关键注意事项
  • 最大延时限制:16位计数器的最大计数值为65535,若时钟源为9MHz,则delay_us的最大支持值为:65535 / 9 ≈ 7281us(约7.28ms),超过此值需分多次调用;
  • 中断影响:延时过程中关闭SysTick中断(TICKINT=0),避免中断打乱计数;
  • 时钟源一致性:延时函数的精度依赖于时钟源频率的准确性,需确保HCLK配置正确(如72MHz)。

4.2 案例2:SysTick作为RTOS的时基(以FreeRTOS为例)

RTOS(如FreeRTOS)需要一个系统时基来实现任务调度,SysTick是最常用的选择。

FreeRTOS中配置SysTick
// FreeRTOS配置文件(FreeRTOSConfig.h)
#define configUSE_SYSTICK_TIMER     1  // 使用SysTick作为时基
#define configTICK_RATE_HZ          1000  // 时基频率1000Hz(1ms一次中断)// 初始化FreeRTOS时,自动配置SysTick
int main(void)
{HAL_Init();SystemClock_Config();  // 配置HCLK=72MHz// 创建任务xTaskCreate(LED_Task, "LED Task", 128, NULL, 1, NULL);// 启动调度器(内部会配置SysTick为1ms中断)vTaskStartScheduler();while (1);  // 不会执行到这里
}// LED任务(每500ms翻转一次LED)
void LED_Task(void *pvParameters)
{while (1){HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);vTaskDelay(pdMS_TO_TICKS(500));  // 延时500ms(基于SysTick)}
}
原理说明
  • FreeRTOS的vTaskDelay()函数依赖SysTick的定时中断;
  • 每1ms触发一次SysTick中断,FreeRTOS在中断中更新任务状态(如延时计数器减1);
  • 任务调度器根据时基判断任务是否就绪,实现多任务切换。

4.3 案例3:高频数据采集(10kHz采样率)

SysTick的中断响应速度快,适合作为高频数据采集的触发源(如10kHz采样率)。

// 全局变量:采样数据缓冲区
uint16_t adc_buf[1000];
uint16_t adc_idx = 0;// 初始化SysTick为10kHz中断(100us一次)
void SysTick_Init_10kHz(void)
{SYST_CSR &= ~(1 << 0);  // 关闭定时器SYST_CVR = 0;           // 清零计数器SYST_RVR = 900;         // 9MHz / 900 = 10kHz(100us)SYST_CSR |= (1 << 1) | (0 << 2);  // 使能中断,时钟源HCLK/8NVIC_SetPriority(SysTick_IRQn, 0);  // 高优先级SYST_CSR |= (1 << 0);   // 启动定时器
}// SysTick中断服务函数(10kHz)
void SysTick_Handler(void)
{if (adc_idx < 1000){// 读取ADC数据(假设已初始化ADC)adc_buf[adc_idx++] = HAL_ADC_GetValue(&hadc1);}
}// 主函数中处理数据
int main(void)
{// 初始化ADC和SysTickMX_ADC1_Init();SysTick_Init_10kHz();while (1){if (adc_idx >= 1000){// 数据采集完成,处理数据process_adc_data(adc_buf, 1000);adc_idx = 0;  // 重置索引}}
}

五、常见问题与解决方案

5.1 延时函数精度不足

现象delay_ms(1000)实际延时为1050ms,误差超过5%。

可能原因

  1. 系统时钟配置错误(如HCLK实际为64MHz而非72MHz);
  2. SysTick中断被高优先级中断阻塞;
  3. 延时函数中关闭中断不彻底,被其他中断打断;
  4. 重装载值计算错误(如未考虑时钟源分频)。

解决方案

  • 用示波器测量SysTick中断周期,验证时钟源频率;
  • 降低SysTick中断优先级(避免被低优先级中断阻塞);
  • 延时过程中关闭所有可屏蔽中断(临界区保护);
  • 重新计算重装载值:重装载值 = 时钟频率(Hz) * 延时时间(s) - 1

5.2 SysTick中断不触发

现象:初始化后无中断响应,LED不翻转。

可能原因

  1. 未使能SysTick中断(TICKINT=0);
  2. 中断优先级配置错误(被NVIC屏蔽);
  3. 重装载值设置为0(SYST_RVR=0);
  4. 定时器未使能(SYST_CSR的ENABLE=0)。

排查步骤

  1. 检查SYST_CSR寄存器:printf("SYST_CSR: 0x%X\n", SYST_CSR);,确认ENABLE=1、TICKINT=1;
  2. 检查NVIC配置:确保NVIC_EnableIRQ(SysTick_IRQn)已调用;
  3. 验证重装载值:printf("SYST_RVR: 0x%X\n", SYST_RVR);,确认不为0;
  4. 用调试器单步执行,观察计数器是否递减。

5.3 16位计数器溢出问题

现象:需要延时10ms,但SysTick最大只能延时7.28ms,导致计时不准。

解决方案

  • 分多次延时(如10ms = 7ms + 3ms);
  • 结合循环实现长延时:
    void delay_ms_long(uint32_t ms)
    {while (ms > 7)  // 每次延时7ms(小于最大7.28ms){delay_us(7000);ms -= 7;}delay_us(ms * 1000);  // 延时剩余毫秒数
    }
    

5.4 SysTick与HAL_Delay冲突

现象:自定义SysTick配置后,HAL_Delay()函数失效。

原因

  • HAL库的HAL_Delay()依赖SysTick中断(HAL_IncTick());
  • 自定义配置可能覆盖了HAL库的SysTick设置(如重装载值、中断使能)。

解决方案

  • 在自定义中断服务函数中调用HAL_IncTick()
    void SysTick_Handler(void)
    {HAL_IncTick();  // 保留HAL库的滴答计数User_SysTick_Callback();  // 自定义逻辑
    }
    
  • 若无需HAL_Delay(),可在CubeMX中禁用SysTick作为HAL时基(不推荐)。

六、总结与进阶学习

6.1 核心知识点总结

  1. SysTick是Cortex-M内核的16位定时器,适合做系统延时和RTOS时基;
  2. 核心寄存器:SYST_CSR(控制)、SYST_RVR(重装载值)、SYST_CVR(当前值);
  3. 配置方式:HAL库适合快速开发,寄存器操作适合高效场景;
  4. 典型应用:精确延时、RTOS任务调度、高频数据采集。

6.2 进阶学习方向

  1. SysTick在低功耗模式中的应用

    • 深入学习STM32的低功耗模式(STOP、STANDBY),了解SysTick在低功耗下的运行机制;
    • 配置SysTick唤醒低功耗模式,实现周期性唤醒采集数据。
  2. 中断优先级优化

    • 学习NVIC嵌套中断机制,合理设置SysTick中断优先级(如RTOS中设为最低优先级);
    • 避免高优先级中断长时间阻塞SysTick,影响延时精度。
  3. 与DMA结合

    • 结合DMA实现无CPU干预的高频数据传输(如SysTick触发ADC+DMA采集);
    • 减少中断响应时间,提高系统吞吐量。
  4. 跨平台移植

    • 将基于SysTick的代码移植到其他Cortex-M平台(如STM32L4、NRF52832),理解不同内核的差异。

SysTick看似简单,却是嵌入式系统的"基石"。掌握它的工作原理和配置技巧,能为复杂项目开发打下坚实基础。无论是裸机开发还是RTOS应用,SysTick都是你不可或缺的工具——用好这把"瑞士军刀",让你的STM32项目更高效、更稳定!

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

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

相关文章

【微信小程序】12、生物认证能力

1、生物认证 生物认证 是一种基于个体独特生理或行为特征进行身份验证的技术,广泛应用于安全、金融、医疗等领域。 小程序目前暂时只支持指纹识别认证。 2、查询支持的生物认证方式 获取本机支持的 SOTER 生物认证方式&#xff0c;文档 onLoad(options) {wx.checkIsSuppor…

高级机器学习

机器学习常见方法涉及方法&#xff1a;2.半监督学习3.无监督学习4.度量学习5.迁移学习6.多示例多标记学习7.在线学习8.元学习9.联邦学习10.强化学习11.概率图模型独立同分布独立指的是&#xff0c;样本集包括训练集测试集的任意两个样本之间都是不相关的。在表示样本的特征确定…

Chrome 提示 “此扩展程序不再受支持”(MacOS/Windows)

原因 最新 Chrome 使用 Manifest V3, 并在新版浏览器中 停止 V2 支持 处理方法 MacOS 新建一个后缀为 .mobileconfig 的文件, 内容参考 <?xml version"1.0" encoding"UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN&…

C++20协程实战:高效网络库、手机终端、多媒体开发开发指南

基于C++协程和事件循环的网络库 以下是基于C++协程和事件循环的网络库实例,涵盖常见场景和功能实现。示例基于libuv、Boost.Asio或自定义事件循环,结合C++20协程(如std::coroutine)或其他协程库(如cppcoro)实现。 基础TCP服务器 #include <cppcoro/task.hpp> #in…

数据库4.0

索引 事务 JDBC~ 目录 一、MySQL索引 1.0 概述 2.0 相关操作 3.0 注意 4.0 索引背后的原理的理解 二、 事务 1.0 原子性 2.0 隔离性 (1)并发执行 (2) 出现的问题 3.0 使用 三、JDBC编程 1.0 概述 2.0 如何下载驱动包 3.0 jar如何引入到项目之中 4.0 jdbc…

HarmonyOS-ArkUI Web控件基础铺垫6--TCP协议- 流量控制算法与拥塞控制算法

HarmonyOS-ArkUI Web控件基础铺垫1-HTTP协议-数据包内容-CSDN博客 HarmonyOS-ArkUI Web控件基础铺垫2-DNS解析-CSDN博客 HarmonyOS-ArkUI Web控件基础铺垫3--TCP协议- 从规则本质到三次握手-CSDN博客 HarmonyOS-ArkUI Web控件基础铺垫4--TCP协议- 断联-四次挥手解析-CSDN博客…

Dify 从入门到精通(2/100 篇):Dify 的核心组件 —— 从节点到 RAG 管道

Dify 的核心组件&#xff1a;从节点到 RAG 管道 引言 在 Dify 博客系列&#xff1a;从入门到精通&#xff08;100 篇&#xff09; 的第一篇《Dify 究竟是什么&#xff1f;真能开启低代码 AI 应用开发的未来&#xff1f;》中&#xff0c;我们全面介绍了 Dify 的定位、核心特点…

在线培训、远程示教——医疗器械行业的直播解决方案

文章目录前言一、医疗器械直播应用的两大核心场景二、直播平台在医疗场景中的关键技术支持点三、典型功能实现原理总结前言 医疗器械行业对“培训”和“示教”的专业性要求极高&#xff0c;传统的线下模式常因时间、空间、人员成本等受限而效率低下。而随着高清低延迟视频技术…

Mqttnet的MqttClientTlsOptions.CertificateValidationHandler详解

MqttClientTlsOptions.CertificateValidationHandler 是 MQTTnet 库中用于自定义 TLS 证书验证逻辑的关键回调函数。在 MQTT 客户端与服务器建立 TLS 连接时&#xff0c;该回调允许你覆盖默认的证书验证流程&#xff0c;实现自定义的安全策略。核心作用当 MQTT 客户端通过 TLS …

【图像噪点消除】——图像预处理(OpenCV)

目录 1 均值滤波 2 方框滤波 3 高斯滤波 4 中值滤波 5 双边滤波 6 小结 噪声&#xff1a;图像中的一些干扰因素。通常是由于图像采集设备、传输信道等因素造成的&#xff0c;表现为图像中随机的亮度。常见的噪声类型有高斯噪声和椒盐噪声。高斯噪声是一种分布符合正态分布…

Vulnhub napping-1.0.1靶机渗透攻略详解

一、下载靶机 下载地址&#xff1a;https://download.vulnhub.com/napping/napping-1.0.1.ova 下载好后使用VM打开&#xff0c;将网络配置模式改为net&#xff0c;防止桥接其他主机干扰&#xff08;桥接Mac地址也可确定主机&#xff09;。 二、发现主机 使用nmap扫描没有相应…

Kubernetes自动扩容方案

Kubernetes 自动扩容可以概括为 “三层六类”&#xff1a;层级类型触发维度官方/社区方案一句话说明Pod 级HPACPU / 内存 / 自定义 / 外部指标内置副本数横向扩缩&#xff0c;最常用VPACPU / 内存社区组件单 Pod 资源竖向扩缩&#xff0c;不改副本数KEDA任意事件&#xff08;队…

linux命令ps的实际应用

ps&#xff08;Process Status&#xff09;是 ​Linux/Unix 系统中最核心的进程管理工具&#xff0c;用于实时抓取系统进程快照。它直接读取 /proc 文件系统&#xff0c;不持续监控进程&#xff08;区别于 top&#xff09;&#xff0c;但可通过参数组合实现精准进程诊断。下面从…

深入理解C语言:详解直接插入排序的实现与优化

目录 引言 一、直接插入排序的相关概念 1.1、基本概念 1.2、直接插入排序过程详解 二、代码实现 三、时间复杂度 四、希尔排序 4.1、希尔排序的陈述 4.2、代码实现 4.3、时间复杂度 结语 引言 在计算机科学的世界里&#xff0c;排序算法是基础且重要的组成部分。它们…

【DRAM存储器五十五】LPDDR5介绍--command bus training

👉个人主页:highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 参考资料:《某LPDDR5数据手册》 、《JESD209-5A》 在为高频或中频操作启用ODT之前,必须对L

一道曾经百度面试题

&#x1f680;个人主页&#xff1a;BabyZZの秘密日记 &#x1f4d6;收入专栏&#xff1a;C语言 &#x1f30d;文章目入1. 题目重现2. 大小端到底在比什么&#xff1f;3. 解法一&#xff1a;联合体&#xff08;union&#xff09;为什么一行就够&#xff1f;使用示例4. 解法二&am…

VIKOR(Multi-criteria Optimization and Compromise Solution)简介与简单示例

前言 提醒&#xff1a; 文章内容为方便作者自己后日复习与查阅而进行的书写与发布&#xff0c;其中引用内容都会使用链接表明出处&#xff08;如有侵权问题&#xff0c;请及时联系&#xff09;。 其中内容多为一次书写&#xff0c;缺少检查与订正&#xff0c;如有问题或其他拓展…

【算法训练营Day18】二叉树part8

文章目录修剪二叉搜索树将有序数组转换为二叉搜索树把二叉搜索树转换为累加树修剪二叉搜索树 题目链接&#xff1a;669. 修剪二叉搜索树 解题逻辑&#xff1a; 因为在删除的同时要保证相对结构&#xff0c;所以我们不能沿用上一篇文章中的删除逻辑&#xff0c;新的删除逻辑为&…

【C++篇】“内存泄露”的宝藏手段:智能指针

目录 智能指针的使用场景分析 RAII和智能指针的设计思路 C标准库智能指针的使用 auto_ptr的使用&#xff1a; unique_ptr的使用&#xff1a; shared_ptr的使用&#xff1a; 模拟shared_ptr: 定制删除器&#xff1a; shared_ptr的循环引用 weak_ptr 智能指针的使用场景…

【密码学】4. 分组密码

目录分组密码分组密码概述Feistel 密码结构数据加密标准&#xff08;DES&#xff09;差分密码分析与线性密码分析分组密码的运行模式国际数据加密算法&#xff08;IDEA&#xff09;高级加密标准&#xff08;AES&#xff0c;Rijndael&#xff09;中国商用密码 SM4祖冲之密码&…