3021|0

626

帖子

172

TA的资源

一粒金砂(高级)

楼主
 

stm32 PWM捕获学习 [复制链接]

转自:tedeum

发现官方有个例子,固件库里面自带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);  

相关中断函数如下:


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

这个方法经测试,是简单好用的,但根据资料表明这个是通道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 */  
  • }  

还有另外一种方法待测试:
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 );  
  • }  
  • }  



此帖出自ARM技术论坛
加EE小助手好友,
入技术交流群
EE服务号
精彩活动e手掌握
EE订阅号
热门资讯e网打尽
聚焦汽车电子软硬件开发
认真关注技术本身
点赞 关注
 

回复
举报
您需要登录后才可以回帖 登录 | 注册

查找数据手册?

EEWorld Datasheet 技术支持

相关文章 更多>>
关闭
站长推荐上一条 1/9 下一条

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

About Us 关于我们 客户服务 联系方式 器件索引 网站地图 最新更新 手机版

站点相关: 国产芯 安防电子 汽车电子 手机便携 工业控制 家用电子 医疗电子 测试测量 网络通信 物联网

北京市海淀区中关村大街18号B座15层1530室 电话:(010)82350740 邮编:100190

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
快速回复 返回顶部 返回列表