1000字范文,内容丰富有趣,学习的好帮手!
1000字范文 > stm32之TIM-高级定时器应用实例一(详细)

stm32之TIM-高级定时器应用实例一(详细)

时间:2018-10-07 16:49:59

相关推荐

stm32之TIM-高级定时器应用实例一(详细)

硬件:stm32f103c8t6开发工具:Keil uVision4下载调试工具:ARM仿真器

如果第一次接触定时器,可以先看基本定时器。本篇内容较多,如果想直接动手操作,可以跳到后面的实验代码。

stm32标准库对定时器外设建立了4个初始化结构体,定时器分为基本定时器、通用定时器、高级定时器,针对不用的定时器要使用不同初始化结构体。下面是4个初始化结构体的适用分类:

TIM_TimeBaseInitTypeDef (基本定时器、通用定时器、高级定时器)

TIM_OCInitTypeDef (通用定时器、高级定时器)

TIM_ICInitTypeDef (通用定时器、高级定时器)

TIM_BDTRInitTypeDef (高级定时器)

使用哪一个定时器,就配置所有相应的初始化结构体,然后调用初始化函数。下面先理解每个结构体成员的含义和其取值范围。

定时器基本初始化结构体 >>TIM_TimeBaseInitTypeDef

typedef struct{uint16_t TIM_Prescaler; /*定时器预分频设置。 value:(0~0xFFFF)*/uint16_t TIM_CounterMode;/*选择了计数器模式。Value:#define TIM_CounterMode_Up ((uint16_t)0x0000) //TIM 向上计数模式#define TIM_CounterMode_Down((uint16_t)0x0010) //TIM 向下计数模式#define TIM_CounterMode_CenterAligned1((uint16_t)0x0020) //TIM 中央对齐模式 1 计数模式#define TIM_CounterMode_CenterAligned2((uint16_t)0x0040) //TIM 中央对齐模式 2 计数模式*/uint16_t TIM_Period; /*设置了在下一个更新事件装入活动的自动重装载寄存器周期的值。value:0x0000~0xFFFF*/ uint16_t TIM_ClockDivision; /*设置定时器时钟CK_INT频率与死区发生器以及数字滤波器采样时钟频率分频化。Value:#define TIM_CKD_DIV1 ((uint16_t)0x0000)#define TIM_CKD_DIV2 ((uint16_t)0x0100)#define TIM_CKD_DIV4 ((uint16_t)0x0200)*/ uint8_t TIM_RepetitionCounter; /*是否使用重复定时器,当该值不为0的时候,计数器计数值达到周期数时,该值减1,计数器重新计数,当该值减到0的时候才会产生事件。*/} TIM_TimeBaseInitTypeDef;

备注: 若是主频72MHz、TIM_Prescaler的值设置为(72-1),则定时器时钟频率=72MHz/72=1MHz。知道频率就可以算周期了,用1/1MHz 乘以TIM_Period的值就是定时的时间(周期),如果加入了重复定时器,那么还要乘以TIM_RepetitionCounter的值才是定时的时间(周期)。

定时器比较输出初始化结构体 >>TIM_OCInitTypeDef

typedef struct{uint16_t TIM_OCMode;/*比较输出模式选择,共8种。value:#define TIM_OCMode_Timing ((uint16_t)0x0000) // TIM 输出比较时间模式#define TIM_OCMode_Active ((uint16_t)0x0010) //TIM 输出比较主动模式#define TIM_OCMode_Inactive((uint16_t)0x0020) //TIM 输出比较非主动模式#define TIM_OCMode_Toggle ((uint16_t)0x0030) //TIM 输出比较触发模式#define TIM_OCMode_PWM1((uint16_t)0x0060) //TIM 脉冲宽度调制模式 1 #define TIM_OCMode_PWM2((uint16_t)0x0070) //TIM 脉冲宽度调制模式 2*/uint16_t TIM_OutputState;/*比较输出使能,决定信号是否通过外部引脚输出。value:0(Disable)、1(Enable)。 */ uint16_t TIM_OutputNState; /*比较互补输出使能,决定互补信号是否通过外部引脚输出。value:0(Disable)、1(Enable)。*/uint16_t TIM_Pulse; /*比较输出的脉冲宽度,设置占空比。Value:0x0000~0xFFFF*/ uint16_t TIM_OCPolarity; /*比较输出极性,决定定时器通道有效电平的极性。Value:#define TIM_OCPolarity_High((uint16_t)0x0000)#define TIM_OCPolarity_Low ((uint16_t)0x0002)*/uint16_t TIM_OCNPolarity; /*比较互补输出极性,可选高电平有效、低电平有效。Value:#define TIM_OCNPolarity_High((uint16_t)0x0000)#define TIM_OCNPolarity_Low((uint16_t)0x0008)*/uint16_t TIM_OCIdleState; /*空闲状态时通道输出电平设置,可选高电平、低电平。Value:#define TIM_OCNPolarity_High((uint16_t)0x0000)#define TIM_OCNPolarity_Low((uint16_t)0x0008)*/uint16_t TIM_OCNIdleState; /*空闲状态时互补通道输出电平设置,可选高电平、低电平,设定值必须跟TIM_OCIdleState相反。Value:#define TIM_OCNIdleState_Set((uint16_t)0x0200)#define TIM_OCNIdleState_Reset ((uint16_t)0x0000)*/} TIM_OCInitTypeDef;

备注:设置TIM_Pulse的值就可以改变输出波形的占空比了,如果不使用重复定时器,那么占空比=(TIM_Pulse+1)/(TIM_Period+1)x100%。

定时器输入捕获初始化结构体 >>TIM_ICInitTypeDef

typedef struct{uint16_t TIM_Channel; /*输入通道选择,共4个通道。Value:#define TIM_Channel_1 ((uint16_t)0x0000) //使用 TIM 通道 1 #define TIM_Channel_2 ((uint16_t)0x0004) //使用 TIM 通道 2 #define TIM_Channel_3 ((uint16_t)0x0008) //使用 TIM 通道 3#define TIM_Channel_4 ((uint16_t)0x000C) //使用 TIM 通道 4*/uint16_t TIM_ICPolarity; /*输入捕获边沿触发选择,可选上升沿触发、下降沿触发。Value:#define TIM_ICPolarity_Rising ((uint16_t)0x0000) //TIM 输入捕获上升沿#define TIM_ICPolarity_Falling ((uint16_t)0x0002) //TIM 输入捕获下降沿*/uint16_t TIM_ICSelection; /*输入通道选择,共3个通道。Value:#define TIM_ICSelection_DirectTI ((uint16_t)0x0001) //TIM 输入 2,3 或 4 选择对应地与 IC1 或 IC2 或IC3 或 IC4 相连 #define TIM_ICSelection_IndirectTI ((uint16_t)0x0002) //TIM 输入 2,3 或 4 选择对应地与 IC2 或 IC1 或IC4 或 IC3 相连#define TIM_ICSelection_TRC((uint16_t)0x0003) //TIM 输入 2,3 或 4 选择与 TRC 相连*/uint16_t TIM_ICPrescaler; /*输入捕获通道预分频,共(1、2、4、8)种。Value:#define TIM_ICPSC_DIV1 ((uint16_t)0x0000) //TIM 捕获在捕获输入上每探测到一个边沿执行一次#define TIM_ICPSC_DIV2 ((uint16_t)0x0004) // TIM 捕获每 2 个事件执行一次#define TIM_ICPSC_DIV4 ((uint16_t)0x0008) //TIM 捕获每 4 个事件执行一次#define TIM_ICPSC_DIV8 ((uint16_t)0x000C) //TIM 捕获每 8 个事件执行一次*/uint16_t TIM_ICFilter; /*输入捕获滤波器设置,value:0x0~0x0F。一般不用,设置为0*/} TIM_ICInitTypeDef;

备注:定时器捕获信号,可以测量输入信号的脉宽和测量PWM输入信号的频率和占空比;信号的来源可以来自其他的定时器或者外部引脚;滤波器的作用是排除高频的干扰,采样的频率必须大于等于两倍的输入信号。

断路和死区初始化结构体 >>TIM_BDTRInitTypeDef

typedef struct{uint16_t TIM_OSSRState;/*运行模式下关闭状态选择。Value:#define TIM_OSSRState_Enable((uint16_t)0x0800)#define TIM_OSSRState_Disable ((uint16_t)0x0000)*/ uint16_t TIM_OSSIState;/*空闲模式下关闭状态选择。Value:#define TIM_OSSIState_Enable((uint16_t)0x0400)#define TIM_OSSIState_Disable ((uint16_t)0x0000)*/ uint16_t TIM_LOCKLevel;/*锁定配置。Value:#define TIM_LOCKLevel_OFF ((uint16_t)0x0000)#define TIM_LOCKLevel_1((uint16_t)0x0100)#define TIM_LOCKLevel_2((uint16_t)0x0200)#define TIM_LOCKLevel_3((uint16_t)0x0300)*/ uint16_t TIM_DeadTime;/*死区时间。Vlaue:0x0~0xFF*/uint16_t TIM_Break;/*短路输入使能控制。Value:#define TIM_Break_Enable ((uint16_t)0x1000)#define TIM_Break_Disable ((uint16_t)0x0000)*/uint16_t TIM_BreakPolarity;/*断路输出极性。Value:#define TIM_BreakPolarity_Low ((uint16_t)0x0000)#define TIM_BreakPolarity_High ((uint16_t)0x2000)*/ uint16_t TIM_AutomaticOutput;/*自动输出使能。Value:#define TIM_AutomaticOutput_Enable ((uint16_t)0x4000)#define TIM_AutomaticOutput_Disable ((uint16_t)0x0000)*/} TIM_BDTRInitTypeDef;

备注:

上图的黑影部分是死区时间,死区时间是根据与输出信号相连接的器件及其特性来调整的,为了避免OCx和OCxN同时改变时,造成外部器来不及反应所造成的短路问题。

下面通过几个实例,进一步理解初始化结构体成员的含义,熟悉定时器的使用的流程。

实验一.PWM互补输出实验(带死区和断路功能)

一. 设计要求:

双通道互补PWM,带死区和刹车功能。

周期:100ms

占空比:通道一为25%,通道二为60%

死区持续时间:12.8ms

二. 硬件设计:

采用TIM1的通道一和通道二。

PA8、PB13引脚是TIM1通道一的互补输出。PA9、PB14引脚是TIM1通道二的互补输出。为增加断路功能,需要用到TIM1_BKIN引脚,PB12。

三. 设计步骤:

定时器IO口配置。配置时基结构体:TIM_TimeBaseInitTypeDef配置输出比较结构体:TIM_OCInitTypeDef配置断路和死区结构体:TIM_BDTRInitTypeDef启动定时器,输出使能。

>>死区持续时间的计算:

TIM_DeadTime的就是配置寄存器DTG[7:0]的值,是定时器时钟,是死区发生器的时钟,DT是死区持续时间。

本实验定时器时钟配置为10kHz,死区持续时间需要配置成12.8ms,我这里选用第二条公式,具体选用那一条公式,由DTG[7:5]这几个bit位决定,如上图。

根据公式 DTG[7:5]=10x => DT=(64+DTG[5:0]) × Tdtg,Tdtg = 2 × TDTS

那么先计算 =2=2*(1/10kHz)=0.2ms

把参数代入公式 DT=(64+DTG[5:0]) × Tdtg,可算出DTG[5:0]=0,即DTG[7:0]=0x80.

创建TIM_test.h

#ifndef __TIM_TEST_H#define __TIM_TEST_H#include "stm32f10x.h"void GPIO_Configuration(void);void TIME_Configuration(void);#endif

创建TIM_test.c

void GPIO_Configuration(void){/*定义一个GPIO_InitTypeDef类型的结构体*/GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA| \RCC_APB2Periph_GPIOC, ENABLE);//开启GPIOC的外设时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE); GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //设置引脚模式为通用推挽输出GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;GPIO_Init(GPIOB, &GPIO_InitStructure); //调用库函数,初始化GPIOCGPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9;GPIO_Init(GPIOA, &GPIO_InitStructure); //调用库函数,初始化GPIOCGPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;GPIO_Init(GPIOB, &GPIO_InitStructure); //调用库函数,初始化GPIOCGPIO_SetBits(GPIOB,GPIO_Pin_12);}#define ADVANCE_TIM TIM1void TIME_Configuration(void){TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;TIM_OCInitTypeDef TIM_OCInitStructure;TIM_BDTRInitTypeDef TIM_BDTRInitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE); //开启TIM1时钟//时基结构体配置TIM_TimeBaseStructure.TIM_Period = 1000-1;//从0开始计数 一个周期1000次TIM_TimeBaseStructure.TIM_Prescaler =(7200-1); //计数器频率为10kHz 定时器时钟:72MHz/7200=10kHz 周期:(1/10kHz)*1000=100msTIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //不需要分频TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //计数方式 向上计数TIM_TimeBaseStructure.TIM_RepetitionCounter=0; //重复计数器TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure); //调用库函数,初始化TIM1//输出比较结构体配置TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;//选择PWM1模式TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;//信号输出使能TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;//互补信号输出使能TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;//初始化TIM1的通道一TIM_OCInitStructure.TIM_Pulse = 250-1; //占空比=250/1000=25%TIM_OC1Init(ADVANCE_TIM,&TIM_OCInitStructure);TIM_OC1PreloadConfig(ADVANCE_TIM,TIM_OCPreload_Enable);//初始化TIM1通道二TIM_OCInitStructure.TIM_Pulse = 600-1; //占空比=600/1000=60%TIM_OC2Init(ADVANCE_TIM,&TIM_OCInitStructure);TIM_OC2PreloadConfig(ADVANCE_TIM,TIM_OCPreload_Enable);//死区和短路结构体配置TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;TIM_BDTRInitStructure.TIM_DeadTime = 0x80;TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;//低电平有效,如果引脚检测到高电平则会停止PWM的输出,不会产生任何波形TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;TIM_BDTRConfig(ADVANCE_TIM,&TIM_BDTRInitStructure);//使能定时器,计数器开始计数TIM_Cmd(ADVANCE_TIM, ENABLE); //主动输出使能TIM_CtrlPWMOutputs(ADVANCE_TIM,ENABLE);}

创建main.c

#include "stm32f10x.h"#include “TIM_test.h”int main(void){ GPIO_Configuration(); //IO口配置TIME_Configuration(); //定时器配置while(1){}}

四. 实验结果:

把程序编译烧录到开发板里面出,再将PA8,PB13引脚和PA9,PB14引脚接到示波器,并把短路输入引脚PB12拉低,示波器和开发板共地。也可以先在keil里面进行软件仿真。用keil4 模拟仿真显示引脚波形输出分析的步骤

软件仿真:

周期:100ms

死区持续时间:12.8ms

占空比(通道一):25%

占空比(通道二):60%

硬件调试:

信号1接的是PB13引脚,信号2接的是PA8引脚,调整示波器到合适的参数。

调试短路功能可以将PB12引脚处接高电平,那么定时器就会停止产生波形,以达到刹车的功能。高级定时器的PWM输出的功能特性天生就是用来控制电机的。

一个高级定时器可以输出多路PWM,但是他们的周期是一样的,占空比可以不一样,在运行过程中每个通道的占空比是可以通过调用函数来改变。通用定时器跟高级定时器的区别是前者没有死区和断路功能,其他都是一样。

水平有限,仅供参考,错误之处以及不足之处还望多多指教。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。