打印
[应用相关]

stm32 PWM捕获学习

[复制链接]
47|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
laocuo1142|  楼主 | 2024-10-16 10:33 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
发现官方有个例子,固件库里面自带PWM输入功能,经调试稳定可用,代码如下:

C代码  [url=][/url]

//计时器和gpio口的初始化  
GPIO_InitTypeDef GPIO_InitStructure;  
  NVIC_InitTypeDef NVIC_InitStructure;  
  
  /* TIM2 clock enable */  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  
  
  /* GPIOB clock enable */  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  
   
  /* TIM2 chennel2 configuration : PA.01 */  
  GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_1;  
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  GPIO_InitStructure.GPIO_PuPd  = GPIO_PuPd_UP ;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
   
  /* Connect TIM pin to AF1 */  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_1);  
  
  /* Enable the TIM2 global Interrupt */  
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;  
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);  
      
    TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;  
  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 = 0x0;  
  
  TIM_PWMIConfig(TIM2, &TIM_ICInitStructure);  
  
  /* Select the TIM2 Input Trigger: TI2FP2 */  
  TIM_SelectInputTrigger(TIM2, TIM_TS_TI2FP2);  
  
  /* Select the slave Mode: Reset Mode */  
  TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset);  
  TIM_SelectMasterSlaveMode(TIM2,TIM_MasterSlaveMode_Enable);  
  
  /* TIM enable counter */  
  TIM_Cmd(TIM2, ENABLE);  
  
  /* Enable the CC2 Interrupt Request */  
   TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE);  

使用特权

评论回复
沙发
laocuo1142|  楼主 | 2024-10-16 10:33 | 只看该作者
相关中断函数如下:


C代码  [url=]
[/url]

void TIM2_IRQHandler(void)  
{  
  RCC_GetClocksFreq(&RCC_Clocks);  
  
  /* Clear TIM2 Capture compare interrupt pending bit */  
  TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);  
  
  /* Get the Input Capture value */  
  IC2Value = TIM_GetCapture2(TIM2);  
  
  if (IC2Value != 0)  
  {  
    /* Duty cycle computation */  
    DutyCycle = (TIM_GetCapture1(TIM2) * 100) / IC2Value;  
  
    /* Frequency computation  
       TIM2 counter clock = (RCC_Clocks.HCLK_Frequency)/2 */  
  
    Frequency = RCC_Clocks.HCLK_Frequency / IC2Value;  
  }  
  else  
  {  
    DutyCycle = 0;  
    Frequency = 0;  
  }  
}  

使用特权

评论回复
板凳
laocuo1142|  楼主 | 2024-10-16 10:33 | 只看该作者
这个方法经测试,是简单好用的,但根据资料表明这个是通道1和通道2配合实现,其他资料也没有说明如何捕获多个通道,是否能用3和4通道配合捕获,是否1个定时器能捕获2个通道。于是网上查到另一种方法可以1个定时器捕获4个通道,但是待测试,记录如下:

C代码  [url=]
[/url]

// STM32 TIM2 4 Channel Input Capture STM32F0-Discovery - sourcer32@gmail.com  
   
#include "stm32f0xx.h"  
#include "stm32f0_discovery.h"  
   
//**************************************************************************************  
   
void TIM2_Config(void)  
{  
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;  
  TIM_ICInitTypeDef        TIM_ICInitStructure;  
   
  /* TIM2 Periph clock enable */  
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  
   
  /* TIM2 Configuration */  
  TIM_DeInit(TIM2);  
   
  /* Time base configuration */  
  TIM_TimeBaseStructInit(&TIM_TimeBaseStructure);  
  TIM_TimeBaseStructure.TIM_Prescaler = (SystemCoreClock / 1000000) - 1; // 1 MHz, from 48 MHz  
  TIM_TimeBaseStructure.TIM_Period = 0xFFFFFFFF; // Maximal, TIM2 is 32-bit counter  
  TIM_TimeBaseStructure.TIM_ClockDivision = 0x0;  
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;  
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);  
   
  TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // Rising/Falling/BothEdge  
  TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  
  TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  
  TIM_ICInitStructure.TIM_ICFilter = 0x0;  
   
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;  
  TIM_ICInit(TIM2, &TIM_ICInitStructure);  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;  
  TIM_ICInit(TIM2, &TIM_ICInitStructure);  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;  
  TIM_ICInit(TIM2, &TIM_ICInitStructure);  
  TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;  
  TIM_ICInit(TIM2, &TIM_ICInitStructure);  
   
  /* TIM1 enable counter */  
  TIM_Cmd(TIM2, ENABLE);  
   
  /* Enable the CCx Interrupt Request */  
  TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);  
}  
   
//**************************************************************************************  
   
volatile uint32_t Freq[4];  
   
void TIM2_IRQHandler(void)  
{  
    uint32_t Current, Delta;  
    static uint32_t Last[4];  
      
  if (TIM_GetITStatus(TIM2, TIM_IT_CC1) != RESET)  
    {  
        /* Clear TIM2_CH1 Capture compare interrupt pending bit */  
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC1);  
   
        Current = TIM_GetCapture1(TIM2);  
        Delta = Current - Last[0];  
        Last[0] = Current;  
        if (Delta)  
            Freq[0] = 1000000 / Delta; // 1MHz clock  
           
        // ..  
    }  
      
  if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET)  
    {  
        /* Clear TIM2_CH2 Capture compare interrupt pending bit */  
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);  
   
        Current = TIM_GetCapture2(TIM2);  
        Delta = Current - Last[1];  
        Last[1] = Current;  
        if (Delta)  
            Freq[1] = 1000000 / Delta; // 1MHz clock  
           
        // ..  
    }  
      
  if (TIM_GetITStatus(TIM2, TIM_IT_CC3) != RESET)  
    {  
        /* Clear TIM2_CH3 Capture compare interrupt pending bit */  
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC3);  
   
        Current = TIM_GetCapture3(TIM2);  
        Delta = Current - Last[2];  
        Last[2] = Current;  
        if (Delta)  
            Freq[2] = 1000000 / Delta; // 1MHz clock  
           
        // ..  
    }  
      
  if (TIM_GetITStatus(TIM2, TIM_IT_CC4) != RESET)  
    {  
        /* Clear TIM2_CH4 Capture compare interrupt pending bit */  
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC4);  
   
        Current = TIM_GetCapture4(TIM2);  
        Delta = Current - Last[3];  
        Last[3] = Current;  
        if (Delta)  
            Freq[3] = 1000000 / Delta; // 1MHz clock  
           
        // ..  
    }  
}  
   
//**************************************************************************************  
   
void NVIC_Config(void)  
{  
  NVIC_InitTypeDef NVIC_InitStructure;  
   
  /* Enable and set TIM2 Interrupt */  
  NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
  NVIC_InitStructure.NVIC_IRQChannelPriority = 0x00;  
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
  NVIC_Init(&NVIC_InitStructure);  
}  
   
//**************************************************************************************  
   
void GPIO_Config(void)  
{  
  GPIO_InitTypeDef GPIO_InitStructure;  
   
  /* GPIOA Periph clock enable */  
  RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA, ENABLE);  
   
  /* Configure TIM2 input */  
  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_3;  
  GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_AF;  
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;  
  GPIO_Init(GPIOA, &GPIO_InitStructure);  
   
  /* Connect TIM pins to AF2 */  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource5, GPIO_AF_2); // TIM2_CH1 PA5  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_2); // TIM2_CH2 PA1  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_2); // TIM2_CH3 PA2  
  GPIO_PinAFConfig(GPIOA, GPIO_PinSource3, GPIO_AF_2); // TIM2_CH4 PA3  
}  
   
//**************************************************************************************  
   
int main(void)  
{  
  NVIC_Config();  
   
  GPIO_Config();  
   
  TIM2_Config();  
   
  while(1); /* Infinite loop */  
}  

使用特权

评论回复
地板
laocuo1142|  楼主 | 2024-10-16 10:34 | 只看该作者
还有另外一种方法待测试:
C代码  [url=]
[/url]

// Hold onto the Channel 1 init structure -- we will use it to reverse  
// polarity on every edge interrupt.  
static TIM_ICInitTypeDef TIM_CH1_ICInitStructure;  
  
#define GPIO_AF_TIM2 GPIO_AF_2  
  
void ConfigPwmIn() {  
GPIO_InitTypeDef GPIO_InitStructure;  
TIM_ICInitTypeDef TIM_ICInitStructure;  
NVIC_InitTypeDef NVIC_InitStructure;  
  
TIM_DeInit(TIM2 );  
  
/* TIM2 clock enable */  
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);  
  
/* GPIOC clock enable */  
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD, ENABLE);  
  
/* TIM2 GPIO pin configuration : CH1=PD3, C2=PD4, CH3=PD7, CH4=PD6 */  
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_7 | GPIO_Pin_6;  
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;  
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;  
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;  
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;  
GPIO_Init(GPIOD, &GPIO_InitStructure);  
  
/* Connect pins to TIM3 AF2 */  
GPIO_PinAFConfig(GPIOD, GPIO_PinSource3, GPIO_AF_TIM2 );  
GPIO_PinAFConfig(GPIOD, GPIO_PinSource4, GPIO_AF_TIM2 );  
GPIO_PinAFConfig(GPIOD, GPIO_PinSource7, GPIO_AF_TIM2 );  
GPIO_PinAFConfig(GPIOD, GPIO_PinSource6, GPIO_AF_TIM2 );  
  
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;  
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;  
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;  
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;  
NVIC_Init(&NVIC_InitStructure);  
  
/* Enable capture*/  
TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;  
TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  
TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  
TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  
TIM_CH1_ICInitStructure.TIM_ICFilter = 0;  
TIM_ICInit(TIM2, &TIM_ICInitStructure);  
TIM_ICInitStructure.TIM_Channel = TIM_Channel_2;  
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;  
TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;  
TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;  
TIM_ICInitStructure.TIM_ICFilter = 0;  
TIM_ICInit(TIM2, &TIM_ICInitStructure);  
TIM_ICInitStructure.TIM_Channel = TIM_Channel_3;  
TIM_ICInit(TIM2, &TIM_ICInitStructure);  
TIM_ICInitStructure.TIM_Channel = TIM_Channel_4;  
TIM_ICInit(TIM2, &TIM_ICInitStructure);  
  
/* Enable TIM2 */  
TIM_Cmd(TIM2, ENABLE);  
  
/* Enable CC1-4 interrupt */  
TIM_ITConfig(TIM2, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4, ENABLE);  
  
/* Clear CC1 Flag*/  
TIM_ClearFlag(TIM2, TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4 );  
}  
  
static volatile uint32_t ccr[4];  
static volatile char pulseState = 0;  
  
void TIM2_IRQHandler() {  
if (TIM2 ->SR & TIM_IT_CC1 ) {  
  TIM2 ->SR &= (~TIM_IT_CC1 );  
  
  if (pulseState == 0) {  
   TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling;  
  
   // Any time we get a rising edge on CH1, we reset the counter. All channels are  
   // phase aligned, so they all use this as a reference.  
   TIM_SetCounter(TIM2, 0);  
  } else {  
   TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;  
  
   // Pull the value on the falling edge.  
   ccr[0] = TIM_GetCapture1(TIM2 );  
  }  
  pulseState = !pulseState;  
  
  // Reverse polarity.  
  TIM_ICInit(TIM2, &TIM_CH1_ICInitStructure);  
}  
  
if (TIM2 ->SR & TIM_IT_CC2 ) {  
  TIM2 ->SR &= (~TIM_IT_CC2 );  
  ccr[1] = TIM_GetCapture2(TIM2 );  
}  
if (TIM2 ->SR & TIM_IT_CC3 ) {  
  TIM2 ->SR &= (~TIM_IT_CC3 );  
  ccr[2] = TIM_GetCapture3(TIM2 );  
}  
if (TIM2 ->SR & TIM_IT_CC4 ) {  
  TIM2 ->SR &= (~TIM_IT_CC4 );  
  ccr[3] = TIM_GetCapture4(TIM2 );  
}  
}  

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

1120

主题

4989

帖子

12

粉丝