stm32专题二十六:测量PWM 频率 + 占空比

stm32专题二十六:测量PWM 频率 + 占空比计数周期不能设置的太小 如果我们设置的计数周期 PWM 周期 那么就无法捕获 PWM 脉冲 一般驱动电机的 PWM 是 10k 25kHz 当设置的周期为 1ms 对应频率为 1kHz 那么就可以捕获 1kHz 以

大家好,欢迎来到IT知识分享网。

stm32专题二十六:测量PWM 频率 + 占空比

stm32专题二十六:测量PWM 频率 + 占空比

计数周期不能设置的太小,如果我们设置的计数周期 < PWM周期,那么就无法捕获PWM脉冲,一般驱动电机的PWM是10k ~ 25kHz,当设置的周期为1ms,对应频率为1kHz,那么就可以捕获1kHz以下的PWM 信号;

stm32专题二十六:测量PWM 频率 + 占空比

stm32专题二十六:测量PWM 频率 + 占空比

bsp_AdvanceTim.h

#ifndef __BSP_ADVANCETIME_H #define __BSP_ADVANCETIME_H #include "stm32f10x.h" /高级定时器TIM参数定义,只限TIM1和TIM8/ // 当使用不同的定时器的时候,对应的GPIO是不一样的,这点要注意 // 这里我们使用高级控制定时器TIM1 #define ADVANCE_TIM TIM1 #define ADVANCE_TIM_APBxClock_FUN RCC_APB2PeriphClockCmd #define ADVANCE_TIM_CLK RCC_APB2Periph_TIM1 // 输入捕获能捕获到的最小的频率为 72M/{ (ARR+1)*(PSC+1) } #define ADVANCE_TIM_PERIOD (1000-1) #define ADVANCE_TIM_PSC (72-1) // 中断相关宏定义 #define ADVANCE_TIM_IRQ TIM1_CC_IRQn #define ADVANCE_TIM_IRQHandler TIM1_CC_IRQHandler // TIM1 输入捕获通道1 #define ADVANCE_TIM_CH1_GPIO_CLK RCC_APB2Periph_GPIOA #define ADVANCE_TIM_CH1_PORT GPIOA #define ADVANCE_TIM_CH1_PIN GPIO_Pin_8 #define ADVANCE_TIM_IC1PWM_CHANNEL TIM_Channel_1 #define ADVANCE_TIM_IC2PWM_CHANNEL TIM_Channel_2 /函数声明/ void ADVANCE_TIM_Init(void); #endif /* __BSP_ADVANCETIME_H */ 

bsp_AdvanceTim.c

 #include "bsp_AdvanceTim.h" / * @brief 高级控制定时器 TIMx,x[1,8]中断优先级配置 * @param 无 * @retval 无 */ static void ADVANCE_TIM_NVIC_Config(void) { NVIC_InitTypeDef NVIC_InitStructure; // 设置中断组为0 NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0); // 设置中断来源 NVIC_InitStructure.NVIC_IRQChannel = ADVANCE_TIM_IRQ; // 设置抢占优先级 NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; // 设置子优先级 NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } / * @brief 高级定时器PWM输入用到的GPIO初始化 * @param 无 * @retval 无 */ static void ADVANCE_TIM_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure; RCC_APB2PeriphClockCmd(ADVANCE_TIM_CH1_GPIO_CLK, ENABLE); GPIO_InitStructure.GPIO_Pin = ADVANCE_TIM_CH1_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(ADVANCE_TIM_CH1_PORT, &GPIO_InitStructure); } ///* // * 注意:TIM_TimeBaseInitTypeDef结构体里面有5个成员,TIM6和TIM7的寄存器里面只有 // * TIM_Prescaler和TIM_Period,所以使用TIM6和TIM7的时候只需初始化这两个成员即可, // * 另外三个成员是通用定时器和高级定时器才有. // *----------------------------------------------------------------------------- // *typedef struct // *{ TIM_Prescaler 都有 // * TIM_CounterMode TIMx,x[6,7]没有,其他都有 // * TIM_Period 都有 // * TIM_ClockDivision TIMx,x[6,7]没有,其他都有 // * TIM_RepetitionCounter TIMx,x[1,8,15,16,17]才有 // *}TIM_TimeBaseInitTypeDef; // *----------------------------------------------------------------------------- // */ /* ---------------- PWM信号 周期和占空比的计算--------------- */ // ARR :自动重装载寄存器的值 // CLK_cnt:计数器的时钟,等于 Fck_int / (psc+1) = 72M/(psc+1) // PWM 信号的周期 T = ARR * (1/CLK_cnt) = ARR*(PSC+1) / 72M // 占空比P=CCR/(ARR+1) / * @brief 高级定时器PWM输入初始化和用到的GPIO初始化 * @param 无 * @retval 无 */ static void ADVANCE_TIM_Mode_Config(void) { // 开启定时器时钟,即内部时钟CK_INT=72M ADVANCE_TIM_APBxClock_FUN(ADVANCE_TIM_CLK,ENABLE); /*--------------------时基结构体初始化-------------------------*/ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断 TIM_TimeBaseStructure.TIM_Period=ADVANCE_TIM_PERIOD; // 驱动CNT计数器的时钟 = Fck_int/(psc+1) TIM_TimeBaseStructure.TIM_Prescaler= ADVANCE_TIM_PSC; // 时钟分频因子 ,配置死区时间时需要用到 TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 计数器计数模式,设置为向上计数 TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 重复计数器的值,没用到不用管 TIM_TimeBaseStructure.TIM_RepetitionCounter=0; // 初始化定时器 TIM_TimeBaseInit(ADVANCE_TIM, &TIM_TimeBaseStructure); /*--------------------输入捕获结构体初始化-------------------*/ // 使用PWM输入模式时,需要占用两个捕获寄存器,一个测周期,另外一个测占空比 TIM_ICInitTypeDef TIM_ICInitStructure; // 捕获通道IC1配置 // 选择捕获通道 TIM_ICInitStructure.TIM_Channel = ADVANCE_TIM_IC1PWM_CHANNEL; // 设置捕获的边沿 TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; // 设置捕获通道的信号来自于哪个输入通道,有直连和非直连两种 TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // 1分频,即捕获信号的每个有效边沿都捕获 TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 不滤波 TIM_ICInitStructure.TIM_ICFilter = 0x0; // 初始化PWM输入模式 TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure); // 当工作做PWM输入模式时,只需要设置触发信号的那一路即可(用于测量周期) // 另外一路(用于测量占空比)会由硬件自带设置,不需要再配置 // 捕获通道IC2配置 // TIM_ICInitStructure.TIM_Channel = ADVANCE_TIM_IC1PWM_CHANNEL; // TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_IndirectTI; // TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // TIM_ICInitStructure.TIM_ICFilter = 0x0; // TIM_PWMIConfig(ADVANCE_TIM, &TIM_ICInitStructure); // 选择输入捕获的触发信号 TIM_SelectInputTrigger(ADVANCE_TIM, TIM_TS_TI1FP1); // 选择从模式: 复位模式 // PWM输入模式时,从模式必须工作在复位模式,当捕获开始时,计数器CNT会被复位 TIM_SelectSlaveMode(ADVANCE_TIM, TIM_SlaveMode_Reset); TIM_SelectMasterSlaveMode(ADVANCE_TIM,TIM_MasterSlaveMode_Enable); // 使能捕获中断,这个中断针对的是主捕获通道(测量周期那个) TIM_ITConfig(ADVANCE_TIM, TIM_IT_CC1, ENABLE); // 清除中断标志位 TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1); // 使能高级控制定时器,计数器开始计数 TIM_Cmd(ADVANCE_TIM, ENABLE); } / * @brief 高级定时器PWM输入初始化和用到的GPIO初始化 * @param 无 * @retval 无 */ void ADVANCE_TIM_Init(void) { ADVANCE_TIM_GPIO_Config(); ADVANCE_TIM_NVIC_Config(); ADVANCE_TIM_Mode_Config(); } /*END OF FILE/ 

stm32专题二十六:测量PWM 频率 + 占空比

触发源选择,选择指定的一个信号。得到TRGI,TRGI去触发从模式。从模式可以在这个列表里。选择一项操作来自动执行。

想让TI1FP1信号自动触发CNT清零, 那触发源选择。就可以选中这里的TI1FP1, 从模式执行的操作。就可以选择执行Reset的操作, 这样TI1FP1的信号就可以自动触发从模式,从模式自动清零CNT,实现硬件全自动测量。

stm32专题二十六:测量PWM 频率 + 占空比

中断服务函数

 __IO uint16_t IC2Value = 0; __IO uint16_t IC1Value = 0; __IO float DutyCycle = 0; __IO float Frequency = 0; /* * 如果是第一个上升沿中断,计数器会被复位,锁存到CCR1寄存器的值是0,CCR2寄存器的值也是0 * 无法计算频率和占空比。当第二次上升沿到来的时候,CCR1和CCR2捕获到的才是有效的值。其中 * CCR1对应的是周期,CCR2对应的是占空比。 */ void ADVANCE_TIM_IRQHandler(void) { /* 清除中断标志位 */ TIM_ClearITPendingBit(ADVANCE_TIM, TIM_IT_CC1); /* 获取输入捕获值 */ IC1Value = TIM_GetCapture1(ADVANCE_TIM); IC2Value = TIM_GetCapture2(ADVANCE_TIM); //printf("IC1Value = %d IC2Value = %d ",IC1Value,IC2Value); // 注意:捕获寄存器CCR1和CCR2的值在计算占空比和频率的时候必须加1,因为计数器是从 0 开始计数的。 if (IC1Value != 0) { /* 占空比计算 */ DutyCycle = (float)((IC2Value+1) * 100) / (IC1Value+1); /* 频率计算 */ Frequency = (/(ADVANCE_TIM_PSC+1))/(float)(IC1Value+1); printf("占空比:%0.2f%% 频率:%0.2fHz\n",DutyCycle,Frequency); } else { DutyCycle = 0; Frequency = 0; } } 

stm32专题二十六:测量PWM 频率 + 占空比

main.c

 // TIM—高级定时器-PWM输入捕获应用,通用定时器产生PWM波,高级定时器则捕获这个PWM,并测量周期和占空比 #include "stm32f10x.h" #include "bsp_led.h" #include "bsp_AdvanceTim.h" #include "bsp_GeneralTim.h" #include "bsp_usart.h" / * @brief 主函数 * @param 无 * @retval 无 */ int main(void) { /* 串口初始化 */ USART_Config(); /* 通用定时器初始化,用于生成PWM信号 */ GENERAL_TIM_Init(); /* 高级定时器初始化 ,用户捕获PWM信号*/ ADVANCE_TIM_Init(); while(1) { } } /*END OF FILE/ 

stm32专题二十六:测量PWM 频率 + 占空比

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/154640.html

(0)
上一篇 2025-02-24 18:26
下一篇 2025-02-24 18:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信