定时器简介

TIM定义:对输入的时钟进行计数,并在计数值达到设定值时触发中断

TIM:

  • 时基单元:16位计数器,预分频器,自动重装寄存器

  • 分类:高级定时器 通用定时器 基本定时器

  • 计数模式 向上计数模式:cnt == arr溢出 向下计数: cnt = arr -> 0 溢出 中央对齐模式:cnt == arr,cnt = arr -> 0 注意 中央对齐模式先向上计数,再向下计数

  • 定时器溢出效应: 更新中断 更新事件: 影子寄存器更新:将预装载寄存器的值立即更新到影子寄存器中包括ARR、PSC和比较值(CCR) 中心对齐模式计数器计数方向改变 注意 影子寄存器是实际起作用的寄存器,预装载寄存器供读写

  • 定时器时钟源选择: 内部时钟源:系统时钟 外部时钟模式1 外部时钟模式2:TIM2_ETR引脚 注意 stm32f103c8t6的TIM2_ETR引脚位PA0

  • 各时钟频率 基准计数时钟频率(内外时钟源) 计数器计数时钟频率(基准计数时钟分频后) 计数器溢出频率:基准计数时钟/分频系数+1/重装载值+1

定时器函数

时基单元初始化函数:

  • 函数使用 函数:TIM_TimeBaseInit 入参:定时器 结构体指针 返回值:无 注意: 为了寄存器重载,函数内部会让定时器产生一个更新事件,同时伴随更新中断,这样板子一上电,定时器就会进入一次中断; 措施:调用TIM_ClearFlag(TIM2, TIM_IT_Flag);

  • TIM_TimeBaseInitTypedef结构体成员: TIM_ClockDivision: 配置滤波器时钟,对时基单元无影响 TIM_CKD_DIV1 / TIM_CKD_DIV2 / TIM_CKD_DIV4 TIM_CounterMode: 计数器模式TIM_CounterMode_Up / TIM_CounterMode_Down TIM_Period: ARR数值 TIM_Prescaler: 预分频系数 TIM_RepetitionCounter: 高级定时器控制更新中断的发生频率

  • 时基单元初始化函数调用示例

TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;              
TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;     
TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; 
TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;               
TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;             
TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;            
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);             

定时器配置外部时钟模式2函数:

  • 函数使用: 函数:TIM_ETRClockMode2Config 入参:定时器 外部时钟分频 外部触发极性 外部触发滤波器 返回值:无

  • 入参解析 外部时钟分频: TIM_ExtTRGPSC_OFF / TIM_ExtTRGPSC_DIV2 / TIM_ExtTRGPSC_DIV4 / TIM_ExtTRGPSC_DIV8 外部触发极性: TIM_ExtTRGPolarity_Inverted 上升沿触发 / TIM_ExtTRGPolarity_NonInverted 下降沿触发 外部触发滤波器:外部触发滤波器

  • 函数调用示例

TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x0F);

定时器中断使能函数:

  • 函数使用 函数:TIM_ITConfig 入参:定时器 待使能的中断标志位 ENABLE/DISABLE 返回值:无

  • 定时器中断使能函数调用示例

TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);

定时器使能函数:

  • 函数使用 函数:TIM_Cmd 入参:定时器 ENABLE/DISABLE 返回值:无

  • 定时器使能函数调用示例

TIM_Cmd(TIM2, ENABLE);

定时器查询CNT函数:

  • 函数使用 函数:TIM_GetCounter 入参:定时器 返回值:CNT值

  • 定时器使能函数调用示例

uint16_t cnt = TIM_GetCounter(TIM2);

定时器标志位: TIM_GetITStatus函数: TIM_IT_Update:定时器产生更新中断

定时器中断服务函数:

EXTI中断服务函数示例
void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update))
    {
        //中断处理事件
        TIM_ClearITPendingBit(TIM2, TIM_IT_Update);
    }
}

定时器输出比较简介

OC前置:

  • 英文: OC:输出比较 IC:输入捕获 CCR:捕获/比较寄存器, OC:比较寄存器 IC:捕获寄存器

OC定义: 通过比较CNT与CCR寄存器值的关系,对输出电平进行置1,置0操作,用于输出一定占空比的PWM波

OC:

  • 模式:PWM模式1

  • PWM波: 定义: 配置不同占空比的PWM波,等效模拟参量

参数计算: 周期:定时器中断周期 占空比:OC值 / ARR值 分辨率:1 / ARR + 1

  • 高级定时器PWM波: 需调用PWM波输出使能函数:TIM_CtrlPWMOutputs(TIM1, ENABLE);

定时器输出比较函数

OC初始化函数:

  • 函数使用 函数:TIM_OC1Init 入参:定时器 结构体指针 返回值:返回值 注意:OC1借用TIM2_CH1输出

  • TIM_OCInitTypedef结构体成员变量 TIM_OCMode: PWM1模式 TIM_OCMode_PWM1 TIM_OCPolarity: 输出极性 TIM_OCPolarity_High / TIM_OCPolarity_Low 输出高低电平取反 TIM_OutputState: 输出使能 TIM_OutputState_Enable / TIM_OutputState_Disable TIM_Pulse: OC值

  • 函数调用示例:

TIM_OCInitTypeDef TIM_OCInitStructure;                          
TIM_OCStructInit(&TIM_OCInitStructure);                                                            
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;               
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;       
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;   
TIM_OCInitStructure.TIM_Pulse = 0;                              
TIM_OC2Init(TIM2, &TIM_OCInitStructure);                     

输出比较模式修改OC值函数:

  • 函数使用 函数:TIM_SetCompare1 入参:定时器 OC值 返回值:无

  • 函数调用示例

TIM_SetCompare1(TIM2, 33);

定时器输入捕获简介

IC前置:

  • 测量频率的方法: 测频法:时基1s内的数波形有多少个上升沿,波形数就是频率 测周发:波形俩个上升沿按一定频率fc,数N次,fc/N就是频率

IC定义: 通道输入引脚出现指定电平跳变时,当前CNT的值将被锁存到CCR中

IC:

  • 通道: 定时器输出比较与输入捕获共用4个通道,OC1 OC2 OC3 OC4 IC1 IC2 IC3 IC4,同一通道输出比较与输入捕获不可同时进行

  • 输入捕获模式测频率: TIM2_CH1通道输入的PWM波,给单片机的输入滤波器和边沿检测器,得到TI1FP1信号,再经过分频器进行分频,每来一个触发信号,CNT值锁存到CCR1中后清零,根据CNT的驱动时钟频率fc,得频率:fc/CNT 注意 若fc频率过低,可能导致CNT溢出

  • 输入捕获模式测PWM波频率占空比:

PWMI模式: TIM2_CH1通道输入的PWM波,经过单片机的输入滤波器和边沿检测器,得到TI1FP1与TI2FP2俩路信号; IC1配置为上升沿触发,直连,捕获TI1FP1上升沿;IC2配置为下降沿触发,交叉,捕获TI1FP1下升沿; 再经过分频器进行分频,TI1FP1来一个上升沿,CNT值锁存到CCR1中后清零,TI2FP2来一个下降沿,CNT锁存到CCR2中; 根据CNT的驱动时钟频率fc,得频率:fc/CCR1 得占空比:CCR2/CCR1 注意 TI1FP1与TI2FP2相同的信号,只不过被不同的通道捕获 CCR1就是一个周期的计数值;CCR2就是高电平的计数值

定时器输入捕获函数

输入捕获初始化函数:

  • 函数使用: 函数:TIM_ICInit 入参:定时器 结构体指针 返回值:无

  • TIM_ICInitTypedef结构体成员变量: TIM_Channel: 选择IC通道 TIM_Channel_1 / TIM_Channel_2 / TIM_Channel_3 / TIM_Channel_4 TIM_ICFilter: 触发锁存边沿 TIM_ICPolarity_Rising / TIM_ICPolarity_Falling / TIM_ICPolarity_BothEdge

TIM_ICPrescaler: 捕获预分频,选择不分频,每次信号都触发捕获TIM_ICPSC_DIV1 / TIM_ICPSC_DIV2 / TIM_ICPSC_DIV4 / TIM_ICPSC_DIV8

TIM_ICSelection: 输入信号交叉与否 TIM_ICSelection_DirectTI 只测频率 / TIM_ICSelection_IndirectTI 测频率与占空比

  • 函数调用示例:

TIM_ICInitTypeDef TIM_ICInitStructure;							
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;				
TIM_ICInitStructure.TIM_ICFilter = 0xF;							
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;		
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;			
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;	
TIM_ICInit(TIM3, &TIM_ICInitStructure);

PWMI模式配置函数:

  • 函数使用: 函数:TIM_PWMIConfig 入参:定时器 结构体指针 返回值:无 注意 仅支持通道1与通道2的配合使用

  • 函数调用示例:

TIM_ICInitTypeDef TIM_ICInitStructure;							
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;				
TIM_ICInitStructure.TIM_ICFilter = 0xF;							
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;		
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;			
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;	
TIM_PWMIConfig(TIM3, &TIM_ICInitStructure);                                                     

注意 TIM_PWMIConfig()内部会调用一次IC_init在配置通道1为上升沿触发、直连的同时,会将通道2自动配置为下降沿触发,并将其输入选择为“间接”(从通道1获取信号),以实现对同一PWM信号周期和脉宽的测量。

输入触发源选择函数:

  • 函数使用: 函数:TIM_SelectInputTrigger 入参:定时器 输入触发源 返回值:无

  • 函数调用示例:

TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

从模式选择函数:

  • 函数使用: 函数:TIM_SelectSlaveMode 入参:定时器 从模式 返回值:无

  • 函数调用示例:

TIM_SelectInputTrigger(TIM3, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(TIM3, TIM_SlaveMode_Reset);

注意 前面TI1FP1配置为上升沿触发,这里表示每来一个上升沿作为触发源都会引发从模式把CNT计数值清0

CCR寄存器读取函数:

  • 函数使用: 函数:TIM_GetCapture1 入参:定时器 返回值:CCR值

  • 函数调用示例:

uint16_t ccr = TIM_GetCapture1(TIM3);

定时器输入捕获模块函数

void IC_Init(void)

{
	RCC_APB1PeriphClockCmd//开启TIM3的时钟
	RCC_APB2PeriphClockCmd//开启GPIOA的时钟
	
	GPIO_Init//将PA6引脚初始化为上拉输入
	

	TIM_TimeBaseInit

	TIM_PWMIConfig

	TIM_SelectInputTrigger//触发源选择TI1FP1
	TIM_SelectSlaveMode//从模式选择复位
																
	TIM_Cmd
}

uint32_t IC_GetFreq(void)

{
	return 1000000 / (TIM_GetCapture1(TIM3));		//测周法得到频率fx = fc / N
}

uint32_t IC_GetDuty(void)

{
    return (TIM_GetCapture2(TIM3) + 1) * 100 / (TIM_GetCapture1(TIM3) + 1); 
}

定时器编码器接口

编码器接口前置:

  • 正交编码器 输出A B俩相波形,俩个波形相位相差90度

正转波形:A相波形上升沿,B相低电平;A相波形下降沿,B相高电平;B相波形上升沿,A相高电平;B相波形下降沿,A相低电平 反转波形:A相波形上升沿,B相高电平;B相波形上升沿,A相低电平;A相波形下降沿,B相低电平;B相波形下降沿,A相高电平

编码器接口定义: 接收正交编码器信号,通过定时器输入捕获的通道1与通道2,输入到定时器编码器接口,正转编码器接口控制CNT自增,反转控制自减

编码器接口:

  • 资源 每一个高级定时器与通用定时器都有一个编码器接口

  • 工作模式 仅在TI1计数 仅在TI2计数 在TI1与TI2都计数

定时器编码器接口函数

编码器接口配置函数:

  • 函数使用: 函数:TIM_EncoderInterfaceConfig 入参:定时器 计数模式 A相波形极性 B相波形极性 返回值:无

  • 参数解析 计数模式:选择单相波形计数,还是俩项波形都计数TIM_EncoderMode_TI1 / TIM_EncoderMode_TI2 / TIM_EncoderMode_TI12

A相波形极性:A相波形不反转 TIM_ICPolarity_Rising / A相波形反转 TIM_ICPolarity_Falling B相波形极性:B相波形不反转 TIM_ICPolarity_Rising / B相波形反转 TIM_ICPolarity_Falling

  • 函数调用示例:

TIM_EncoderInterfaceConfig(TIM3, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);

定时器编码器接口模块函数

int16_t Encoder_Get(void)

{
    int16_t Temp;
    Temp = TIM_GetCounter(TIM3);
    TIM_SetCounter(TIM3, 0);
    return Temp;
}

注意 TIM_GetCounter函数返回的是uint16_t类型的数据,范围0~65535 赋值给int16_t类型的数据,范围-32768~32767

TIM_GetCounter返回45678,对应temp -19858,俩者相减为65536

隔一段时间,取一次CNT值就代表编码器转速

Logo

智能硬件社区聚焦AI智能硬件技术生态,汇聚嵌入式AI、物联网硬件开发者,打造交流分享平台,同步全国赛事资讯、开展 OPC 核心人才招募,助力技术落地与开发者成长。

更多推荐