项目场景:
无刷电机FOC控制,配置通用定时器TIM4为霍尔输入检测。
控制平台,国民N32G435CBL7。
问题描述
端口配置:
/* Hall port configuration. */
GPIO_InitStructure.Pin = GPIO_PIN_6 | GPIO_PIN_7 | GPIO_PIN_8;
GPIO_InitStructure.GPIO_Current = GPIO_DC_2mA;
GPIO_InitStructure.GPIO_Slew_Rate = GPIO_Slew_Rate_High;//Default High
GPIO_InitStructure.GPIO_Pull = GPIO_Pull_Up;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Input;
GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM4;
GPIO_InitPeripheral(GPIOB, &GPIO_InitStructure);
TIM4配置:
/* Check RCC_Configuration()
Enable TIM4 Clock, GPIO, AFIO
RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM4, ENABLE);
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_GPIOB | RCC_APB2_PERIPH_AFIO, ENABLE);
*/
/* TIM4 Configuration */
TIM_DeInit(TIM4);
/* Time Base configuration */
TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
TIM_TimeBaseStructure.Prescaler = 0;
TIM_TimeBaseStructure.CntMode = TIM_CNT_MODE_UP;
TIM_TimeBaseStructure.Period = APB1_CLK_FREQ / 1000000 * 2000;//Notice calculation procedure to avoid overflow.
TIM_TimeBaseStructure.ClkDiv = 0;
TIM_TimeBaseStructure.RepetCnt = 0;
TIM_InitTimeBase(TIM4, &TIM_TimeBaseStructure);
TIM_ICInitType TIM_ICInitStructure;
TIM_InitIcStruct(&TIM_ICInitStructure);
TIM_ICInitStructure.Channel = TIM_CH_1;
TIM_ICInitStructure.IcPolarity = TIM_IC_POLARITY_RISING;
TIM_ICInitStructure.IcSelection = TIM_IC_SELECTION_TRC;
TIM_ICInitStructure.IcPrescaler = TIM_IC_PSC_DIV1;
TIM_ICInitStructure.IcFilter = 0x0;
TIM_ICInit(TIM4, &TIM_ICInitStructure);
//Adjust to TIM_IC_POLARITY_BOTHEDGE
// TIM4->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1EN);
// TIM4->CCMOD1 |= 0x0003;
// TIM4->CCEN |= 0x000A;
// TIM4->CCEN |= ((uint32_t)TIM_CCEN_CC1EN);
/* TIM4 Input Capture configuration */
TIM_SelectHallSensor(TIM4, ENABLE);//XOR(CC1,CC2,CC3)->TI1F_ED
TIM_SelectInputTrig(TIM4, TIM_TRIG_SEL_TI1F_ED);
TIM_SelectSlaveMode(TIM4, TIM_SLAVE_MODE_RESET);
TIM_SelectMasterSlaveMode(TIM4, TIM_MASTER_SLAVE_MODE_ENABLE);
/* Clear Timer Interrupt Pending Bit */
TIM_ClrIntPendingBit(TIM4,TIM_INT_TRIG);
/* Enable Timer Interrupt */
TIM_ConfigInt(TIM4,TIM_INT_TRIG,ENABLE);
TIM_ConfigInt(TIM4,TIM_INT_UPDATE,ENABLE);
/* Enable TIM4 */
TIM_Enable(TIM4,ENABLE);
初版代码
TIM_ICInitStructure.IcPolarity = TIM_IC_POLARITY_BOTHEDGE;
双边沿检测,编译可以通过,但代码会卡死,进入TIM_ICInit,发现初始化函数只支持TIM4进行单边沿检测。
/**
* @brief Initializes the TIM peripheral according to the specified
* parameters in the TIM_ICInitStruct.
* @param TIMx where x can be 1 to 8 except 6 and 7 to select the TIM peripheral.
* @param TIM_ICInitStruct pointer to a TIM_ICInitType structure
* that contains the configuration information for the specified TIM peripheral.
*/
void TIM_ICInit(TIM_Module* TIMx, TIM_ICInitType* TIM_ICInitStruct)
{
/* Check the parameters */
assert_param(IsTimCh(TIM_ICInitStruct->Channel));
assert_param(IsTimIcSelection(TIM_ICInitStruct->IcSelection));
assert_param(IsTimIcPrescaler(TIM_ICInitStruct->IcPrescaler));
assert_param(IsTimInCapFilter(TIM_ICInitStruct->IcFilter));
if ((TIMx == TIM1) || (TIMx == TIM8) || (TIMx == TIM2) || (TIMx == TIM3) || (TIMx == TIM4) || (TIMx == TIM5) || (TIMx == TIM9))
{
assert_param(IsTimIcPalaritySingleEdge(TIM_ICInitStruct->IcPolarity));
}
else
{
assert_param(IsTimIcPolarityAnyEdge(TIM_ICInitStruct->IcPolarity));
}
if (TIM_ICInitStruct->Channel == TIM_CH_1)
{
assert_param(IsTimList8Module(TIMx));
/* TI1 Configuration */
ConfigTI1(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter);
/* Set the Input Capture Prescaler value */
TIM_SetInCap1Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler);
}
else if (TIM_ICInitStruct->Channel == TIM_CH_2)
{
assert_param(IsTimList6Module(TIMx));
/* TI2 Configuration */
ConfigTI2(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter);
/* Set the Input Capture Prescaler value */
TIM_SetInCap2Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler);
}
else if (TIM_ICInitStruct->Channel == TIM_CH_3)
{
assert_param(IsTimList3Module(TIMx));
/* TI3 Configuration */
ConfigTI3(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter);
/* Set the Input Capture Prescaler value */
TIM_SetInCap3Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler);
}
else
{
assert_param(IsTimList3Module(TIMx));
/* TI4 Configuration */
ConfigTI4(TIMx, TIM_ICInitStruct->IcPolarity, TIM_ICInitStruct->IcSelection, TIM_ICInitStruct->IcFilter);
/* Set the Input Capture Prescaler value */
TIM_SetInCap4Prescaler(TIMx, TIM_ICInitStruct->IcPrescaler);
}
}
实测配置为上升沿检测霍尔状态也能正常检测。
或者尝试通过寄存器直接配置为双边沿,上面代码中在
TIM_ICInit(TIM4, &TIM_ICInitStructure);之后有如下被注释代码颗进行双边沿配置。
//Adjust to TIM_IC_POLARITY_BOTHEDGE
// TIM4->CCEN &= (uint32_t) ~((uint32_t)TIM_CCEN_CC1EN);
// TIM4->CCMOD1 |= 0x0003;
// TIM4->CCEN |= 0x000A;
// TIM4->CCEN |= ((uint32_t)TIM_CCEN_CC1EN);
具体参考用户手册。
论坛发现STM32双边沿检测也有类似的问题,需要在硬件设计中注意,且在代码中进行必要调整。
解决方案:
如上代码。