`

stm32 pwm捕获学习笔记

阅读更多

前段时间抄袭其他的stm多通道捕获代码,调试没有通过,由于半路出家也不是读得太懂,后来发现官方有个例子,原来固件库里面自带PWM输入功能,经调试稳定可用,代码如下:

 

//计时器和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);

 相关中断函数如下:

 

 

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;
  }
}

 这个方法经测试,是简单好用的,但根据资料表明这个是通道1和通道2配合实现,其他资料也没有说明如何捕获多个通道,是否能用3和4通道配合捕获,是否1个定时器能捕获2个通道。于是网上查到另一种方法可以1个定时器捕获4个通道(),但是待测试,记录如下:

 

// 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 */
}

 还有另外一种方法待测试:

// 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 );
 }
}

 

 

0
0
分享到:
评论

相关推荐

    STM32F407基于标准库的输入捕获工程与学习笔记,实现获取脉冲周期与频率功能

    输入捕获实验: 1. 初始化定时器,用于计算脉冲溢出多少次,重装载值为ARR 2. 初始化输入捕获相关参数 ...实验中,设置ARR重装载值为32位0XFFFFFFFF 84分频,因此定时器每个定时周期 = 84M / 84 = 1M = 1us

    STM32各模块学习笔记

    本学习笔记主要涵盖了STM32的各个核心模块,旨在帮助开发者深入理解并熟练掌握STM32的使用。 一、STM32概述 STM32系列提供多种型号,不同型号间的性能、内存大小和外设接口有所不同。其内核包括Cortex-M0、M3、M4和...

    stm32 pwm输入捕捉模式学习笔记

    在这一模式下,STM32定时器的输入捕获功能被用于处理PWM(脉宽调制)信号。输入捕获的基本原理是当连接到定时器的GPIO引脚上的信号发生电平变化时,定时器会记录下当前的计数值,并将其存储到特定的寄存器中。这种...

    STM32学习笔记PWM波形输出.pdf

    在我们的学习笔记中,第一步就是通过调用SystemInit()函数将系统时钟设置为72MHz。这一过程包括选择合适的时钟源、配置PLL(相位锁定环)参数以及设置AHB、APB总线的时钟分频器等,确保微控制器的CPU和外设能够按照...

    脉冲宽度计(占空比) 单输入捕获+中断方式(STM32+CubeIDE+HAL)

    通过这个项目,开发者不仅可以学习如何利用STM32的定时器和中断功能进行脉冲宽度测量,还能深入了解CubeIDE和HAL库的使用,提升嵌入式系统的开发技能。同时,项目提供的源码和测试数据对于初学者来说是一份宝贵的...

    stm32f0例程和笔记

    通过这些例程和笔记,你不仅可以学习到STM32F0的基本操作,还能深入理解其工作原理和应用技巧。无论是初学者还是有经验的开发者,都能从中受益匪浅,提升自己的STM32编程技能。同时,这些实例也提供了实践平台,方便...

    基于STM32F407的五路PWM输出控制舵机-学习笔记

    在本学习笔记中,我们将深入探讨如何利用STM32F407微控制器实现五路PWM(脉宽调制)输出来控制舵机。STM32F407是一款高性能的ARM Cortex-M4内核MCU,具有浮点运算单元(FPU),广泛应用于嵌入式系统设计,特别是涉及...

    STM32 F103C8T6学习笔记4:时钟树、滴答计时器、定时器定时中断.rar

    在本学习笔记中,我们将深入探讨STM32 F103C8T6型号芯片中的三个关键概念:时钟树、滴答计时器(也称为系统定时器)以及定时器定时中断。这些知识点对于理解和有效地使用STM32进行实时控制至关重要。 首先,时钟树...

    stm32自学笔记蒙博宇扫描版

    "STM32自学笔记蒙博宇扫描版"是一本专门针对STM32学习的书籍,适合新手和有一定基础的老手参考。 这本书可能涵盖了以下关键知识点: 1. **STM32基础知识**:介绍STM32系列的基本结构,包括不同型号的区别、内核...

    STM32 F103C8T6学习笔记5:定时器输出不同占空比PWM驱动舵机旋转角度.rar

    在本篇STM32 F103C8T6的学习笔记中,我们将深入探讨如何使用定时器输出不同占空比的脉宽调制(PWM)信号来驱动舵机旋转到不同的角度。舵机是一种常见的微型伺服电机,在机器人、无人机等领域广泛应用,通过控制输入...

    GD32学习笔记第三章:PWM控制LED

    在本GD32学习笔记第三章中,我们将深入探讨如何使用PWM(脉宽调制)技术来控制LED的亮度。PWM是一种广泛应用于嵌入式系统中的数字模拟转换方法,通过改变脉冲宽度来调节输出信号的平均功率,进而实现对LED亮度的控制...

    STM32F103C8T6 的MINI板程序开发笔记和例程序_stm32f103c8t6_程序开发笔记_STM32F103C8T

    本篇开发笔记将围绕STM32F103C8T6进行深入探讨,涵盖多个关键功能模块的程序开发,包括PWM、USART、USB、ADC、TIM定时器、CRC、读取芯片ID以及按键处理等。 首先,我们来看PWM(脉宽调制)的应用。在"高级例程-基于...

    STM32F407ZGT6学习笔记

    本学习笔记将深入探讨其中的关键特性,尤其是中断系统的管理和一些实用功能,如串口通信、外部中断、定时器、PWM输出以及输入捕获和电容触摸屏实验。 首先,中断系统在STM32F407中扮演着核心角色,它允许处理器高效...

    STM32中文应用笔记

    笔记内容详细介绍了STM32F10XX的各种外设功能及其实现方法,是学习和开发STM32不可或缺的技术参考资料。 1. **GPIO(通用输入/输出)**:STM32F10XX具有丰富的GPIO端口,支持多种工作模式,如输入浮空、推挽、开漏...

    STM32F407基于标准库的定时器PWM工程与学习笔记,实现PWM调节LED亮度功能

    PWM输出实验: 使用PF9引脚,TIM14通道1输出PWM,连接到PF9上的LED灯,可以控制...6. 设置不同的CCR1值,也就是捕获/比较值,用于控制PWM的高低电平占空比。 7. PWM低电平期间,LED亮,低电平时间越长,则LED亮度越高

    STM32F103C8T6核心板文档资料_STM32F103C8T6pdf_stm32f103c8t6_

    通过深入学习这些文档,开发者可以了解STM32F103C8T6的工作原理,掌握如何进行硬件设计、编写程序、调试系统等。对于初学者,可以从基础的LED闪烁程序开始,逐渐掌握更复杂的功能实现。对于经验丰富的工程师,这些...

    STM32 IO口模拟串口

    STM32 IO口模拟串口是微控制器编程中常见的技术,尤其在资源有限或特定应用场景...文件名为"IO_UART"可能包含的就是实现这一功能的代码示例或者库文件,可以作为参考学习如何在STM32F103CBT6上实现IO口模拟串口的功能。

    PWM学习笔记

    【PWM学习笔记】 脉冲宽度调制(PWM)是一种广泛应用于数字控制系统的技术,它通过调整脉冲信号的宽度来模拟连续变化的电压或电流。在微处理器系统中,PWM允许我们使用数字信号来控制模拟电路,例如调节电机速度、...

    44-STM32F429_IDENTIFICATION.7z

    STM32F429是意法半导体(STMicroelectronics)推出的一款基于ARM Cortex-M4内核的微控制器,...通过学习这些资料,开发者可以深入理解STM32F429的特性和功能,有效利用其强大的性能,进行高效且可靠的嵌入式系统设计。

Global site tag (gtag.js) - Google Analytics