其他分享
首页 > 其他分享> > stm32通用定时器pwm输入模式

stm32通用定时器pwm输入模式

作者:互联网

简介

stm32通用定时器有多种输入模式,其中包括了pwm输入模式。

原理

pwm输入模式是在输入捕获的基础上使用两组输入捕获通道对同一个TIM引脚进行捕获。
如下图所示:
12345述
TIMx_CH1引脚输入一个pwm信号,经过输入滤波和边沿检测之后一路(TI1FP1)给到了IC1,一路(TI1FP2)给到了IC2,从而实现两个捕获通道捕获同一个pwm信号。IC1负责测量pwm信号的周期,而IC2负责测量pwm信号的脉宽。

12

总的来说是基于输入捕获功能实现了对输入pwm信号的测量。

功能实现

以STM32F103RC为例,我们选择PA6引脚,使用TIM3_CH1功能,如下图:
123

下面列出主要步骤:

第一步:打开TIM3和GPIO的时钟。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);//时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);//使能GPIOA时钟

第二步:初始化GPIO引脚功能

//PA6引脚GPIO初始化,用于捕获输入的pwm信号,测量其周期
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_6;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);

第三步:初始化定时器timebase

//定时器初始化
TIM_ARRPreloadConfig(TIM3, ENABLE);
TIM_TimeBaseInitTypeStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseInitTypeStruct.TIM_CounterMode = TIM_CounterMode_Up;//计数方式
TIM_TimeBaseInitTypeStruct.TIM_Period = arr;//自动装载值
TIM_TimeBaseInitTypeStruct.TIM_Prescaler = psc;//预分频系数
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseInitTypeStruct);

第四步:初始化捕获参数

//channel1 设置捕获参数
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1;
TIM_ICInitStruct.TIM_ICFilter = 0xf;    //采样频率设为0.56MHz,连续采8次,可以滤掉14微秒的干扰
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;  //捕获极性
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; //每检测到一个有效边沿就捕获一次
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; 
TIM_PWMIConfig(TIM3, &TIM_ICInitStruct);

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

第五步:配置定时器的中断

//使能定时器的中断,包括更新中断、CC1捕获中断
TIM_ITConfig(TIM3,TIM_IT_Update|TIM_IT_CC1,ENABLE);

第六步:配置NVIC irq通道,初始化NVIC

//中断优先级分组
NVIC_InitTypeStruct.NVIC_IRQChannel = TIM3_IRQn;//中断通道 
NVIC_InitTypeStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_InitTypeStruct.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitTypeStruct.NVIC_IRQChannelSubPriority = 0;
NVIC_Init(&NVIC_InitTypeStruct);

第七步:使能定时器

TIM_Cmd(TIM3,ENABLE);

第八步:编写定时器中断服务函数

//中断服务函数
void TIM3_IRQHandler(void)
{
	//判断是否为定时器3产生的中断
	if(TIM_GetITStatus(TIM3,TIM_IT_Update)==SET)
	{   
        if(s_tim3_IC_edge == 1)		//在一个pwm周期内计数器溢出要计数
		{
			s_tim3_exceed++;
		}
        
		//要手动的清理中断标志位
		TIM_ClearITPendingBit(TIM3,TIM_IT_Update);
	}

    if(TIM_GetITStatus(TIM3,TIM_IT_CC1)==SET)   //捕获CC1中断
    {
        //要手动的清理中断标志位
        TIM_ClearITPendingBit(TIM3,TIM_IT_CC1);
        
        /* Get the Input Capture value */
        s_tim3_IC_val = TIM_GetCapture1(TIM3);

        if (s_tim3_IC_val != 0)
        {
            /* Duty cycle computation */
            s_tim3_pwminput_dutycycle = (TIM_GetCapture2(TIM3) * 100) / s_tim3_IC_val;

            /* Frequency computation */
            s_tim3_pwminput_freq = TIM3_TIME_BASE / s_tim3_IC_val;
        }
        else
        {
            s_tim3_pwminput_dutycycle = 0;
            s_tim3_pwminput_freq = 0;
        }
    }
}

主任务通过以下函数获取pwm的频率和占空比:

uint16_t timer_get_pwm_period(void)
{
    return s_tim3_pwminput_freq;
}

uint16_t timer_get_pwm_dutycycle(void)
{
    return s_tim3_pwminput_dutycycle;
}

目前没有开发板,无法进行硬件实验,后面有时间再慢慢补充相关知识点和可能遇到的问题。

注意事项

1、输入滤波如何设置。

原理:
输入信号可以通过数字滤波器进行滤波,滤波器的时钟由定时器的时钟(CK_INT)分频得到;滤波原理是使用采样信号对输入信号进行采样,根据连续多次采样的结果来判定输入电平是否跳变,如果连续采集到的结果都是同一个新的电平状态,就判定输入电平发生了跳变,然后给到边沿检测电路进行边沿检测;否则,判定电平状态没有发生改变,实现对干扰信号的过滤。

设置:
首先在初始化timebase的时候要选择时钟分频因子TIM_ClockDivision,这个参数用来确定数字滤波器的时钟频率,寄存器描述如下:
123
然后在初始化捕获参数时配置TIM_ICFilter,寄存器描述如下:
3
4

标签:TIM3,定时器,tim3,NVIC,stm32,TIM,GPIO,pwm
来源: https://www.cnblogs.com/lxyjrx/p/16272208.html