完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
最近由于需要写了一个用定时器的多通道输入捕获功能来同时检测4个反馈信号为PWM波的设备的速度,这里跟大家分享一下!!!
首先是引脚和定时器的初始化: /* ********************************************************************************************************* * BSP_DeviceSpdCheckPortinit() * * Description : Initialize the all Device speed check port * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : BSP_SpdCheckPortInit() * * Note(s) : none. ********************************************************************************************************* */ static void BSP_DeviceSpdCheckPortInit(void) { GPIO_InitTypeDef GPIO_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* 时钟使能 */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE); //TIM3默认的引脚不在这个脚上,需要定时器三完全重映射 /*初始化IO口*/ //初始化水泵速度检测引脚 GPIO_InitStructure.GPIO_Pin = BSP_GPIOC_PUMP_SPEED_CHECK_PORT_NMB; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //输入上拉,根据电路图; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(BSP_GPIOC_PUMP_SPEED_CHECK_PORT, &GPIO_InitStructure); //初始化小风机速度检测引脚 GPIO_InitStructure.GPIO_Pin = BSP_GPIOC_HYDRG_FAN_SPEED_CHECK_PORT_NMB; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(BSP_GPIOC_HYDRG_FAN_SPEED_CHECK_PORT, &GPIO_InitStructure); //初始化大风扇1速度检测引脚 GPIO_InitStructure.GPIO_Pin = BSP_GPIOC_STACK_FAN1_SPEED_CHECK_PORT_NMB; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(BSP_GPIOC_STACK_FAN1_SPEED_CHECK_PORT, &GPIO_InitStructure); //初始化大风扇2速度检测引脚 GPIO_InitStructure.GPIO_Pin = BSP_GPIOC_STACK_FAN2_SPEED_CHECK_PORT_NMB; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(BSP_GPIOC_STACK_FAN2_SPEED_CHECK_PORT, &GPIO_InitStructure); /*初始化定时器*/ TIM_DeInit(TIM3); TIM_TimeBaseStructure.TIM_Period = 999; //自动重载值 TIMX->ARR,当定时器从0计数到999,即为1000次为一个定时周期0.5s TIM_TimeBaseStructure.TIM_Prescaler = 35999; //不预分频, 使TIMx_CLK= 2KHz TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //输入时钟不分频 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //向上计数 TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //4通道输入捕获 //TIM_ICInitStructure.TIM_ICMode = TIM_ICMode_ICAP; TIM_ICInitStructure.TIM_Channel = TIM_Channel_1; //捕获通道 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 = 0x0; //捕获输入不滤波 TIM_ICInit(TIM3, &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 = 0x0; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_3; 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 = 0x0; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_ICInitStructure.TIM_Channel = TIM_Channel_4; 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 = 0x0; TIM_ICInit(TIM3, &TIM_ICInitStructure); TIM_ARRPreloadConfig(TIM3, ENABLE); //使能ARR预装载缓冲器(影子功能) TIM_GenerateEvent(TIM3,TIM_EventSource_Update); // 产生软件更新事件,立即更新数据 TIM_ClearFlag(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_FLAG_Update); //清除标志位。定时器一打开便产生更新事件,若不清除,将会进入中断 TIM_ITConfig(TIM3, TIM_IT_CC1 | TIM_IT_CC2 | TIM_IT_CC3 | TIM_IT_CC4 | TIM_IT_Update, ENABLE); TIM_Cmd(TIM3, ENABLE); BSP_IntVectSet(BSP_INT_ID_TIM3, SpdCaptureFinishedHandler);//捕获完成中断产生进入中断 BSP_IntEn(BSP_INT_ID_TIM3); } 然后就是中断服务函数: /********************************************************************************************************* * SpdCaptureFinishedHandler() * * Description : 速度控制设备速度输入捕获完成中断服务函数. * * Argument(s) : none. * * Return(s) : none. * * Caller(s) : none. * * Note(s) : ISR. *********************************************************************************************************/ void SpdCaptureFinishedHandler(void) { uint16_t g_u16SpdCaptureCurrentCounter; uint8_t i; //泵速捕获完成中断产生 if(TIM_GetITStatus(TIM3, TIM_IT_CC1) != RESET) { if(g_eSpdCaptureWorkSwitch[PUMP_SPD_MONITOR_CHANNEL] == ON) { g_u16SpdCaptureCurrentCounter = TIM_GetCapture1(TIM3); //10代表经过10个定时更新周期—5s,仍然没有捕获到下降沿 if((g_eSpdCaptureTriggersCrossCycleNmb[0] > 0) && (g_eSpdCaptureTriggersCrossCycleNmb[0] < 10)) { g_u16SpdCaptureFrequency[0] = 2000 / ((1000 - g_u16SpdCaptureLastTimeCounter[0]) + (g_eSpdCaptureTriggersCrossCycleNmb[0] *2000)+g_u16SpdCaptureCurrentCounter); } else { g_u16SpdCaptureFrequency[0] = 2000 / (g_u16SpdCaptureCurrentCounter - g_u16SpdCaptureLastTimeCounter[0]); } g_u16SpdCaptureLastTimeCounter[0] = g_u16SpdCaptureCurrentCounter; g_eSpdCaptureTriggersCrossCycleNmb[0] = 0; } else {} TIM_ClearITPendingBit(TIM3, TIM_IT_CC1); } //小风机速度捕获完成中断产生 if(TIM_GetITStatus(TIM3, TIM_IT_CC2) != RESET) { if(g_eSpdCaptureWorkSwitch[HYDROGEN_FAN_SPD_MONITOR_CHANNEL] == ON) { g_u16SpdCaptureCurrentCounter = TIM_GetCapture2(TIM3); if((g_eSpdCaptureTriggersCrossCycleNmb[1] > 0) && (g_eSpdCaptureTriggersCrossCycleNmb[1] < 10)) { g_u16SpdCaptureFrequency[1] = 2000 / ((1000 - g_u16SpdCaptureLastTimeCounter[1]) + (g_eSpdCaptureTriggersCrossCycleNmb[1] * 2000)+ g_u16SpdCaptureCurrentCounter); } else { g_u16SpdCaptureFrequency[1] = 2000 / (g_u16SpdCaptureCurrentCounter - g_u16SpdCaptureLastTimeCounter[1]); } g_u16SpdCaptureLastTimeCounter[1] = g_u16SpdCaptureCurrentCounter; g_eSpdCaptureTriggersCrossCycleNmb[1] = 0; } else {} TIM_ClearITPendingBit(TIM3, TIM_IT_CC2); } //风扇1速度捕获完成中断产生 if(TIM_GetITStatus(TIM3, TIM_IT_CC3) != RESET) { if(g_eSpdCaptureWorkSwitch[STACK_FAN1_SPD_MONITOR_CHANNEL] == ON) { g_u16SpdCaptureCurrentCounter = TIM_GetCapture3(TIM3); if((g_eSpdCaptureTriggersCrossCycleNmb[2] > 0) && (g_eSpdCaptureTriggersCrossCycleNmb[2] < 10)) { g_u16SpdCaptureFrequency[2] = 2000 / ((1000 - g_u16SpdCaptureLastTimeCounter[2]) + (g_eSpdCaptureTriggersCrossCycleNmb[2] * 2000)+ g_u16SpdCaptureCurrentCounter); } else { g_u16SpdCaptureFrequency[2] = 2000 / (g_u16SpdCaptureCurrentCounter - g_u16SpdCaptureLastTimeCounter[2]); } g_u16SpdCaptureLastTimeCounter[2] = g_u16SpdCaptureCurrentCounter; g_eSpdCaptureTriggersCrossCycleNmb[2] = 0; } else {} TIM_ClearITPendingBit(TIM3, TIM_IT_CC3); } //风扇2速度捕获完成中断产生 if(TIM_GetITStatus(TIM3, TIM_IT_CC4) != RESET) { if(g_eSpdCaptureWorkSwitch[STACK_FAN2_SPD_MONITOR_CHANNEL] == ON) { g_u16SpdCaptureCurrentCounter = TIM_GetCapture4(TIM3); if((g_eSpdCaptureTriggersCrossCycleNmb[3] > 0) && (g_eSpdCaptureTriggersCrossCycleNmb[3] < 10)) { g_u16SpdCaptureFrequency[3] = 2000 / ((1000 - g_u16SpdCaptureLastTimeCounter[3]) + (g_eSpdCaptureTriggersCrossCycleNmb[3] * 2000)+ g_u16SpdCaptureCurrentCounter); } else { g_u16SpdCaptureFrequency[3] = 2000 / (g_u16SpdCaptureCurrentCounter - g_u16SpdCaptureLastTimeCounter[3]); } g_u16SpdCaptureLastTimeCounter[3] = g_u16SpdCaptureCurrentCounter; g_eSpdCaptureTriggersCrossCycleNmb[3] = 0; } else {} TIM_ClearITPendingBit(TIM3, TIM_IT_CC4); } //更新中断产生 if(TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { for(i = 0; i < 4; i++) { if(g_eSpdCaptureWorkSwitch[i] == ON) { g_eSpdCaptureTriggersCrossCycleNmb[i]++; if(g_eSpdCaptureTriggersCrossCycleNmb[i] >= 10) { g_eSpdCaptureTriggersCrossCycleNmb[i] = 0; } } else { g_eSpdCaptureTriggersCrossCycleNmb[i] = 0; g_u16SpdCaptureFrequency[i] = 0; g_u16SpdCaptureLastTimeCounter[i] = 0; } } TIM_ClearITPendingBit(TIM3, TIM_IT_Update); } } 最后就是在相应的地方打开对应的速度监测通道: /* ********************************************************************************************************* * SetSpdMonitorSwitch() * * Description : Turn on the running speed control device monitor. * * Arguments : none. * * Returns : none. * * Notes : none. ********************************************************************************************************* */ void SetSpdMonitorSwitch(SPEED_MONITOR_CHANNEL_Typedef i_SpdMonitorChannel) { g_eSpdCaptureWorkSwitch[i_SpdMonitorChannel] = ON; } /* ********************************************************************************************************* * ResetSpdMonitorSwitch() * * Description : Turn off the running speed control device monitor. * * Arguments : none. * * Returns : none. * * Notes : none. ********************************************************************************************************* */ void ResetSpdMonitorSwitch(SPEED_MONITOR_CHANNEL_Typedef i_SpdMonitorChannel) { g_eSpdCaptureWorkSwitch[i_SpdMonitorChannel] = OFF; } 对应的通道名称由自定义的枚举量来表示,这样就可以很好的实现对对应的通道进行速度监测,当然这里的速度监测都是对于反馈的 信号为PWM波~~~第一次发帖,求支持,大神轻喷~~ |
|
相关推荐
|
|
|
|
|
|
|
|
原来发的感觉捕获中断部分不够完善,现在完善了一下,共同进步
![]() if(TIM_GetITStatus(TIM4, TIM_IT_CC3) != RESET) { if(g_eSpdCaptureWorkSwitch[PUMP_SPD_MONITOR_CHANNEL] == ON) { u16SpdCaptureCurrentCounter = TIM_GetCapture3(TIM4); if(g_u8SpdCaptureTriggersCrossCycleNmb[0] < 1)//未跨计时周期 { if((u16SpdCaptureCurrentCounter - 2) >= g_u16SpdCaptureLastTimeCounter[0]) { g_fSpdCaptureFrequency[0] = 4000.0 / (u16SpdCaptureCurrentCounter - g_u16SpdCaptureLastTimeCounter[0]); } else//否则对其频率值不做修改 { g_fSpdCaptureFrequency[0] = 0; } } else if(g_u8SpdCaptureTriggersCrossCycleNmb[0] < 10)//跨周期时间为1-10个 { g_fSpdCaptureFrequency[0] = 4000.0 / ((1000 - 1 - g_u16SpdCaptureLastTimeCounter[0]) + ((g_u8SpdCaptureTriggersCrossCycleNmb[0] - 1) * 1000)+ u16SpdCaptureCurrentCounter);// } else//跨周期超过10个,认为未转动 { g_fSpdCaptureFrequency[0] = 0; } g_u16SpdCaptureLastTimeCounter[0] = u16SpdCaptureCurrentCounter; g_u8SpdCaptureTriggersCrossCycleNmb[0] = 0; } else {} TIM_ClearITPendingBit(TIM4, TIM_IT_CC3); } 然后得到的频率转化为转速的计算方法: uint16_t GetPumpFdBckSpd(void) { return (u16)(g_fSpdCaptureFrequency[0] * 30);//频率值向转速值(转/分)转换,2脉冲/转 } |
|
|
|
|
|
小梨^大枣 发表于 2016-4-5 11:22 这是f1还是f4啊 |
|
|
|
|
|
STM32CUBEMX(12)--IIC,12864OLED(0.96寸)移植
105 浏览 0 评论
STM32CUBEMX(5)--自定义红外NEC解码,定时器TIM捕获方式
512 浏览 0 评论
stm32f407vet6+LAN8720A调试以太网遇到软件复位失败问题
883 浏览 0 评论
使用STM32CubeMX对红外波形进行GPIO输出,并LED显示
427 浏览 0 评论
470 浏览 0 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-10 23:50 , Processed in 0.666394 second(s), Total 82, Slave 65 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191