基于STM32单片机模块练习——高级定时器
功能简介
两边计数:从0计数到CCR的值,再从CCR的值计数到零。
高级定时器GPIO引脚说明
高级定时器功能框图
1.时钟源 1.内部时钟 内部时钟 CK_INT 即来自于芯片内部,等于 72M,一般情况下,我们都是使用内部时钟。当从模式控制寄存器 TIMx_SMCR 的 SMS 位等于 000 时,则使用内部时钟。 2.外部时钟模式一 2.外部时钟模式二 3.内部触发输入(了解) 2.时基 3.输入捕获
使用PWM输入捕获,一个输入通道会占用两个捕获通道,一个(进行脉宽的测量,一个进行周期的测量。PWM输入捕获只能使用CH1和CH2。 在直连模式下,选择TI1FP1为触发信号进行周期的测量,那么TI1FP2自动进入IC2进行脉宽的测量;在非直连模式下,选择TI1FP2为触发信号进入IC2进行周期的测量,那么TI1FP2自动进入IC1进行脉宽的测量;
应用: 当第一次捕获到上升沿,进入中断将CNT的值清零,那么锁存到CCR的值也就为0,若此时改变捕获边沿为下降沿,那么第二次进入中断的CCR值就是测量脉宽的;若此时不改变捕获边沿,那么第二次进入中断的CCR值就是测量周期的。
注意:IC再次捕获的值要加上一才是真实的计数值。
4.输出比较(输出PWM) 比较寄存器 当计数器 CNT 的值跟比较寄存器 CCR 的值相等的时候,输出参考信号 OCxREF 的信号的极性就会改变,其中 OCxREF=1(高电平)称之为有效电平,OCxREF=0(低电平)称之为无效电平,并且会产生比较中断 CCxI,相应的标志位 CCxIF(SR 寄存器中)会置位。然后 OCxREF 再经过一系列的控制之后就成为真正的输出信号 OCx/OCxN。
CCR决定PWM信号的占空比,ARR决定周期
死区发生器
为什么要有死区???? 因为电子原件不能立即进行打开和关闭操作,而是会存在纳秒级别的反应时间,所以单片机输出的信号要留出这段时间来等待一下,而这段等待时间成为死区。
在生成的参考波形 OCxREF 的基础上,可以插入死区时间,用于生成两路互补的输出 信号 OCx 和 OCxN,死区时间的大小具体由 BDTR 寄存器的位 DTG[7:0]配置。死区时间 的大小必须根据与输出信号相连接的器件及其特性来调整。
应用: 注意:同一个定时器要么工作在输出模式要么工作在输入捕获模式,不能同时工作在两种模式。
程序编写
1.PWM互补输出
高级定时器GPIO配置
static void ADVANCE_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1N_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1N_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_CH1N_PORT, &GPIO_InitStructure);
RCC_APB2PeriphClockCmd(ADVANCE_TIM_BKIN_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_BKIN_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(ADVANCE_TIM_BKIN_PORT, &GPIO_InitStructure);
GPIO_ResetBits(ADVANCE_TIM_BKIN_PORT,ADVANCE_TIM_BKIN_PIN);
}
高级定时器模式配置
static void ADVANCE_TIM_Mode_Config(void)
{
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
TIM_OCInitStructure.TIM_Pulse = ADVANCE_TIM_PULSE;
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;
TIM_OC1Init(ADVANCE_TIM, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(ADVANCE_TIM, TIM_OCPreload_Enable);
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
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 = 11;
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(ADVANCE_TIM, &TIM_BDTRInitStructure);
TIM_Cmd(ADVANCE_TIM, ENABLE);
TIM_CtrlPWMOutputs(ADVANCE_TIM, ENABLE);
}
相关宏定义
#define ADVANCE_TIM TIM8
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM8
#define ADVANCE_TIM_PERIOD (100-1)
#define ADVANCE_TIM_PSC (72-1)
#define ADVANCE_TIM_PULSE 50
#define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOC
#define ADVANCE_TIM_CH1_PORT GPIOC
#define ADVANCE_TIM_CH1_PIN GPIO_Pin_6
#define ADVANCE_TIM_CH1N_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_CH1N_PORT GPIOA
#define ADVANCE_TIM_CH1N_PIN GPIO_Pin_7
#define ADVANCE_TIM_BKIN_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_BKIN_PORT GPIOA
#define ADVANCE_TIM_BKIN_PIN GPIO_Pin_6
void ADVANCE_TIM_Init(void);
2.脉宽测量 通用定时器GPIO配置
static void GENERAL_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(GENERAL_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = GENERAL_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_Init(GENERAL_TIM_CH1_PORT, &GPIO_InitStructure);
}
通用定时器模式配置
static void GENERAL_TIM_Mode_Config(void)
{
GENERAL_TIM_APBxClock_FUN(GENERAL_TIM_CLK,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period=GENERAL_TIM_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler= GENERAL_TIM_PSC;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(GENERAL_TIM, &TIM_TimeBaseStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = GENERAL_TIM_CHANNEL_x;
TIM_ICInitStructure.TIM_ICPolarity = GENERAL_TIM_STRAT_ICPolarity;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_ICInit(GENERAL_TIM, &TIM_ICInitStructure);
TIM_ClearFlag(GENERAL_TIM, TIM_FLAG_Update|GENERAL_TIM_IT_CCx);
TIM_ITConfig (GENERAL_TIM, TIM_IT_Update | GENERAL_TIM_IT_CCx, ENABLE );
TIM_Cmd(GENERAL_TIM, ENABLE);
}
中断配置
static void GENERAL_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = GENERAL_TIM_IRQ ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
中断服务函数
void GENERAL_TIM_INT_FUN(void)
{
if ( TIM_GetITStatus ( GENERAL_TIM, TIM_IT_Update) != RESET )
{
TIM_ICUserValueStructure.Capture_Period ++;
TIM_ClearITPendingBit ( GENERAL_TIM, TIM_FLAG_Update );
}
if ( TIM_GetITStatus (GENERAL_TIM, GENERAL_TIM_IT_CCx ) != RESET)
{
if ( TIM_ICUserValueStructure.Capture_StartFlag == 0 )
{
TIM_SetCounter ( GENERAL_TIM, 0 );
TIM_ICUserValueStructure.Capture_Period = 0;
TIM_ICUserValueStructure.Capture_CcrValue = 0;
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Falling);
TIM_ICUserValueStructure.Capture_StartFlag = 1;
}
else
{
TIM_ICUserValueStructure.Capture_CcrValue =
GENERAL_TIM_GetCapturex_FUN (GENERAL_TIM);
GENERAL_TIM_OCxPolarityConfig_FUN(GENERAL_TIM, TIM_ICPolarity_Rising);
TIM_ICUserValueStructure.Capture_StartFlag = 0;
TIM_ICUserValueStructure.Capture_FinishFlag = 1;
}
TIM_ClearITPendingBit (GENERAL_TIM,GENERAL_TIM_IT_CCx);
}
}
main函数里的脉冲计算
while ( 1 )
{
if(TIM_ICUserValueStructure.Capture_FinishFlag == 1)
{
time = TIM_ICUserValueStructure.Capture_Period * (GENERAL_TIM_PERIOD+1) +
(TIM_ICUserValueStructure.Capture_CcrValue+1);
printf ( "\r\n测得高电平脉宽时间:%d.%d s\r\n",time/TIM_PscCLK,time%TIM_PscCLK );
TIM_ICUserValueStructure.Capture_FinishFlag = 0;
}
}
头文件内容
#define GENERAL_TIM TIM5
#define GENERAL_TIM_APBxClock_FUN RCC_APB1PeriphClockCmd
#define GENERAL_TIM_CLK RCC_APB1Periph_TIM5
#define GENERAL_TIM_PERIOD (65536 - 1)
#define GENERAL_TIM_PSC (72-1)
#define GENERAL_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA
#define GENERAL_TIM_CH1_PORT GPIOA
#define GENERAL_TIM_CH1_PIN GPIO_Pin_0
#define GENERAL_TIM_CHANNEL_x TIM_Channel_1
#define GENERAL_TIM_IT_CCx TIM_IT_CC1
#define GENERAL_TIM_IRQ TIM5_IRQn
#define GENERAL_TIM_INT_FUN TIM5_IRQHandler
#define GENERAL_TIM_GetCapturex_FUN TIM_GetCapture1
#define GENERAL_TIM_OCxPolarityConfig_FUN TIM_OC1PolarityConfig
#define GENERAL_TIM_STRAT_ICPolarity TIM_ICPolarity_Rising
#define GENERAL_TIM_END_ICPolarity TIM_ICPolarity_Falling
typedef struct
{
uint8_t Capture_FinishFlag;
uint8_t Capture_StartFlag;
uint16_t Capture_CcrValue;
uint16_t Capture_Period;
}TIM_ICUserValueTypeDef;
extern TIM_ICUserValueTypeDef TIM_ICUserValueStructure;
void GENERAL_TIM_Init(void);
3.PWM输入捕获 高级定时器GPIO配置
static void ADVANCE_TIM_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE);
GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure);
}
高级定时器模式配置
static void ADVANCE_TIM_Mode_Config(void)
{
ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD;
TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC;
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure);
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = ADVANCE_TIM_IC1PWM_CHANNEL;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICInitStructure.TIM_ICFilter = 0;
TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure);
TIM_SelectInputTrigger(ADVANCE_TIM, TIM_TS_TI1FP1);
TIM_SelectSlaveMode(ADVANCE_TIM, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable);
TIM_ITConfig(ADVANCE_TIM, TIM_IT_CC1, ENABLE);
TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);
TIM_Cmd(ADVANCE_TIM, ENABLE);
}
中断配置
static void ADVANCE_TIM_NVIC_Config(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);
NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
中断服务函数
__IO uint16_t IC2Value = 0;
__IO uint16_t IC1Value = 0;
__IO float DutyCycle = 0;
__IO float Frequency = 0;
void ADVANCE_TIM_IRQHandler(void)
{
TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1);
IC1Value = TIM_GetCapture1(ADVANCE_TIM);
IC2Value = TIM_GetCapture2(ADVANCE_TIM);
if (IC1Value != 0)
{
DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1);
Frequency = (72000000/(ADVANCE_TIM_PSC+1))/(float)(IC1Value+1);
printf("占空比:%0.2f%% 频率:%0.2fHz\n",DutyCycle,Frequency);
}
else
{
DutyCycle = 0;
Frequency = 0;
}
}
相关头文件
#define ADVANCE_TIM TIM1
#define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd
#define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1
#define ADVANCE_TIM_PERIOD (1000-1)
#define ADVANCE_TIM_PSC (72-1)
#define ADVANCE_TIM_IRQ TIM1_CC_IRQn
#define ADVANCE_TIM_IRQHandler TIM1_CC_IRQHandler
#define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA
#define ADVANCE_TIM_CH1_PORT GPIOA
#define ADVANCE_TIM_CH1_PIN GPIO_Pin_8
#define ADVANCE_TIM_IC1PWM_CHANNEL TIM_Channel_1
#define ADVANCE_TIM_IC2PWM_CHANNEL TIM_Channel_2
void ADVANCE_TIM_Init(void);
疑惑
1.是不是同一个定时器在使用输入捕获的时候就不能进行定时功能的使用???
|