【arm】国民N32G435通用定时器霍尔配置,双边沿输入捕获配置

项目场景:

无刷电机FOC控制,配置通用定时器TIM4为霍尔输入检测。

控制平台,国民N32G435CBL7。


问题描述

端口配置:

c 复制代码
    /* 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配置:

c 复制代码
/*  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进行单边沿检测。

c 复制代码
/**
* @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双边沿检测也有类似的问题,需要在硬件设计中注意,且在代码中进行必要调整。


解决方案:

如上代码。

相关推荐
待什么青丝21 小时前
【TMS570LC4357】之相关驱动开发学习记录1
c语言·arm开发·驱动开发·学习
南玖yy2 天前
x86 汇编逻辑运算全解析:从【位操作】到实际应用(AND,OR,NOT,XOR,TEST)
开发语言·汇编·arm开发·后端·架构·策略模式
菜只因C3 天前
嵌入式系统:从技术原理到未来趋势(驱动程序篇)
arm开发
!chen5 天前
鲲鹏Arm+麒麟V10 K8s 离线部署教程
java·arm开发·kubernetes
ScilogyHunter5 天前
ARM P15协处理器指令详解:架构、编程与应用实践
arm开发·协处理器指令·cp15
apolloyhl6 天前
1-Wire 一线式总线:从原理到实战,玩转 DS18B20 温度采集
arm开发·stm32·单片机·嵌入式硬件
二进制coder6 天前
芯片:数字时代的算力引擎——鲲鹏、升腾、海光、Intel 全景解析
arm开发·架构·硬件架构
荆楚闲人6 天前
Keil MDK5.37或更高版本不再预装ARM Compiler Version5导致编译错误的解决方法
arm开发
MonKingWD6 天前
【Redis原理】四万字总结Redis网络模型的全部概念
网络·arm开发·redis
程序猿阿伟6 天前
《算力觉醒!ONNX Runtime + DirectML如何点燃Windows ARM设备的AI引擎》
arm开发·人工智能