学习笔记(STM32通用定时器)

PS:自己做的笔记,质量不高T_T

【源教程视频】https://www.bilibili.com/video/BV1th411z7sn?vd_source=e9a6e1a7cd4e8068209a469f8be0be16

•STM32F103C8T6定时器资源:TIM1(高级APB2)、TIM2、TIM3、TIM4(通用APB1)

STM32通用定时器框图

存在的预装载的寄存器:ARR,CCR,PSC

库函数简介

void TIM_DeInit(TIM_TypeDef* TIMx);
//设置为缺省值
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//时基单元初始化函数
void TIM_OC1Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
//输出比较单元初始化函数
void TIM_OC2Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC3Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_OC4Init(TIM_TypeDef* TIMx, TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_ICInit(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
//输入捕获单元初始化函数(2个通道)
void TIM_PWMIConfig(TIM_TypeDef* TIMx, TIM_ICInitTypeDef* TIM_ICInitStruct);
//配置为PWMI模式(2个通道)
void TIM_BDTRConfig(TIM_TypeDef* TIMx, TIM_BDTRInitTypeDef *TIM_BDTRInitStruct);

void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
//把TIM_TimeBaseInitStruct 中的每一个参数按缺省值填入
void TIM_OCStructInit(TIM_OCInitTypeDef* TIM_OCInitStruct);
void TIM_ICStructInit(TIM_ICInitTypeDef* TIM_ICInitStruct);
void TIM_BDTRStructInit(TIM_BDTRInitTypeDef* TIM_BDTRInitStruct);

void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);//开启定时器,CNT开始计数
void TIM_CtrlPWMOutputs(TIM_TypeDef* TIMx, FunctionalState NewState);//*高级定时器输出PWM时需要调用
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState);//中断输出控制
void TIM_GenerateEvent(TIM_TypeDef* TIMx, uint16_t TIM_EventSource);
void TIM_DMAConfig(TIM_TypeDef* TIMx, uint16_t TIM_DMABase, uint16_t TIM_DMABurstLength);
void TIM_DMACmd(TIM_TypeDef* TIMx, uint16_t TIM_DMASource, FunctionalState NewState);

//时钟选择
void TIM_InternalClockConfig(TIM_TypeDef* TIMx);
//内部时钟
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//其他定时器的时钟
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource, uint16_t TIM_ICPolarity, uint16_t ICFilter);
//捕获通道
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//外部时钟1
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);
//外部时钟2



void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,uint16_t ExtTRGFilter);
//ETR时钟的极性选择,边沿检测,预分频等
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode);
//单独设置PSC,TIM_PSCReloadMode:写入立即生效或更新事件后生效
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode);
//设置计数模式
void TIM_SelectInputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource);
//选择输入触发源TRGI
void TIM_EncoderInterfaceConfig(TIM_TypeDef* TIMx, uint16_t TIM_EncoderMode,uint16_t TIM_IC1Polarity, uint16_t TIM_IC2Polarity);//设置编码器模式


void TIM_ForcedOC1Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
//通道1强制输出高低电平
void TIM_ForcedOC2Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC3Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);
void TIM_ForcedOC4Config(TIM_TypeDef* TIMx, uint16_t TIM_ForcedAction);

void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
//使能或者失能TIMx在ARR上的预装载寄存器
void TIM_SelectCOM(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_SelectCCDMA(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_CCPreloadControl(TIM_TypeDef* TIMx, FunctionalState NewState);

void TIM_OC1PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
//使能或者失能TIMx在CCR1上的预装载寄存器
void TIM_OC2PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC3PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);
void TIM_OC4PreloadConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPreload);

void TIM_OC1FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);//*快速使能
void TIM_OC2FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC3FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);
void TIM_OC4FastConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCFast);

void TIM_ClearOC1Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);//*外部事件时,清除REF信号
void TIM_ClearOC2Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC3Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);
void TIM_ClearOC4Ref(TIM_TypeDef* TIMx, uint16_t TIM_OCClear);

void TIM_OC1PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
//设置极性(输出电平是否反转)。这里可以单独设置,初始化结构体也可设置
void TIM_OC1NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
//设置互补通道极性
void TIM_OC2PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC2NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC3PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);
void TIM_OC3NPolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCNPolarity);
void TIM_OC4PolarityConfig(TIM_TypeDef* TIMx, uint16_t TIM_OCPolarity);

void TIM_CCxCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCx);
//输出比较使能。这里可以单独设置,初始化结构体也可设置
void TIM_CCxNCmd(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_CCxN);//互补通道
void TIM_SelectOCxM(TIM_TypeDef* TIMx, uint16_t TIM_Channel, uint16_t TIM_OCMode);
void TIM_UpdateDisableConfig(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_UpdateRequestConfig(TIM_TypeDef* TIMx, uint16_t TIM_UpdateSource);
void TIM_SelectHallSensor(TIM_TypeDef* TIMx, FunctionalState NewState);
void TIM_SelectOnePulseMode(TIM_TypeDef* TIMx, uint16_t TIM_OPMode);
void TIM_SelectOutputTrigger(TIM_TypeDef* TIMx, uint16_t TIM_TRGOSource);
//选择输出触发源TRGO
void TIM_SelectSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_SlaveMode);
//选择从模式
void TIM_SelectMasterSlaveMode(TIM_TypeDef* TIMx, uint16_t TIM_MasterSlaveMode);
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);//写CNT
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);//写ARR

void TIM_SetCompare1(TIM_TypeDef* TIMx, uint16_t Compare1);//设置CCR
void TIM_SetCompare2(TIM_TypeDef* TIMx, uint16_t Compare2);
void TIM_SetCompare3(TIM_TypeDef* TIMx, uint16_t Compare3);
void TIM_SetCompare4(TIM_TypeDef* TIMx, uint16_t Compare4);


void TIM_SetIC1Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);//设置 TIMx 输入捕获 1 预分频
void TIM_SetIC2Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC3Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetIC4Prescaler(TIM_TypeDef* TIMx, uint16_t TIM_ICPSC);
void TIM_SetClockDivision(TIM_TypeDef* TIMx, uint16_t TIM_CKD);


uint16_t TIM_GetCapture1(TIM_TypeDef* TIMx);//获得 TIMx 输入捕获 1 CCR 的值
uint16_t TIM_GetCapture2(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture3(TIM_TypeDef* TIMx);
uint16_t TIM_GetCapture4(TIM_TypeDef* TIMx);

uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);//获取CNT的值
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);//获取PSC的值
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//获取标志位寄存器
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);//清除标志位寄存器
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);//获取中断标志位
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);//清除中断标志位

实例1:定时中断

    • 基本原理

    • 实现代码

使用内部时钟

#include "stm32f10x.h"                  // Device header

extern uint16_t NUM;

void Timer_Init(void)
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    
    TIM_InternalClockConfig(TIM2);//选择内部时钟
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 10000 - 1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 7200 -1;//PSC
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复计数器
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
    //ferq = Sys_CLK(72M)/(PSC+1)/(ARR+1)
    
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 1;
  NVIC_Init(&NVIC_InitStruct);
    
    TIM_Cmd(TIM2,ENABLE);

}


void TIM2_IRQHandler()
{
    
    if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        NUM ++;
    }
  
}
    

使用外部时钟(可以用作测脉冲)

#include "stm32f10x.h"                  // Device header

uint16_t times;
void Timer_Init()
{
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    
    TIM_ETRClockMode2Config(TIM2,TIM_ExtTRGPSC_OFF,TIM_ExtTRGPolarity_NonInverted,0x0F);
    
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 10-1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1;//PSC
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//Öظ´¼Ä´æÆ÷
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
    TIM_ClearFlag(TIM2,TIM_IT_Update);
    //清除中断标志位,由于PSC存在缓冲寄存器,值PSC并立即生效时需要产生更新事件,导致中断标志寄存器制位
    TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);//    
    
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
    NVIC_InitTypeDef NVIC_InitStruct;
    NVIC_InitStruct.NVIC_IRQChannel = TIM2_IRQn;
    NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
    NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStruct.NVIC_IRQChannelSubPriority = 2;
    NVIC_Init(&NVIC_InitStruct);
    
    TIM_Cmd(TIM2,ENABLE);
}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {times++,TIM_ClearITPendingBit(TIM2,TIM_IT_Update);}

}

实例2:OC(Output Compare)输出比较

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

•每个高级定时器和通用定时器都拥有4个输出比较通道

•高级定时器的前3个通道额外拥有死区生成和互补输出的功能

    • 基本原理

基本定时器输出比较单元结构图

TIMx_CCER:极性选择

输出比较模式:

模式

描述

冻结

CNT=CCR时,REF保持为原状态

匹配时置有效电平

CNT=CCR时,REF置有效电平

匹配时置无效电平

CNT=CCR时,REF置无效电平

匹配时电平翻转

CNT=CCR时,REF电平翻转

强制为无效电平

CNT与CCR无效,REF强制为无效电平

强制为有效电平

CNT与CCR无效,REF强制为有效电平

PWM模式1

向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平

向下计数:CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平

PWM模式2

向上计数:CNT<CCR时,REF置无效电平,CNT≥CCR时,REF置有效电平

向下计数:CNT>CCR时,REF置有效电平,CNT≤CCR时,REF置无效电平

    • 实现代码(输出PWM波形)

#include "stm32f10x.h"                  // Device header

void PWM_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
    
    TIM_InternalClockConfig(TIM2);
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 2000-1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 36000-1;//PSC
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复寄存器
    TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStruct);
    TIM_ClearFlag(TIM2,TIM_IT_Update);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP;//这里使用复用推挽输出
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    TIM_OCInitTypeDef TIM_OC1Init_Struct;
    TIM_OC1Init_Struct.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OC1Init_Struct.TIM_Pulse = 0;//CCR[0,ARR]
    TIM_OC1Init_Struct.TIM_OCPolarity = TIM_OCPolarity_High;//电平不反转
    TIM_OC1Init_Struct.TIM_OutputState = TIM_OutputState_Enable;//使能输出
    TIM_OC2Init(TIM2,&TIM_OC1Init_Struct);
    
    TIM_Cmd(TIM2,ENABLE);
    
}

void Set_CCR(uint16_t CCR)
{
    TIM_SetCompare2(TIM2,CCR);
}

实例3:IC(Input Capture)输入捕获

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

•每个高级定时器和通用定时器都拥有4个输入捕获通道

•可配置为PWMI模式,同时测量频率和占空比

可配合主从触发模式,实现硬件全自动测量

    • 主从触发模式

注意:

通用定时器和高级定时器只有通道1,2输入才能触发从模式,所以PWM全硬件自动测量需要使用CCR1,CCR2

RESET:清除CNT

    • 基本原理

•PWM频率: Freq= CK_PSC / (PSC + 1) / (ARR +1)

•PWM占空比: Duty= CCR / (ARR + 1)

•PWM分辨率: Reso= 1 / (ARR + 1)

测量频率的基本方法

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

fx = N/T

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

fx = fc/N

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

fm =

    • 实现代码(PWMI模式测频率和占空比)

这里我们采用测周法

//测量频率的下限:72M/(PSC+1)/ARR (72M/72/65535 = 15.2)

测频率

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    TIM_InternalClockConfig(TIM3);
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 65535-1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;//PSC 
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复寄存器
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
    TIM_ClearFlag(TIM3,TIM_IT_Update);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    TIM_ICInitTypeDef TIM_ICInitStruct;
    TIM_ICStructInit(&TIM_ICInitStruct);
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 ;// 通道1
    TIM_ICInitStruct.TIM_ICFilter = 0x06;//输入滤波¨
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择

    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//·ÖƵ
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接使用TR1FP1(直连通道)
    TIM_ICInit(TIM3,&TIM_ICInitStruct);
    
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//选择输入触发源TRGI
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//从模式清除CNT
    
    TIM_Cmd(TIM3,ENABLE);
    
}

uint32_t Get_Freq()
{
    return 1000000/(TIM_GetCapture1(TIM3)+1);
}

PWMI

#include "stm32f10x.h"                  // Device header

void IC_Init(void)
{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    TIM_InternalClockConfig(TIM3);
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 65535-1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 72-1;//PSC 
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复寄存器
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
    TIM_ClearFlag(TIM3,TIM_IT_Update);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    TIM_ICInitTypeDef TIM_ICInitStruct;
    TIM_ICStructInit(&TIM_ICInitStruct);
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 ;// 通道1
    TIM_ICInitStruct.TIM_ICFilter = 0x06;//输入滤波¨
    TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择

    TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;//不
    TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;//直接使用TR1FP1(直连通道)
    TIM_PWMIConfig(TIM3,&TIM_ICInitStruct);
    
    TIM_SelectInputTrigger(TIM3,TIM_TS_TI1FP1);//选择输入触发源TRGI
    TIM_SelectSlaveMode(TIM3,TIM_SlaveMode_Reset);//从模式清除CNT
    
    TIM_Cmd(TIM3,ENABLE);
    
}

uint32_t Get_Freq()
{
    return 1000000/(TIM_GetCapture1(TIM3)+1);
}

uin32_t Get_Duty()
{
    return (TIM_GetCapture2(TIM3)+1)*1000/(TIM_GetCapture1(TIM3)+1)
}//占空比X/1000

实例四:编码器接口测速

•Encoder Interface 编码器接口

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

•每个高级定时器和通用定时器都拥有1个编码器接口

•两个输入引脚借用了输入捕获的通道1和通道2

    • 基本原理

编码器接口基本结构

计数模式

    • 实现代码

#include "stm32f10x.h"                  // Device header

void Encodeing_Init()
{
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);    
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
    
    TIM_InternalClockConfig(TIM3);
    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStruct;
    TIM_TimeBaseInitStruct.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseInitStruct.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInitStruct.TIM_Period = 65536-1;//ARR
    TIM_TimeBaseInitStruct.TIM_Prescaler = 1-1;//PSC 
    TIM_TimeBaseInitStruct.TIM_RepetitionCounter = 0;//重复寄存器
    TIM_TimeBaseInit(TIM3,&TIM_TimeBaseInitStruct);
    TIM_ClearFlag(TIM3,TIM_IT_Update);
    
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;
    GPIO_InitStruct.GPIO_Speed  = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA,&GPIO_InitStruct);
    
    TIM_ICInitTypeDef TIM_ICInitStruct;
    TIM_ICStructInit(&TIM_ICInitStruct);
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 ;// 通道1
    TIM_ICInitStruct.TIM_ICFilter = 0x0F;//输入滤波
    //TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择
    TIM_ICInit(TIM3,&TIM_ICInitStruct);
    
    TIM_ICStructInit(&TIM_ICInitStruct);
    TIM_ICInitStruct.TIM_Channel = TIM_Channel_2 ;// 通道1
    TIM_ICInitStruct.TIM_ICFilter = 0x0F;//输入滤波
    //TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;//极性选择
    TIM_ICInit(TIM3,&TIM_ICInitStruct);
    
    TIM_EncoderInterfaceConfig(TIM3,TIM_EncoderMode_TI12,TIM_ICPolarity_Rising,TIM_ICPolarity_Rising);
    
    TIM_Cmd(TIM3,ENABLE);
}

int16_t Get_Encoder()
{
    return TIM_GetCounter(TIM3);
}
#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Encodeing.h"
#include "timer.h"
int16_t Speed;
int main(void)
{
    OLED_Init();
    OLED_Clear();
    Timer_Init();
    Encodeing_Init();
    OLED_ShowString(1, 1, "Speed:");    
    while (1)
    {
        OLED_ShowSignedNum(1,7, Speed,3);
    }
}

void TIM2_IRQHandler(void)
{
    if(TIM_GetITStatus(TIM2, TIM_IT_Update) == SET)
    {
        TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
        Speed = Get_Encoder();
        TIM_SetCounter(TIM3,0);
    }
}
  • 4
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值