STM32速成笔记—定时器

news2024/11/26 17:47:52

文章目录

  • 一、什么是定时器
  • 二、定时器有什么用
  • 三、通用定时器详细介绍
    • 3.1 时钟来源
    • 3.2 预分频器,计数器,自动重装载寄存器
      • 3.2.1 预分频器
      • 3.2.2 计数器
      • 3.2.3 自动重装载寄存器
    • 3.3 触发控制器
  • 四、PWM
    • 4.1 什么是PWM
    • 4.2 什么是占空比
    • 4.3 STM32F1 PWM介绍
    • 4.4 PWM频率计算
  • 五、通用定时器输出引脚
  • 六、实战项目
    • 6.1 呼吸灯
    • 6.2 实现思路
    • 6.3 定时器配置
    • 6.4 定时器中断实现呼吸灯
    • 6.5 使用PWM实现呼吸灯
  • 七、拓展

一、什么是定时器

关于什么是定时器,简单来讲,就是是用来定时的。STM32F103ZET6有两个基本定时器TIM6和TIM7,四个通用定时器TIM2~TIM5和两个高级定时器TIM1,TIM8。每一个定时器都是完全独立的,不共享任何资源。

根据中文参考手册介绍,基本定时器最为简单,类似于51单片机的定时器。通用定时器在基本定时器的基础上增加了输入捕获和输出比较功能。高级定时器相比通用定时器,又增加了可编程死区互补输出,重复计数器等功能。

STM32F103ZET6的通用定时器是一个通过可编程预分频器驱动的16位自动装载计数器构成。使用定时器预分频器和RCC时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。

这里介绍一下对于定时器的个人理解。定时器的定时原理实际可以理解为按照固定的频率数数。按照固定频率就说明定时器一定要有输入时钟。比如输入为一个1KHz的时钟,那么数一个数的时间就是1ms。另外,数数也不是无限地数,数值有一个上限。可以规定是从0开始数到上限值,还是从上限值数到0。而且每次数到头,需要重新开始。比如,需要控制灯亮200ms。那么只需要在点亮LED之后,等到数到200时熄灭即可。当数到上限值或者数到0时,重新开始数。

二、定时器有什么用

定时器有许多用途,以通用定时器为例。它可以测量输入信号的脉冲宽度,产生PWM波。此外定时器也可以用于触发ADC采集,按键检测等方面。

中文参考手册介绍如下

中文参考手册对于通用定时器功能的描述

三、通用定时器详细介绍

速成选手可以线跳过这一部分,直接看下面,后来再返回来仔细看。

3.1 时钟来源

根据中文参考手册,通用定时器的时钟来源有四个。

  • 内部CK_INT
  • 外部触发时钟输入TIMx_ETR(外部时钟模式2)
  • 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器
  • 外部引脚输入(外部时钟模式1)
    通用定时器时钟来源
    通过配置TIMx_SMCR寄存器来选择,关于寄存器这里就不再详细介绍了,大家可以去看中文参考手册。

根据中文参考手册关于时钟的介绍,通用定时器挂接在APB1总线。对于APB1总线的时钟如下

APB1时钟介绍

如果APB1的预分频系数为1,那么通用定时器的输入时钟频率为36MHz,否则为72MHz。但是通常APB1总线的预分频系数我们不会设置成1,所以通用定时器的时钟频率为72MHz。

3.2 预分频器,计数器,自动重装载寄存器

预分频器,计数器和自动重装载寄存器

3.2.1 预分频器

预分频器是对时钟进行分频,范围是1~65536。比如通用定时器输入时钟频率为72MHz,此时,将预分频值设置为72,那么最终计数时的时钟频率为72MHz / 72 = 1MHz。

3.2.2 计数器

计数器就是用来计数的,计数值取值范围是0~65535。有三种计数方式:向上计数,向下计数,中央对齐模式(向上/向下计数)。

向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。

向下计数模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。

中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

3.2.3 自动重装载寄存器

比如,选择向下计数模式,初始值为2000。当计数到0时,会再次从2000开始向下计数。这就叫重装载。但是实际起作用的并不是这里的自动重装载寄存器,而是影子寄存器。关于影子寄存器这里就不再做介绍了,大家可以自行了解。

3.3 触发控制器

从图中的右上角可以注意到,有一个触发控制器。它可以用来触发一些外设,比如触发ADC采集,也可以用来给其他定时器提供时钟。

四、PWM

4.1 什么是PWM

PWM(脉冲宽度调制),它是一种利用微处理器的数字输出来对模拟电路进行控制的技术,也可以理解为是对模拟信号电平进行数字编码的方法。PWM可被应用于电机驱动,调光,通信等方面。

4.2 什么是占空比

一个PWM是有固定频率的,也就意味着周期一定,一个周期内有效电平持续时间占整个周期的比例可以称为占空比。比如一个周期100ms,其中50ms持续为有效电平,那么占空比就是50%。正是通过调节占空比,来调节电机转速,或者用不同占空比代表不同信号,用于通信。

4.3 STM32F1 PWM介绍

STM32F1系列单片机,除了基本定时器TIM6和TIM7外,都可以产生PWM输出。其中高级定时器TIM1和TIM8可以同时产生高达7路PWM输出。PWM输出其实就是对外输出占空比可调的方波,信号频率由自动重装载寄存器ARR的值决定,占空比由比较寄存器CCR的值决定。假设高电平为有效电平,见下图。ARR决定了周期(频率),CCR调节占空比。
PWM示意图
根据中文参考手册介绍,STM32F1的PWM比较输出模式共有8种。脉冲宽度调制模式可以产生一个由TIMx_ARR寄存器确定频率、由TIMx_CCRx寄存器确定占空比的信号。在TIMx_CCMRx寄存器中的OCxM位写入’110’(PWM模式1)或’111’(PWM模式2),能够独立地设置每个OCx输出通道产生一路PWM。有关寄存器的内容,这里就不不再做详细介绍。

这里介绍一下8种输出模式中比较常用的两种PWM输出模式,PWM1和PWM2。其实这两种输出模式差别不大,只不过输出电平的极性不同。

模式计数器CNT计数方式说明
PWM1递增CNT < CCR,通道输出有效电平,否则输出无效电平
PWM1递减CNT > CCR,通道输出无效电平,否则输出有效电平
PWM2递增CNT < CCR,通道输出无效电平,否则输出有效电平
PWM2递减CNT > CCR,通道输出有效电平,否则输出无效电平

4.4 PWM频率计算

频率 = (主时钟频率(72MHz) / (分频系数 + 1)) / 自动重装载值(单位为Hz)

五、通用定时器输出引脚

通道1通道2通道3通道4
TIM2PA0PA1PA2PA3
TIM3PA6PA7PB0PB1
TIM4PB6PB7PB8PB9
TIM5PA0PA1PA2PA3

六、实战项目

这里以一个经典项目——呼吸灯,来一起熟悉一下定时器的配置和使用,要求灭—>亮—>灭,时间为2.5s。

6.1 呼吸灯

呼吸灯是指灯能够像人的呼吸一样,实现由暗到亮或由亮到暗的变化,通常用于消息提示功能,或者作为系统正在运行的提示。之前一篇博文介绍过三种呼吸灯的实现方式,这里针对普中核心板,来介绍一下如果实现呼吸灯。

6.2 实现思路

这里用两种方法来实现一下呼吸灯。分别是定时器的溢出中断和PWM。其实第一种和PWM类似,我非就是控制LED点亮时间。

  • 定时器中断实现
    配置好预分频系数和重装载值,使每0.25ms进入一次定时器中断,记录进入中断次数(count)。当进入次数满100次之后(2.5ms),控制LED点亮的变量(t)值加1。主函数的while(1)轮询中,如果t小于等于count的时候,LED点亮,否则LED熄灭。t的值累计100加次后(2.5s),开始递减,LED由亮到灭。控制t是递增还是递减的是一个标志位(flag),初始值为0,具体可以看程序设计。
  • PWM
    利用PWM实现呼吸灯就更加简单了,只需要不断调节占空比即可。

6.3 定时器配置

配置通用定时器,有以下步骤

  • 使能定时器时钟
  • 初始化定时器参数,包括自动重装载值,分频系数,计数方式等
  • 设置中断类型,并使能
  • 设置中断优先级,使能定时器中断通道
  • 开启定时器
  • 编写定时器中断服务函数

需要注意的是,配置预分频系数时,比如设置为6,实际是6 + 1。

定时时间T = 自动重装载值 * ((预分频系数 + 1) / 主时钟频率)。主时钟频率为72MHz。
(为了避免误导,这里写的主时钟频率为72MHz是APB1总线分频系数不是1的前提下。)

6.4 定时器中断实现呼吸灯

定时器配置程序如下,使用定时器2,控制LED1实现呼吸灯,由灭—>亮—>灭,时间为5秒。

/*
 *==============================================================================
 *函数名称:TIM2_Iint
 *函数功能:初始化定时器2
 *输入参数:per:自动重装载值;psc:预分频系数
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void TIM2_Iint (u16 per,u16 psc)
{
	// 结构体定义
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	NVIC_InitTypeDef NVIC_InitStructure;
	
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);   // 使能TIM2时钟
	
	TIM_TimeBaseInitStructure.TIM_Period = per;   // 自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;   // 分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;   // 不分频
	TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up;   // 设置向上计数模式
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);   // 开启定时器中断
	TIM_ClearITPendingBit(TIM2,TIM_IT_Update);   // 使能更新中断
	
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;   // 定时器中断通道
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;   // 抢占优先级
	NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;   // 子优先级
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;   // IRQ通道使能
	NVIC_Init(&NVIC_InitStructure);	
	
	TIM_Cmd(TIM2,ENABLE);   // 使能定时器	
}

初始化时定时器的程序如下

TIM2_Iint(250,71);   // TIM2初始化

预分频系数为71 + 1 = 72,计数到250进入一次中断,也就是0.25ms进入一次中断。累计进入100次(25ms)中断开始调节一点LED的亮度。由灭到亮,累计调节100次(2.5s)。主函数和中断服务函数如下

u8 gTimIrqCunt = 0;   // 进入中断次数计数变量
u8 gLedLightCtrl = 0;   // LED亮度控制变量
u8 gLedFlag = 0;   // LED亮灭控制标志位,0:灭—>亮;1:亮—>灭

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		if (gLedLightCtrl <= gTimIrqCunt)
		{
			Med_Led_StateCtrl (LED1,LED_OFF);   // 熄灭LED1
		}
		if (gLedLightCtrl > gTimIrqCunt)
		{
			Med_Led_StateCtrl (LED1,LED_ON);   // 熄灭LED1
		}
	}
}

// TIM2中断服务函数
void TIM2_IRQHandler(void)   // TIM2中断
{
	// 产生更新中断
	if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
	{
		gTimIrqCunt = gTimIrqCunt + 1;   // 进入中断次数加1
		
		// 累计进入100次中断,且是由灭到亮
		if (gTimIrqCunt >= 100 && gLedFlag < 100)
		{
			gTimIrqCunt = 0;   // 清零进入中断计数变量
			gLedLightCtrl = gLedLightCtrl + 1;   // LED亮度控制变量加1
			gLedFlag = gLedFlag + 1;   // LED亮灭控制标志位加1
		}
		
		// 累计进入100次中断,且是由亮到灭
		if (gTimIrqCunt >= 100 && gLedFlag >= 100)
		{
			gTimIrqCunt = 0;   // 清零进入中断计数变量
			gLedLightCtrl = gLedLightCtrl - 1;   // LED亮度控制变量加1
			gLedFlag = gLedFlag + 1;   // LED亮灭控制标志位加1
		}
		
		// 一个亮灭周期结束
		if (gLedFlag >= 200)
		{
			gLedFlag = 0;   // 清零LED亮灭控制标志位
		}
	}
	
	TIM_ClearITPendingBit(TIM2, TIM_IT_Update);   // 清除TIM2更新中断标志
}

6.5 使用PWM实现呼吸灯

PWM配置步骤

  • 使能定时器以及GPIO时钟,设置引脚复用映射
  • 初始化定时器参数,包括自动重装载值,分频系数,计数方式等
  • 初始化PWM输出参数,包括PWM模式,输出极性,使能等
  • 开启定时器
  • 修改CCRx的值来修改占空比
  • 使能TIMx在CCRx上的预装载寄存器
  • 使能TIMx在ARR上的预装载寄存器允许位

TIM3的通道1配置程序如下

/*
 *==============================================================================
 *函数名称:TIM3_CH1_PWM_Init
 *函数功能:初始化定时器3的PWM通道1
 *输入参数:per:自动重装载值;psc:预分频系数
 *返回值:无
 *备  注:无
 *==============================================================================
 */
void TIM3_CH1_PWM_Init (u16 per,u16 psc)
{
	// 结构体定义
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	TIM_OCInitTypeDef TIM_OCInitStructure;
	GPIO_InitTypeDef GPIO_InitStructure;
	
	// 开启时钟
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
	
	// 初始化GPIO
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;   // 复用推挽输出
	GPIO_Init(GPIOC,&GPIO_InitStructure);
	
	GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);   // 改变指定管脚的映射	
	
	// 初始化定时器参数
	TIM_TimeBaseInitStructure.TIM_Period = per;   // 自动装载值
	TIM_TimeBaseInitStructure.TIM_Prescaler = psc;   // 分频系数
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;   // 设置向上计数模式
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStructure);	
	
	// 初始化PWM参数
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   // 比较输出模式
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;   // 输出极性
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   // 输出使能
	TIM_OC1Init(TIM3,&TIM_OCInitStructure);   // 输出比较通道1初始化
	
	TIM_OC1PreloadConfig(TIM3,TIM_OCPreload_Enable);   // 使能TIMx在 CCR1 上的预装载寄存器
	TIM_ARRPreloadConfig(TIM3,ENABLE);   // 使能预装载寄存器
	
	TIM_Cmd(TIM3,ENABLE);   // 使能定时器
		
}

实现呼吸灯时,只需要在main函数中不断调整占空比即可,调整占空比的函数为

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1)

这里main函数就不在列出来了。需要注意的是,设置的CCR的值,不能超过自动重装载值 - 1。

七、拓展

之前介绍按键检测时,介绍过检测按键长短按的方法。当时比较简单粗暴,这里介绍另一种,使用定时器来判断按键WK UP的长短按。假设规定,按下时间在10ms~500ms之间为短按,按下时间大于等于1s,为长按。短按LED1点亮,长按LED1熄灭。之前是利用delay来实现时间控制,现在改用定时器实现时间控制,但是基本思路都是相同的。

关于按键部分的程序这里就不再做介绍了。首先配置定时器,10ms进入一次更新中断,预分频系数为72,自动重装载值为10000。使用TIM2,定时器配置程序和上面一样,初始化程序如下填写

TIM2_Iint(10000,71);   // TIM2初始化

main函数以及中断服务函数如下

u32 gKeyDownTimeCunt = 0;   // 按键按下时间计数变量
u8 gKeyLongFlag = 0;   // 按键长按标志位
u8 gKeyShotFlag = 0;   // 按键短按标志位

int main(void)
{
	Med_Mcu_Iint();   // 系统初始化
	
	while(1)
  {
		// 短按
		if (gKeyShotFlag == 1)
		{
			Med_Led_StateCtrl (LED1,LED_ON);   // 点亮LED1
			gKeyShotFlag = 0;   // 清除短按标志位
		}
		
		// 长按
		if (gKeyLongFlag == 1)
		{
			Med_Led_StateCtrl (LED1,LED_OFF);   // 熄灭LED1
			gKeyLongFlag = 0;   // 清除长按标志位
		}
	}
}

// TIM2中断服务函数
	void TIM2_IRQHandler(void)   // TIM2中断
	{
		// 产生更新中断
		if (TIM_GetITStatus(TIM2, TIM_IT_Update) != RESET)
		{
			if (KEY_UP == 1)
			{
				gKeyDownTimeCunt = gKeyDownTimeCunt + 1;   // 时间计数变量加1
			}
			// 松开后
			else
			{
				// 短按
				if (1 <= gKeyDownTimeCunt && gKeyDownTimeCunt <= 50)
				{
					gKeyDownTimeCunt = 0;   // 清除时间计数变量
					gKeyShotFlag = 1;   // 短按标志位置1
				}
				// 长按
				if (gKeyDownTimeCunt >= 100)
				{
					gKeyDownTimeCunt = 0;   // 清除时间计数变量
					gKeyLongFlag = 1;   // 长按标志位置1
				}
			}
		}
		
		TIM_ClearITPendingBit(TIM2, TIM_IT_Update);   // 清除TIM2更新中断标志
	}

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

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

相关文章

【Python 随练】打印菱形图案

题目&#xff1a; 打印出如下图案&#xff08;菱形&#xff09; ********* ****************简介&#xff1a; 在本篇博客中&#xff0c;我们将使用Python代码打印一个菱形图案。我们将提供问题的解析&#xff0c;并给出一个完整的代码示例来生成这个菱形图案。 问题分析&am…

阿里云开源离线同步工具DataX3.0,用于数据仓库、数据集市、数据备份

DataX是阿里云开源的一款离线数据同步工具&#xff0c;支持多种数据源和目的地的数据同步&#xff0c;包括但不限于MySQL、Oracle、HDFS、Hive、ODPS等。它可以通过配置文件来定义数据源和目的地的连接信息、数据同步方式、数据过滤等&#xff0c;从而实现数据的高效、稳定、可…

C++初阶—完善适配器(反向迭代器)

目录 0. 前言 1、反向迭代器定义 2、反向迭代器需要实现的相关函数 3、反向迭代器分析 4、针对vector物理空间结构分析 5、针对list物理空间结构分析 6、反向迭代器适配器的实现及测试 0. 前言 本篇文章主要根据前面所实现的STL中支持迭代器的容器进行完善&#xff0c;使…

Mysql数据库日志和数据的备份恢复(去看一看海吧)

文章目录 一、数据库备份的重要性二、数据库备份的分类1.物理备份&#xff1a;对数据库操作系统的物理文件&#xff08;如数据文件、日志文件等)的备份。2.逻辑备份&#xff1a;对数据库逻辑组件&#xff08;如表等数据库对象&#xff09;的备份&#xff0c;导出sql文件。3.完全…

被卖到 2w 的 ChatGPT 提示词 Prompt 你确定不想要吗?

有朋友说&#xff0c;用 ChatGPT 生成的文案刻板化&#xff0c;格式化&#xff0c;而且往往也不是我想要的。‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 想要用好 ChatGPT 人工智能工具太难了&#xff0c;想一个好的提示词&#xff0c;也太不容易了&#xff0c;ChatGPT 就像一个宝藏…

3ds MAX绘制休闲椅

首先绘制一个长方形&#xff0c;并用上边两端点和底边中点绘制一个样条曲线 将上述曲线旋转复制&#xff0c;形成一个交叉的样条曲线&#xff0c;并移动两端点的位置&#xff0c;形成一上一下的结构 这就是休闲椅的大致形状 通过创建线将四个端点连接起来&#xff0c;形成空间…

UI组件——滑块简介

滑块控件是调整音量和亮度等设置的首选解决方案。它们立即生效&#xff0c;并允许用户通过移动手柄来微调值。滑块可以很好地达到目的&#xff0c;尤其是在精度不是很重要的情况下。 但是&#xff0c;这些控件可能会令人困惑&#xff0c;难以抓取并设置为精确值。另外&#xf…

人类智能的未来在于东西方智能的融合

有人认为&#xff1a;“只有时空的对齐&#xff0c;没有价值的对齐&#xff0c;智能或许就是智障”&#xff0c;即智能技术必须要与人类的价值观念和道德标准相一致&#xff0c;否则它所产生的结果可能会对人类社会造成负面影响。在现代社会中&#xff0c;智能技术已经越来越广…

【Elacticsearch】 分片副本机制,集群发现机制 ,负载机制,容错机制,扩容机制, 分片路由原理

集群发现机制 Elasticsearch采用了master-slave模式&#xff0c; ES会在集群中选取一个节点成为主节点&#xff0c;只有Master节点有资格维护全局的集群状态&#xff0c;在有节点加入或者退出集群的时候&#xff0c;它会重新分配分片&#xff0c;并将集群最新状态发送给集群中其…

Netty中的零拷贝机制

零拷贝机制(Zero-Copy)是在操作数据时不需要将数据从一块内存区域复制到另一块内存区域的技术,这样就避免了内存的拷贝,使得可以提高CPU的。零拷贝机制是一种操作数据的优化方案,通过避免数据在内存中拷贝达到的提高CPU性能的方案。 1.操作系统的零拷贝机制 操作系统的存储空间…

C++基础(5)——类和对象(3)

前言 本文主要介绍了C中类和对象的基本知识 4.3.1&#xff1a;成员变量和成员函数分开存储 只有非静态成员变量才属于类的对象上 C语言中结构体为空时使用sizeof&#xff08;&#xff09;打印的结果是0 C中类和结构体为空&#xff0c;用sizeof关键字可以算出是空类占1字节、…

OpenCV项目开发实战--图像识别和目标检测之(手写数字分类)

文末附基于Python和C++两种方式实现的测试代码下载链接 在本教程中,我们将使用 OpenCV 构建一个简单的手写数字分类器。一如既往,我们将分享用 C++ 和 Python 编写的代码。 最后两个帖子旨在提供了解基础知识所需的教育。这篇文章旨在提供成功实施图像分类器所需的培训。那么…

SpringBoot集成阿里云OSS实现图片存储服务

SpringBoot集成阿里云OSS实现图片存储服务 1、OSS概述2、账号申请2.1 购买服务2.2 创建Bucket 3、抽取模板工具OssProperties配置类OssTemplate模板对象AutoConfiguration配置类yml配置内容 4、测试 阿里云OSS&#xff08;Object Storage Service&#xff09;是一种强大的云存储…

ASO优化之关于应用商店的展示量

应用的展示数据代表应用在整个应用市场内的曝光次数&#xff0c;被展示的位置包括&#xff1a;首页精品推荐&#xff0c;搜索结果列表&#xff0c;应用详情页等。 应用的展示数据是衡量ASO搜索优化的关键指标。当关键词的覆盖数增加了&#xff0c;展示的次数没有增加&#xff…

【Nacos源码系列】服务注册的原理

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站。 文章目录 Nacos介绍服务注册客户端注册服务端 总结 Nacos介绍 Nacos是一个基于云原生的动态服务发现、配置管理和服务治理平台&#xff…

cppzmq编译和使用(ubuntu22.04)

libzmq libzmq&#xff0c;也称为 ZeroMQ&#xff0c;是一个高性能、异步消息传递库&#xff0c;用于构建分布式和并发系统。它提供了简单而强大的原语&#xff0c;使得开发者可以方便地在应用程序之间进行异步通信。 以下是对 libzmq 的详细介绍&#xff1a; 简介&#xff1…

VOC数据洞察在淘宝详情页的应用与实践

本专题共10篇内容&#xff0c;包含淘宝APP基础链路过去一年在用户体验数据科学领域&#xff08;包括商详、物流、性能、消息、客服、旅程等&#xff09;一些探索和实践经验&#xff0c;本文为该专题第二篇。 在商详页基于用户动线和VOC挖掘用户决策因子带来浏览体验提升&#x…

如何使用 PowerPoint 2021 制作演示文稿(PPT)?

软件安装&#xff1a;办公神器office2021安装教程&#xff0c;让你快速上手_正经人_____的博客-CSDN博客 引言 PowerPoint 是一款非常常用的演示文稿制作工具&#xff0c;它可以帮助您创建漂亮的幻灯片&#xff0c;展示您的想法和信息。如果您是 PowerPoint 的新手&#xff…

如何选择初始化向量【密码学】(5)

目录 一、分组算法如何计算 二、什么影响算法的安全性 三、密钥的使用次数限制 一、分组算法如何计算 分组算法包括3个部分&#xff1a;数据分组&#xff0c;分组运算和链接模式。 数据分组&#xff1a;将数据分割成加密函数能够处理的数据块&#xff0c;如果不能整分&#x…

【MYSQL篇】mysql不同存储引擎中索引是如何实现的?

前言 不同的存储引擎文件是不一样&#xff0c;我们可以查看数据文件目录&#xff1a; show VARIABLES LIKE datadir;每 张 InnoDB 的 表 有 两 个 文 件 &#xff08; .frm 和 .ibd &#xff09;&#xff0c; MyISAM 的 表 有 三 个 文 件 &#xff08;.frm、.MYD、.MYI&…