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


解决方案:

如上代码。

相关推荐
天骄t15 小时前
裸机开发:ARMv7-A中断驱动LED/蜂鸣器实战
arm开发
秋深枫叶红16 小时前
嵌入式第四十九篇——ARM系列——IMX6ULL开发板
arm开发·嵌入式硬件
南烟斋..17 小时前
ARM Cortex-A7(IMX6ULL)嵌入式裸机开发指南:从点灯到中断
arm开发·单片机·嵌入式硬件
ArrebolJiuZhou17 小时前
03 rtp,rtcp,sdp的包结构
linux·运维·服务器·网络·arm开发
松涛和鸣18 小时前
59、 IMX6ULL按键驱动开发:轮询到中断的实现
linux·服务器·c语言·arm开发·数据库·驱动开发
切糕师学AI18 小时前
ARM Cortex-M 存储器映射
arm开发
VekiSon18 小时前
ARM架构——中断系统详解
c语言·arm开发·嵌入式硬件
ZL.zheng18 小时前
can范围唤醒的那些事?
arm开发
ShiMetaPi18 小时前
GM-3568JHF丨ARM+FPGA异构开发板应用开发教程:04 MIPI屏幕检测案例
arm开发·fpga开发·rk3568
代码游侠19 小时前
学习笔记——GPIO按键与中断系统
c语言·开发语言·arm开发·笔记·嵌入式硬件·学习·重构