MCSDK 杂记

//================//

//================//

//================//

//================//

//================//

我们从TIM_ClearFlag()与TIM_ClearITPendingBit()的函数体对比发现,完全一摸一样,可以互换使用

//================//
 

8.4.2 TIM6 和 TIM7 DMA/中断使能寄存器 (TIMx_DIER)

img

位 0 UIE:更新中断使能 (Update interrupt enable) 0:禁止更新中断。 1:使能更新中断。

8.4.3 TIM6 和 TIM7 状态寄存器 (TIMx_SR)>> 只有一位:更新中断标志位

img

位 0 UIF:更新中断标志 (Update interrupt flag) 该位在发生更新事件时通过硬件置 1。但需要通过软件清零。 0:未发生更新。 1:更新中断挂起。该位在以下情况下更新寄存器时由硬件置 1: — 上溢或下溢并且当 TIMx_CR1 寄存器中 UDIS = 0 时。 — 当由于 TIMx_CR1 寄存器中 URS = 0 且 UDIS = 0 而通过软件使用 TIMx_EGR 寄存器中 的 UG 位重新初始化 CNT 时。

//================//
 

中断标志位不清除会怎么样?
中断标志位不清除, 结果是完成中断处理程序后, 它就继续再进中断, 根本不会回到主程序。

代码如下(示例):

void EXTI2_IRQHandler(void)
{
    delay_ms(10);    //消抖
    if(KEY2==0)      
    {                 
   LED0=!LED0; 
    }         
     //EXTI_ClearITPendingBit(EXTI_Line2);//清除LINE2上的中断标志位 
1
2
3
4
5
6
7
8
这里的清除中断标志位的一行代码被我注释掉了,所以并没有清除中断标志位。这样的话会发生什么呢?按下KEY2时,完成中断处理程序后仍然进入中断,中断服务函数里的内容会被一直重复执行,知道松开KEY2。这样的话并不能控制LED0的翻转了,所以中断结束之后一定要清楚中断标志位。
————————————————

                            版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
                        
原文链接:https://blog.csdn.net/weixin_45847849/article/details/115797441

//================//
 

[STM32定时器学习-002]PWM和OC输出

/**
  * @brief  It enables PWM generation on the proper Timer peripheral acting on MOE
  *         bit
  * @param  pHdl: handler of the current instance of the PWM component
  * @retval none
  */
__weak void R3_2_SwitchOnPWM( PWMC_Handle_t * pHdl )
{  
  PWMC_R3_2_Handle_t * pHandle = (PWMC_R3_2_Handle_t *) pHdl;
  TIM_TypeDef* TIMx = pHandle->pParams_str->TIMx;

  pHandle->_Super.TurnOnLowSidesAction = false;

  /* Set all duty to 50% */
  LL_TIM_OC_SetCompareCH1(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH2(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH3(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH4(TIMx, (uint32_t)(pHandle->Half_PWMPeriod - 5u));

  /* wait for a new PWM period */
	int a=READ_BIT(TIMx->SR, TIM_SR_UIF);
	printf("TIMx->SR, TIM_SR_UIF111=%d\r\n",a);
    LL_TIM_ClearFlag_UPDATE(TIMx);
    a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF222=%d\r\n",a);
  while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0 )
  {
	  printf("AAAAAAAAA\r\n");

  }
  a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF333=%d\r\n",a);
  /* Clear Update Flag */
  LL_TIM_ClearFlag_UPDATE(TIMx);
  a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF444=%d\r\n\r\n",a);
  /* Main PWM Output Enable */
  TIMx->BDTR |= LL_TIM_OSSI_ENABLE;
  LL_TIM_EnableAllOutputs( TIMx );//GGI//使能所有通道输出

  if ( ( pHandle->pParams_str->LowSideOutputs ) == ES_GPIO )
  {
    if ( LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u )
    {
    	printf("LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u\r\n");
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_u_port, pHandle->pParams_str->pwm_en_u_pin );
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_v_port, pHandle->pParams_str->pwm_en_v_pin );
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_w_port, pHandle->pParams_str->pwm_en_w_pin );
    }
    else
    {
    	printf("LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u !!!!!!\r\n");
      /* It is executed during calibration phase the EN signal shall stay off */
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_u_port, pHandle->pParams_str->pwm_en_u_pin );
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_v_port, pHandle->pParams_str->pwm_en_v_pin );
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_w_port, pHandle->pParams_str->pwm_en_w_pin );
    }
  }
  else
  {
  	printf("!!!!!!!!( pHandle->pParams_str->LowSideOutputs ) == ES_GPIO \r\n");
  }

  /* Clear Update Flag */
  LL_TIM_ClearFlag_UPDATE( TIMx );
  /* Enable Update IRQ */
  LL_TIM_EnableIT_UPDATE(TIMx);//GGI//使能定时器更新中断,TIM1_UP_TIM10_IRQHandler


  return;
}

17.4.1
TIM1 and TIM8 control register 1 (TIMx_CR1)
Address offset: 0x00
Reset value: 0x0000

Bit 0 CEN: Counter enable
0: Counter disabled
1: Counter enabled
Note: External clock, gated mode and encoder mode can work only if the CEN bit has been
previously set by software. However trigger mode can set the CEN bit automatically by
hardware.

//================//
 

电机状态初始化

MX_MotorControl_Init(); ->MCboot(pMCI,pMCT);->STM_Init(&STM[M1]);

__weak void STM_Init( STM_Handle_t * pHandle )

{

pHandle->bState = IDLE;//GGI//电机初始状态为IDEL

pHandle->hFaultNow = MC_NO_FAULTS;

pHandle->hFaultOccurred = MC_NO_FAULTS;

}

//================//

MX_MotorControl_Init(); ->MCboot(pMCI,pMCT);->

EAC_Init(&EncAlignCtrlM1,pSTC[M1],&VirtualSpeedSensorM1,&ENCODER_M1);

__weak void EAC_Init( EncAlign_Handle_t * pHandle, SpeednTorqCtrl_Handle_t * pSTC, VirtualSpeedSensor_Handle_t * pVSS,

ENCODER_Handle_t * pENC )

{

pHandle->pSTC = pSTC;

pHandle->pVSS = pVSS;

pHandle->pENC = pENC;

pHandle->EncAligned = false;

pHandle->EncRestart = false;

}

bool EncRestart; /*!< This flag is used to force a restart of the

motor after the encoder alignment. It is true

if a restart is programmed else false*/

编码器对齐后,要强制进行电机重启。这个电机重启标志位,pHandle->EncRestart,在EAC_Init函数中初始化为false.

//================//

TIM1 定时器中断中,更新配置ADC寄存器,并使能。

  /* Disabling trigger to avoid unwanted conversion */
  LL_ADC_INJ_StopConversionExtTrig(ADCx_1);
  LL_ADC_INJ_StopConversionExtTrig(ADCx_2);

  /* Set next current channel according to sector  */
  ADCx_1->JSQR = pHandle->pParams_str->ADCConfig1[pHandle->_Super.Sector];
  ADCx_2->JSQR = pHandle->pParams_str->ADCConfig2[pHandle->_Super.Sector];

  LL_ADC_INJ_SetTriggerSource(ADCx_1,pHandle->ADC_ExternalTriggerInjected);
  LL_ADC_INJ_SetTriggerSource(ADCx_2,pHandle->ADC_ExternalTriggerInjected);
    
  /* enable ADC trigger source */
  LL_TIM_CC_EnableChannel(TIMx, LL_TIM_CHANNEL_CH4);
  LL_ADC_INJ_StartConversionExtTrig(ADCx_1, pHandle->ADCTriggerEdge);
  LL_ADC_INJ_StartConversionExtTrig(ADCx_2, pHandle->ADCTriggerEdge);

  /* reset default edge detection trigger */
  pHandle->ADCTriggerEdge = LL_ADC_INJ_TRIG_EXT_RISING;

  return &( pHandle->_Super.Motor );

//================//

ADC中断中,执行高频任务,首先做FOC计算,根据FOC计算的结果,得出TIM1每个通道的占空比,进而得到每个通道的CCR寄存器的数值(PWMC_SetPhaseVoltage)。

FOC控制库MCSDK5.4.4梳理(1)——SVPWM

    if ( wZ < 0 )
    {
      pHandle->Sector = SECTOR_5;
      wTimePhA = ( int32_t )( pHandle->PWMperiod ) / 4 + ( ( wY - wZ ) / ( int32_t )262144 );
      wTimePhB = wTimePhA + wZ / 131072;
      wTimePhC = wTimePhA - wY / 131072;
      pHandle->lowDuty = wTimePhC;
      pHandle->midDuty = wTimePhA;
      pHandle->highDuty = wTimePhB;
    }

并且计算得到ADC的采样点时刻(R3_2_SetADCSampPointSectX),再调用R3_2_WriteTIMRegisters更新寄存器。

/**
  * @brief  Configure the ADC for the current sampling related to sector 1.
  *         It means set the sampling point via TIMx_Ch4 value and polarity
  *         ADC sequence length and channels.
  *         And call the WriteTIMRegisters method.
  * @param  pHdl: handler of the current instance of the PWM component
  * @retval none
  */
__weak uint16_t R3_2_SetADCSampPointSectX( PWMC_Handle_t * pHdl )//GGI
{
  PWMC_R3_2_Handle_t * pHandle = ( PWMC_R3_2_Handle_t * )pHdl;

  uint16_t hCntSmp;
  uint16_t hDeltaDuty;
  register uint16_t lowDuty = pHdl->lowDuty;
  register uint16_t midDuty = pHdl->midDuty;

  /* Check if sampling AB in the middle of PWM is possible */
  if ( ( uint16_t )( pHandle->Half_PWMPeriod - lowDuty ) > pHandle->pParams_str->hTafter )
  {
    /* When it is possible to sample in the middle of the PWM period, always sample the same phases
     * (AB are chosen) for all sectors in order to not induce current discontinuities when there are differences
     * between offsets */

    /* sector number needed by GetPhaseCurrent, phase A and B are sampled wIch corresponds
     * to sector 4 */
    pHandle->_Super.Sector = SECTOR_4;

    /* set sampling  point trigger in the middle of PWM period */
    hCntSmp = ( uint32_t )( pHandle->Half_PWMPeriod ) - 1u;
  }
  else
  {
    /* ADC Injected sequence configuration. The stator phase with minimum value of complementary
    duty cycle is set as first. In every sector there is always one phase with maximum complementary duty,
    one with minimum complementary duty and one with variable complementary duty. In this case, phases
    with variable complementary duty and with maximum duty are converted and the first will be always
    the phase with variable complementary duty cycle */

    /* Crossing Point Searching */
    hDeltaDuty = ( uint16_t )( lowDuty - midDuty );

    /* Definition of crossing point */
    if ( hDeltaDuty > ( uint16_t )( pHandle->Half_PWMPeriod - lowDuty ) * 2u )
    {
      /* hTbefore = 2*Ts + Tc, where Ts = Sampling time of ADC, Tc = Conversion Time of ADC */
      hCntSmp = lowDuty - pHandle->pParams_str->hTbefore;
    }
    else
    {
      /* hTafter = DT + max(Trise, Tnoise) */
      hCntSmp = lowDuty + pHandle->pParams_str->hTafter;

      if ( hCntSmp >= pHandle->Half_PWMPeriod )
      {
          /* It must be changed the trigger direction from positive to negative
               to sample after middle of PWM*/
        pHandle->ADCTriggerEdge = LL_ADC_INJ_TRIG_EXT_FALLING;

        hCntSmp = ( 2u * pHandle->Half_PWMPeriod ) - hCntSmp - 1u;
      }
    }
  }

  return R3_2_WriteTIMRegisters( &pHandle->_Super, hCntSmp );
}

///
__STATIC_INLINE uint16_t R3_2_WriteTIMRegisters( PWMC_Handle_t * pHdl, uint16_t hCCR4Reg )//GGI
{
  PWMC_R3_2_Handle_t * pHandle = (PWMC_R3_2_Handle_t *) pHdl;
  TIM_TypeDef * TIMx = pHandle->pParams_str->TIMx;
  uint16_t hAux;

  LL_TIM_OC_SetCompareCH1( TIMx, pHandle->_Super.CntPhA );
  LL_TIM_OC_SetCompareCH2( TIMx, pHandle->_Super.CntPhB );
  LL_TIM_OC_SetCompareCH3( TIMx, pHandle->_Super.CntPhC );
  LL_TIM_OC_SetCompareCH4( TIMx, hCCR4Reg );

  /* Limit for update event */
  /* Check the if TIMx CH4 is enabled. If it is set, an update event has occurred
  and thus the FOC rate is too high */
  if (LL_TIM_CC_IsEnabledChannel(TIMx, LL_TIM_CHANNEL_CH4))
  {
    hAux = MC_FOC_DURATION;
  }
  else
  {
    hAux = MC_NO_ERROR;
  }
  if ( pHandle->_Super.SWerror == 1u )
  {
    hAux = MC_FOC_DURATION;
    pHandle->_Super.SWerror = 0u;
  }
  return hAux;
}

//================//

更新配置TIM1定时器的寄存器:LL_TIM_OC_SetCompareCH1

定时器PWM输出使能:R3_2_SwitchOnPWM->LL_TIM_EnableAllOutputs

定时器中断使能:R3_2_SwitchOnPWM->LL_TIM_EnableIT_UPDATE

/**
  * @brief  It enables PWM generation on the proper Timer peripheral acting on MOE
  *         bit
  * @param  pHdl: handler of the current instance of the PWM component
  * @retval none
  */
__weak void R3_2_SwitchOnPWM( PWMC_Handle_t * pHdl )
{  
  PWMC_R3_2_Handle_t * pHandle = (PWMC_R3_2_Handle_t *) pHdl;
  TIM_TypeDef* TIMx = pHandle->pParams_str->TIMx;

  pHandle->_Super.TurnOnLowSidesAction = false;

  /* Set all duty to 50% */
  LL_TIM_OC_SetCompareCH1(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH2(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH3(TIMx, (uint32_t)(pHandle->Half_PWMPeriod  >> 1));
  LL_TIM_OC_SetCompareCH4(TIMx, (uint32_t)(pHandle->Half_PWMPeriod - 5u));

  /* wait for a new PWM period */
	int a=READ_BIT(TIMx->SR, TIM_SR_UIF);
	printf("TIMx->SR, TIM_SR_UIF111=%d\r\n",a);
    LL_TIM_ClearFlag_UPDATE(TIMx);
    a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF222=%d\r\n",a);
  while ( LL_TIM_IsActiveFlag_UPDATE( TIMx ) == 0 )
  {
	  printf("AAAAAAAAA\r\n");

  }
  a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF333=%d\r\n",a);
  /* Clear Update Flag */
  LL_TIM_ClearFlag_UPDATE(TIMx);
  a=READ_BIT(TIMx->SR, TIM_SR_UIF);
 	printf("TIMx->SR, TIM_SR_UIF444=%d\r\n\r\n",a);
  /* Main PWM Output Enable */
  TIMx->BDTR |= LL_TIM_OSSI_ENABLE;
  LL_TIM_EnableAllOutputs( TIMx );

  if ( ( pHandle->pParams_str->LowSideOutputs ) == ES_GPIO )
  {
    if ( LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u )
    {
    	printf("LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u\r\n");
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_u_port, pHandle->pParams_str->pwm_en_u_pin );
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_v_port, pHandle->pParams_str->pwm_en_v_pin );
      LL_GPIO_SetOutputPin( pHandle->pParams_str->pwm_en_w_port, pHandle->pParams_str->pwm_en_w_pin );
    }
    else
    {
    	printf("LL_TIM_CC_IsEnabledChannel(TIMx,TIMxCCER_MASK_CH123) != 0u !!!!!!\r\n");
      /* It is executed during calibration phase the EN signal shall stay off */
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_u_port, pHandle->pParams_str->pwm_en_u_pin );
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_v_port, pHandle->pParams_str->pwm_en_v_pin );
      LL_GPIO_ResetOutputPin( pHandle->pParams_str->pwm_en_w_port, pHandle->pParams_str->pwm_en_w_pin );
    }
  }
  else
  {
  	printf("!!!!!!!!( pHandle->pParams_str->LowSideOutputs ) == ES_GPIO \r\n");
  }

  /* Clear Update Flag */
  LL_TIM_ClearFlag_UPDATE( TIMx );
  /* Enable Update IRQ */
  LL_TIM_EnableIT_UPDATE(TIMx);

  return;
}

//================//

6.3.13
RCC APB1 peripheral clock enable register (RCC_APB1ENR)
Address offset: 0x40
Reset value: 0x0000 0000
Access: no wait state, word, half-word and byte access.

Bit 0 TIM2EN: TIM2 clock enable
This bit is set and cleared by software.
0: TIM2 clock disabled
1: TIM2 clock enabled

//================//

17.4.5
TIM1 and TIM8 status register (TIMx_SR)
Address offset: 0x10
Reset value: 0x0000

Bit 0 UIF: Update interrupt flag
This bit is set by hardware on an update event. It is cleared by software.
0: No update occurred.
1: Update interrupt pending. This bit is set by hardware when the registers are updated:
– At overflow or underflow regarding the repetition counter value (update if repetition counter
= 0) and if the UDIS=0 in the TIMx_CR1 register.
– When CNT is reinitialized by software using the UG bit in TIMx_EGR register, if URS=0 and
UDIS=0 in the TIMx_CR1 register.
– When CNT is reinitialized by a trigger event (refer to Section 17.4.3: TIM1 and TIM8 slave
mode control register (TIMx_SMCR)), if URS=0 and UDIS=0 in the TIMx_CR1 register.

//================//

17.4.18
TIM1 and TIM8 break and dead-time register (TIMx_BDTR)
Address offset: 0x44
Reset value: 0x0000

Bit 15 MOE: Main output enable
This bit is cleared asynchronously by hardware as soon as the break input is active. It is set
by software or automatically depending on the AOE bit. It is acting only on the channels
which are configured in output.
0: OC and OCN outputs are disabled or forced to idle state.
1: OC and OCN outputs are enabled if their respective enable bits are set (CCxE, CCxNE in
TIMx_CCER register).
See OC/OCN enable description for more details (Sec

//================//

17.4.4     TIM1 and TIM8 DMA/interrupt enable register (TIMx_DIER)
Address offset: 0x0C
Reset value: 0x0000

/** @brief  Enable the specified TIM interrupt.
  * @param  __HANDLE__ specifies the TIM Handle.
  * @param  __INTERRUPT__ specifies the TIM interrupt source to enable.
  *          This parameter can be one of the following values:
  *            @arg TIM_IT_UPDATE: Update interrupt
  *            @arg TIM_IT_CC1:   Capture/Compare 1 interrupt
  *            @arg TIM_IT_CC2:  Capture/Compare 2 interrupt
  *            @arg TIM_IT_CC3:  Capture/Compare 3 interrupt
  *            @arg TIM_IT_CC4:  Capture/Compare 4 interrupt
  *            @arg TIM_IT_COM:   Commutation interrupt
  *            @arg TIM_IT_TRIGGER: Trigger interrupt
  *            @arg TIM_IT_BREAK: Break interrupt
  * @retval None
  */
#define __HAL_TIM_ENABLE_IT(__HANDLE__, __INTERRUPT__)    ((__HANDLE__)->Instance->DIER |= (__INTERRUPT__))

//================//

__HAL_RCC_TIM4_CLK_ENABLE();//时钟使能
HAL_TIM_Base_Start(&htim4);//定时器使能
HAL_TIM_Base_Start_IT(&htim4);//定时器使能+定时器更新中断使能

/**
  * @brief  Starts the TIM Base generation.
  * @param  htim TIM Base handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_Base_Start(TIM_HandleTypeDef *htim)
{
  uint32_t tmpsmcr;

  /* Check the parameters */
  assert_param(IS_TIM_INSTANCE(htim->Instance));

  /* Set the TIM state */
  htim->State = HAL_TIM_STATE_BUSY;

  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
  tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
  if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
  {
    __HAL_TIM_ENABLE(htim);
  }

  /* Change the TIM state*/
  htim->State = HAL_TIM_STATE_READY;

  /* Return function status */
  return HAL_OK;
}


/**
  * @brief  Starts the TIM Base generation in interrupt mode.
  * @param  htim TIM Base handle
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_TIM_Base_Start_IT(TIM_HandleTypeDef *htim)
{
  uint32_t tmpsmcr;

  /* Check the parameters */
  assert_param(IS_TIM_INSTANCE(htim->Instance));

  /* Enable the TIM Update interrupt */
  __HAL_TIM_ENABLE_IT(htim, TIM_IT_UPDATE);//定时器更新中断使能

  /* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
  tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
  if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
  {
    __HAL_TIM_ENABLE(htim);//定时器使能
  }

  /* Return function status */
  return HAL_OK;
}

//================//

//================//

//================//

//================//

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值