STM32笔记归纳9:定时器

定时器

目录

定时器

一、时基单元

1.1.定时器简介

1.2.时基单元的基本结构

1.3.上计数、下计数和中心对齐

1.3.1.上计数

1.3.2.下计数

1.3.3.中心对齐

1.4.时钟的来源

1.5.寄存器预加载

二、自制延迟函数

2.1.获取单片机的当前时间

2.2.实现延迟函数

2.3.初始化时基单元

2.3.1.使能时钟

2.3.2.配置时基单元的参数

2.3.3.使能总开关

2.4.4.总代码

2.4.配置中断

2.4.1.开启中断

2.4.2.配置NVIC

2.5.编写中断响应函数

2.6.总代码

三、输出比较

3.1.输出比较简介

3.2.基本工作原理(PWM)

3.3.8种工作模式

3.4.互补输出

3.5.极性选择

四、呼吸灯实验

4.1.呼吸灯原理

4.2.初始化IO引脚

4.3.配置时基单元

4.4.配置输出比较的参数

4.5.改变PWM占空比

4.6.总代码

五、输入捕获

5.1.输入捕获的基本原理

5.2.输入捕获的内部结构

5.3.输入滤波

5.4.边沿检测

5.5.信号选择

5.6.分频器

六、超声波测距实验

6.1.HCSR04模块的使用方法

6.2.搭建电路

6.3.梳理思路

6.4.初始化时基单元

6.5.初始化输入捕获

6.6.编程

七、从模式控制器

7.1.什么是从模式控制器

7.2.8种从模式

7.3.8种主模式

7.4.定时器级联的例子

7.5.定时器同时启停的例子

八、PWM参数测量原理

8.1.参考手册的定时器结构框图

8.2.输入捕获节点的名字

8.3.TRGI的来源

8.4.PWM参数测量原理

九、PWM参数测量实验

9.1.实验原理

9.2.产生PWM信号

9.3.初始化时基单元

9.4.初始化输入捕获

9.5.初始化模式控制器

9.6.测量PWM参数


一、时基单元

1.1.定时器简介

单片机内部的片上外设

参考手册13:高级定时器(TIM1、TIM8功能最全)

参考手册14:通用定时器(TIM2~5、TIM9~14)

参考手册15:基本定时器(TIM6、TIM7)

定时器结构框图:

1.2.时基单元的基本结构

**时钟来源:**产生时基单元的时钟信号

  • 来源1:时钟树
  • 来源2:从模式控制器

**预分频器:**对时钟信号进行降频

  • 分频系数:/ (PSC + 1)

**计数器(CNT):**对分频后的脉冲信号计数

  • 每来一个脉冲,计数器加一

**自动重装寄存器(ARR):**设置定时周期

  • 当计数器增长到与ARR相等时溢出
  • 计数器从0开始重新进行计数
  • 周期等于ARR+1

**重复计数器(RCR):**设置重复计算的次数

  • 计数器需要溢出RCR+1次才会产生update事件

1.3.上计数、下计数和中心对齐

1.3.1.上计数
1.3.2.下计数
1.3.3.中心对齐

1.4.时钟的来源

**分辨率:**计时的最小间隔(比如手表:1s)

周期: 循环一次的总时间(比如手表:60s)

时钟来源:

TIM1:

如果APB2分频器的分频系数为1

倍频器的倍频系数为1,TIM_CLK = PCLK2

如果APB2分频器的分频系数不为1

倍频器的倍频系数为2,TIM_CLK = PCLK2 * 2

TIM2~4:

如果APB1分频器的分频系数为1

倍频器的倍频系数为1,TIM_CLK = PCLK1

如果APB2分频器的分频系数不为1

倍频器的倍频系数为2,TIM_CLK = PCLK1 * 2

**示例:**将TIM3的时基单元设置为分辨率1us、周期1ms

1us = 1 * 10^(-6) s = 1MHz

1MHz = 72MHz / (71 + 1)

1ms = (999 + 1) * 1us

输入信号的频率为72MHz

预分频器PSC设置为71

自动重装载寄存器ARR设置为999

重复计数器RCR设置为0

1.5.寄存器预加载

**预加载:**将修改值存入影子寄存器,等到上一个周期结束后再生效

示例:

假设不使用寄存器预加载,在定时器运行过程中突然改变ARR

写入值立即生效,如果当前值大于改变值,则会一直增加到65535

再次发生溢出,此时的周期就变成了65536

二、自制延迟函数

**延迟函数:**系统滴答定时器(内核定时器)

2.1.获取单片机的当前时间

配置时基单元,让单片机每毫秒产生一个中断

创建记录时间的变量

cpp 复制代码
//记录当前时间(单位:ms)
volatile uint32_t currentTick = 0;

**注:**volatile关键字:防止编译器对变量进行优化,保证每次访问变量时都直接从其内存地址读取或写入,而不是使用可能过期的缓存值

2.2.实现延迟函数

cpp 复制代码
//
//@简介:延迟一段时间
//@参数:ms:要延迟的时间(单位:ms)
//
void App_Delay(uint32_t ms)
{
	/*设置延迟结束时间*/
	uint32_t expireTime = currentTick + ms;
	/*等待延迟结束*/
	while(currentTick < expireTime);
}

2.3.初始化时基单元

2.3.1.使能时钟
cpp 复制代码
//#1:开启定时器3的时钟
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
2.3.2.配置时基单元的参数
cpp 复制代码
//#2:配置时基单元的参数
/*声明TIM结构体变量*/
TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
/*设置预分频系数*/
TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
/*设置自动重装寄存器*/
TIM_TimeBaseInitStruct.TIM_Period = 999;
/*设置计数方向*/
TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
/*设置重复计数器*/
TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
/*初始化TIM3*/
TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
2.3.3.使能总开关
cpp 复制代码
//#3:闭合时基单元的开关
TIM_Cmd(TIM3,ENABLE);
2.4.4.总代码
cpp 复制代码
//创建TIM3初始化函数
void App_TIM3_TimeBaseInit(void)
{
	//#1:开启定时器3的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	//#2:配置时基单元的参数
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//#3:闭合时基单元的开关
	TIM_Cmd(TIM3,ENABLE);
}

2.4.配置中断

2.4.1.开启中断
cpp 复制代码
void TIM_ITConfig(TIM_TypeDef* TIMx,uint16_t TIM_IT,FunctionalState NewState);

解析:

**参数1:**定时器名字

**参数2:**中断的名字

  • TIM_IT_Update
  • TIM_IT_Trigger
  • TIM_IT_CC1~TIM_IT_CC4

**参数3:**ENALE(使能)DISABLE(禁止)

**作用:**使能/禁止定时器的中断

cpp 复制代码
//#4:使能Update中断
TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
2.4.2.配置NVIC
cpp 复制代码
int main(void)
{
	/*配置中断优先级分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	App_TIM3_TimeBaseInit();

	while(1)
	{
		
	}
}

//创建TIM3初始化函数
void App_TIM3_TimeBaseInit(void)
{
	//#1:开启定时器3的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	//#2:配置时基单元的参数
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//#3:闭合时基单元的开关
	TIM_Cmd(TIM3,ENABLE);
	
	//#4:使能Update中断
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
	
	//#5:配置NVIC模块
	/*声明NVIC结构变量*/
	NVIC_InitTypeDef NVIC_InitStruct;
	/*设置TIM3_IRQn中断名称*/
	NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
	/*设置抢占优先级*/
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	/*子优先级*/
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	/*闭合中断开关*/
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	/*初始化NVIC*/
	NVIC_Init(&NVIC_InitStruct);
}

2.5.编写中断响应函数

cpp 复制代码
void TIM3_IRQHandler(void)
{
	/*如果是Update触发中断*/
	if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET)
	{
		/*清除中断标志位*/
		TIM_ClearFlag(TIM3,TIM_FLAG_Update);
		/*时间变量加一*/
		currentTick++;
	}
}

2.6.总代码

cpp 复制代码
#include "stm32f10x.h"

//记录当前时间(单位:ms)
volatile uint32_t currentTick = 0;
//声明延迟函数
void App_Delay(uint32_t ms);
//声明TIM3初始化函数
void App_TIM3_TimeBaseInit(void);
//声明板载LED初始化函数
void App_OnBoardLED_Init(void);

int main(void)
{
	/*配置中断优先级分组*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	App_TIM3_TimeBaseInit();
	App_OnBoardLED_Init();
	while(1)
	{
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
		App_Delay(50);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		App_Delay(500);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
		App_Delay(50);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		App_Delay(500);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_RESET);
		App_Delay(500);
		GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
		App_Delay(500);
	}
}

void TIM3_IRQHandler(void)
{
	/*如果是Update触发中断*/
	if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET)
	{
		/*清除中断标志位*/
		TIM_ClearFlag(TIM3,TIM_FLAG_Update);
		/*时间变量加一*/
		currentTick++;
	}
}

//
//@简介:延迟一段时间
//@参数:ms:要延迟的时间(单位:ms)
//
void App_Delay(uint32_t ms)
{
	/*设置延迟结束时间*/
	uint32_t expireTime = currentTick + ms;
	/*等待延迟结束*/
	while(currentTick < expireTime);
}

//创建TIM3初始化函数
void App_TIM3_TimeBaseInit(void)
{
	//#1:开启定时器3的时钟
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	
	//#2:配置时基单元的参数
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
	
	//#3:闭合时基单元的开关
	TIM_Cmd(TIM3,ENABLE);
	
	//#4:使能Update中断
	TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE);
	
	//#5:配置NVIC模块
	/*声明NVIC结构变量*/
	NVIC_InitTypeDef NVIC_InitStruct;
	/*设置TIM3_IRQn中断名称*/
	NVIC_InitStruct.NVIC_IRQChannel = TIM3_IRQn;
	/*设置抢占优先级*/
	NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;
	/*子优先级*/
	NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;
	/*闭合中断开关*/
	NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
	/*初始化NVIC*/
	NVIC_Init(&NVIC_InitStruct);
}


//创建板载LED初始化函数
void App_OnBoardLED_Init(void)
{
	/*启动GPIOC时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PC13引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	/*通用输出开漏模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PC13引脚*/
	GPIO_Init(GPIOC,&GPIO_InitStruct);
	/*熄灭板载LED*/
	GPIO_WriteBit(GPIOC,GPIO_Pin_13,Bit_SET);
}

三、输出比较

3.1.输出比较简介

中间是CCRx寄存器:

捕获比较寄存器

左边为输入捕获

外部信号通过CHx引脚输入到定时器内部,测量输入信号的周期、占空比等参数

右边为输出比较

通过定时器产生稳定性方波信号,再由CHx引脚将信号输出

3.2.基本工作原理(PWM)

**PWM(Pulse Width Modulation):**脉冲宽度调制

一种周期固定、占空比可调的信号,通过调节占空比,等效地调节信号的输出幅度

**占空比:**一个周期中,高电平占整个周期的比例

**示例:**使用定时器生成30%占空比的方波信号

3.3.8种工作模式

**OCxRef(Output Compare x Reference):**输出比较通道x参考

**冻结:**OCxRef保持原有的电平不变

**相等有效(高电平):**当CNT与CCR相等时,OCxRef输出高电平,否则为低电平

**相等无效(低电平):**当CNT与CCR相等时,OCxRef输出低电平,否则为高电平

**翻转:**当CNT与CCR相等时,电平高低切换

**强制无效:**OCxRef始终为低电平

**强制有效:**OCxRef始终为高电平

**PWM模式1:**当CNT < CCR时,OCxRef为高电平,否则为低电平

**PWM模式2:**当CNT < CCR时,OCxRef为低电平,否则为高电平

3.4.互补输出

**互补输出:**参考信号经过反相器与CHxN引脚相连,与正常输出的电平波形相反

**示例:**通过同步buck电路将12V的电压降为3.3V

3.5.极性选择

**目的:**灵活翻转输出电平的有效极性

四、呼吸灯实验

4.1.呼吸灯原理

蓝色Led:连接在定时器1通道1的正常输出(CH1)

红色Led:连接在定时器1通道1的互补输出(CH1N)

**现象本质:**让Led的亮度连续变化

y = 0.5 * (sin(2πt) + 1)

波形配置:

占空比 = 0.5 * (sin(2πt) + 1)

周期 = 1ms

4.2.初始化IO引脚

Led长脚为正极

cpp 复制代码
void App_PWM_Init(void)
{
	//#1:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA8*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOB的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	/*选择PB13引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PB13*/
	GPIO_Init(GPIOB,&GPIO_InitStruct);
}

4.3.配置时基单元

时钟:

TIM1挂在APB2总线(分频系数为1),从PCLK2(72MHz)获取时钟信号,此时倍频系数为1

所以时钟信号为72MHz

预分频器:

分辨率为1us = 1MHz,所以PSC = 71,72 / (71 + 1) = 1MHz

自动重装寄存器:

定时周期为1ms = 1us * 1000,所以ARR = 999,1us * (999 + 1)= 1ms

重复计数器:

RCR = 0,每溢出1次,产生一次update事件

cpp 复制代码
void App_PWM_Init(void)
{
	//#1:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA8*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOB的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	/*选择PB13引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PB13*/
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	//#2:配置时基单元的参数
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	/*使能Update中断*/
	TIM_ITConfig(TIM1,TIM_IT_Update,ENABLE);
}

4.4.配置输出比较的参数

cpp 复制代码
//@简介:初始化输出比较通道1的参数
//@参数:初始化参数列表
void TIM_OC1Init(TIM_TypeDef* TIM,TIM_OCInitTypeDef* TIM_OCInitStruct);
cpp 复制代码
//@简介:闭合/断开MOE开关
//@参数:ENABLE(闭合) DISABLE(断开)
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx,FunctionalState NewState);

**注:**只有使用高级定时器时才需要闭合MOE开关

cpp 复制代码
//创建初始化PWM函数
void App_PWM_Init(void)
{
	//#1:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA8*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOB的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	/*选择PB13引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PB13*/
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	//#2:配置时基单元的参数
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	
	//#3:初始化输出比较
	
	/*声明输出比较结构体变量*/
	TIM_OCInitTypeDef TIM_InitStruct;
	/*设置为PWM1模式*/
	TIM_InitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	/*设置互补通道为高极性*/
	TIM_InitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;
	/*设置正常通道为高极性*/
	TIM_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	/*开启互补通道开关*/
	TIM_InitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
	/*开启正常通道开关*/
	TIM_InitStruct.TIM_OutputState = TIM_OutputState_Enable;
	/*设置CCR初值*/
	TIM_InitStruct.TIM_Pulse = 0;
	/*初始化通道1*/
	TIM_OC1Init(TIM1,&TIM_InitStruct);
	/*闭合MOE总开关*/
	TIM_CtrlPWMOutputs(TIM1,ENABLE);
	/*手动开启CCR预加载*/
	TIM_CCPreloadControl(TIM1,ENABLE);
}

4.5.改变PWM占空比

cpp 复制代码
//@简介:设置CCR1的值
void TIM_SetCompare1(TIM_TypeDef* TIMx,uint16_t Compare1);
cpp 复制代码
#include "stm32f10x.h"
#include "delay.h"
#include "math.h"

//声明初始化PWM函数
void App_PWM_Init(void);
	
int main(void)
{
	App_PWM_Init();
	while(1)
	{
		/*获取当前时间*/
		float t = GetTick() * 1.0e-3f;
		/*计算占空比*/
		float duty = 0.5* (sin(2*3.14*t) + 1);
		/*计算CCR1*/
		uint16_t ccr1 = duty * 1000;
		/*设置CCR1*/
		TIM_SetCompare1(TIM1,ccr1);
	}
}

4.6.总代码

cpp 复制代码
#include "stm32f10x.h"
#include "delay.h"
#include "math.h"

//声明初始化PWM函数
void App_PWM_Init(void);
	
int main(void)
{
	App_PWM_Init();
	while(1)
	{
		/*获取当前时间*/
		float t = GetTick() * 1.0e-3f;
		/*计算占空比*/
		float duty = 0.5* (sin(2*3.14*t) + 1);
		/*计算CCR1*/
		uint16_t ccr1 = duty * 1000;
		/*设置CCR1*/
		TIM_SetCompare1(TIM1,ccr1);
	}
}


//创建初始化PWM函数
void App_PWM_Init(void)
{
	//#1:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA8*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOB的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
	/*选择PB13引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PB13*/
	GPIO_Init(GPIOB,&GPIO_InitStruct);
	
	//#2:配置时基单元的参数
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	
	//#3:初始化输出比较
	
	/*声明输出比较结构体变量*/
	TIM_OCInitTypeDef TIM_InitStruct;
	/*设置为PWM1模式*/
	TIM_InitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	/*设置互补通道为高极性*/
	TIM_InitStruct.TIM_OCNPolarity = TIM_OCNPolarity_High;
	/*设置正常通道为高极性*/
	TIM_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	/*开启互补通道开关*/
	TIM_InitStruct.TIM_OutputNState = TIM_OutputNState_Enable;
	/*开启正常通道开关*/
	TIM_InitStruct.TIM_OutputState = TIM_OutputState_Enable;
	/*设置CCR初值*/
	TIM_InitStruct.TIM_Pulse = 0;
	/*初始化通道1*/
	TIM_OC1Init(TIM1,&TIM_InitStruct);
	/*闭合MOE总开关*/
	TIM_CtrlPWMOutputs(TIM1,ENABLE);
	/*手动开启CCR预加载*/
	TIM_CCPreloadControl(TIM1,ENABLE);
}

五、输入捕获

外部信号通过CHx引脚输入到定时器内部,测量输入信号的周期、占空比等参数

5.1.输入捕获的基本原理

输入信号由一个一个的上升沿与下降沿组成

输入捕获电路可以捕捉到这些电平信号变化

当事件发生时,会发生拍照动作

计数器将当前数值存放在CCR中

脉宽 = (8 - 2)/ 1us = 6us

5.2.输入捕获的内部结构

5.3.输入滤波

由输入滤波电路组成

**作用:**对输入信号进行滤波

输入信号由于噪声的影响,会在波形中产生毛刺,干扰后续测量

5.4.边沿检测

由边沿检测电路与复用器组成

**作用:**检测输入信号的变化边沿

上升沿脉冲检测上升沿,下降沿脉冲检测下降沿

5.5.信号选择

由复位器组成

**TRC:**来自于从模式控制器

**直接:**通道信号来自于本身

**间接:**通道信号来自于另一个通道

交叉引用可以节省引脚:

5.6.分频器

由分频器组成

**作用:**出现分配系数次的上升沿才能产生事件,发生拍照动作

六、超声波测距实验

6.1.HCSR04模块的使用方法

距离 = 声速(340m/s)* 时间 / 2

**VCC:**电源正

**GND:**地

**Trig:**触发引脚,用于启动测量

**Echo:**回声引脚,用于返回脉冲

工作流程:

  • 向Trig引脚输入大于10us的脉冲信号
  • 发送器连续发送8个49KHz的超声波后
  • Echo引脚立即输出高电平
  • 接收器连续接收8个周期的回声后
  • Echo引脚立即输出低电平
  • Echo引脚上的脉冲宽度等于超声波收发时间间隔
  • 通过定时器的输入捕获来测量脉冲宽度

6.2.搭建电路

6.3.梳理思路

初始化串口:

cpp 复制代码
#include "stm32f10x.h"
#include "usart.h"

//声明USART1初始化函数
void App_USART1_Init(void);
	
int main(void)
{
	App_USART1_Init();
	//测试代码
	My_USART_SendString(USART1,"Hello world. \r\n");
	
	while(1)
	{
	}
}

//创建USART1初始化函数
void App_USART1_Init(void)
{
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*声明GPIO结构*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA9引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	/*设置复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速度为10MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	/*初始化PA9引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*选择PA10引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	/*设置输入上拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	/*初始化PA10引脚*/
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	/*开启USART1模块时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	/*USART结构的前置声明*/
	USART_InitTypeDef USART_InitStruct;
	/*波特率为115200*/
	USART_InitStruct.USART_BaudRate = 115200;
	/*数据位为8位*/
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	/*停止位为1位*/
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	/*校验方式为无*/
	USART_InitStruct.USART_Parity = USART_Parity_No;
	/*收发方向为双向*/
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	/*初始化USART1*/
	USART_Init(USART1,&USART_InitStruct);
	/*闭合串口总开关*/
	USART_Cmd(USART1,ENABLE);
}

  • 对计数器CNT清零(防止CNT溢出)
  • 对CC1和CC2清零(标志位)
  • 开启定时器,闭合时基单元开关
  • 发送脉冲启动传感器
  • 等待CC1和CC2(从0变成1)
  • 关闭定时器,断开时基单元开关

6.4.初始化时基单元

**分辨率:**足够精细(不能取无限小)

**周期:**长度最大脉宽,越长越好

由于HCSR04芯片的最大测距精度最高为3mm

3mm / 340 m/s ≈ 8us

所以分辨率要小于8us,可以取1us

由于PSC、ARR、CNT、RCR都为16位寄存器

它们的值域都为0~65535

所以周期可以取65535

cpp 复制代码
//创建HCSR04初始化函数
void App_HCSR04_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
}

6.5.初始化输入捕获

注:

由于Echo引脚空闲时两边都处于低电压,所以最好配置成输入下拉模式,保证电平稳定

cpp 复制代码
//创建HCSR04初始化函数
void App_HCSR04_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	
	//#2:初始化输入捕获引脚
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
}
cpp 复制代码
//创建HCSR04初始化函数
void App_HCSR04_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	
	//#2:初始化输入捕获引脚
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输入捕获通道1
	
	/*声明IC结构变量*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	/*选择通道1*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获上升沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为直接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	/*初始化通道1*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#3:初始化输入捕获通道2
	
	/*选择通道2*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获下降沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为间接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
	/*初始化通道2*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
}

6.6.编程

cpp 复制代码
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"

//声明USART1初始化函数
void App_USART1_Init(void);
//声明HCSR04初始化函数
void App_HCSR04_Init(void);

int main(void)
{
	App_USART1_Init();
	App_HCSR04_Init();
	while(1)
	{
		//#1:向CNT写0
		TIM_SetCounter(TIM1,0);
		
		//#2:向CC1和CC2写0
		TIM_ClearFlag(TIM1,TIM_FLAG_CC1);
		TIM_ClearFlag(TIM1,TIM_FLAG_CC2);
		
		//#3:开启定时器
		TIM_Cmd(TIM1,ENABLE);
		
		//#4:向Trig引脚发送10us脉冲
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_SET);
		/*延迟10us*/
		DelayUs(10);
		GPIO_WriteBit(GPIOA,GPIO_Pin_0,Bit_RESET);
		
		//#5:等待CC1和CC2标志位
		while(TIM_GetFlagStatus(TIM1,TIM_FLAG_CC1) == RESET);
		while(TIM_GetFlagStatus(TIM1,TIM_FLAG_CC2) == RESET);
		
		//#6:关闭定时器
		TIM_Cmd(TIM1,DISABLE);
		
		/*读取CCR1的值*/
		uint16_t ccr1 = TIM_GetCapture1(TIM1);
		/*读取CCR2的值*/
		uint16_t ccr2 = TIM_GetCapture2(TIM1);
		/*计算距离:(CCR1 - CCR2)* 分辨率 * 声速 / 2*/
		float distance = (ccr2 - ccr1) * 1.0e-6f * 340.0f / 2;
		/*打印结果*/
		My_USART_Printf(USART1,"distance = %.4f\r\n",distance);
		/*延迟100ms*/
		Delay(100);
	}
}

//创建USART1初始化函数
void App_USART1_Init(void)
{
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*声明GPIO结构*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA9引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	/*设置复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速度为10MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	/*初始化PA9引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*选择PA10引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10;
	/*设置输入上拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
	/*初始化PA10引脚*/
	GPIO_Init(GPIOA, &GPIO_InitStruct);
	
	/*开启USART1模块时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	/*USART结构的前置声明*/
	USART_InitTypeDef USART_InitStruct;
	/*波特率为115200*/
	USART_InitStruct.USART_BaudRate = 115200;
	/*数据位为8位*/
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	/*停止位为1位*/
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	/*校验方式为无*/
	USART_InitStruct.USART_Parity = USART_Parity_No;
	/*收发方向为双向*/
	USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	/*初始化USART1*/
	USART_Init(USART1,&USART_InitStruct);
	/*闭合串口总开关*/
	USART_Cmd(USART1,ENABLE);
}

//创建HCSR04初始化函数
void App_HCSR04_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM1*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	
	//#2:初始化输入捕获引脚
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输入捕获通道1
	
	/*声明IC结构变量*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	/*选择通道1*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获上升沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为直接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	/*初始化通道1*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#3:初始化输入捕获通道2
	
	/*选择通道2*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获下降沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为间接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
	/*初始化通道2*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#4:初始化Trig引脚
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*选择PA0引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
	/*设置通用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP;
	/*最大输出速度为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA0引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
}

七、从模式控制器

7.1.什么是从模式控制器

**TRGI(Trigger Input):**触发输入

相当于红外接收头,接收命令

从而控制时基单元,做出指定动作

控制定时器开关、控制计数器清零、增减

**TRGO(Trigger Output):**触发输出

相当于遥控器,发送命令,将定时器内部事件输出

从而控制另外一个定时器(定时器的级联)

或者控制其他模块的采样时机(ADC模块)

7.2.8种从模式

**从模式:**通过TRGI接收控制信号,用来控制时基单元,做出相应动作

(定时器为被控对象)

8种从模式

**从模式禁止:**不通过TRGI接收控制信号

**编码器模式1:**与编码器有关

**编码器模式2:**与编码器有关

**编码器模式3:**与编码器有关

**复位模式:**TRGI上升沿对CNT清零

**门模式:**TRGI高、总开关闭合;TRGI低、总开关断开

**触发模式:**TRGI上升沿闭合总开关

**外部时钟模式1:**TRGI作为时基单元的时钟来源

7.3.8种主模式

8种主模式:

**复位:**手动产生Update事件时,TRGO输出脉冲

**使能:**总开关闭合,TRGO为0;总开关打开,TRGO为1

**Update:**每个update事件,TRGO输出脉冲

**比较脉冲:**与输出比较通道1有关

**比较OC1REF:**OC1REF作为TRGO

**比较OC2REF:**OC2REF作为TRGO

**比较OC3REF:**OC3REF作为TRGO

**比较OC4REF:**OC4REF作为TRGO

7.4.定时器级联的例子

让TIM1、TIM2、TIM3同时启停

当TIM1开关闭合时,TIM2、TIM3也跟着闭合

当TIM1开关断开时,TIM2、TIM3也跟着断开

将TIM1的TRGO设置为使能模式

将TIM2、TIM3的TRGI设置为门模式

将TIM1的TRGO与TIM2、TIM3的TRGI相连

7.5.定时器同时启停的例子

八、PWM参数测量原理

捕获PWM信号的周期与占空比

8.1.参考手册的定时器结构框图

参考手册13:高级定时器(TIM1、TIM8功能最全)

8.2.输入捕获节点的名字

**TI(Timer Input):**定时器输入

**F(Filtered):**滤波后的

**P(Polarized):**选择了极性的

示例:

**TI1FP1:**输入信号从定时器通道1输入进来,经过了滤波与极性选择后,给通道1使用

**TI2FP1:**输入信号从定时器通道2输入进来,经过了滤波与极性选择后,给通道1使用

8.3.TRGI的来源

**TI1FP1:**通道1直接信号

**TI2FP2:**通道2直接信号

**TIMx_ETR:**外部参考信号(实际使用较少)

**TRC:**ITR0~ITR3(其他定时器的TRGO信号)、TI1F_ED(实际使用较少)

TIM2和TIM3都为通用定时器:

TIM2的ITR0表示TIM1的TRGO

TIM2的ITR1表示TIM8的TRGO

TIM2的ITR2表示TIM3的TRGO

TIM2的ITR3表示TIM4的TRGO

所以TIM2选择ITR0

TIM3的ITR0表示TIM1的TRGO

TIM3的ITR0表示TIM2的TRGO

TIM3的ITR0表示TIM5的TRGO

TIM3的ITR0表示TIM4的TRGO

所以TIM3选择ITR0

8.4.PWM参数测量原理

通道1捕获上升沿,通道2捕获下降沿

TRGI选择复位模式,TRGI的信号来源为TI1FP1

检测到上升沿,CCR1存放当前数值,随后计数清零

检测到下降沿,CCR2存放当前数值,继续计数

再次检测到上升沿,CCR1存放当前数值,计数清零

其中CCR2是一个周期中高电平时间

CCR1 - CCR2 是一个周期中低电平时间

九、PWM参数测量实验

9.1.实验原理

TIM3通道1产生PWM信号

TIM1通道1接收PWM信号

将参数值输出到USART1

初始化串口:

cpp 复制代码
#include "stm32f10x.h"
#include "usart.h"

//声明串口初始化函数
void App_USART1_Init(void);

int main(void)
{
	App_USART1_Init();
	
	My_USART_SendString(USART1,"你好世界");
	
	while(1)
	{
	}
}

//创建串口初始化函数
void App_USART1_Init(void)
{
	//#1:初始化IO引脚 PA9 AF_PP
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	/*选择PA9引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	/*设置复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速度为10MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	/*初始化PA9引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#2:配置USART1参数
	
	/*开启USART1模块时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	/*USART结构的前置声明*/
	USART_InitTypeDef USART_InitStruct = {0};
	/*波特率为115200*/
	USART_InitStruct.USART_BaudRate = 115200;
	/*无硬件流控*/
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	/*数据位为8位*/
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	/*停止位为1位*/
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	/*校验方式为无*/
	USART_InitStruct.USART_Parity = USART_Parity_No;
	/*收发方向为发送方向*/
	USART_InitStruct.USART_Mode = USART_Mode_Tx;
	/*初始化USART1*/
	USART_Init(USART1,&USART_InitStruct);
	/*闭合串口总开关*/
	USART_Cmd(USART1,ENABLE);
}

9.2.产生PWM信号

cpp 复制代码
​#include "stm32f10x.h"
#include "usart.h"

//声明串口初始化函数
void App_USART1_Init(void);
//声明TIM3初始化函数
void App_TIM3_Init(void);

int main(void)
{
	App_USART1_Init();
	
	App_TIM3_Init();

    TIM_SetCompare1(TIM3,200);
	
	while(1)
	{
	}
}

//创建TIM3初始化函数
void App_TIM3_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器3的时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM3,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM3,ENABLE);
	
	//#2:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA6引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA6引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输出比较
	
	/*声明输出比较结构体变量*/
	TIM_OCInitTypeDef TIM_InitStruct;
	/*设置为PWM1模式*/
	TIM_InitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	/*设置正常通道为高极性*/
	TIM_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	/*开启正常通道开关*/
	TIM_InitStruct.TIM_OutputState = TIM_OutputState_Enable;
	/*设置CCR初值*/
	TIM_InitStruct.TIM_Pulse = 0;
	/*初始化通道1*/
	TIM_OC1Init(TIM3,&TIM_InitStruct);
	/*闭合MOE总开关*/
	TIM_CtrlPWMOutputs(TIM3,ENABLE);
	/*手动开启CCR预加载*/
	TIM_CCPreloadControl(TIM3,ENABLE);
}

9.3.初始化时基单元

cpp 复制代码
//创建TIM1初始化函数
void App_TIM1_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535 ;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
}

9.4.初始化输入捕获

cpp 复制代码
//创建TIM1初始化函数
void App_TIM1_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535 ;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	
	//#2:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输入捕获通道1
	
	/*声明IC结构变量*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	/*选择通道1*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获上升沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为直接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	/*初始化通道1*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#3:初始化输入捕获通道2
	
	/*选择通道2*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获下降沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为间接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
	/*初始化通道2*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
}

9.5.初始化模式控制器

cpp 复制代码
//创建TIM1初始化函数
void App_TIM1_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535 ;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	
	//#2:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输入捕获通道1
	
	/*声明IC结构变量*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	/*选择通道1*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获上升沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为直接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	/*初始化通道1*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#3:初始化输入捕获通道2
	
	/*选择通道2*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获下降沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为间接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
	/*初始化通道2*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#4:初始化从模式控制器
	
	/*选择TI1FP1作为TRGI信号源*/
	TIM_SelectInputTrigger(TIM1,TIM_TS_TI1FP1);
	/*TRGI设为复位模式*/
	TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Reset);
}

9.6.测量PWM参数

cpp 复制代码
#include "stm32f10x.h"
#include "usart.h"
#include "delay.h"

//声明串口初始化函数
void App_USART1_Init(void);
//声明TIM3初始化函数
void App_TIM3_Init(void);
//声明TIM1初始化函数
void App_TIM1_Init(void);

int main(void)
{
	App_USART1_Init();
	
	App_TIM3_Init();
	
	App_TIM1_Init();
	
	TIM_SetCompare1(TIM3,200);
	
	while(1)
	{
		//#1:清除Trigger标志位
		TIM_ClearFlag(TIM1,TIM_FLAG_Trigger);
		
		//#2:等待Trigger标志位从0变成1
		while(TIM_GetFlagStatus(TIM1,TIM_FLAG_Trigger) == RESET);
		
		//#3:计算
		uint16_t ccr1 = TIM_GetCapture1(TIM1);
		uint16_t ccr2 = TIM_GetCapture2(TIM1);
		
		float period = ccr1 * 1.0e-6f * 1.0e3f;
		float duty = (float)ccr2 / ccr1 * 100.0f;
		
		My_USART_Printf(USART1,"周期 = %.3fms,占空比 = %.2f%%\r\n",period,duty);
		
		Delay(100);
	}
}

//创建串口初始化函数
void App_USART1_Init(void)
{
	//#1:初始化IO引脚 PA9 AF_PP
	
	/*开启GPIOA时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct = {0};
	/*选择PA9引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9;
	/*设置复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速度为10MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_10MHz;
	/*初始化PA9引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#2:配置USART1参数
	
	/*开启USART1模块时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
	/*USART结构的前置声明*/
	USART_InitTypeDef USART_InitStruct = {0};
	/*波特率为115200*/
	USART_InitStruct.USART_BaudRate = 115200;
	/*无硬件流控*/
	USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
	/*数据位为8位*/
	USART_InitStruct.USART_WordLength = USART_WordLength_8b;
	/*停止位为1位*/
	USART_InitStruct.USART_StopBits = USART_StopBits_1;
	/*校验方式为无*/
	USART_InitStruct.USART_Parity = USART_Parity_No;
	/*收发方向为发送方向*/
	USART_InitStruct.USART_Mode = USART_Mode_Tx;
	/*初始化USART1*/
	USART_Init(USART1,&USART_InitStruct);
	/*闭合串口总开关*/
	USART_Cmd(USART1,ENABLE);
}

//创建TIM3初始化函数
void App_TIM3_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器3的时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 999;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM3,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM3,ENABLE);
	
	//#2:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA6引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
	/*复用输出推挽模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;
	/*最大输出速率为2MHz*/
	GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
	/*初始化PA6引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输出比较
	
	/*声明输出比较结构体变量*/
	TIM_OCInitTypeDef TIM_InitStruct;
	/*设置为PWM1模式*/
	TIM_InitStruct.TIM_OCMode = TIM_OCMode_PWM1;
	/*设置正常通道为高极性*/
	TIM_InitStruct.TIM_OCPolarity = TIM_OCPolarity_High;
	/*开启正常通道开关*/
	TIM_InitStruct.TIM_OutputState = TIM_OutputState_Enable;
	/*设置CCR初值*/
	TIM_InitStruct.TIM_Pulse = 0;
	/*初始化通道1*/
	TIM_OC1Init(TIM3,&TIM_InitStruct);
	/*闭合MOE总开关*/
	TIM_CtrlPWMOutputs(TIM3,ENABLE);
	/*手动开启CCR预加载*/
	TIM_CCPreloadControl(TIM3,ENABLE);
}

//创建TIM1初始化函数
void App_TIM1_Init(void)
{
	//#1:初始化时基单元
	
	/*开启定时器1的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
	/*声明TIM结构体变量*/
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
	/*设置预分频系数*/
	TIM_TimeBaseInitStruct.TIM_Prescaler = 71;
	/*设置自动重装寄存器*/
	TIM_TimeBaseInitStruct.TIM_Period = 65535 ;
	/*设置计数方向*/
	TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
	/*设置重复计数器*/
	TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;
	/*初始化TIM3*/
	TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStruct);	
	/*手动开启ARR预加载*/
	TIM_ARRPreloadConfig(TIM1,ENABLE);
	/*闭合时基单元的开关*/
	TIM_Cmd(TIM1,ENABLE);
	
	//#2:初始化IO引脚
	
	/*开启GPIOA的时钟*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	/*声明GPIO结构变量*/
	GPIO_InitTypeDef GPIO_InitStruct;
	/*选择PA8引脚*/
	GPIO_InitStruct.GPIO_Pin = GPIO_Pin_8;
	/*输入下拉模式*/
	GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPD;
	/*初始化PA8引脚*/
	GPIO_Init(GPIOA,&GPIO_InitStruct);
	
	//#3:初始化输入捕获通道1
	
	/*声明IC结构变量*/
	TIM_ICInitTypeDef TIM_ICInitStruct;
	/*选择通道1*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获上升沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为直接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
	/*初始化通道1*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#3:初始化输入捕获通道2
	
	/*选择通道2*/
	TIM_ICInitStruct.TIM_Channel = TIM_Channel_2;
	/*不使用输入滤波器*/
	TIM_ICInitStruct.TIM_ICFilter = 0;
	/*捕获下降沿*/
	TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Falling;
	/*分频系数为1*/
	TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
	/*复用器为间接*/
	TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_IndirectTI;
	/*初始化通道2*/
	TIM_ICInit(TIM1,&TIM_ICInitStruct);
	
	//#4:初始化从模式控制器
	
	/*选择TI1FP1作为TRGI信号源*/
	TIM_SelectInputTrigger(TIM1,TIM_TS_TI1FP1);
	/*TRGI设为复位模式*/
	TIM_SelectSlaveMode(TIM1,TIM_SlaveMode_Reset);
}
相关推荐
逐步前行1 小时前
STM32_新建工程(寄存器版)
stm32·单片机·嵌入式硬件
m0_719084112 小时前
React笔记张天禹
前端·笔记·react.js
bai5459362 小时前
STM32 CubeIDE 通过PWM占空比控制舵机角度
stm32·单片机·嵌入式硬件
松涛和鸣3 小时前
72、IMX6ULL驱动实战:设备树(DTS/DTB)+ GPIO子系统+Platform总线
linux·服务器·arm开发·数据库·单片机
简单中的复杂4 小时前
【避坑指南】RK3576 Linux SDK 编译:解决 Buildroot 卡死在 host-gcc-final 的终极方案
linux·嵌入式硬件
r i c k4 小时前
数据库系统学习笔记
数据库·笔记·学习
上海合宙LuatOS4 小时前
LuatOS核心库API——【audio 】
java·网络·单片机·嵌入式硬件·物联网·音视频·硬件工程
Hhh __灏5 小时前
stm32的SRAM内存不足如何分析和优化?堆栈空间如何优化?
单片机
LS_learner5 小时前
Snapd和Apt—Linux 上两种完全不同的软件包管理系统
嵌入式硬件