使用的库:串行外设库
硬件:
端口 D 引脚 12 Tim4 通道 1 端口 D 引脚 13 Tim4 通道 2
测试台频率/PWM 生成工作正常,因此无需调试。
硬件和电缆连接正确(我们已经三重检查)
问题出现在另一块板上:计算的占空比似乎只指向一个信号,所以如果我断开另一个信号的电缆,我仍然可以计算出两个占空比,同时应该为零
引脚 12 端口 D 定时器 4 通道 1 配置:
void myPWM4_Config_1(tmyPWMInput *me)
{
RCC_ClocksTypeDef __RCC_CLOCK;
myPWMInputCtor(me);
RCC_GetClocksFreq(&__RCC_CLOCK);
me->clock = __RCC_CLOCK.PCLK1_Frequency * 2; //APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
me->GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
me->GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
me->GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
me->GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
me->GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &me->GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource12, GPIO_AF_TIM4);
TIM4_IRQHandler_ptf = TIM4_IRQ_PWM;
me->NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
me->NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelCmd = 1;
NVIC_Init(&me->NVIC_InitStructure);
me->TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
me->TIM_TimeBaseStructure.TIM_Prescaler = 840 - 1;
me->TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
me->TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;
me->TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &me->TIM_TimeBaseStructure);
me->TIM_CH1_ICInitStructure.TIM_Channel = TIM_Channel_1;
me->TIM_CH1_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
me->TIM_CH1_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
me->TIM_CH1_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
me->TIM_CH1_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM4, &me->TIM_CH1_ICInitStructure);
// Select the TIM8 Input Trigger: TI1FP1
TIM_SelectInputTrigger(TIM4, TIM_TS_TI1FP1);
// Select the slave Mode: Reset Mode
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
// Enables TIM8 peripheral Preload register on ARR.
TIM_ARRPreloadConfig(TIM4, ENABLE);
// Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit)
TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);
// Enable the CC1 and the update Interrupt Request
TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_Cmd(TIM4, ENABLE);
}
引脚 13 端口 D Tim4 通道 2 配置:
void myPWM4_Config_2(tmyPWMInput *me)
{
RCC_ClocksTypeDef __RCC_CLOCK;
myPWMInputCtor(me);
RCC_GetClocksFreq(&__RCC_CLOCK);
me->clock = __RCC_CLOCK.PCLK1_Frequency * 2; //APB1
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);
me->GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
me->GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
me->GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
me->GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
me->GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_Init(GPIOD, &me->GPIO_InitStructure);
GPIO_PinAFConfig(GPIOD, GPIO_PinSource13, GPIO_AF_TIM4);
TIM4_IRQHandler_ptf = TIM4_IRQ_PWM;
me->NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;
me->NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
me->NVIC_InitStructure.NVIC_IRQChannelCmd = 1;
NVIC_Init(&me->NVIC_InitStructure);
me->TIM_TimeBaseStructure.TIM_Period = 0xFFFF;
me->TIM_TimeBaseStructure.TIM_Prescaler = 840 - 1;
me->TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up;
me->TIM_TimeBaseStructure.TIM_ClockDivision= TIM_CKD_DIV1;
me->TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM4, &me->TIM_TimeBaseStructure);
me->TIM_CH2_ICInitStructure.TIM_Channel = TIM_Channel_2;
me->TIM_CH2_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
me->TIM_CH2_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI;
me->TIM_CH2_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1;
me->TIM_CH2_ICInitStructure.TIM_ICFilter = 0x0;
TIM_PWMIConfig(TIM4, &me->TIM_CH2_ICInitStructure);
// Select the TIM8 Input Trigger: TI1FP1
TIM_SelectInputTrigger(TIM4, TIM_TS_TI2FP2);
// Select the slave Mode: Reset Mode
TIM_SelectSlaveMode(TIM4, TIM_SlaveMode_Reset);
TIM_SelectMasterSlaveMode(TIM4, TIM_MasterSlaveMode_Enable);
// Enables TIM8 peripheral Preload register on ARR.
TIM_ARRPreloadConfig(TIM4, ENABLE);
// Configures the TIM8 Update Request Interrupt source (SETS the CR1->URS bit)
TIM_UpdateRequestConfig(TIM4, TIM_UpdateSource_Regular);
// Enable the CC1 and the update Interrupt Request
TIM_ITConfig(TIM4, TIM_IT_CC2, ENABLE);
TIM_ClearFlag(TIM4, TIM_FLAG_Update);
TIM_Cmd(TIM4, ENABLE);
}
捕获/比较中断代码:
void TIM4_IRQHandler( void )
{
if (TIM_GetITStatus(TIM4, TIM_IT_CC1) != RESET) {
tmyPWMInput *pPWM4_1 = &myCTRL.myHW.myPortDCfg.myPWM4_1; //PIN12
// Clear TIM8 Capture Compare1 interrupt pending bit
TIM_ClearITPendingBit(TIM4, TIM_IT_CC1);
pPWM4_1->HighPeriod = TIM_GetCapture1(TIM4); // length of high-portion
pPWM4_1->FullPeriod = TIM_GetCapture2(TIM4); // total period
myPWMCalc(pPWM4_1); //Calculate the frequency and duty cycle
}
if (TIM_GetITStatus(TIM4, TIM_IT_CC2) != RESET) {
tmyPWMInput *pPWM4_2 = &myCTRL.myHW.myPortDCfg.myPWM4_2; //PIN13
// Clear TIM8 Capture Compare1 interrupt pending bit
TIM_ClearITPendingBit(TIM4, TIM_IT_CC2);
pPWM4_2->HighPeriod = TIM_GetCapture1(TIM4); // length of high-portion
pPWM4_2->FullPeriod = TIM_GetCapture2(TIM4); // total period
myPWMCalc(pPWM4_2); //Calculate the frequency and duty cycle
}
}
myPWMCalc 函数:
void myPWMCalc(tmyPWMInput *me)
{
uint32_t myClk;
uint32_t HighPeriod, FullPeriod;
myClk = (me->clock / (me->TIM_TimeBaseStructure.TIM_Prescaler+1));
// complete period of overflow
FullPeriod = me->FullPeriod;
HighPeriod = me->HighPeriod;
if (FullPeriod < HighPeriod) // lost an overflow
{
FullPeriod += me->TIM_TimeBaseStructure.TIM_Period;
}
me->Frequency = (10 * myClk) / FullPeriod;
me->DutyCycle = (10000 * HighPeriod) / FullPeriod;
/* reset overflow */
me->Overflow = 0;
}
如何读取从测试台收到的两个不同的 PWM 信号占空比? (频率测量正确)
我得到的输出:我计算的两个占空比相等,因为它们指向相同的频率信号,所以如果我断开另一个信号的电缆,我仍然读取两个 PWM 占空比。
我应该看到的是:占空比类似,当我断开一个信号时,断开信号的占空比应该为零。
哪个STM32?
STM32参考手册(RM)TIM章节中描述的“PWM输入”“功能”需要一个定时器上的CH1和CH2输入一个信号。这是合乎逻辑的 - 您希望硬件捕获两个参数(周期和高时间/占空比),为此,您需要两个硬件寄存器来捕获值。
该“功能”的工作原理是: 1. 在非直接连接的通道上使用“间接”捕获(在两个相对的边缘上捕获); 2. 使用定时器的从模式控制器的复位模式。因此,您无法将其用于两个信号,因为一个信号使用可用于此功能的两个通道,而且每个计时器只有一个从模式控制器。请阅读 RM 中“PWM 输入”的说明。
并且,您所做的是,第二个配置功能完全覆盖第一个配置功能的设置。
解决方案是 A. 使用两个计时器;或者,B. 如果边沿之间的距离保证始终足够远,则使用与同一定时器的两个通道上的两个信号的连接,并在两个通道的both边沿上使用捕获+中断,并计算周期/占空比每个通道独立于三个连续捕获的值。
我建议你选A。
PS.
使用的库:串行外设库
这里的 SPL 代表“标准外设库”,请注意,它可能已经被弃用了十年。