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


解决方案:

如上代码。

相关推荐
dadaobusi1 天前
qemu构建arm环境(AI生成)
arm开发
mucheni2 天前
迅为RK3562开发板ARM四核A53核心板多种系统适配全开源
arm开发
阿让啊2 天前
单片机获取真实时间的实现方法
c语言·开发语言·arm开发·stm32·单片机·嵌入式硬件
手打猪大屁2 天前
ARM裸机开发——I.MX6U_汇编LED灯驱动
汇编·arm开发
深圳信迈科技DSP+ARM+FPGA2 天前
基于ARM+FPGA+DSP的储能协调控制器解决方案,支持国产化
arm开发·fpga开发·信号处理
承接电子控制相关项目2 天前
STM32F103 单片机(基于 ARM Cortex-M3 内核)的启动过程涉及硬件初始化、固件配置和程序执行流程。
arm开发·stm32·单片机·cortex-m3内核启动
技术领导力2 天前
事关数据安全,ARM被爆不可修复漏洞
arm开发
完成大叔3 天前
嵌入式:ARM公司发展史与核心技术演进
arm开发·嵌入式硬件
木木不迷茫(˵¯͒¯͒˵)3 天前
Keil MDK‑5 中使用 GNU ARM GCC 的 -Wno-* 选项屏蔽编译警告
arm开发·gnu·keil
迷路的小灰仔3 天前
ESP32 搭建IDF+Vscode环境(详细教程)
c语言·arm开发·单片机·mcu·物联网·visual studio·iot