STM32 定时器介绍--通用、高级定时器

news2024/11/24 10:45:24

目录

高级定时器

1.功能框图

1-时钟源

2-时基单元

3-输入捕获

4-输出比较

2.输入捕获的应用

3.输出比较的应用

4.初始化结构体

1-时基初始化结构体

2-输出比较结构体

3-PWM信号 周期和占空比的计算--以通用定时器为例

4-输入捕获结构体

5-断路和死区初始化结构体

5.程序设计

1-高级定时器定时功能设计

2-通用定时器PWM输出功能设计


前面文章中说过,STM32F103系列单片机中除了有系统定时器SysTick外,还有2个高级定时器TIM1和TIM8,4个通用定时器TIM2/3/4/5,2个基本定时器TIM6和TIM7。通用定时器的功能在高级定时器中都存在,不做赘述,这篇文章主要介绍STM32中的高级定时器。对于系统定时器SysTick和基本定时器的介绍分别如下:

STM32 系统定时器--SysTick_systick中断_Haohao fighting!的博客-CSDN博客

STM32 定时器介绍--基本定时器_Haohao fighting!的博客-CSDN博客

高级定时器简介

计数器16bit,可从上/下/两边计数,上:从0计数到用户配置的值;下:从用户配置的值倒数到0;两边:从0计数到用户配置的值,再从用户配置的值倒数到0。TIM1和TIM8,时基单元里还有一个重复计数器RCR,独有。

相比基本定时器,通用定时器和高级定时器有4个GPIO,其中通道1~3还有互补输出GPIO,加起来共有7个。

时钟来自PCLK2,为72M(所有的定时器都是72M),可实现1~65536分频。

高级定时器

1.功能框图

1-时钟源  2-控制器 3-时基 4-输入捕获 5-输出比较 6-断路功能

1-时钟源

内部时钟源

时钟源有四种模式,我们最常用的就是CK_INT:来自RCC的TIMx_CLK

高级定时器挂载到APB2总线上,APB2的预分频系数是1,所以不变,还是72M。

外部时钟模式1—外部的GPIO Tix(x=1 2 3 4)和外部时钟模式2—外部的GPIO ETR不常用。外部时钟模式1可以从外部的引脚(功能框图左侧的TIMx_CH1、2、3、4引脚)给计数器提供时钟;外部时钟模式2可以从外部的特殊引脚(功能框图左侧的TIMx_ETR引脚)给计数器提供时钟。

这些引脚对应哪些具体引脚,参考下图

外部时钟1:

虽然有4个引脚,但不能同时使用两个,只能使用1个。

①时钟信号输入引脚 外部的GPIO Tix,对应:TIMx_CH1/2/3/4,TIM_CCMRx寄存器的位CCxS[1:0]配置,其中CCMR1控制TI1/2,CCMR2控制TI3/4。

②滤波器 如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对ETRP信号重新采样,来达到降频或者去除高频干扰的目的,由TIMx_CCMRx寄存器的位ICxF[3:0]配置。

③边沿检测 边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决定是上升沿有效还是下降沿有效。由TIMx_CCER寄存器的位CCxP和CCxNP 配置。

④触发选择 当使用外部时钟模式1时,触发源有两个,一个是滤波后的定时器输入1(TI1FP1)和滤波后的定时器输入2(TI2FP2)。由TIMx_SMCR寄存器的位TS[2:0]配置。

⑤从模式选择 选定了触发源信号后,最后我们需把信号连接到TRGI引脚,让触发信号成为外部时钟模式1的输入,最终等于 CK_PSC,然后驱动计数器CNT计数。具体的配置TIMx_SMCR寄存器的位SMS[2:0]为 000 即可选择外部时钟模式1。

经过上面的5个步骤之后, 最后我们只需使能计数器开始计数,外部时钟模式1的配置就算完成。使能计数器由TIMx_CR1寄存器的位CEN 配置。

外部时钟2

①时钟信号输入引脚 当使用外部时钟模式2的时候,时钟信号来自于定时器的特定输入通道TIMx_ETR,只有1个。

②外部触发极性 来自ETR引脚输入的信号可以选择为上升沿或者下降沿有效。具体的由TIMx_SMCR寄存器的位ETP 配置。

③外部触发预分频器 由于ETRP的信号的频率不能超过TIMx_CLK(180M)的 1/4,当触发信号的频率很高的情况下,就必须使用分频器来降频。具体的由TIMx_SMCR寄存器的位ETPS[1:0]配置。

④滤波器 如果ETRP的信号的频率过高或者混杂有高频干扰信号的,需要使用滤波器对ETRP信号重新采样,来达到降频或者去除高频干扰的目的。具体的由TIMx_SMCR寄存器的位ETF[3:0]配置,其中的fDTS是由内部时钟CK_INT分频得到,具体的由TIMx_CR1寄存器的位CKD[1:0]配置。

⑤从模式选择 经过滤波器滤波的信号连接到ETRF引脚后,触发信号成为外部时钟模式2的输入,最终等于CK_PSC,然后驱动计数器 CNT 计数。具体的配置TIMx_SMCR寄存器的位ECE为 1即可选择外部时钟模式2。

经过上面的5个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式2的配置就算完成。使能计数器由TIMx_CR1寄存器的位CEN配置。

2-时基单元

预分频器 PSC

16位,由预分频器(TIMx_PSC)控制。有一个输入时钟CK_PSC和一个输出时钟CK_CNT。输入时钟CK_PSC就是上面时钟源的输出,输出CK_CNT则用来驱动计数器CNT计数。通过设置预分频器PSC的值可以得到不同的CK_CNT。计数器的时钟频率(CK_CNT)=fck_psc/( PSC[15:0]+1)

计数器CNT

16位,由计数器(TIMx_CNT)控制。

递增计数模式下,计数器从0开始计数,每来一个CK CNT脉冲计数器就增加1,直到计数器的值与自动重载寄存器ARR值相等,然后计数器又从0开始计数并生成计数器上溢事件,计数器总是如此循环计数。如果禁用重复计数器,在计数器生成上溢事件就马上生成更新事件(UEV);如果使能重复计数器,每生成一次上溢事件重复计数器内容就减1,直到重复计数器内容为0时才会生成更新事件。

递减计数模式下,计数器从自动重载寄存器ARR值开始计数,每来一个CK CNT脉冲计数器就减1,直到计数器值为0,然后计数器又从自动重载寄存器ARR值开始递减计数并生成计数器下溢事件,计数器总是如此循环计数。如果禁用重复计数器,在计数器生成下溢事件就马上生成更新事件:如果使能重复计数器,每生成一次下溢事件重复计数器内容就减1,直到重复计数器内容为0时才会生成更新事件。

中心对齐模式下,计数器从0开始递增计数,直到计数值等于(ARR-1)值生成计数器上溢事件,然后从ARR值开始递减计数直到1生成计数器下溢事件。然后又从0开始计数,如此循环。每次发生计数器上溢和下溢事件都会生成更新事件。

自动重装载寄存器ARR

16位,由自动重装载寄存器(TIMx_ARR)控制,与前面基本定时器的ARR基本相同。

重复计数器RCR

8位。由重复计数寄存器(TIMx_RCR)控制。基本/通用定时器,发生上/下溢事件时,直接生成更新事件。高级控制定时器多出了重复计数器。定时器发生上溢、下溢事件时,递减重复计数器的值。当重复计数器为0时,才会生成更新事件。发生N+1个上溢、下溢事件(N为RCR的值)时,产生更新事件。

3-输入捕获

输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输入信号的脉宽和测量PWM输入信号的频率和占空比这两种。

 

输入捕获的大概的原理就是,当捕获到信号的跳变沿(上升或者下降沿)的时候,把计数器CNT的值锁存到捕获寄存器CCR中,把前后两次捕获到的CCR寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我们需要做额外的处理。

①输入通道 当使用需要被测量的信号从定时器的外部引脚 TIMx_CH1/2/3/4进入,通常叫TI1/2/3/4,我们称被测量的信号为Tix。

②输入滤波和边沿检测 当输入的信号存在高频干扰的时候,我们需要对输入信号进行滤波,即进行重新采样,根据采样定律,采样的频率必须大于等于两倍的输入信号。比如输入的信号为1M,又存在高频的信号干扰,那么此时就很有必要进行滤波,我们可以设置采样频率为2M,这样可以在保证采样到有效信号的基础上把高于2M的高频干扰信号过滤掉。

    滤波器的配置由CR1寄存器的位CKD[1:O]和CCMR1/2的位ICxF[3:0]控制。从ICxF位的描述可知,采样频率fSAMPLE可以由fCK INT和fDTs分频后的时钟提供,其中是fCK_INT内部时钟,Ds是fCK INT经过分频后得到的频率,分频因子由CKD[1:O]决定,可以是不分频,2分频或者是4分频。

边沿检测器用来设置信号在捕获的时候是什么边沿有效,可以是上升沿,下降沿,或者是双边沿,具体的由CCER寄存器的位CCxP和CCxNP决定。

③捕获通道 捕获通道就是图中的IC1/2/3/4,每个捕获通道都有相对应的捕获寄存器CCR1/2/3/4,当发生捕获的时候,计数器CNT的值就会被锁存到捕获寄存器中。

这里我们要搞清楚输入通道和捕获通道的区别,输入通道是用来输入信号的,捕获通道是用来捕获输入信号的通道,一个输入通道的信号可以同时输入给两个捕获通道。比如输入通道TI1的信号经过滤波边沿检测器之后的TIIFP1和TIIFP2可以进入到捕获通道IC1和IC2,其实这就是我们后面要讲的PWM输入捕获,只有一路输入信号(TI1)却占用了两个捕获通道(IC1和IC2),一路测量周期,一路测量占空比。PWM信号输入只能通道12有这种功能。PWM信号可以分为TIxFP1TIxFP2,分别和两个捕获寄存器联系起来,要选择一路作为触发从模式,哪一路触发从模式,哪一路就是测量周期;另外一路测量占空比。TIxFP1触发从模式,测量周期称为直连;TIxFP2触发从模式,测量周期称为非直连。

当只需要测量输入信号的脉宽时候,用一个捕获通道即可。输入通道和捕获通道的映射关系具体由寄存器CCMRx的位CCxS[1:0]配置。

④预分频器 一般不分频。

⑤捕获寄存器 经过预分频器的信号ICxPS是最终被捕获的信号,当发生捕获时(第一次),计数器CNT的值会被锁存到捕获寄存器CCR中,还会产生CCxI中断,相应的中断位CCxIF(在SR寄存器中)会被置位,通过软件或者读取CCR中的值可以将CCxF清0。如果发生第二次捕获(即重复捕获:CCR寄存器中已捕获到计数器值且CCxF标志已置1),则捕获溢出标志位CCxOF(在SR寄存器中)会被置位,CCxOF只能通过软件清零。

4-输出比较

例如:输出一个PWM波信号。

CCR寄存器用于输出信号叫做比较寄存器。计数器从0开始计数,计数到CCR的时候输出高电平或者低电平;从CCR计数到ARR输出低电平或者高电平。然后重新开始计数一轮。占空比就与比较寄存器CCR相关。信号在输出通道输出之前,还要经过一个寄存器的控制:刹车和死区寄存器(TIMx_BDTR)。

什么是死区时间?

MOTORA是用来驱动电机的,由上下两个MOS管来控制,

一路(一个MOS管)高电平转换成低电平之后,延迟一段时间之后另一路(另一个MOS管)才由低电平转换成高电平;反之亦然。这样就不会同时导通,从而避免功率元件烧毁;延迟的那段时间称为死区时间,死区时间控制在通常的单片机所配备的PWM中都有这样的功能。

死区时间由刹车和死区寄存器(TIMx_BDTR)的UTG[7:0]位控制。

其中的Tdts跟内部时钟相关,由TIM1和TIM8控制寄存器 1(TIMx_CR1)的CKD[1:0]位控制。

在刹车和死区寄存器(TIMx_BDTR)中:

2.输入捕获的应用

一是测量脉宽和频率

上升沿捕获到一次之后进入中断,在中断中改变捕获的边沿,改成下降沿捕获;捕获到下降沿之后,进入中断再次改变为上升沿捕获……

二是PWM输入模式

只能通过通道12进行捕获,3、4通道不能捕获。

3.输出比较的应用

1-输出比较模式总共有 8 种,常用的是PWM模式。

2-由寄存器CCMRx的位OCxM[2:0]配置。

PWM 输出就是对外输出脉宽(即占空比)可调的方波信号,信号频率由自动重装寄存器 ARR 的值决定,占空比由比较寄存器 CCR 的值决定。

PWM的输出模式:

有效:高电平;无效:低电平

边沿对齐与中心对齐的不同

最常用的是边沿对齐

1-根据CNT的计数方向,PWM波形分成边沿对齐和中心对齐两种。边沿对齐主要用于直流电机,中心对齐主要用于交流电机。

2-边沿对齐时,CNT只工作在递增或者递减。

3-中心对齐时,CNT工作在递增和递减。

4.初始化结构体

1-时基初始化结构体

TIM_TimeBaseInitTypeDef,也就是前面功能框图里面的时基单元。

typedef struct 
{
    uint16_t TIM_Prescaler;         // 预分频器
    uint16_t TIM_CounterMode;       // 计数模式
    uint32_t TIM_Period;            // 定时器周期
    uint16_t TIM_ClockDivision;     // 时钟分频
    uint8_t TIM_RepetitionCounter;  // 重复计算器
} TIM_TimeBaseInitTypeDef;

TIM_Prescaler:定时器预分频器设置,时钟源经该预分频器才是定时器计数时钟CK_CNT,它设定 PSC 寄存器的值。计算公式为: 计数器时钟频率 (fCK_CNT) 等于fCK_PSC / (PSC[15:0] + 1)【对应TIMx_PSC寄存器】,可实现 1 至 65536 分频。

TIM_CounterMode:定时器计数方式,可设置为向上计数、向下计数以及中心对齐。高级控制定时器允许选择任意一种。基本定时器只能选择向上计数,配置基本定时器时不用配置此成员。对应TIM_CR1寄存器的DIR位。

TIM_Period:定时器周期,实际就是设定自动重载寄存器ARR的值,ARR为要装载到实际自动重载寄存器(即影子寄存器) 的值, 可设置范围为0至65535。(具体介绍看基本定时器)

TIM_ClockDivision:时钟分频,设置定时器时钟 CK_INT 频率与死区发生器以及数字滤波器采样时钟频率分频比。可以选择1、2、4 分频。

TIM_RepetitionCounter:重复计数器,只有 8 位,只存在于高级定时器。

2-输出比较结构体

TIM_OCInitTypeDef

typedef struct 
{
    uint16_t TIM_OCMode;            // 比较输出模式
    uint16_t TIM_OutputState;       // 比较输出使能
    uint16_t TIM_OutputNState;      // 比较互补输出使能
    uint32_t TIM_Pulse;             // 脉冲宽度
    uint16_t TIM_OCPolarity;        // 输出极性
    uint16_t TIM_OCNPolarity;       // 互补输出极性
    uint16_t TIM_OCIdleState;       // 空闲状态下比较输出状态
    uint16_t TIM_OCNIdleState;      // 空闲状态下比较互补输出状态
} TIM_OCInitTypeDef;

TIM_OCMode:比较输出模式选择,总共有八种,常用的为 PWM1/PWM2。它设定CCMRx(x控制1或2通道)寄存器OCxM[2:0]位的值。

TIM_OutputState:比较输出使能,决定最终的输出比较信号OCx 是否通过外部引脚输出。它设定TIMx_CCER寄存器CCxE位的值。也就是说启用之后可以产生PWM波信号。

TIM_OutputNState:比较互补输出使能,决定 OCx 的互补信号 OCxN 是否通过外部引脚输出。它设定 CCER 寄存器 CCxNE 位的值。

TIM_Pulse:比较输出脉冲宽度,实际设定比较寄存器 CCR 的值,决定脉冲宽度。可设置范围为 0 至 65535。

TIM_OCPolarity:比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。它设定 CCER 寄存器的 CCxP 位的值。也就是正周期的电平是高/低。

TIM_OCNPolarity:比较互补输出极性,可选OCxN 为高电平有效或低电平有效。它设定 TIMx_CCER 寄存器的 CCxNP 位的值。

当我们需要输出PWM波时(小车电机驱动),就需要配置时基结构体和输出比较结构体即可,而输出比较结构体只需要配置三个加粗的成员即可。

3-PWM信号 周期和占空比的计算--以通用定时器为例

这一部分在时基结构体初始化中配置

ARR :自动重装载寄存器的值

CLK_cnt:计数器的时钟(驱动CNT计数器的时钟周期),等于 Fck_int / (psc+1) = 72M/(psc+1)  psc = GENERAL_TIM_Prescaler 宏定义的值为 71。CLK_cnt = 1 MHZ

PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M。这里的ARR代表的是自动重装载寄存器的值,累计TIM_Period+1,TIM_Period在宏定义中为9,也就是9+1=10。周期 = 10 * (1 / 1 MHZ) = 10 us

占空比 P = CCR/ARR = CCR/(TIM_Period+1)  TIM_Period就是宏定义中 GENERAL_TIM_Period 值为9,也就是说,占空比为 = CCR / 10


详细例程如下,这是一个定时器3,四路PWM通道不同输出值的配置程序,主要是看一下PWM周期和占空比是如何配置的:

.c文件内容,定时器3配置函数:

static void GENERAL_TIM3_Mode_Config(void)
{
  // 开启定时器时钟,即内部时钟CK_INT=72M
	GENERAL_TIM3_APBxClock_FUN(GENERAL_TIM3_CLK,ENABLE);

/*--------------------时基结构体初始化-------------------------*/
	// 配置周期,这里配置为100K
	
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自动重装载寄存器的值ARR,累计TIM_Period+1个频率后产生一个更新或者中断  	TIM_Period+1  9+1=10
	TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM3_Period;	
	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM3_Prescaler;	
	// 时钟分频因子 ,配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
	// 计数器计数模式,设置为向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	// 初始化定时器
	TIM_TimeBaseInit(GENERAL_TIM3, &TIM_TimeBaseStructure);

	/*--------------------输出比较结构体初始化-------------------*/	 // 需要 PWM波 输出的就需要配置此结构体
	// 占空比配置
	uint16_t CCR1_Val = 9;  // 占空比 = CCR1_Val / (GENERAL_TIM_Period + 1)
	uint16_t CCR2_Val = 6;
	uint16_t CCR3_Val = 3;
	uint16_t CCR4_Val = 1;
	
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	// 配置为PWM模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  //比较输出模式选择.常用的为 PWM1/PWM2
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //比较输出使能,决定最终的输出比较信号OCx是否通过外部引脚输出,也就是说启用之后可以产生PWM波信号
	// 输出通道电平极性配置	
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。也就是正周期的电平是高/低
	
	// 输出比较通道 1
	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
	TIM_OC1Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 2
	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
	TIM_OC2Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 3
	TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
	TIM_OC3Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 4
	TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
	TIM_OC4Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 使能计数器
	TIM_Cmd(GENERAL_TIM3, ENABLE);
}

.h文件内容,一些宏定义:

/************************************通用定时器TIM参数定义,只限TIM2、3、4、5********************************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
/******************************* TIM3 ***************************************/

#define            GENERAL_TIM3                   TIM3
#define            GENERAL_TIM3_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM3_CLK               RCC_APB1Periph_TIM3
#define            GENERAL_TIM3_Period            9
#define            GENERAL_TIM3_Prescaler         71
// TIM3 输出比较通道1
#define            GENERAL_TIM3_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM3_CH1_PORT          GPIOA
#define            GENERAL_TIM3_CH1_PIN           GPIO_Pin_6

// TIM3 输出比较通道2
#define            GENERAL_TIM3_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM3_CH2_PORT          GPIOA
#define            GENERAL_TIM3_CH2_PIN           GPIO_Pin_7

// TIM3 输出比较通道3
#define            GENERAL_TIM3_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM3_CH3_PORT          GPIOB
#define            GENERAL_TIM3_CH3_PIN           GPIO_Pin_0

// TIM3 输出比较通道4
#define            GENERAL_TIM3_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM3_CH4_PORT          GPIOB
#define            GENERAL_TIM3_CH4_PIN           GPIO_Pin_1

整个工程的详细代码在文末有下载链接。参照  5.2-通用定时器PWM输出功能设计

4-输入捕获结构体

typedef struct 
{
    uint16_t TIM_Channel; // 输入通道选择
    uint16_t TIM_ICPolarity; // 输入捕获触发选择
    uint16_t TIM_ICSelection; // 输入捕获选择
    uint16_t TIM_ICPrescaler; // 输入捕获预分频器
    uint16_t TIM_ICFilter; // 输入捕获滤波器
} TIM_ICInitTypeDef;

TIM_Channel:捕获通道ICx选择,可选 TIM_Channel_1、 TIM_Channel_2、TIM_Channel_3 或 TIM_Channel_4 四个通道。它设定 CCMRx 寄存器 CCxS 位 的值。

TIM_ICPolarity:输入捕获边沿触发选择,可选上升沿触发、下降沿触发或边沿跳变触发。它设定 CCER 寄存器 CCxP 位和 CCxNP 位的值。

TIM_ICSelection:输入通道选择,捕获通道 ICx 的信号可来自三个输入通道,分别为:TIM_ICSelection_DirectTI、TIM_ICSelection_IndirectTI 或 TIM_ICSelection_TRC。它设定 CCRMx 寄存器的 CCxS[1:0]位的值。

TIM_ICPrescaler:输入捕获通道预分频器,可设置 1、 2、 4、 8 分频,它设定 CCMRx寄存器的 ICxPSC[1:0]位的值。如果需要捕获输入信号的每个有效边沿,则设置 1 分频即可。

TIM_ICFilter:输入捕获滤波器设置,可选设置 0x0 至 0x0F。它设定 CCMRx 寄存器ICxF[3:0]位的值。一般我们不使用滤波器,即设置为 0。

5-断路和死区初始化结构体

 TIM_BDTRInitTypeDef

断路和死区结构体 TIM_BDTRInitTypeDef 用于断路和死区参数的设置,属于高级定时器专用,用 于配置断路时通道输出状态,以及死区时间。它与 TIM_BDTRConfig 函数配置使用完成参数配置。 这个结构体的成员只对应寄存器断路和死区寄存器:TIMx_BDTR。 

typedef struct 
{
    uint16_t TIM_OSSRState;         // 运行模式下的关闭状态选择
    uint16_t TIM_OSSIState;         // 空闲模式下的关闭状态选择
    uint16_t TIM_LOCKLevel;         // 锁定配置
    uint16_t TIM_DeadTime;          // 死区时间
    uint16_t TIM_Break;             // 断路输入使能控制
    uint16_t TIM_BreakPolarity;     // 断路输入极性
    uint16_t TIM_AutomaticOutput;   // 自动输出使能
} TIM_BDTRInitTypeDef;

 (1) TIM_OSSRState:运行模式下的关闭状态选择,它设定 BDTR 寄存器 OSSR 位的值。

 (2) TIM_OSSIState:空闲模式下的关闭状态选择,它设定 BDTR 寄存器 OSSI 位的值。

 (3) TIM_LOCKLevel:锁定级别配置,BDTR 寄存器 LOCK[1:0] 位的值。

 (4) TIM_DeadTime:配置死区发生器,定义死区持续时间,可选设置范围为 0x0 至 0xFF。它设定 BDTR 寄存器 DTG[7:0] 位的值。

 (5) TIM_Break:断路输入功能选择,可选使能或禁止。它设定 BDTR 寄存器 BKE 位的值。

 (6) TIM_BreakPolarity:断路输入通道 BRK 极性选择,可选高电平有效或低电平有效。它设定 BDTR 寄存器 BKP 位的值。

 (7) TIM_AutomaticOutput:自动输出使能,可选使能或禁止,它设定 BDTR 寄存器 AOE 位的值。

这个在我平常做的时候用不到这个功能,就不做相应配置了。

5.程序设计

1-高级定时器定时功能设计

功能设计:使用高级定时器实现双色LED灯间隔1秒完成红绿颜色切换(高级定时器的定时功能)

配置过程:

首先进行定时器和中断优先级的配置:

#include "bsp_AdvanceTim.h" 

// 中断优先级配置
static void ADVANCE_TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    // 设置中断组为0
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);		
		// 设置中断来源
    NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ ;	
		// 设置主优先级为 0
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;	 
	  // 设置抢占优先级为3
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;	
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有
// *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有
// *  TIM_Period               都有
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// */
static void ADVANCE_TIM_Mode_Config(void)
{
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;		
		// 开启定时器时钟,即内部时钟CK_INT=72M
    ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK, ENABLE);	
		// 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断
    TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_Period;
	  // 时钟预分频数
    TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_Prescaler;	
		// 时钟分频因子 ,没用到不用管
    TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
		// 计数器计数模式,设置为向上计数
    TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 		
		// 重复计数器的值,没用到不用管
		TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	  // 初始化定时器
    TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
	
		// 清除计数器中断标志位
    TIM_ClearFlag(ADVANCE_TIM, TIM_FLAG_Update);
	  
		// 开启计数器中断
    TIM_ITConfig(ADVANCE_TIM,TIM_IT_Update,ENABLE);
		
		// 使能计数器
    TIM_Cmd(ADVANCE_TIM, ENABLE);
}

void ADVANCE_TIM_Init(void)
{
	ADVANCE_TIM_NVIC_Config();
	ADVANCE_TIM_Mode_Config();		
}

关于高级定时器的一些宏定义:

#ifndef __BSP_ADVANCETIME_H
#define __BSP_ADVANCETIME_H


#include "stm32f10x.h"


/********************高级定时器TIM参数定义,只限TIM1、8************/
#define ADVANCE_TIM1 // 如果使用TIM8,注释掉这个宏即可

#ifdef  ADVANCE_TIM1 // 使用高级定时器TIM1

#define            ADVANCE_TIM                   TIM1
#define            ADVANCE_TIM_APBxClock_FUN     RCC_APB2PeriphClockCmd
#define            ADVANCE_TIM_CLK               RCC_APB2Periph_TIM1
#define            ADVANCE_TIM_Period            (1000-1)
#define            ADVANCE_TIM_Prescaler         71
#define            ADVANCE_TIM_IRQ               TIM1_UP_IRQn
#define            ADVANCE_TIM_IRQHandler        TIM1_UP_IRQHandler

#else  // 使用高级定时器TIM8
#define            ADVANCE_TIM                   TIM8
#define            ADVANCE_TIM_APBxClock_FUN     RCC_APB2PeriphClockCmd
#define            ADVANCE_TIM_CLK               RCC_APB2Periph_TIM8
#define            ADVANCE_TIM_Period            (1000-1)
#define            ADVANCE_TIM_Prescaler         71
#define            ADVANCE_TIM_IRQ               TIM8_UP_IRQn
#define            ADVANCE_TIM_IRQHandler        TIM8_UP_IRQHandler

#endif
/**************************函数声明********************************/

void ADVANCE_TIM_Init(void);


#endif	/* __BSP_ADVANCETIME_H */


高级定时器的中断函数:

void  ADVANCE_TIM_IRQHandler (void)
{
	if ( TIM_GetITStatus( ADVANCE_TIM, TIM_IT_Update) != RESET ) 
	{	
		time++;
		TIM_ClearITPendingBit(ADVANCE_TIM , TIM_FLAG_Update);  		 
	}		 	
}

主函数程序:

int main(void)
{
	LED_GPIO_Config();//初始化函数
	ADVANCE_TIM_Init();
	
  while(1)
	{
		if(time == 1000)
		{	    
			GPIO_SetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
			GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
		}
		else if(time == 2000)
		{
			time=0;
			GPIO_ResetBits(LED1_GPIO_PORT,LED1_GPIO_PIN);
			GPIO_SetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
		}
	}
}

想要验证这个程序,需要一个双色LED灯,当然也可以用别的外设去替代。完整程序链接如下:

链接:https://pan.baidu.com/s/1ZVEE6FaTZV8grSiQIiQrWg 
提取码:ssun 
--来自百度网盘超级会员V1的分享

2-通用定时器PWM输出功能设计

功能设计:通过四个通用定时器2、3、4、5分别实现LED灯四级亮度等级变化(4个通道有不同的占空比,代表4个不同的亮度等级)。这个程序只是展示了通用定时器的 PWM波输出功能,在使用此功能时,是不需要使用中断的。

配置过程:

单以定时器3为例,其实定时器3做出来了,其他的也就会了,只不过改改引脚即可。

首先配置定时器3:

#include "bsp_GeneralTim.h" 

/******************************** TIM3 PWM输出配置 ******************************/

static void GENERAL_TIM3_GPIO_Config(void) 
{
  GPIO_InitTypeDef GPIO_InitStructure;

  // 输出比较通道1 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM3_CH1_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM3_CH1_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM3_CH1_PORT, &GPIO_InitStructure);
	
	// 输出比较通道2 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM3_CH2_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM3_CH2_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM3_CH2_PORT, &GPIO_InitStructure);
	
	// 输出比较通道3 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM3_CH3_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM3_CH3_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM3_CH3_PORT, &GPIO_InitStructure);
	
	// 输出比较通道4 GPIO 初始化
	RCC_APB2PeriphClockCmd(GENERAL_TIM3_CH4_GPIO_CLK, ENABLE);
  GPIO_InitStructure.GPIO_Pin =  GENERAL_TIM3_CH4_PIN;
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
  GPIO_Init(GENERAL_TIM3_CH3_PORT, &GPIO_InitStructure);
}


///*
// * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有
// * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可,
// * 另外三个成员是通用定时器和高级定时器才有.
// *-----------------------------------------------------------------------------
// *typedef struct
// *{ TIM_Prescaler            都有   定时器的预分频值。预分频值越大,计数频率越低,定时器的计数周期就越长。
// *	TIM_CounterMode			     TIMx,x[6,7]没有,其他都有   定时器的计数模式(向上、向下、中心对齐)
// *  TIM_Period               都有   定时器的自动重装载值。当计数器达到自动重装载值时,会产生更新事件,并重新从0开始计数。
// *  TIM_ClockDivision        TIMx,x[6,7]没有,其他都有   定时器的时钟分频系数。用于将计数器时钟进一步分频,从而得到一个更低的计数频率。时钟分频系数的取值范围为1到65535。
// *  TIM_RepetitionCounter    TIMx,x[1,8,15,16,17]才有  配置定时器在重复计数模式下的重复计数次数。高级定时器特有
// *}TIM_TimeBaseInitTypeDef; 
// *-----------------------------------------------------------------------------
// */

/* ----------------   PWM信号 周期和占空比的计算--------------- */
// ARR :自动重装载寄存器的值
// CLK_cnt:计数器的时钟(驱动CNT计数器的时钟周期),等于 Fck_int / (psc+1) = 72M/(psc+1)  psc = GENERAL_TIM_Prescaler 宏定义的值为 71
//          CLK_cnt = 1 MHZ
// PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M  
//          这里的ARR代表的是自动重装载寄存器的值,累计TIM_Period+1,也就是9+1=10,跟下面的ARR不一样,下面的ARR没加一
//          周期 = 10 * (1 / 1 MHZ) = 10 us
// 占空比 P = CCR/(GENERAL_TIM_Period+1)  GENERAL_TIM_Period 宏定义中为9,也就是说,占空比为 = CCR / 10

static void GENERAL_TIM3_Mode_Config(void)
{
  // 开启定时器时钟,即内部时钟CK_INT=72M
	GENERAL_TIM3_APBxClock_FUN(GENERAL_TIM3_CLK,ENABLE);

/*--------------------时基结构体初始化-------------------------*/
	// 配置周期,这里配置为100K
	
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	// 自动重装载寄存器的值ARR,累计TIM_Period+1个频率后产生一个更新或者中断  	TIM_Period+1  9+1=10
	TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM3_Period;	
	// 驱动CNT计数器的时钟 = Fck_int/(psc+1)
	TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM3_Prescaler;	
	// 时钟分频因子 ,配置死区时间时需要用到
	TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;		
	// 计数器计数模式,设置为向上计数
	TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;		
	// 重复计数器的值,没用到不用管
	TIM_TimeBaseStructure.TIM_RepetitionCounter=0;	
	// 初始化定时器
	TIM_TimeBaseInit(GENERAL_TIM3, &TIM_TimeBaseStructure);

	/*--------------------输出比较结构体初始化-------------------*/	 // 需要 PWM波 输出的就需要配置此结构体
	// 占空比配置
	uint16_t CCR1_Val = 9;  // 占空比 = CCR1_Val / (GENERAL_TIM_Period + 1)
	uint16_t CCR2_Val = 6;
	uint16_t CCR3_Val = 3;
	uint16_t CCR4_Val = 1;
	
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	// 配置为PWM模式1
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;  //比较输出模式选择.常用的为 PWM1/PWM2
	// 输出使能
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;  //比较输出使能,决定最终的输出比较信号OCx是否通过外部引脚输出,也就是说启用之后可以产生PWM波信号
	// 输出通道电平极性配置	
	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;  //比较输出极性,可选 OCx 为高电平有效或低电平有效。它决定着定时器通道有效电平。也就是正周期的电平是高/低
	
	// 输出比较通道 1
	TIM_OCInitStructure.TIM_Pulse = CCR1_Val;
	TIM_OC1Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC1PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 2
	TIM_OCInitStructure.TIM_Pulse = CCR2_Val;
	TIM_OC2Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC2PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 3
	TIM_OCInitStructure.TIM_Pulse = CCR3_Val;
	TIM_OC3Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC3PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 输出比较通道 4
	TIM_OCInitStructure.TIM_Pulse = CCR4_Val;
	TIM_OC4Init(GENERAL_TIM3, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(GENERAL_TIM3, TIM_OCPreload_Enable);
	
	// 使能计数器
	TIM_Cmd(GENERAL_TIM3, ENABLE);
}

void GENERAL_TIM3_Init(void)
{
	GENERAL_TIM3_GPIO_Config();  // 通用定时器GPIO口配置
	GENERAL_TIM3_Mode_Config();	// 通用定时器输出模式等配置	
}

.h文件进行引脚等宏定义:

#ifndef __BSP_GENERALTIME_H
#define __BSP_GENERALTIME_H


#include "stm32f10x.h"


/*******************通用定时器TIM参数定义,只限TIM2、3、4、5******************/
// 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意
/******************************* TIM3 ***************************************/

#define            GENERAL_TIM3                   TIM3
#define            GENERAL_TIM3_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            GENERAL_TIM3_CLK               RCC_APB1Periph_TIM3
#define            GENERAL_TIM3_Period            9
#define            GENERAL_TIM3_Prescaler         71
// TIM3 输出比较通道1
#define            GENERAL_TIM3_CH1_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM3_CH1_PORT          GPIOA
#define            GENERAL_TIM3_CH1_PIN           GPIO_Pin_6

// TIM3 输出比较通道2
#define            GENERAL_TIM3_CH2_GPIO_CLK      RCC_APB2Periph_GPIOA
#define            GENERAL_TIM3_CH2_PORT          GPIOA
#define            GENERAL_TIM3_CH2_PIN           GPIO_Pin_7

// TIM3 输出比较通道3
#define            GENERAL_TIM3_CH3_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM3_CH3_PORT          GPIOB
#define            GENERAL_TIM3_CH3_PIN           GPIO_Pin_0

// TIM3 输出比较通道4
#define            GENERAL_TIM3_CH4_GPIO_CLK      RCC_APB2Periph_GPIOB
#define            GENERAL_TIM3_CH4_PORT          GPIOB
#define            GENERAL_TIM3_CH4_PIN           GPIO_Pin_1

/**************************函数声明********************************/

void GENERAL_TIM3_Init(void);

#endif	/* __BSP_GENERALTIME_H */

main函数:

int main(void)
{
	LED_GPIO_Config();//初始化函数
	//GENERAL_TIM3_Init();
	//GENERAL_TIM2_Init();
	//GENERAL_TIM4_Init();
	GENERAL_TIM5_Init();
	
  while(1)
	{
		GPIO_ResetBits(LED2_GPIO_PORT,LED2_GPIO_PIN);
	}
}

想要验证这个程序,需要一个LED灯,当然也可以用别的可现实PWM变化的外设去替代。完整程序链接如下:

链接:https://pan.baidu.com/s/1BLrr-MkQEAeBW7fP4Z7O4g 
提取码:wa4e 
--来自百度网盘超级会员V1的分享

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

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

相关文章

05. 机器学习入门 - 动态规划

文章目录 从一个案例开始动态规划 Hi, 你好。我是茶桁。 咱们之前的课程就给大家讲了什么是人工智能,也说了每个人的定义都不太一样。关于人工智能的不同观点和方法,其实是一个很复杂的领域,我们无法用一个或者两个概念确定什么是人工智能&a…

对一条Linux命令的解读(sed find egrep)

目录 1 sed -i的意义 2 $的作用 3 find . -type f的意义 4 -exec .... {} \;的意义 5 egrep -l的意义 6 综合以上 在前面的博客源码编译elfutils_金色熊族的博客-CSDN博客中,我使用了一条指令 sed -i s/-Werror//g $(find . -type f -exec egrep -l _no_Werr…

学信息系统项目管理师第4版系列15_资源管理基础

1. 项目资源 1.1. 实物资源 1.1.1. 着眼于以有效和高效的方式,分配和使用完成项目所需的实物资源 1.1.2. 包括设备、材料、设施和基础设施 1.2. 团队资源 1.2.1. 人力资源 1.2.2. 包含了技能和能力要求 2. 人力资源管理 2.1. 不仅是组织中最重要的资源之一&…

C语言结构体指针学习

结构体变量存放内存中,也有起始地址,定义一个变量来存放这个地址,那这个变量就是结构体指针; typedef struct mydata{int a1;int a2;int a3; }mydata;void CJgtzzView::OnDraw(CDC* pDC) {CJgtzzDoc* pDoc GetDocument();ASSERT…

【算法分析与设计】回溯法(上)

目录 一、学习要点1.1 回溯法1.2 问题的解空间1.3 0-1背包问题的解空间1.4 旅行售货员问题的解空间1.5 生成问题状态的基本方法 二、回溯法的基本思想三、回溯算法的适用条件四、递归回溯五、迭代回溯六、子集树与排列树七、装载问题八、批处理作业调度问题 一、学习要点 理解回…

Scala第十一章节

Scala第十一章节 1.模式匹配 2. Option 类型 3.偏函数 4.正则表达式 5.异常处理 6.提取器 7.案例:随机职业 scala总目录 文档资料下载

大数据Flink(九十五):DML:Window TopN

文章目录 DML:Window TopN DML:Window TopN Window TopN 定义(支持 Streaming):Window TopN 是一种特殊的 TopN,它的返回结果是每一个窗口内的 N 个最小值或者最大值。 应用场景

【C语言】模拟实现strstr

strstr这个库函数看到这个名字大概率猜不到这是什么函数, 但经过学习就可以很好的认识到这个函数 目录 介绍:模拟实现:思路:代码实现: 介绍: 可以看到此函数是用来寻找一个字符串中是否含有另一个字符串 代…

云安全之HTTP协议介绍补充

HTTP是一个基于TCP/IP通信协议来传递数据的协议,传输的数据类型为HTML文件、图片文件、查询结果等。HTTP协议一般用于B/S架构。浏览器作为HTTP客户端通过URL向HTTP服务端即WEB服务器发送所有请求。 URI、URL、URN HTTP使用统一资源标识符(Uniform Resource ldentif…

WebSocket实战之二协议分析

一、前言 上一篇 WebSocket实战之一 讲了WebSocket一个极简例子和基础的API的介绍,这一篇来分析一下WebSocket的协议,学习网络协议最好的方式就是抓包分析一下什么就都明白了。 二、WebSocket协议 本想盗一张网络图,后来想想不太好&#x…

ImportSelector使用详解

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl ImportSelector概述 利用Import和ImportSelector可将组件批量添加至IoC容器 ImportSelector案例 在此,介绍ImportSelector使用案例。 定义ImportSelector S…

Kotlin前置检测判断check,require,requireNotNull

Kotlin前置检测判断check&#xff0c;require&#xff0c;requireNotNull &#xff08;1&#xff09;check fun main(args: Array<String>) {val b falsecheck(b) {println("check $b")}println("end") } check监测到值非真时候&#xff0c;抛出一…

国庆作业day5

应用层&#xff1a;提供用户与网络应用程序之间的接口。表示层&#xff1a;负责数据的格式转换、加密和解密。会话层&#xff1a;负责建立、管理和终止会话。它提供会话控制和同步&#xff0c;允许应用程序之间建立连接和交换数据。传输层&#xff1a;提供端到端的连接。网络层…

【ppt技巧】给ppt文件设置带有密码的只读模式

有没有同学&#xff0c;想要给PPT文件设置修改权限&#xff0c;却没有找到功能&#xff0c;给PPT文件设置只读模式&#xff0c;没有密码设置的&#xff1f;今天给大家分享给PPT文件设置带有密码的只读模式&#xff08;修改权限&#xff09;。 打开PPT文件之后&#xff0c;将PP…

数据结构与算法课后题-第三章(顺序队和链队)

#include <iostream> //引入头文件 using namespace std;typedef int Elemtype;#define Maxsize 5 #define ERROR 0 #define OK 1typedef struct {Elemtype data[Maxsize];int front, rear;int tag; }SqQueue;void InitQueue(SqQueue& Q) //初始化队列 {Q.rear …

WebSocket实战之一

一、前言 2017年做股票软件开始关注WebSoocket技术&#xff0c;不过当时客户端是Native采用的网络通讯框架是Netty&#xff0c;这次做收银台项目决定把WebSocket技术实践一把&#xff0c;主要应用于实时销量大盘数据展示以及消息系统提醒功能等。 注&#xff1a;一个技术点尽…

10.4号作业

Qt实现客户端搭建的代码和现象 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QTcpSocket> #include <QMessageBox>QT_BEGIN_NAMESPACE namespace Ui { class Widget; } QT_END_NAMESPACEclass Widget : public QWidget {Q_OBJ…

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石④

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石④ 第十九章 驱动程序基石④19.7 工作队列19.7.1 内核函数19.7.1.1 定义 work19.7.1.2 使用 work&#xff1a;schedule_work19.7.1.3 其他函数 19.7.2 编程、上机19.7.3 内部机制19.7.3.1 Linux 2.x的工作队列创建过程19.7.3…

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石⑤

嵌入式Linux应用开发-基础知识-第十九章驱动程序基石⑤ 第十九章 驱动程序基石⑤19.9 mmap19.9.1 内存映射现象与数据结构19.9.2 ARM架构内存映射简介19.9.2.1 一级页表映射过程19.9.2.2 二级页表映射过程 19.9.3 怎么给APP新建一块内存映射19.9.3.1 mmap调用过程19.9.3.2 cach…

傅里叶系列 P1 的定价选项

如果您想了解更多信息&#xff0c;请查看第 2 部分和第 3 部分。 一、说明 这是第一篇文章&#xff0c;我将帮助您获得如何使用这个新的强大工具来解决金融中的半分析问题并取代您的蒙特卡洛方法的直觉。 我们都知道并喜欢蒙特卡洛数字积分方法&#xff0c;但是如果我告诉你你可…