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

STM32-TIM定时中断(6)

目录

一、TIM介绍

1、TIM简介

2、定时器类型

3、基本定时器

4、通用定时器

5、定时中断基本结构

6、时基单元的时序

(1)预分频器时序

(2)计数器时序

7、RCC时钟树

二、定时器输出比较功能(PWM)

1、PWM波形介绍

2、PWM的基本结构

3、PWM的参数计算

三、定时器输入捕获(测频率和占空比)

1、频率测量

2、主从触发模式

3、输入捕获基本结构

4、PWMI基本结构

四、定时器的编码器接口

1、编码器接口简介

2、正交编码器

3、编码器接口的基本结构


一、TIM介绍

1、TIM简介

TIM(Timer)定时器 

定时器的基本功能:定时器可以对输入的时钟进行计数,并在计数值达到设定值时触发中断。

即定时触发中断,同时也可以看出,定时器就是一个计数器,当这个计数器的输入是一个准确可靠的基准时钟的时候, 那它在对这个基准时钟进行计数的过程,实际上就是计时的过程。

比如在STM32中,定时器的基准时钟一般都是主频72MHz,如果对72MHz计72个数,计1个数的周期那就是1MHz,1/1MHz=0.000001s,也就是1us的时间,如果对72MHz计72000个数,计1个数的周期那就是1KHz,1/1KHz=0.001,也就是1ms的时间。

STM32的定时器拥有16位计数器、预分频器、自动重装寄存器的时基单元,在72MHz计数时钟下可以实现最大59.65s的定时,STM32是16位的,因此如果预分频器设置最大,自动重装也设置最大,2的16次方就是65536,即1/(72MHz/65536/65536) = 59.65s。

这里计数器就是用来执行计数定时的一个寄存器,每来一个时钟,计数器加1。

预分频器,可以对计数器的时钟进行分频,让这个计数更加灵活。

自动重装寄存器就是计数的目标值,就是想要计多少个时钟申请中断。

这些寄存器构成了定时器最核心的部分,我们把这一块电路称为时基单元。

STM32的定时器,不仅具备基本的定时中断功能,而且还包含内外时钟源选择、输入捕获、输出比较、编码器接口、主从触发模式等多种功能。

以上功能分为四个部分介绍:

第一部分是定时器中断和内外时钟源选择的功能;

第二部分是输出比较;

第三部分输入捕获和主从触发模式;

第四部分是编码器接口。

文章主要就是介绍第一部分,定时器中断和内外时钟源选择的功能。

STM32的定时器,根据复杂程度和应用场景分为了高级定时器、通用定时器和基本定时器三种类型。

其中高级定时器最复杂,通用定时器中等复杂但最常用,基本定时器最简单,本篇文章主要就是介绍通用定时器。

2、定时器类型

STM32F103C8T6内部拥有的定时器资源是:TIM1、TIM2、TIM3、TIM4,即一个高级定时器,3个通用定时器,没有基本定时器。

不同的芯片型号,拥有的定时器资源是不同的

3、基本定时器

基本定时器拥有定时中断和主模式触发DAC的功能。

预分频器之前,连接的就是基准计数时钟的输入,由于基本定时器只能选择内部时钟,所以可以直接认为预分频器的输入是由内部时钟过来的,内部时钟的来源是RCC_TIMxCLK,这里的频率值一般都是系统的主频72MHz,所以通向时基单元的计数基准频率就是72MHz。

接下来看下面部分,由三个最重要的寄存器组成,分别是计数器、预分频器、自动重装寄存器,它们构成了最基本的计数计时电路,所以这一块电路就叫做时基单元。

预分频器可以对72MHz的计数时钟进行预分频,比如预分频器写0,那就是不分频,或者说是1分频,这时候输出频率=输入频率=72MHz,如果预分频器写1,那就是2分频,,输出频率=输入频率/2=36MHz,如果预分频写2,就是3分频,输出频率=输入频率/3=24MHz,以此类推,所以预分频器的值和实际的分频系数相差了1,即实际分频系数=预分频器的值+1,这个预分频器是16位的,所以最大值可以写65535,也就是65536分频。

计数器可以对预分频后的计数时钟进行计数,计数时钟每来一个上升沿,计数器的直接就加1,这个计数器也是16位的,所以里面的值可以从0一直加到65535,如果再加,计数器就会回到0重新开始,计数器的值是在计时过程中会不断地自增运行,当自增运行到目标值时,产生中断,那就完成了定时任务。

所以还需要一个存储目标值的寄存器,那就是自动重装寄存器,自动重装寄存器也是16位的,它存的就是我们写入的计数目标,在运行的过程中,计数值不断自增,自动重装值是固定的目标,当计数值等于自动重装时,也就是计时时间到了,那它就会产生一个中断信号,并且清零计数器,计数器自动开始下一次的计数计时。

图里面右下角画的一个向上的折线箭头UI,就代表这里会产生中断信号,像这种计数值等于自动重装值产生的中断,一般称作为“更新中断”,这个更新中断之后就会通往NVIC,我们再配置好NVIC的定时器通道,那定时器的更新中断就能够得到CPU的响应了。

右下角画的向下的箭头U,代表的是会产生一个事件,这里对应的事件就叫做“更新事件”,更新事件不会触发中断,但可以触发内部其他电路的工作。

以上这些,就是定时器定时中断的全部流程了。

4、通用定时器

通用定时器除了基本定时器的功能外,计数器的计数模式就不止向上计数(计数器从0开始,向上自增,计数到重装值,清零同时申请中断)这一种了,还支持向下计数模式和中央对齐模式。

向下计数模式,就是从重装值开始,向下自减,减到0之后,回到重装值同时申请中断,然后继续下一轮,依次循环,这就是向下计数。

中央对齐的计数模式,就是从0开始,先向上自增,计数到重装值,申请中断,然后再向下自减,计数到重装值,再申请中断,然后继续下一轮,依次循环,这就是中央对齐模式。

在中间时基单元的上方,是内外时钟源选择和主从触发模式的结构。

先看内外时钟源选择,对于基本定时器而言,定时只能选择内部时钟,也就是系统频率72MHz,对于通用定时器,时钟源不仅可以选择内部的72MHz时钟,还可以选择外部时钟。

具体包括:
        第一个外部时钟就是来自TIMx_ETR引脚上的外部时钟,参考引脚定义表可知,可以看到PA0处有TIM2_CH1_ETR功能,意思是这个TIM2的CH1和ETR都是复用在了PA0引脚位置。              可以在TIM2的ETR引脚,也就是PA0上接一个外部方波时钟,然后配置一下内部的极性选择、边沿检测和预分频电路,再配置一下输入滤波电路,这两块电路可以对外部时钟进行一定的整形,因为是外部引脚的时钟,所以难免会有些毛刺,那这些电路就可以对输入的波形进行滤波,最后,滤波后的信号,兵分两路,上面一路ETRF进入触发控制器,紧跟着就可以选择作为时基单元的时钟了。                                                                                                                                              如果想在ETR外部引脚提供时钟,或者想对ETR时钟进行计数,把这个定时器当作计数器来用的话,那就可以配置这一路的电路,在STM32中,这一路也叫做“外部时钟模式2”。

除了外部引脚ETR可以提供时钟外,下面还有一路可以提供时钟,就是TRGI(Trigger In),这一路从名字上来看的话,主要作用是用作触发输入来使用的,这个触发输入可以触发定时器的从模式,也可以作为外部时钟来使用,当TRGI当作外部时钟使用时,这一路就叫做“外部时钟模式1”。

具体有哪些外部时钟通过TRGI这一路,首先是ETR引脚的信号,这里ETR引脚的信号既可以通过ETRF上面一路来当作时钟,又可以通过TRGI下面一路来当作时钟,两种情况对于时钟输入而言是等价的,只不过是下面这一路输入会占用触发输入的通道而已。

其次就是ITR信号,这一部分的时钟信号是来自其他定时器,从右边可以看出,这个主模式的输出TRGO可以通向其他定时器,通向其他定时器的时候,就接到了其他定时器的ITR引脚上来了。左边输入的ITR0和ITR3分别来自其他4个定时器的TRGO输出,定时器的ITRx和定时器TIMx的TRGO连接方式如下图所示。
通过这一路,就可以实现定时器级联的功能。比如,可以先初始化TIM3,然后使用主模式把它的更新事件映射到TRGO上,接着再初始化TIM2,这里选择ITR2,对应的就是TIM3的TRGO,然后后面再选择时钟为外部时钟模式1,这样TIM3的更新事件就可以驱动TIM2的时基单元,也就实现了定时器的级联。

 最后,还可以选择TI1F_ED信号,这里连接的是下面的输入捕获单元的CH1引脚,也就是从CH1引脚获得时钟,后缀ED(edge)就是边沿的意思,通过TIMx_CH1这一路输入的时钟,上升沿和下降沿均有效,最后这个时钟还可以通过TI1FP1和TI2FP2获得。

在中间时基单元的下方,包含了两块电路,右边一块是输出比较电路,总共有四个通道,分别对应CH1到CH4的引脚,可以用于输出PWM波形、驱动电机;左边一块是输入捕获电路,也是四个通道,可以用于测量输入方波的频率等;中间的一个寄存器是捕获/比较寄存器,是输入捕获和输出比较电路共用的,因为输入捕获和输出比较不能同时使用,所以这里的寄存器是共用的,引脚也是共用的。

5、定时中断基本结构

首先时基单元下方的运行控制,就是控制寄存器的一些位,比如启动停止、向上或向下计数等等,操作这些寄存器就能控制时基单元的运行。

中间黄色块及左边区域,是为时基单元提供时钟的部分,这里可以选择RCC提供的内部时钟,也可以选择ETR引脚提供的外部时钟模式2,还可以选择触发输入,当做外部时钟模式1,对应的有ETR外部时钟、ITRx其他定时器、TIx输入捕获通道,这些就是定时器所有可选的时钟源了。
最后的编码器模式是编码器独用的模式,普通的时钟用不到这个。

时基单元的右边,就是计时时间到,产生更新中断后的信号去向,中断信号会在状态寄存器里置一个中断标志位, 这个标志位会通过中断输出控制,到NVIC申请中断。中断输出控制就是一个中断输出的允许位,如果需要某个中断,才打开允许位。

6、时基单元的时序

(1)预分频器时序

CK_PSC:预分频器的输入时钟,选内部时钟一般是72MHz;

CN_EN:计数器使能,高电平计数器正常运行,低电平计数器停止;

CK_CNT:计数器时钟,它既是预分频器的时钟输出,也是计数器的时钟输入。
计数器未使能时,计数器时钟不运行,使能后,前半段,预分频系数为1,计数器的时钟等于预分频器的时钟,后半段,预分频器系数变为2了,计数器的时钟也变为之前的一半了。

计数器寄存器:在计数器时钟的驱动下,计数器寄存器也跟随时钟的上升沿不断自增。

自动重装值是FC,当计数值计数到和重装值相等时,在下一个时钟来临时,计数值才清零,同时下面产生一个更新事件,这就是一个计数周期的工作流程。

在计数计到一半时,改变了预分频控制寄存器的分频值,这个变化不会立刻生效,而是会等到本次计数周期结束时,产生了更新事件,预分频控制寄存器的值才会被传递到缓冲寄存器里面去,变化才会生效。

预分频计数器:预分频器内部实际上也是靠计数来分频的,当预分频值为0时,计数器就一直为0,直接输出原频率,当预分频器为1时,计数器就0、1、0、1这样计数,再回到0的时候,输出一个脉冲,这样输出频率就是输入频率的2分频,预分频器的值(PSC)和实际的分频系数之间有一个数的偏移,计数器时钟= 72MHz / (预分频器值 + 1)。

(2)计数器时序

CK_INT:内部时钟72MHz

CNT_EN:时钟使能,高电平启动

CK_CNT:计数器时钟,因为分频系数为2,所以这个频率是内部时钟频率的二分之一

计数器寄存器:在计数器时钟每个上升沿时自增

自动重装初值为0036,因此在0036后的一个计数器时钟上升沿处,计数器寄存器清零,计数器溢出,产生一个更新事件脉冲UEV,还会置一个更新中断标志UIF,这个标志位只要置1,就会申请中断,中断响应后,需要在中断程序中手动清零。

计数器溢出频率=72MHz/(预分频器值+1)/(自动重装值+1),溢出时间=1/计数器溢出频率

通过设置ARPE位,就可以选择是否使用预装功能。

计数器无预装时序时

改变自动重装初值为36时,计数器寄存器计到36就会计数器溢出,直接更新事件,开启下一轮计数。

计数器有预装时序时

在计数中途,将自动重装值由F5改成36,在本轮计数目标仍然会是F5,计数器寄存器会计数到F5后,计数器溢出,更新事件,影子寄存器才会将自动重装值由F5改成36,开启下一轮计数的自动重装值才会变成36。

引入影子(缓存)寄存器,是为了让值的变化和更新事件,同步发生,防止在运行途中更改造成错误。

7、RCC时钟树

在程序中主函数之前,程序还会执行一个SystemInit函数,这个函数就是用来配置时钟树的。

图中左边部分都是时钟的产生电路,右边的都是时钟的分配电路,中间的SYSCLK就是系统时钟72MHz。

在时钟产生电路中,有四个震荡源,分别是内部的8MHz高速RC振荡器(HSI RC);外部的4-16MHz高速石英晶体振荡器,也就是晶振(HSE OSC),一般接8MHz;外部的32.768KHz低速晶振(LSE OSC),这个一般是给RTC提供时钟的;最后是内部的40KHz低速RC振荡器(LSI RC),这个可以给看门狗提供时钟。

上面两个高速晶振,是用来提供系统时钟的,AHB、APB2、APB1的时钟都来源于这两个高速晶振,外部的石英振荡器比内部的RC振荡器相对来说更加稳定一些,所以一般都用外部晶振,如果系统简单,而且不需要那么精确的时钟,也可以用内部RC振荡器,这样就可以省下外部晶振的电路。

在SystemInit函数里,ST公司是按下面这样来配置时钟的。首先会启动内部时钟,选择内部8MHz为系统时钟,暂时以内部8MHz的时钟运行,然后再启动外部时钟,配置外部时钟如上图所示,进入PLLXTPRE锁相环进行倍频,8MHz倍频9倍,得到72MHz,等到锁相环输出稳定后,选择锁相环输出为系统时钟,这样就把系统时钟由8MHz切换成了72MHz。 

CSS是时钟安全系统,它也是负责切换时钟的,它可以监测外部时钟的运行状态,一但外部时钟失效,它就会自动把外部时钟切换回内部时钟,保证系统时钟的运行,防止程序卡死造成事故。外部时钟和内部时钟时间差了大概10倍左右。

在时钟分配电路中,首先系统时钟72MHz进入AHB总线,AHB总线有一个预分频器,在SystemInit里配置的分配系数是1,因此AHB的时钟就是72MHz,然后进入APB1总线,这里配置的分频系数为2,所以APB1总线的时钟就是36MHz,由下面的电路,时钟频率又乘2,因此APB1总线的时钟也是72MHz,所以无论是高级、通用还是基本定时器,它们的内部基准时钟都是72MHz。

二、定时器输出比较功能(PWM)

输出比较简称OC(Output Compare),输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。

CNT是计数器,CCR是捕获/比较寄存器,当CCR为比较寄存器时,CNT计数自增的值会与CCR中的给定值相比较,当CNT的值小于、等于或大于CCR中给定值时,CCR就会输出对应的置1、置0、置1、置0,这样就可以输出一个电平不断跳变的PWM波形,这就是输出比较的基本功能。 

每个高级定时器和通用定时器都拥有4个输出比较通道,但是它们是共用一个CNT计数器的。

1、PWM波形介绍

脉冲宽度调制简称PWM(Pulse Width Modulation),在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,即通过输入数字量,来得到输出模拟量,常应用于电机控速等领域。

PWM参数

T_S:周期,T_ON:高电平,T_OFF:低电平
频率 = 1 / T_S            占空比 = T_ON / T_S           
分辨率 = 占空比变化步距(分辨率为1%,则占空比按1%、2%、3%变化)

输出比较的8个模式


其中有效电平就是指高电平,无效电平就是指低电平。
这里主要使用PWM模式1中的向上计数。

2、PWM的基本结构

PWM初始化配置
(1)RCC开启TIM外设和GPIO的时钟;
(2)配置时钟源;
(3)配置时基单元;
(4)配置输出比较单元,包括CCR的值,输出比较模式、极性选择和输出使能;
(5)配置GPIO口,把PWM对应的GPIO口,初始化为复用推挽输出;
(6)运行控制,启动计数器。


配置好时基单元后,CNT就会不断自增运行,CCR是给定值,CNT和CCR会不断比较,后面的输出模式控制器采用PWM模式1,向上计数方式。

当CNT<CCR时,REF参考值输出高电平;当CNT≥CCR时,REF参考值输出低电平。

上图中,黄色线是ARR自动重装器的值,蓝色线是CNT计数器不断自增的值,红色线是CCR中给定值。
假设给ARR=99,CCR=30时,当CNT=0~29,输出高电平给GPIO;当CNT=30~99,输出低电平给GPIO。这样就能通过这三个寄存器的值来调控PWM的频率和占空比了。

3、PWM的参数计算

PWM频率:  Freq = CK_PSC / (PSC + 1) / (ARR + 1)
PWM占空比:  Duty = CCR / (ARR + 1)
PWM分辨率:  Reso = 1 / (ARR + 1)

CK_PSC:预分频器的输入时钟,选内部时钟一般是72MHz;
PSC:预分频器的值
ARR:自动重装器的值
CCR:比较器的值

三、定时器输入捕获(测频率和占空比)

输入捕获简称IC(Input Capture),输入捕获模式下,当通道输入引脚出现指定电平跳变时,当前CNT(计数器)的值将被锁存到CCR(捕获寄存器)中,可用于测量PWM波形的频率(脉冲间隔)、占空比(电平持续时间)等参数。

每个高级定时器和通用定时器都拥有4个输入捕获通道。
可配置为PWMI模式,同时测量频率和占空比;
可配合主从触发模式,实现硬件全自动测量(在CNT值存到CCR中后,将CNT清零)。

1、频率测量

测频法(适合测量高频信号):在闸门时间T内,对上升沿计次,得到N,则频率:

测周法(适合测量低频信号):两个上升沿内,以标准频率fc计次,得到N ,则频率:

中界频率:测频法与测周法误差相等的频率点:

当信号频率大于中界频率时,采用测频法;当信号频率小于中界频率时,采用测周法。

本次实验测量PWM信号的频率和占空比采用的是测周法。
上升沿用于触发输出捕获,CNT用于计数计时,每来一个上升沿,就取CNT的值,自动存在CCR里, CCR捕获到的值就是计次N,CNT的驱动时钟就是标准频率fc(72M/预分频系数),通过fc/N就能得到信号频率。

每次捕获CNT的值存在CCR中后,都要将CNT清零,这样下次上升沿再捕获的时候,取出的CNT才是两个上升沿的时间间隔。


2、主从触发模式

主从触发模式:为主模式、从模式和触发源选择三个模式的简称。

主模式可以将定时器内部的信号,映射到TRGO引脚,用于触发别的外设;
从模式就是接收其他外设或者自身外设的一些信号,用于控制自身定时器的运行,也就是被别的信号所控制;
触发源选择就是选择从模式的触发信号源,选择指定的一个信号,得到TRGI去触发从模式,然后从模式就可以在列表中选择一项来自动执行,也可以认为触发源选择是从模式的一部分。 

因此为了使捕获CNT的值存在CCR中后,将CNT清零操作,触发源选择TI1FP1,然后从模式执行的操作选择Reset,这样TI1FP1的信号就可以自动触发从模式,从模式自动清零CNT。

3、输入捕获基本结构

这里只使用了一个输入捕获通道,只能测量频率。

首先将右上角的时基单元配置好,启动定时器,CNT就会开始自增。
从GPIO会输入一个左上角的方波信号,经过滤波器和边沿检测,选择TIFP1为上升沿触发,之后输入选择直连的通道,分频器选择不分频,当TIFP1出现上升沿时,CNT的当前计数值存到CCR1里;之后触发源选择,选中TIFP1为触发信号,从模式选择复位操作,这样TIFP1的上升沿就会通过上面的Reset去触发CNT清零。

计算信号频率:f=标准频率fc(72M/预分频系数)/N(CCR)

4、PWMI基本结构

PWMI模式使用两个通道同时捕获一个引脚,可以同时测量周期和占空比。

TI1FP1配置上升沿触发,触发捕获和清零CNT;
TI1FP2配置下降沿触发,通过交叉通道,去触发通道2的捕获单元。
如左上角图所示,第一个上升沿是TI1FP1触发上升沿,将CNT值存在CCR1中,之后CNT清零;第一个下降沿,就是TI1FP2触发,将这时的CNT值存到CCR2中,这里的CNT值就是高电平期间的计数值,并不触发CNT清零。
所以CCR2就是高电平期间的计数值,CCR1就是一整个周期的计数值。

占空比=CCR2/CCR1

输入捕获模式初始化配置:
(1)RCC开启时钟,将TIM和GPIO的时钟打开;
(2)GPIO初始化,把GPIO配置成输入模式,一般选择上拉输入或浮空输入;
(3)配置时基单元,让CNT计数器在内部时钟的驱动下自增运行;
(4)配置输入捕获单元,包括滤波器、极性、直连通道还是交叉通道、分频器这些参数;
(5)选择从模式的触发源,触发源选择为TI1FP1;
(6)选择触发之后的操作,执行Reset操作;
(7)调用TIM_Cmd函数,开启定时器。 

四、定时器的编码器接口

触发外部中断手动计次(5-2程序):当电机高速旋转时,每秒产生成千上万个脉冲,程序就得频繁中断,进中断后,完成的任务又只是简单得加1减1,软件资源就会被简单又低级的工作占用了,所以对于需要频繁执行,操作又比较简单的任务,一般都会设计一个硬件电路模块来自动完成。因此采用定时器的编码器接口自动计次(6-8程序),会更好的利用软件资源。

1、编码器接口简介

编码器接口(Encoder Interface),可接收增量(正交)编码器的信号,根据编码器旋转产生的正交信号脉冲,自动控制CNT自增或自减,从而指示编码器的位置、旋转方向和旋转速度。

每个高级定时器和通用定时器都拥有1个编码器接口,两个输入引脚借用了输入捕获的通道1和通道2。

2、正交编码器

当编码器的旋转轴转起来时,A相和B相就会输出上图所示的方波信号给STM32,转的越快,这个方波的频率就越高,所以频率就代表了速度,取出任意相的信号来测频率,就能得到旋转速度。但是只有一相的信号时,无法测出旋转方向。

编码器接口的设计逻辑
首先把A相和B相的所有边沿作为计数器的计数时钟,出现边沿信号时,就计数自增或自减,具体是增还是减就需要靠另一项状态来决定。当出现某个边沿时,判断另一相的高低电平,如果另一项状态为上表中,则判断为正传,计数自增;反之,当出现某个边沿时,另一项的状态符合下表,则判断为反转,计数自减。

TI1FP1对应A相,TI1FP2对应B相。相对信号的电平对应另一相的高低电平。
向上计数意思就是正传,向下计数意思就是反转。

仅在T1计数,意思是只在A相上升沿和下降沿的时候计数,不考虑B相;
仅在T2计数,意思是只在B相上升沿和下降沿的时候计数,不考虑A相;
在T1和T2计数,意思是同时考虑A相和B相的上升沿和下降沿时候计数。**(一般使用这个模式,精度最高)**

采用在T1和T2同时计数时,下面是实例(均不反相)。
中间的毛刺就是噪声,通过检测A相和B相两个方波信号,可以滤掉噪声。

采用在T1和T2同时计数时,下面是实例(反相)。
这里的TI1信号是反相的,需要将TI1高低电平取反之后,查表才是正确的。
如果接一个编码器,发现数据的加减方向反了,这时候就可以调整以下极性,把任意一个引脚反相,就能反转计数方向了,或者也可以将A相和B相的引脚换一下,也可以改变极性。


3、编码器接口的基本结构

(1)RCC开启时钟,开启GPIO和定时器时钟;
(2)配置GPIO口,需要把PA6和PA7配置成输入模式;
(3)配置时基单元,预分频器一般选择不分频,自动重装其ARR一般给最大值65535,只需要CNT执行计数就可以了;
(4)配置输入捕获单元,只有滤波器和极性两个参数有用到;
(5)配置编码器接口模式;
(6)启动定时器。 
 

相关文章:

STM32-TIM定时中断(6)

目录 一、TIM介绍 1、TIM简介 2、定时器类型 3、基本定时器 4、通用定时器 5、定时中断基本结构 6、时基单元的时序 &#xff08;1&#xff09;预分频器时序 &#xff08;2&#xff09;计数器时序 7、RCC时钟树 二、定时器输出比较功能&#xff08;PWM&#xff09; …...

Godot4.3类星露谷游戏开发之【昼夜循环】

千里之行&#xff0c;始于足下 文章目录 零、 笔记一、创造时间二、产生颜色三、搭建测试环境四、测试五、免费开源资产包 零、 笔记 为了让游戏可以拥有白天和黑夜&#xff0c;我们需要像上帝一样&#xff0c;在游戏中创造时间的规则&#xff0c;并在不同的时间点产生不同的颜…...

工业与协议融合篇:如何将多个协议集成进一个系统?

🏭 本文为《嵌入式通信协议全解析》第六篇,深入探讨如何在工业或物联网系统中同时集成 BLE、CAN、LoRa、MQTT、RS485 等多种通信协议,实现一个高效、可控、稳定运行的嵌入式通信架构。 🧭 一、为什么需要多协议融合? 在真实产品中,单一通信协议往往无法满足所有业务需…...

java-----------------多态

多态&#xff0c;当前的成指的是 java 所呈现出来的一个对象 多态 定义 多态是指同一个行为具有多个不同表现形式或形态的能力。在面向对象编程中&#xff0c;多态通过方法重载和方法重写来实现。 强弱类型语言 javascript 或者python 是弱类型语言 C 语言&#xff0c;或…...

vLLM部署Qwen2-7B模型推理

vllm简介 vLLM是一个高效的大语言模型推理和部署服务系统&#xff0c;专为大型语言模型的高效执行而设计。它不仅支持多种量化技术以减少模型大小和加速推理过程&#xff0c;还提供了与OpenAI API兼容的服务接口&#xff0c;使得现有的应用程序能够无缝对接。 一、前提环境 …...

SSL证书格式详解:PEM、CER、DER、JKS、PKCS12等

引言 在网络安全领域&#xff0c;SSL/TLS证书是保障互联网通信安全的核心工具。它们通过加密连接&#xff0c;确保服务器与客户端之间的数据隐私和完整性。然而&#xff0c;对于初学者来说&#xff0c;SSL证书的多种格式——PEM、CER、JKS、PKCS12、PFX等——常常令人困惑。每…...

idea spring boot 打包成可执行的 JAR包

idea 2023 spring boot 2.6.13 打包成可执行的 JAR包 创建一个 简单的 spring boot 程序 idea File — New — Project 11 22 11 package com.example.demo.controller;import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.b…...

设计模式-迭代器模式

写在前面 Hello&#xff0c;我是易元&#xff0c;这篇文章是我学习设计模式时的笔记和心得体会。如果其中有错误&#xff0c;欢迎大家留言指正&#xff01; 案例 假设有一个Book类和一个管理书籍的BookCollection类&#xff0c;我们需要遍历BookCollection类中所有书籍信息。 一…...

Java 匿名内部类的作用

简化代码&#xff1a;无需专门定义一个具名类来实现接口或继承类&#xff0c;减少类文件数量&#xff0c;在只需简单实现特定功能时&#xff0c;让代码更简洁紧凑 。比如创建线程时&#xff0c;使用匿名内部类实现 Runnable 接口&#xff0c;直接在代码块中编写线程执行逻辑&am…...

MySQL数据库故障排查与解决方案

一、故障排查流程图 #mermaid-svg-hF8hhP2lrqWDbNhV {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hF8hhP2lrqWDbNhV .error-icon{fill:#552222;}#mermaid-svg-hF8hhP2lrqWDbNhV .error-text{fill:#552222;stroke:…...

C#学习——继承、封装、多态

一、继承 1&#xff09;什么是继承&#xff1f; 官方话&#xff1a;允许一个类继承另一个类的字段和方法 个人理解&#xff1a;子类可以使用父类已经授权的所有字段和方法&#xff0c;子承父业 2&#xff09;使用方式 方式&#xff1a;子类&#xff1a;父类 class…...

数据库基础:概念、原理与实战示例

在当今信息时代&#xff0c;数据已经成为企业和个人的核心资产。无论是社交媒体、电子商务、金融交易&#xff0c;还是物联网设备&#xff0c;几乎所有的现代应用都依赖于高效的数据存储和管理。数据库&#xff08;Database&#xff09;作为数据管理的核心技术&#xff0c;帮助…...

AI与计算机视觉(CV):目标检测与图像分割的最新进展

AI与计算机视觉&#xff08;CV&#xff09;&#xff1a;目标检测与图像分割的最新进展 系统化学习人工智能网站&#xff08;收藏&#xff09;&#xff1a;https://www.captainbed.cn/flu 文章目录 AI与计算机视觉&#xff08;CV&#xff09;&#xff1a;目标检测与图像分割的…...

嵌入式开发学习日志Day17

第十一章 结构体与共用体 一、结构体 1、结构体 一般形式 【struct 标识符】 结构体中的标识符一般首字母大写&#xff1b; 【.】结构体成员运算符&#xff1b; 优先级 1 级 结合方向&#xff1a;从左至右&#xff1b; 【->】:指向结构体成员运算符&#x…...

awesome-digital-human本地部署及配置:打造高情绪价值互动指南

在数字化交互的浪潮中&#xff0c;awesome-digital-human-live2d项目为我们打开了本地数字人互动的大门。结合 dify 聊天 api&#xff0c;并借鉴 coze 夸夸机器人的设计思路&#xff0c;能为用户带来充满情绪价值的交互体验。本文将详细介绍其本地部署步骤、dify 配置方法及情绪…...

ClickHouse多表join的性能优化:原理与源码详解

本文将从底层原理和源代码的角度详细解释 ClickHouse 多表 JOIN 的处理过程&#xff0c;尽量用通俗移动的语言&#xff0c;让初学者也能理解。本文会分步骤推导&#xff0c;涵盖 JOIN 的原理、实现方式、关键代码逻辑以及优化机制&#xff0c;同时确保逻辑清晰、内容全面。最后…...

国产Excel处理控件Spire.XLS系列教程:C# 将Excel文件转换为Markdown格式

Microsoft Excel 是一款强大的数据管理工具&#xff0c;广泛用于数据处理和分析。然而&#xff0c;其专有格式&#xff08;如 XLS 和 XLSX&#xff09;在不同平台之间共享时&#xff0c;常常面临兼容性问题。相比之下&#xff0c;Markdown 是一种轻量级的标记语言&#xff0c;因…...

C++线程库

1. 基本概念 1.1 线程&#xff08;Thread&#xff09; 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一个进程可以并发多个线程&#xff0c;每条线程并行执行不同的任务。 1.2 并发与并行 并发&#xff08;Concurren…...

Missashe计网复习笔记(随时更新)

Missashe计算机网络复习笔记 前言&#xff1a;这篇笔记用于博主对计网这门课所学进行记录和总结&#xff0c;也包括一些个人的理解。正在更新当中…… 第一章 计算机网络体系结构 考纲内容 (一) 计算机网络概述 计算机网络的概念、组成与功能;计算机网络的分类; 计算机网络…...

解决osx-arm64平台上conda默认源没有提供 python=3.7 的官方编译版本的问题

CONDA_SUBDIRosx-64 conda create -n py37_env python3.7 是一个用于创建特定架构环境的命令&#xff0c;主要针对 macOS 系统。下面为你详细解析它的功能和作用&#xff1a; 命令功能解析 这个命令的主要功能是创建一个名为 py37_env 的 Conda 环境&#xff0c;并且指定该环…...

Cjson格式解析与接入AI大模型

JSON格式的解析与构造 基本概念 JSON是JavaScript Object Notation的简称&#xff0c;中文含义为“JavaScript 对象表示法”&#xff0c;它是一种数据交换的文本格式&#xff0c;而不是一种编程语言。 JSON 是一种轻量级的数据交换格式&#xff0c;采用完全独立于编程语言的…...

RocketMQ 深度解析:架构设计与最佳实践

在分布式系统架构日益复杂的今天&#xff0c;消息中间件作为系统间通信的桥梁&#xff0c;扮演着至关重要的角色。RocketMQ 作为阿里开源的高性能分布式消息中间件&#xff0c;凭借其卓越的性能、丰富的功能以及高可用性&#xff0c;在电商、金融、互联网等众多领域得到广泛应用…...

【Light】帕多瓦大学超表面技术:开启矢量光束相位偏振定制新时代

01 前言 近年来&#xff0c;完美涡旋光束&#xff08;Perfect Vortex Beams&#xff09;因其独特的环形强度分布和与拓扑电荷无关的特性&#xff0c;成为研究热点。然而&#xff0c;传统方法在生成此类光束时面临相位和偏振控制的挑战&#xff0c;通常需要复杂的光学系统或多重…...

2021-11-15 C++下一个生日天数

缘由c今日日期到生日天数-编程语言-CSDN问答 int isLeap(int year)//判断闰年 {//缘由https://ask.csdn.net/questions/7567048?spm1005.2025.3001.5141return ((!(year % 4) && year % 100) || !(year % 400)); } int daysInMonth(int year, int month)//返回月天数…...

基于nodejs + Koa +Nuxt3的订单系统项目实战

以下是一个基于 Node.js Koa Nuxt3 的订单系统项目实战指南&#xff0c;包含关键实现步骤和代码示例&#xff1a; 一、项目架构设计 project/ ├── backend/ # Koa 后端 │ ├── config/ # 配置文件 │ ├── controllers/ # 控制器 │ ├──…...

# YOLOv2:目标检测的升级之作

YOLOv2&#xff1a;目标检测的升级之作 在目标检测领域&#xff0c;YOLO&#xff08;You Only Look Once&#xff09;系列算法以其高效的速度和创新的检测方式受到了广泛关注。今天&#xff0c;我们就来深入探讨一下 YOLOv2&#xff0c;看看它是如何在继承 YOLOv1 的基础上进行…...

国债收益率、需求与抛售行为的逻辑解析

国债收益率、需求与抛售行为的逻辑解析 1. 国债收益率的定义 国债收益率是衡量国债投资回报的核心指标&#xff0c;分为两种常见计算方式&#xff1a; 当前收益率&#xff08;Current Yield&#xff09;&#xff1a;年利息收入 债券当前市场价格 例如&#xff1a;面值100元、…...

使用Python和TensorFlow实现图像分类的人工智能应用

最近研学过程中发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击链接跳转到网站人工智能及编程语言学习教程。读者们可以通过里面的文章详细了解一下人工智能及其编程等教程和学习方法。下面开始对正文内容的…...

嵌入式培训之C语言学习完(十七)结构体、共用体、枚举、typedef关键字与位运算

目录 一、结构体&#xff08;struct关键字&#xff09; &#xff08;一&#xff09;声明一个结构体数据类型 &#xff08;二&#xff09;结构体的成员初始化与赋值 a、结构体变量赋值 b、结构体成员初始化 c、结构体的定义形式 &#xff08;三&#xff09;考点&#xff…...

cilium路由模式和aws-eni模式下的IPAM

来看Cilium路由的几种核心模式。 封装模式&#xff08;overlay&#xff09; 首先是最基础的封装模式。这是默认情况下&#xff0c;如果你没有特别配置&#xff0c;Cilium会自动运行的模式。它的最大特点就是对底层网络环境的要求非常低&#xff0c;可以说是开箱即用。具体怎么…...

深入理解 Java 代理模式:从基础到实战​

在软件开发的世界里&#xff0c;设计模式是程序员智慧的结晶&#xff0c;它们为解决常见问题提供了经过验证的最佳实践。代理模式作为一种常用的结构型设计模式&#xff0c;在 Java 开发中有着广泛的应用。本文将深入探讨 Java 代理模式&#xff0c;从基本概念、分类、实现原理…...

Python毕业设计219—基于python+Django+vue的房屋租赁系统(源代码+数据库+万字论文)

毕设所有选题&#xff1a; https://blog.csdn.net/2303_76227485/article/details/131104075 基于pythonDjangovue的房屋租赁系统(源代码数据库万字论文)219 一、系统介绍 本项目前后端分离&#xff0c;分为租客、房东、管理员三种角色 1、租客&#xff1a; 注册、登录、公…...

Spring Boot 框架概述

1. 简介 Spring Boot 是由 Pivotal 团队开发的一个用于简化 Spring 应用开发的框架。它通过提供默认配置、嵌入式服务器和自动配置等特性&#xff0c;让开发者能够更快速地构建独立的、生产级别的 Spring 应用。 Spring Boot 的主要特点包括&#xff1a; 快速创建独立的 Spri…...

MySQL 8.0(主从复制)

MySQL 8.0 的 主从复制&#xff08;Master-Slave Replication&#xff09; 是一种数据库高可用和数据备份的核心技术&#xff0c;下面用 一、什么是主从复制&#xff1f; 就像公司的「领导-秘书」分工&#xff1a; 主库&#xff08;Master&#xff09;&#xff1a;负责处理所…...

探索大型语言模型的 LLM 安全风险和 OWASP 十大漏洞

大型语言模型 (LLM) 引领着技术进步,推动着包括医疗保健在内的各个领域的自动化进程。在 Halodoc,我们通过 AI 驱动技术的运用直接见证了这一变化。然而,强大的功能伴随着同样重大的责任——保障这些系统的安全对于保护敏感信息和维护信任至关重要。本博客探讨了与 LLM 相关…...

算法与数据结构 - 二叉树结构入门

目录 1. 普通二叉树结构 1.1. 常见术语 1.2. 完全二叉树 (Complete Binary Tree) 1.3. 满二叉树 (Full Binary Tree) 2. 特殊二叉树结构 2.1. 二叉搜索树 (BST) 2.1.1. BST 基本操作 - 查找 2.1.2. BST 基本操作 - 插入 2.1.3. BST 基本操作 - 删除 2.2. 平衡二叉树…...

基于AQS实现Reentrantlcok

好久没有更新了 这次来补充上一次AQS还没有实现的可重入锁部分&#xff01; 我们知道ReentrantLock是可重入的锁&#xff0c;主要的核心是state&#xff0c;他是一个原子性的整数&#xff0c;我们只需要将获取锁的代码boolean由false到true变成0->1即可完成。在完成删除逻辑…...

TiDB预研-分页查询、连接查询、执行计划

目录 分页查询原理连接查询原理查询计划分析 https://docs.pingcap.com/zh/tidb/stable/dev-guide-join-tables/ https://cn.pingcap.com/blog/tidb-query-optimization-and-tuning-1/ https://github.com/pingcap/blog-cn/blob/master/how-to-use-tidb.md 分页查询 深分…...

五、【LLaMA-Factory实战】模型部署与监控:从实验室到生产的全链路实践

【LLaMA-Factory实战】模型部署与监控&#xff1a;从实验室到生产的全链路实践 一、引言 在大模型应用落地过程中&#xff0c;从实验室研究到生产环境部署存在巨大挑战。本文基于LLaMA-Factory框架&#xff0c;详细介绍大模型部署与监控的完整流程&#xff0c;包含推理优化、…...

Unity 点击按钮,打开 Windows 文件选择框,并加载图片

代码如下&#xff1a; using System; using System.Collections; using System.Runtime.InteropServices; using UnityEngine; using UnityEngine.Events; using UnityEngine.Networking; using UnityEngine.UI;/// <summary> /// 文件日志类 /// </summary> // […...

深入解析磁盘 I/O 与零拷贝技术:从传统读取到高效传输

深入解析磁盘 I/O 与零拷贝技术&#xff1a;从传统读取到高效传输 在现代计算机系统中&#xff0c;磁盘 I/O 操作是数据处理的核心环节之一。无论是读取文件、写入数据&#xff0c;还是进行网络传输&#xff0c;磁盘 I/O 的效率直接影响到系统的整体性能。本文将深入探讨磁盘 I…...

第十六章,网络型攻击防范技术

网络攻击介绍 网络攻击 --- 指的是入侵或破坏网络上的服务器 ( 主机 ) &#xff0c;盗取服务器的敏感数据或占用网络带宽。 网络攻击分类&#xff1a; 流量型攻击 网络层攻击 应用层攻击 单包攻击 畸形报文攻击 --- 向目标主机发送有缺陷的IP报文&#xff0c;使得目标在…...

线程的生命周期·

知识点详细说明 Java线程的生命周期由Thread.State枚举明确定义,包含以下6种状态: 1. 新建状态(NEW) 定义:线程对象被创建后,但未调用start()方法。特点: 未分配系统资源(如CPU时间片)。可通过Thread.getState()获取状态为NEW。示例:Thread t = new Thread(); // 状…...

kafka 面试总结

Kafka的幂等性是一种机制&#xff0c;确保生产者发送的每条消息在Broker端只被持久化一次&#xff0c;即使生产者因网络问题等原因重试发送&#xff0c;也不会导致消息重复。 实现原理 生产者ID&#xff08;PID&#xff09; 每个生产者实例在初始化时&#xff0c;会被分配一个…...

Webpack基本用法学习总结

Webpack 基本使用核心概念处理样式资源步骤&#xff1a; 处理图片资源修改图片输出文件目录 自动清空上次打包的内容EslintBabel处理HTML资源搭建开发服务器生产模式提取css文件为单独文件问题&#xff1a; Css压缩HTML压缩 小结1高级SourceMap开发模式生产模式 HMROneOfInclud…...

5月9日复盘-混合注意力机制

5月9日复盘 四、混合注意力 混合注意力机制&#xff08;Hybrid Attention Mechanism&#xff09;是一种结合空间和通道注意力的策略&#xff0c;旨在提高神经网络的特征提取能力。 1. CBAM Convolution Block Attention Module &#xff0c;卷积块注意力模块 论文地址&…...

YOLOv8 优化:基于 Damo-YOLO 与 DyHead 检测头融合的创新研究

文章目录 YOLOv8 的背景与发展Damo-YOLO 的优势与特点DyHead 检测头的创新之处融合 Damo-YOLO 与 DyHead 检测头的思路融合后的模型架构融合模型的代码实现导入必要的库定义 Damo-YOLO 的主干网络定义特征金字塔网络&#xff08;FPN&#xff09;定义 DyHead 检测头定义融合后的…...

【网安播报】Meta 推出 LlamaFirewall开源框架以阻止 AI 越狱、注入和不安全代码

1、Meta 推出 LlamaFirewall 框架以阻止 AI 越狱、注入和不安全代码 Meta 宣布推出 LlamaFirewall&#xff0c;这是一个开源框架&#xff0c;旨在保护人工智能 &#xff08;AI&#xff09; 系统免受新出现的网络风险&#xff0c;例如提示词注入、越狱和不安全代码等。除了 Llam…...

QT 解决msvc fatal error C1060: 编译器的堆空间不足

一.物理内存太小&#xff0c;代码又比较复杂&#xff0c;递归嵌套之类的。 1.修改虚拟内存的大小&#xff0c;一般设置为物理内存的1.5倍。 二.msvc工程的编译默认开启的是多线程编译&#xff0c;所以电脑内存确实不够&#xff0c;采用如下设置。 QMAKE_CXXFLAGS -j1 三.ms…...

PX4开始之旅(一)自动调参

核心知识点&#xff1a;无人机震动与滤波参数 1. 通俗易懂的解释 想象一下&#xff0c;你的无人机就像一个非常敏感的“听众”&#xff0c;它的“耳朵”就是陀螺仪和加速度计这些传感器&#xff0c;用来感知自己是如何移动和旋转的。理想情况下&#xff0c;它应该只“听”到你…...