STM32 高级定时器TIM与PWM时序波形

TIM 高级控制定时器是STM32系列比较复杂的外设。可以说是一个分水岭
通过阅读这个模块,你甚至可以窥探到IC的外设为何要如此设计,因为它是满足应用层的需求。
内部的信号流动和逻辑关系是TIM的关键。
面对如此复杂的外设,只能先从全局入手,再去看内部模块的构成。最后去看分解的子模块逻辑时序关系。
在这里插入图片描述在这里插入图片描述
向下的箭头表示产生更新事件,向上的箭头代表 中断和DMA输出

TIM1 主要有几个部分组成
1.时钟输入
2.信号输入
3.一个16位向上/下计数器
4.输入处理单元(边沿检测,滤波,分频)
5.捕获比较
6,输出单元

时钟配置

1.时钟输入
来自时钟树总线的时钟CK_INT 内部时钟
来自外部输入引脚的ETR
来自内部的触发输入ITR->TRC
来自外部的TIx引脚输入

在这里插入图片描述

CNT 计数器的时钟来源还经过PSC分频器。

寄存器SMCR slave mode control register
在这里插入图片描述
从模式选择器SMS,为什么叫做从模式,主要是看框图,他是时钟输入的选择器。

直接由CK_INT提供计数器的时钟
下面代码按照分频系数7200

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	TIM_PrescalerConfig(TIM1, 7200, TIM_PSCReloadMode_Immediate);
	TIM_Cmd(TIM1,ENABLE);

从模式寄存器默认为0.

TRGI信号都有SMS管理。CEN Counter Enable 。

在这里插入图片描述

上图最左边为输入TI2,下图可以可以看到它的来源。也就是说可以使用TIM 两个通道的输入信号来驱动CNT。在这里插入图片描述

例如,要使递增计数器在 TI2 输入出现上升沿时计数,请执行以下步骤:

  1. 通过在 TIMx_CCMR1 寄存器中写入 CC2S =“01”来配置通道 2,使其能够检测 TI2输入的上升沿。
  2. 通过在 TIMx_CCMR1 寄存器中写入 IC2F[3:0] 位来配置输入滤波时间(如果不需要任何滤波,请保持 IC2F=0000)。
  3. 通过在 TIMx_CCER 寄存器中写入 CC2P=0 和 CC2NP=0 来选择上升沿极性。
  4. 通过在 TIMx_SMCR 寄存器中写入 SMS=111,使定时器在外部时钟模式 1 下工作。
  5. 通过在 TIMx_SMCR 寄存器中写入 TS=110 来选择 TI2 作为触发输入源。
  6. 通过在 TIMx_CR1 寄存器中写入 CEN=1 来使能计数器。

官方手册上对于时钟的配置步骤如上
.CCMR capture/compare mode register

  1. 通过在 TIMx_CCMR1 寄存器中写入 CC2S =“01”来配置通道 2,使其能够检测 TI2输入的上升沿。
    CC2为输入模式
    在这里插入图片描述
    IC2 映射到TI2上,如下图所示
    在这里插入图片描述
    通过在 TIMx_CCER 寄存器中写入 CC2P=0 和 CC2NP=0 来选择上升沿极性。

  2. 刚才配置的是输入
    所以OC1,OC1N都是高电平有效。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

  3. 通过在 TIMx_SMCR 寄存器中写入 TS=110 来选择 TI2 作为触发输入源。在这里插入图片描述
    6。CEN=1 使能计数器
    在这里插入图片描述

2.外部时钟模式
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
这种模式下的信号通路图。
该种方法比较简单在SMCR寄存器的几个控制位就可以配置完成。
1.配置使能 ECE=1
2.配置滤波器000
3.预分频配置
4.跳边沿记性配置
5.使能CNT

计数方式

向上
重点------------事件

在递增计数模式下,计数器从 0 计数到自动重载值( TIMx_ARR 寄存器的内容),然后重新从 0 开始计数并生成计数器上溢事件
如果使用重复计数器,则当递增计数的重复次数达到重复计数器寄存器中编程的次数加一次(TIMx_RCR+1) 后,将生成更新事件
(UEV)。否则,将在每次计数器上溢时产生更新事件。

上溢事件 和 更新事件

通过软件将 TIMx_CR1 寄存器中的 UDIS 位置 1 可禁止 UEV 事件。
发生更新事件时,将更新所有寄存器且将更新标志( TIMx_SR 寄存器中的 UIF 位)置 1(取
决于 URS 位):
● 重复计数器中将重新装载 TIMx_RCR 寄存器的内容
● 自动重载影子寄存器将以预装载值 (TIMx_ARR) 进行更新
● 预分频器的缓冲区中将重新装载预装载值( TIMx_PSC 寄存器的内容)

在这里插入图片描述
重复计数器可以产生UI中断

递减计数模式
在递减计数模式下,计数器从自动重载值( TIMx_ARR 寄存器的内容)开始递减计数到 0,然后重新从自动重载值开始计数并生成计数器下溢事件。

此外,如果 TIMx_CR1 寄存器中的 URS 位(更新请求选择)已置 1,则将 UG 位置 1 会生
成更新事件 UEV,但不会将 UIF 标志置 1(因此,不会发送任何中断或 DMA 请求)。这样
一来,如果在发生捕获事件时将计数器清零,将不会同时产生更新中断和捕获中断。

中心对齐模式(递增/递减计数)
在中心对齐模式下,计数器从 0 开始计数到自动重载值( TIMx_ARR 寄存器的内容) — 1,生成计数器上溢事件;然后从自动重载值开始向下计数到 1 并生成计数器下溢事件。之后从0 开始重新计数。

重复计数器
只有当重复计数器达到零时,才会生成更新事件。
重复计数器在下列情况下递减:
● 递增计数模式下的每个计数器上溢。
● 递减计数模式下的每个计数器下溢。
● 中心对齐模式下每个计数器上溢和计数器下溢。尽管这使得最大重复次数不超过 128 个
PWM 周期,但在每个 PWM 周期内可更新占空比两次。当在中心对齐模式下,每个
PWM 周期仅刷新一次比较寄存器时,由于模式的对称性,最大分辨率为 2xTck。

上溢事件,或者下溢事件产生后,重复计数器才会递减。上溢或者下溢事件的产生是应为ARR的开启

练习(1)
时钟分频,上溢事件,重复计数更新事件,中断产生
168M/50400 = 3333.33

void app_tim_train1(void)

{
	NVIC_InitTypeDef NVIC_InitStruct;


	NVIC_InitStruct.NVIC_IRQChannel =TIM1_UP_TIM10_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority =3;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority =0;
	NVIC_Init(&NVIC_InitStruct);

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

	TIM_PrescalerConfig(TIM1,50400,TIM_PSCReloadMode_Immediate);

	TIM_SetAutoreload(TIM1,3333);
	TIM1->RCR = 3;

	
	TIM_ARRPreloadConfig(TIM1, ENABLE);	



	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);

	TIM_Cmd(TIM1,ENABLE);

}
void TIM1_UP_TIM10_IRQHandler(void)
{
	GPIO_ToggleBits(GPIOF,GPIO_Pin_9);

	TIM_ClearITPendingBit(TIM1, TIM_IT_Update);
}


对CNT的监控方法,使用SEGGER J SCOPE
初始化的方法

	uint16_t buf[1024];
	SEGGER_RTT_ConfigUpBuffer(1, "JScope_u2", buf, 2048, SEGGER_RTT_MODE_NO_BLOCK_SKIP);

在task的循环中加入数据上传

    while(1)
    {
    
 		SEGGER_RTT_Write(1, &TIM1->CNT, 2);
        vTaskDelay(10);
	
     
    }

图形如下所示
在这里插入图片描述
vTaskDelay(1);
在这里插入图片描述

可以看到CNT的计数方式是递增计数,达到Reload值的时候变为 0,从新开始计数

使用递减计数时的CNT变化

	TIM_CounterModeConfig(TIM1,TIM_CounterMode_Down);

在这里插入图片描述

TIM_CounterModeConfig(TIM1,TIM_CounterMode_CenterAligned3);

在这里插入图片描述

捕获/比较通道

捕获/比较 的运作方式入下图所示
输入模式下 捕获的意思是在捕获信号触发下抓取CNT计数器的值(下图“捕获处”)
输出模式下 是比较器,比较CNT与寄存器的值产生产生输出(下图比较器“”)
在这里插入图片描述
图99为输出阶段的控制,在比较器产生了比较结果后,信号传输到上图的输出模式控制器,从而产生OC1REF信号。这个信号同时分两路
通过不同的寄存器分别输出到OC1,OC1N管脚上。

要搞清楚捕获比较,就必须对上面的两张图中的信号流动寄存器作用有深刻的认知。
图98
CCR 捕获比较寄存器
CC1S:捕获/比较 1 选择 (Capture/Compare 1 Selection),选择CC1通道输入还输出。
以上两项,输出状态下才需要填入CCR值。因为输入状态下是捕获CNT值。

OC1PE:输出比较 1 预装载使能 (Output Compare 1 preload enable) CCR的预装载使能
UEV 更新事件
OC1PE | UEV 表示更新时是否使用预装载,或者直接装载

所以需要确定当前是输出状态,写入到CCR的值才会有效。

一但输入有效,那么比较器就会产生比较
CNT >CCR1
CNT =CCR1
比较的结果会输入到输出模式控制器
图99
输出模式控制器,决定OC1REF的输出

OC1CE:输出比较 1 清零使能 (Output Compare 1 Clear Enable)
0: OC1Ref 不受 ETRF 输入影响
1: ETRF 输入上检测到高电平时, OC1Ref 立即清零。

OC1M Output Compare 1 mode

也就是利用
CNT >CCR1
CNT =CCR1
这两个信号来产生不同的OC1REF
前三中模式 主要是 CNT =CCR1 信号
后几种主要是 CNT >CCR1 信号
在这里插入图片描述

死区的配置暂时跳过。

CC1E:捕获 / 比较 1 输出使能 (Capture/Compare 1 output enable)
CC1NE:捕获 / 比较 1 互补输出使能 (Capture/Compare 1 complementary output enable)

这组寄存器,控制信号是否流到下个节点。

CC1P:捕获/比较 1 输出极性 (Capture/Compare 1 output polarity)
OC1REF为有效信号时,输出使能电路的输入电平为 高还是低
CC1NP同理

输出使能电路

CC1NE:捕获 / 比较 1 互补输出使能 (Capture/Compare 1 complementary output enable)
CC1E:捕获 / 比较 1 输出使能 (Capture/Compare 1 output enable)
用来使能OC1,OC1N

MOE:主输出使能 (Main output enable)
OC 和 OCN 的共同使能位,禁止时OC 和 OCN 进入空闲模式

OSSI:空闲模式下的关闭状态选择 (Off-state selection for Idle mode)
OC 和 OCN 此位在 MOE=0 时作用于配置为输出的通道

OSSR:运行模式下的关闭状态选择 (Off-state selection for Run mode)
此位在 MOE=1 时作用于配置为输出模式且具有互补输出的通道。如果定时器中没有互补输出,则不存在 OSSR。

设置完成以上的信号,OC1,OC1N即可产生我们需要的PWM信号

练习(2)
下面的代码直接操作了寄存器,原因是根据手册上的图一步一步的设定参数
了解外围设备的内部运作和逻辑关系,这里修炼的是内功。库函数和HAL库是招式。

void app_tim_train2(void)
{


	TIM_OCInitTypeDef TIM_OCInitStruct;
	app_tim1_train2_gpio();
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

	TIM_PrescalerConfig(TIM1,16800,TIM_PSCReloadMode_Immediate);
	TIM_CounterModeConfig(TIM1,TIM_CounterMode_CenterAligned3);

	TIM_SetAutoreload(TIM1,10000);
	
	TIM_ARRPreloadConfig(TIM1, ENABLE);	
	
	



	/*CC1S   output  bit 1:0  00  */
	TIM1->CCMR1 = TIM1->CCMR1 & 0xFFFC;

	/*OC1CE  bit 7  8+0+2+1=11->B   0xFFBF  */
	TIM1->CCMR1 = TIM1->CCMR1 & 0xFFBF;

	/*OC1M 6:4  110=5    6<<4*/
	TIM1->CCMR1 = TIM1->CCMR1 | (0x0006<<4);


	/*	CC1E Bit 0,CC1EN bit2     1111=	F	*/
	TIM1->CCER = TIM1->CCER | ( 0x000F );

	/*CC1P  bit1 set 0 CC1PN bit 3 set 0        0110 =6 */
	//TIM1->CCER = TIM1->CCER & 0xFFF6;

	/*MOE bit15 1*/
	TIM1->BDTR = TIM1->BDTR | (0x0001<<15);

	/*OSSR bit11 set 1*/
	//TIM1->BDTR = TIM1->BDTR | (0x0001<<11);

	TIM_SetCompare1(TIM1,1000);

	TIM_Cmd(TIM1,ENABLE);


}

在这里插入图片描述

CNT和OC1输出应交的情况上图所示。
使用J-SCOPE HSS模式显示多变量

uint16_t Tim_cnt=0;
uint16_t Tim_gpio_out=0;
uint16_t Tim_gpio_ou2t=0;
void task2_task(void *pvParameters)
{
    while(1)
    {
		Tim_cnt = TIM1->CNT;
		Tim_gpio_out = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_8);
		Tim_gpio_ou2t = GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_13);
        vTaskDelay(1);
    }
    
}

可以看到CNT < CCR的时候输出的是低电平(无效电平),CNT>CCR的时候输出是高电平。OC1M位决定
在这里插入图片描述
OC1M = 111如上图所示
111: PWM 模式 2–– 在递增计数模式下,只要 TIMx_CNT<TIMx_CCR1,通道 1 便为无
效状态,否则为有效状态。在递减计数模式下,只要 TIMx_CNT>TIMx_CCR1,通道 1 便为
有效状态,否则为无效状态。
无效状态 的电位值 是多少

/*CC1P  bit1 set 0 CC1PN bit 3 set 0        0110 =6 */
	//TIM1->CCER = TIM1->CCER & 0xFFF6;
CC1P:捕获/比较 1 输出极性 (Capture/Compare 1 output polarity)
CC1 通道配置为输出:
0: OC1 高电平有效
1: OC1 低电平有效

Bit1 为1 也就是低电平有效,高电平无效,所以TIMx_CNT<TIMx_CCR1 输出无效也就是高电平。

互补输出和死区

互补输出已经介绍过。
死区的概念大体上是 互补PWM输出的时候两路信号的跳变沿会错开一段时间。来源是电子电路开关管防止上下管同时导通产生短路的对策,不再展开叙述。

CCxE 和 CCxNE 位同时置 1 并且 MOE 位置 1(如果存在断路)时,将使能死区插入
CC1NE:捕获 / 比较 1 互补输出使能 (Capture/Compare 1 complementary output enable)
CC1E:捕获 / 比较 1 输出使能 (Capture/Compare 1 output enable)
用来使能OC1,OC1N

● 输出信号 OCx 与参考信号相同,只是其上升沿相对参考上升沿存在延迟。
● 输出信号 OCxN 与参考信号相反,并且其上升沿相对参考下降沿存在延迟。

输入捕获

输入捕获也就是检测到触发信号后,捕获CNT计数器的数值。触发信号可以使TIx.
在这里插入图片描述
上图的TIMx_CH1输入信号,经过边沿检测和滤波信号后,传输到捕获比较寄存器,用于触发捕获。
那么详细的过程,会回到图98。这次只看左半部分
在这里插入图片描述

CCR1H,CCR1L 就是CCR捕获寄存器
CC1S:捕获/比较 1 选择 (Capture/Compare 1 Selection)
此位域定义通道方向(输入/输出)以及所使用的输入。

在这里插入图片描述
IC1PS 输入信号
CC1E:捕获 / 比较 1 输出使能 (Capture/Compare 1 output enable)
CC1 通道配置为输入:
此位决定了是否可以实际将计数器值捕获到输入捕获 / 比较寄存器 1 (TIMx_CCR1) 中。
0:禁止捕获。
1:使能捕获。

CC1G:捕获/比较 1 生成 (Capture/Compare 1 generation)
此位由软件置 1 以生成事件,并由硬件自动清零。
软件捕获触发
捕获的触发部分比较单纯 ,触发捕获是由使能和信号组成

输入信号的配置
在这里插入图片描述
TI1 信号
CC1S:捕获/比较 1 选择 (Capture/Compare 1 selection)此位域定义通道方向(输入/输出)以及所使用的输入。
00: CC1 通道配置为输出
01: CC1 通道配置为输入, IC1 映射到 TI1 上
10: CC1 通道配置为输入, IC1 映射到 TI2 上
11: CC1 通道配置为输入, IC1 映射到 TRC 上。此模式仅在通过 TS 位( TIMx_SMCR 寄存器)选择内部触发输入时有效
CC1S直接 选择TI1 或者TI2

然后自取配置输入滤波器和边沿检测器

IC1F[3:0]:输入捕获 1 滤波器 (Input capture 1 filter)
此位域可定义 TI1 输入的采样频率和适用于 TI1 的数字滤波器带宽。数字滤波器由事件计数器组成,
每 N 个事件才视为一个有效边沿:
0000:无滤波器,按 fDTS 频率进行采样
0001: fSAMPLING=fCK_INT, N=2

经过数字滤波器的信号 TI1FP1 过IC1选择
CC1 通道配置为输入:
CC1NP/CC1P 位可针对触发或捕获操作选择 TI1FP1 和 TI2FP1 的有效极性。
00:非反相/上升沿触发电路对 TIxFP1 上升沿敏感(在复位模式、外部时钟模式或触发模式下执行捕获或触发操作), TIxFP1 未反相(在门控模式或编码器模式下执行触发操作)。
01:反相/下降沿触发
电路对 TIxFP1 下升沿敏感(在复位模式、外部时钟模式或触发模式下执行捕获或触发操作), TIxFP1 反相(在门控模式或编码器模式执行触发操作)。
10:保留,不使用此配置。
11:未反相/边沿触发。
电路对 TIxFP1 上升沿和下降沿都敏感(在复位模式、外部时钟模式或触发模式下执行捕获或触发操作), TIxFP1 未反相(在门控模式下执行触发操作)。编码器模式下不得使用此配置。

对输入预分频器进行编程。

发生输入捕获时:
● 发生有效跳变沿时, TIMx_CCR1 寄存器会获取计数器的值。
● 将 CC1IF 标志置 1(中断标志)。如果至少发生了两次连续捕获,但 CC1IF 标志未被清零,这样 CC1OF 捕获溢出标志会被置 1。
● 根据 CC1IE 位生成中断。
● 根据 CC1DE 位生成 DMA 请求。

捕获的过程还是比较清晰的

练习(3)
使用导线把TIM1 的TIM1_CH1 输出接入到TIM8_CH1 输入
TIM1

void app_tim1_train2_gpio(void)
{
	/*PA 8  TIM1 CH1*/
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA ,ENABLE);


	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_7;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN ;
	GPIO_InitStruct.GPIO_Speed =GPIO_Speed_25MHz;


	GPIO_Init(GPIOA,&GPIO_InitStruct);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1);
	GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1);

}
/*TIM 1PWM  output*/
void app_tim_train2(void)
{


	TIM_OCInitTypeDef TIM_OCInitStruct;
	app_tim1_train2_gpio();
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);

	TIM_PrescalerConfig(TIM1,16800,TIM_PSCReloadMode_Immediate);
	TIM_CounterModeConfig(TIM1,TIM_CounterMode_CenterAligned3);

	TIM_SetAutoreload(TIM1,10000);
	
	TIM_ARRPreloadConfig(TIM1, ENABLE);	
	
	
	/*compare*/
	TIM_OCInitStruct.TIM_OCIdleState = TIM_OCIdleState_Set;
	TIM_OCInitStruct.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
	
	TIM_OCInitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStruct.TIM_OCNPolarity = TIM_OCNPolarity_Low;
	TIM_OCInitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	
	TIM_OCInitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
	TIM_OCInitStruct.TIM_OutputState = TIM_OutputState_Enable ; 
	TIM_OCInitStruct.TIM_Pulse= 3000;
	TIM_OC1Init(TIM1, &TIM_OCInitStruct);
	
	TIM1->BDTR = TIM1->BDTR | (0x0001<<15);


	TIM_Cmd(TIM1,ENABLE);

}

TIM 1 输出的是周期为2 second 的占空比30%的PWM信号
TIM8 使用一个输入通道去测量 TIM1 的周期
TIM8 预分频后 3333CNT为1second

/*Input capture train3*/
void app_tim1_train3_gpio(void)
{
	/*PC6 TIM8 CH1 */
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC ,ENABLE);


	GPIO_InitTypeDef  GPIO_InitStruct;
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF;
	GPIO_InitStruct.GPIO_OType = GPIO_OType_PP;
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	GPIO_InitStruct.GPIO_PuPd = GPIO_PuPd_DOWN ;
	GPIO_InitStruct.GPIO_Speed =GPIO_Speed_25MHz;


	GPIO_Init(GPIOC,&GPIO_InitStruct);
	GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8);


}

void app_tim_train3(void)
{	
	/*use TIM8 to capture TIM1  PWM */
	NVIC_InitTypeDef  NVIC_InitStruct;


	NVIC_InitStruct.NVIC_IRQChannel = TIM8_CC_IRQn;
	NVIC_InitStruct.NVIC_IRQChannelCmd= ENABLE;
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 13;
	NVIC_InitStruct.NVIC_IRQChannelSubPriority =0;

	app_tim1_train3_gpio();

	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE);
	
	TIM_PrescalerConfig(TIM8,50400,TIM_PSCReloadMode_Immediate);

	TIM_CounterModeConfig(TIM8,TIM_CounterMode_Up);



	

	/*input selcet CC1S bit 1:0   IC1->TI1  set 01  */
	TIM8->CCMR1 = TIM8->CCMR1 | (0x0001);


	/*CC1E (Capture/Compare 1 output enable)*/
	/*bit 0 enable capture set 1*/
	TIM8->CCER  = TIM8->CCER  | (0x0001);

	/*IC1F[3:0]: (Input capture 1 filter)*/
	/*set 000 */
	TIM8->CCMR1 =TIM8->CCMR1 & (0xFFF8);

	/*CC1P: (Capture/Compare 1 output polarity)*/
	/*bit 1 bit3  0X0X*/
	TIM8->CCER = TIM8->CCER & (0xFFF5);

	NVIC_Init(&NVIC_InitStruct);
	TIM_ITConfig(TIM8,TIM_IT_CC1,ENABLE);
	TIM_Cmd(TIM8,ENABLE);

}
void TIM8_CC_IRQHandler(void)
{
		value_ccr1_head =TIM8->CCR1;
		TIM_ClearITPendingBit(TIM8, TIM_IT_CC1);
		TIM_SetCounter(TIM8,0x0000);
}

在这里插入图片描述
0x1A0B = 6667
对应周期为 6667/3333 = 2second

PWM输入模式

输入PWM检测PWM的周期和占空比
1.周期 两个相同跳边沿之间的CNT数值
2.占空比 第一个跳边沿和第二个跳边沿之间的CNT值

使用两个捕获比较器
在这里插入图片描述
一个端口的输入可以配置到两个比较器上。PWM输入的原理就是这里。

例如,你需要测量输入到TI1上的PWM信号的长度(TIMx_CCR1寄存器)和占空比(TIMx_CCR2寄存器),具体步骤如下(取决于CK_INT的频率和预分频器的值)
● 选择TIMx_CCR1的有效输入:置TIMx_CCMR1寄存器的CC1S=01(选中TI1)。
在这里插入图片描述
选择输入的通道 CCR1输入为TI1
● 选择TI1FP1的有效极性(用来捕获数据到TIMx_CCR1中和清除计数器):置CC1P=0(上升沿有效)。
配置上升沿有效
● 选择TIMx_CCR2的有效输入:置TIMx_CCMR1寄存器的CC2S=10(选中TI1)。
在这里插入图片描述
配置输入通道CCR2 对应为TI1
● 选择TI1FP2的有效极性(捕获数据到TIMx_CCR2):置CC2P=1(下降沿有效)。

   配置CCR2 为下降沿有效,所以这个通道测的是占空比

分配好两个捕获信号极性后,那么需要一个信号在测量一次后重置计数器。选择触发信号
在这里插入图片描述

其实触发信号并不是和时钟信号使用同一根信号线。上图的画法多少存在一些歧义。

● 选择有效的触发输入信号:置TIMx_SMCR寄存器中的TS=101(选择TI1FP1)。
在这里插入图片描述
在这里插入图片描述
选择触发信号
● 配置从模式控制器为复位模式:置TIMx_SMCR中的SMS=100。
从模式选择器的意思是 触发信号来临时 100:复位模式––在出现所选触发输入 (TRGI) 上升沿时,重新初始化计数器并生成一个寄存器更 新事件。其作用域是CNT
● 使能捕获:置TIMx_CCER寄存器中CC1E=1且CC2E=1。
使能CCR1,CCR2
在这里插入图片描述
TI1信号出现上升沿的时候,CNT进行复位,这个时候CCR1 进行捕获。下降沿来领时,CCR2 捕获CNT。再次上升时CCR1捕获周期值
那么PWM的周期T = CCR1 +1,占空比 (CCR2+1)/(CCR1+1) *100%
上图视乎有个矛盾就是第一个上升沿的时候CCR2 为什么会执行捕获,后面有待考证
如下图所示捕获的条件由 CC1S 输入模式,IC1PS输入,CC1E输入选择,和软件触发EGR决定,所以上升沿的时候CCR2 应该不会捕获。
而且上图CCR1,CCR2的值时钟分别是0004,0002,这不对,只有在捕获的时候CCR的值才会更新。所以官方的给图示有问题。
在这里插入图片描述

输出比较模式

当捕获/比较寄存器与计数器之间相匹配时,输出比较功能:
● 将为相应的输出引脚分配一个可编程值,该值由输出比较模式( TIMx_CCMRx 寄存器中的 OCxM 位)和输出极性( TIMx_CCER 寄存器中的 CCxP 位)定义。匹配时,输出引脚既可保持其电平 (OCXM=000),也可设置为有效电平 (OCXM=001)、无效电平(OCXM=010) 或进 行翻转 (OCxM=011)。
● 将中断状态寄存器中的标志置 1( TIMx_SR 寄存器中的 CCxIF 位)。
● 如果相应中断使能位( TIMx_DIER 寄存器中的 CCXIE 位)置 1,将生成中断。
● 如果相应 DMA 使能位( TIMx_DIER 寄存器的 CCxDE 位, TIMx_CR2 寄存器的 CCDS位,用来选择 DMA 请求)置 1,将发送 DMA 请求。
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值