【MM32】定时器:霍尔传感器接口与六步算法

实现结果

本文的目的是 实现下图所示。
在这里插入图片描述(文档这个图是错的,霍尔信号和CCR2的位置不对,先将就着)

声明

由于实验室缺少电机,所以咱用另一块板子timer3模拟霍尔信号TIH1TIH2TIH3出来。

* 模拟霍尔信号

代码如下:

/*******************************************************************************
* @name : initTIM3
* @brief : init TIM3
* @param : u16 arr, u16 arr
* @retval : void
*******************************************************************************/
void initTIM3(u16 psc, u16 arr)
{
    TIM_TimeBaseInitTypeDef TIM_StructInit;
    GPIO_InitTypeDef GPIO_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    
    TIM_DeInit(TIM3);
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7;                      // TIM3 CH1/2
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;                                                   
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;                                   // TIM3 CH3
    GPIO_Init(GPIOB, &GPIO_InitStructure);
    
    TIM_StructInit.TIM_Prescaler = psc;                                         // set Prescaler: psc + 1
    TIM_StructInit.TIM_Period = arr;                                            // set Period: arr + 1
    TIM_StructInit.TIM_ClockDivision = TIM_CKD_DIV1;                            // set ClockDivision :0                         
    TIM_StructInit.TIM_CounterMode = TIM_CounterMode_Up;                                              
    TIM_TimeBaseInit(TIM3, &TIM_StructInit);   
    
    TIM_CCPreloadControl(TIM3, ENABLE);                                         // Enable ARR preload 
    TIM_ITConfig(TIM3, TIM_IT_Update, ENABLE);                                  // Enable update interrupt
    
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure); 

	TIM_Cmd(TIM3, ENABLE);
}

配置好定时器3后,模拟信号:

/*******************************************************************************
* @name : simMotorPrepareCommutation
* @brief :  simulate hall Input
* @param : void 
* @retval : void
*******************************************************************************/
void simMotorPrepareCommutation(void)
{
    if (gSimStep == 1){
        // Step 1 Configuration
        CH1ON;
        CH2OFF;
        CH3OFF;
        gSimStep++;
    }
    else if (gSimStep == 2){
        // Step 2 Configuration
        CH1ON;
        CH2ON;
        CH3OFF;
        gSimStep++;
    }
    else if (gSimStep == 3){
        // Step 3 Configuration
        CH1ON;
        CH2ON;
        CH3ON;
        gSimStep++;
    }
    else if (gSimStep == 4){
        // Step 4 Configuration
        CH1OFF;
        CH2ON;
        CH3ON;
        gSimStep++;
    }
    else if (gSimStep == 5){
        // Step 5 Configuration
        CH1OFF;
        CH2OFF;
        CH3ON;
        gSimStep++;
    }
    else{
        // Step 6 Configuration      
        CH1OFF;
        CH2OFF;
        CH3OFF;  
        gSimStep = 1;
    }   
}

通过中断调度

/*******************************************************************************
* @name : TIM3_IRQHandler
* @brief :  
* @param : void 
* @retval : void
*******************************************************************************/
void TIM3_IRQHandler(void)
{      
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { 
        TIM_ClearITPendingBit(TIM3, TIM_IT_Update); 
        simMotorPrepareCommutation();
    }
}
/*
--------------------------------------------------------------------------------
      TIM2 (hall timer)            |    TIM3 (Simulate the hall output)
--------------------------------------------------------------------------------
     PA_0  : hall input channel1   |     PA_6 (TIM3_CH1)
--------------------------------------------------------------------------------
     PA_1  : hall input channel2   |     PA_7 (TIM3_CH2)
--------------------------------------------------------------------------------
     PA_2  : hall input channel3   |     PB_0 (TIM3_CH3)
--------------------------------------------------------------------------------
NOTE: if use TIM3 simulate, In order to achieve better results, please use anot-
her board to output and the main function just only init TIM3 and its parameter.
*/


int main(void)
{
	//....
    initTIM3(0x0, 0xFFFF);
    
    //.....
}

MB024引脚图如下:
在这里插入图片描述
好吧,接上逻辑分析仪看看:

在这里插入图片描述结果:
在这里插入图片描述没问题就开始进入正文。

正文

配置霍尔输入定时器配置:


void initHallTimer2()
{
    TIM_TimeBaseInitTypeDef pBase;
    TIM_OCInitTypeDef       pOC;
    TIM_ICInitTypeDef       pIC;
    
    COMMON_EnableIpClock(emCLOCK_TIM2);
    COMMON_NVIC_Configure(TIM2_IRQn, 1, 1);
    GPIO_TIMER2_HALL_INPUT_Configure();
    
    TIM_DeInit(TIM2);
    TIM_TimeBaseStructInit(&pBase);
    pBase.TIM_Period        = 0xFFFF;
    pBase.TIM_Prescaler     = 0;
    pBase.TIM_CounterMode   = TIM_CounterMode_Up;
    pBase.TIM_ClockDivision = TIM_CKD_DIV1;
    pBase.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInit(TIM2, &pBase);
    
    TIM_OCStructInit(&pOC);
    pOC.TIM_Pulse           = 0x1;
    pOC.TIM_OCMode          = TIM_OCMode_PWM2;
    pOC.TIM_OutputState     = TIM_OutputState_Enable;
    pOC.TIM_OCPolarity      = TIM_OCPolarity_High;
    TIM_OC2Init(TIM2, &pOC);
    TIM_ITConfig(TIM2, TIM_IT_CC2, ENABLE); // Add OC2 handle to reduce delay
    
    TIM_SelectHallSensor(TIM2, ENABLE);
    pIC.TIM_Channel     = TIM_Channel_1;
    pIC.TIM_ICPolarity  = TIM_ICPolarity_Rising;
    pIC.TIM_ICSelection = TIM_ICSelection_TRC;
    pIC.TIM_ICPrescaler = TIM_ICPSC_DIV1;
    pIC.TIM_ICFilter    = 0x0;
    TIM_ICInit(TIM2, &pIC);  
    TIM_SelectInputTrigger(TIM2, TIM_TS_TI1F_ED);
    TIM_SelectSlaveMode(TIM2, TIM_SlaveMode_Reset); 
    TIM_SelectOutputTrigger(TIM2, TIM_TRIGSource_OC2Ref);
    
    TIM_Cmd(TIM2, ENABLE);
}

调度:

/* /
|---------|--------------------------------------------------------------------|
| PA_0    |   _|- - -|_ _ _|- - -| _ _ _                                       |
|         |                                                                    |
| PA_1    |   _ _|- - -|_ _ _|- - -| _ _                                       |
|         |                                                                    |
| PA_2    |   _ _ _|- - -|_ _ _|- - -| _                                       |
|---------+--------------------------------------------------------------------|
|pos value|  |0 1 3 7 6 4|0 1 3 7 6 4|..                                       |
|------------------------------------------------------------------------------|
*///
void TIM2_IRQHandler(void)
{      
    if (TIM_GetITStatus(TIM2, TIM_IT_CC2) != RESET) {
        TIM_ClearITPendingBit(TIM2, TIM_IT_CC2);
        /* Calculate motor speed or else with CCR1 values */
        HallCCR1 = TIM_GetCapture1(TIM2);
        
        /* get step position by PA_0 / PA_1 / PA_2 */
        HallPos = (GPIO_ReadInputData(GPIOA)) & 0x0007;
        
        /* Step Motor commutation*/
        BLDCMotorPrepareCommutation(HallPos, TIM_OCMode_PWM1, TIM_OCMode_PWM1);
    }
}

/// @brief  Main function, program entry.
/// @param  None.
/// @retval None.

int main(void)
{
	MCUID = SetSystemClock(emSYSTICK_On, AppTaskTick);
    
    initHallTimer2();
    initMotorTimer1(0, 999);
    
    while(1){
        
    }
}

出来这个玩意?这肯定是前面步进值没算好。继续修改
在这里插入图片描述


void BLDCMotorPrepareCommutation(u8 pos, TIMOCMODE_Typedef TIM_CHxMode, TIMOCMODE_Typedef TIM_CHxNMode)
{
    if (pos == 0){
        /* Channel1 configuration: CH1 output: PWM */
        TIM_SelectOCxM  (TIM1, TIM_Channel_1, TIM_CHxMode);
        TIM_CCxCmd      (TIM1, TIM_Channel_1, TIM_CCx_Enable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_1, TIM_CCxN_Disable);
        
        /* Channel2 configuration: CH2N output: PWM */
        TIM_SelectOCxM  (TIM1, TIM_Channel_2, TIM_CHxNMode);
        TIM_CCxCmd      (TIM1, TIM_Channel_2, TIM_CCx_Disable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_2, TIM_CCxN_Enable);
        
        /* Channel3 configuration: CH3 None */
        TIM_CCxCmd      (TIM1, TIM_Channel_3, TIM_CCx_Disable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_3, TIM_CCxN_Disable); 
    }
    else if (pos == 1){
        /*  Channel1 configuration: CH1 output: PWM */
        TIM_SelectOCxM  (TIM1, TIM_Channel_1, TIM_CHxMode);
        TIM_CCxCmd      (TIM1, TIM_Channel_1, TIM_CCx_Enable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_1, TIM_CCxN_Disable);
        
        /*  Channel2 configuration: CH2 None */
        TIM_CCxCmd      (TIM1, TIM_Channel_2, TIM_CCx_Disable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_2, TIM_CCxN_Disable);
        
        /*  Channel3 configuration: CH3N output: PWM */
        TIM_SelectOCxM  (TIM1, TIM_Channel_3, TIM_CHxNMode);
        TIM_CCxCmd      (TIM1, TIM_Channel_3, TIM_CCx_Disable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_3, TIM_CCxN_Enable);
    }
    else if (pos == 3){
        /* Channel1 configuration: CH1 None */
        TIM_CCxCmd      (TIM1, TIM_Channel_1, TIM_CCx_Disable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_1, TIM_CCxN_Disable);
        
        /* Channel2 configuration: CH2 output: PWM */
        TIM_SelectOCxM  (TIM1, TIM_Channel_2, TIM_CHxMode);
        TIM_CCxCmd      (TIM1, TIM_Channel_2, TIM_CCx_Enable);
        TIM_CCxNCmd     (TIM1, TIM_Channel_2, TIM_CCxN_Disable);
        
        /* Channel3 configuration: CH3N output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_CHxNMode);
        TIM_CCxCmd (TIM1, TIM_Channel_3, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Enable);
    }
    else if (pos == 7){
        /* Channel1 configuration: CH1N output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_CHxNMode);
        TIM_CCxCmd (TIM1, TIM_Channel_1, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);
        
        /* Channel2 configuration: CH2 output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_CHxMode);
        TIM_CCxCmd (TIM1, TIM_Channel_2, TIM_CCx_Enable);
        TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Disable);
        
        /* Channel3 configuration: CH3 None */
        TIM_CCxCmd (TIM1, TIM_Channel_3, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
    }
    else if (pos == 6){
        /* Channel1 configuration: CH1N output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_1, TIM_CHxNMode);
        TIM_CCxCmd (TIM1, TIM_Channel_1, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Enable);
        
        /* Channel2 configuration: CH2 None */
        TIM_CCxCmd (TIM1, TIM_Channel_2, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Disable);
        
        /* Channel3 configuration: CH3 output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_CHxMode);
        TIM_CCxCmd (TIM1, TIM_Channel_3, TIM_CCx_Enable);
        TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
    }
    else if (pos == 4){     
        /* Channel1 configuration: CH1 None */
        TIM_CCxCmd (TIM1, TIM_Channel_1, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_1, TIM_CCxN_Disable);
        
        /* Channel2 configuration: CH2N output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_2, TIM_CHxNMode);
        TIM_CCxCmd (TIM1, TIM_Channel_2, TIM_CCx_Disable);
        TIM_CCxNCmd(TIM1, TIM_Channel_2, TIM_CCxN_Enable);
        
        /* Channel3 configuration: CH3 output: PWM */
        TIM_SelectOCxM(TIM1, TIM_Channel_3, TIM_CHxMode);
        TIM_CCxCmd (TIM1, TIM_Channel_3, TIM_CCx_Enable);
        TIM_CCxNCmd(TIM1, TIM_Channel_3, TIM_CCxN_Disable);
    }
}

改到后面发现还不对,原来是三根霍尔线顺序接错一根,时序终于没问题了。吐了

在这里插入图片描述

在这里插入图片描述

  • 9
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
霍尔传感器是一种常见的非接触式传感器,可以用于测量和检测旋转物体的位置和速度。在STM32HAL库中,可以使用通用定时器来读取和处理霍尔传感器的信号。 首先,需要配置通用定时器以捕获和测量霍尔传感器的信号。可以使用定时器的输入捕获功能来获取霍尔传感器输出的脉冲信号的时间信息。然后,可以通过计算脉冲之间的时间差来确定旋转物体的位置和速度。 具体的操作步骤如下: 1. 初始化通用定时器和GPIO引脚,将其设置为输入模式,用于接收霍尔传感器的信号。 2. 配置定时器的输入捕获功能,设置相关的捕获通道和触发源。 3. 启动定时器,并开始捕获和测量霍尔传感器信号的时间信息。 4. 通过计算脉冲之间的时间差,可以得到旋转物体的位置和速度。 5. 根据需求,可以进一步处理和利用这些信息。 以STM32F407为例,可以使用STM32CubeMX工具来生成初始化代码,并在代码中添加相应的配置和处理逻辑。以下是一个示例代码的初始化部分: ```c // 初始化通用定时器和GPIO引脚 htim3.Instance = TIM3; htim3.Init.Prescaler = 0; htim3.Init.CounterMode = TIM_COUNTERMODE_UP; htim3.Init.Period = 0xFFFF; htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; if (HAL_TIM_IC_Init(&htim3) != HAL_OK) { Error_Handler(); } GPIO_InitTypeDef GPIO_InitStruct = {0}; GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_INPUT; GPIO_InitStruct.Pull = GPIO_NOPULL; HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); // 配置定时器的输入捕获功能 sConfig.ICPolarity = TIM_ICPOLARITY_RISING; sConfig.ICSelection = TIM_ICSELECTION_DIRECTTI; sConfig.ICPrescaler = TIM_ICPSC_DIV1; sConfig.ICFilter = 0; if (HAL_TIM_IC_ConfigChannel(&htim3, &sConfig, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } // 启动定时器 if (HAL_TIM_IC_Start(&htim3, TIM_CHANNEL_1) != HAL_OK) { Error_Handler(); } ``` 以上代码只是一个示例,具体的配置和处理逻辑需要根据实际需求进行调整。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值