STM32:TIM定时中断配置的最全库函数讲解笔记

news2024/11/15 11:12:04

        声明:本博客为哔哩哔哩up主@江协科技 “STM32入门教程”的听课笔记,仅供学习、参考使用,不得用作其他用途,违者必究。如有版权问题,请联系作者修改。

目录

一、综述

二、TIM库

初始化

2.1、TIM_DeInit 恢复缺省值

2.2、TIM_TimeBaseInit 时基单元初始化

2.3、 TIM_TimeBaseStructInit 时基单元结构体默认赋值

2.4、TIM_Cmd 使能计数器

2.5、TIM_ITConfig 使能中断输出信号

2.6、TIM_InternalClockConfig 选择内部时钟

2.7、TIM_ITRxExternalClockConfig

2.8、TIM_TIxExternalClockConfig

2.9、TIM_ETRClockMode1Config

2.10、TIM_ETRClockMode2Config

2.11、TIM_ETRConfig

2.12、6~11讲解

2.13、TIM结构体讲解

2.13.1、TIM_ClockDivision

2.13.2、TIM_CounterMode

2.13.3、TIM_Period

2.13.4、TIM_Prescaler

2.13.5、TIM_RepetitionCounter

参数变更

2.14、TIM_PrescalerConfig 单独写入预分频值

2.15、TIM_CounterModeConfig 改变计数器的计数模式

2.16、TIM_ARRPreloadConfig自动重装器预装功能配置

2.17、TIM_SetCounter 给计数器写入一个值

2.18、TIM_SetAutoreload 写入自动重装值

2.19、TIM_GetCounter 获取当前计数器的值

2.20、TIM_GetPrescaler 获取当前分频器的值

2.21、TIM_GetFlagStatus 主程序标志位获取

2.22、TIM_ClearFlag 主程序中清除标志位

2.23、TIM_GetITStatus 中断程序中获取标志位

2.24、TIM_ClearITPendingBit 中断程序中清除标志位

三、定时中断完整代码

3.1、Timer.h

3.2、Timer.c

3.2.1、具体步骤

3.2.2、完整代码

3.3、main.c

四、一个问题

五、定时中断完整代码(调整后)

5.1、Timer.h

5.2、Timer.c

5.2.1、具体步骤

5.2.2、完整代码

5.3、main.c


一、综述

上图是定时中断的整个框架结构。我们只需要把这里面的每个模块都打通,就可以让定时器工作了。

        具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

二、TIM库

初始化

2.1、TIM_DeInit 恢复缺省值

        函数原型:void TIM_DeInit(TIM_TypeDef* TIMx);

        函数讲解恢复缺省配置

        函数定义

/**
  * @brief  Deinitializes the TIMx peripheral registers to their default reset values.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @retval None
  */
void TIM_DeInit(TIM_TypeDef* TIMx)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx)); 
 
  if (TIMx == TIM1)
  {
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM1, DISABLE);  
  }     
  else if (TIMx == TIM2)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM2, DISABLE);
  }
  else if (TIMx == TIM3)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM3, DISABLE);
  }
  else if (TIMx == TIM4)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM4, DISABLE);
  } 
  else if (TIMx == TIM5)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM5, DISABLE);
  } 
  else if (TIMx == TIM6)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM6, DISABLE);
  } 
  else if (TIMx == TIM7)
  {
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM7, DISABLE);
  } 
  else if (TIMx == TIM8)
  {
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM8, DISABLE);
  }
  else if (TIMx == TIM9)
  {      
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM9, DISABLE);  
   }  
  else if (TIMx == TIM10)
  {      
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM10, DISABLE);  
  }  
  else if (TIMx == TIM11) 
  {     
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM11, DISABLE);  
  }  
  else if (TIMx == TIM12)
  {      
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM12, DISABLE);  
  }  
  else if (TIMx == TIM13) 
  {       
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM13, DISABLE);  
  }
  else if (TIMx == TIM14) 
  {       
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, ENABLE);
    RCC_APB1PeriphResetCmd(RCC_APB1Periph_TIM14, DISABLE);  
  }        
  else if (TIMx == TIM15)
  {
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM15, DISABLE);
  } 
  else if (TIMx == TIM16)
  {
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, ENABLE);
    RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM16, DISABLE);
  } 
  else
  {
    if (TIMx == TIM17)
    {
      RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, ENABLE);
      RCC_APB2PeriphResetCmd(RCC_APB2Periph_TIM17, DISABLE);
    }  
  }
}

2.2、TIM_TimeBaseInit 时基单元初始化

        函数原型:

                        void TIM_TimeBaseInit(TIM_TypeDef* TIMx,

                        TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

        函数讲解:时基单元初始化;两个参数:第一个TIMx选择某个定时器,第二个是结构体,里面包含了配置时基单元的一些参数。

        函数定义

/**
  * @brief  Initializes the TIMx Time Base Unit peripheral according to 
  *         the specified parameters in the TIM_TimeBaseInitStruct.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef
  *         structure that contains the configuration information for the 
  *         specified TIM peripheral.
  * @retval None
  */
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
  uint16_t tmpcr1 = 0;

  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx)); 
  assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
  assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));

  tmpcr1 = TIMx->CR1;  

  if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
     (TIMx == TIM4) || (TIMx == TIM5)) 
  {
    /* Select the Counter Mode */
    tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
  }
 
  if((TIMx != TIM6) && (TIMx != TIM7))
  {
    /* Set the clock division */
    tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
  }

  TIMx->CR1 = tmpcr1;

  /* Set the Autoreload value */
  TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
 
  /* Set the Prescaler value */
  TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
    
  if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))  
  {
    /* Set the Repetition Counter value */
    TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
  }

  /* Generate an update event to reload the Prescaler and the Repetition counter
     values immediately */
  TIMx->EGR = TIM_PSCReloadMode_Immediate;           
}

2.3、 TIM_TimeBaseStructInit 时基单元结构体默认赋值

        函数原型:

        void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

        函数讲解:这个函数可以把结构体变量赋一个默认值。

        函数定义

/**
  * @brief  Fills each TIM_TimeBaseInitStruct member with its default value.
  * @param  TIM_TimeBaseInitStruct : pointer to a TIM_TimeBaseInitTypeDef
  *         structure which will be initialized.
  * @retval None
  */
void TIM_TimeBaseStructInit(TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
  /* Set the default configuration */
  TIM_TimeBaseInitStruct->TIM_Period = 0xFFFF;
  TIM_TimeBaseInitStruct->TIM_Prescaler = 0x0000;
  TIM_TimeBaseInitStruct->TIM_ClockDivision = TIM_CKD_DIV1;
  TIM_TimeBaseInitStruct->TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInitStruct->TIM_RepetitionCounter = 0x0000;
}

2.4、TIM_Cmd 使能计数器

        函数原型:void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState);

        函数讲解:这个函数是用来使能计数器的,对应图中的“运行控制”板块。它有两个参数,第一个TIMx选择定时器,第二个NewState新的状态,也就是使能还是失能。使能的话,计数器就可以运行,失能的话,计数器就不能运行。

        函数定义

/**
  * @brief  Enables or disables the specified TIM peripheral.
  * @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.
  * @param  NewState: new state of the TIMx peripheral.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the TIM Counter */
    TIMx->CR1 |= TIM_CR1_CEN;
  }
  else
  {
    /* Disable the TIM Counter */
    TIMx->CR1 &= (uint16_t)(~((uint16_t)TIM_CR1_CEN));
  }
}

2.5、TIM_ITConfig 使能中断输出信号

        函数原型:

        void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState); 

        函数讲解:这个是用来使能中断输出信号的,对应图中的“中断输出控制”。第一个参数TIMx,选择定时器;第二个参数TIM_IT,选择要配置哪个中断输出;第三个参数新的状态,使能还是失能。这种IT_Config之后会经常遇到,就是使能外设的中断输出。

        第二个参数可以是下面这些值的任意组合

  *     @arg TIM_IT_Update: TIM update Interrupt source
  *     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  *     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  *     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  *     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  *     @arg TIM_IT_COM: TIM Commutation Interrupt source
  *     @arg TIM_IT_Trigger: TIM Trigger Interrupt source
  *     @arg TIM_IT_Break: TIM Break Interrupt source

        函数定义

/**
  * @brief  Enables or disables the specified TIM interrupts.
  * @param  TIMx: where x can be 1 to 17 to select the TIMx peripheral.
  * @param  TIM_IT: specifies the TIM interrupts sources to be enabled or disabled.
  *   This parameter can be any combination of the following values:
  *     @arg TIM_IT_Update: TIM update Interrupt source
  *     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  *     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  *     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  *     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  *     @arg TIM_IT_COM: TIM Commutation Interrupt source
  *     @arg TIM_IT_Trigger: TIM Trigger Interrupt source
  *     @arg TIM_IT_Break: TIM Break Interrupt source
  * @note 
  *   - TIM6 and TIM7 can only generate an update interrupt.
  *   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
  *      TIM_IT_CC2 or TIM_IT_Trigger. 
  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   
  *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. 
  *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    
  * @param  NewState: new state of the TIM interrupts.
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)
{  
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_IT(TIM_IT));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  
  if (NewState != DISABLE)
  {
    /* Enable the Interrupt sources */
    TIMx->DIER |= TIM_IT;
  }
  else
  {
    /* Disable the Interrupt sources */
    TIMx->DIER &= (uint16_t)~TIM_IT;
  }
}

2.6、TIM_InternalClockConfig 选择内部时钟

        函数原型:void TIM_InternalClockConfig(TIM_TypeDef* TIMx);

        函数讲解:选择内部时钟。参数只有一个TIMx。

        函数定义

/**
  * @brief  Configures the TIMx internal Clock
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 8, 9, 12 or 15
  *         to select the TIM peripheral.
  * @retval None
  */
void TIM_InternalClockConfig(TIM_TypeDef* TIMx)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  /* Disable slave mode to clock the prescaler directly with the internal clock */
  TIMx->SMCR &=  (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
}

2.7、TIM_ITRxExternalClockConfig

        函数原型:

        void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_InputTriggerSource);

        函数讲解选择ITR其他定时器的时钟。第一个参数是TIMx,选择要配置的定时器,二个参s数是TIM_InputTriggerSource,选择要接入哪个其他的定时器。

        函数定义

/**
  * @brief  Configures the TIMx Internal Trigger as External Clock
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_ITRSource: Trigger source.
  *   This parameter can be one of the following values:
  * @param  TIM_TS_ITR0: Internal Trigger 0
  * @param  TIM_TS_ITR1: Internal Trigger 1
  * @param  TIM_TS_ITR2: Internal Trigger 2
  * @param  TIM_TS_ITR3: Internal Trigger 3
  * @retval None
  */
void TIM_ITRxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_InputTriggerSource)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  assert_param(IS_TIM_INTERNAL_TRIGGER_SELECTION(TIM_InputTriggerSource));
  /* Select the Internal Trigger */
  TIM_SelectInputTrigger(TIMx, TIM_InputTriggerSource);
  /* Select the External clock mode1 */
  TIMx->SMCR |= TIM_SlaveMode_External1;
}

2.8、TIM_TIxExternalClockConfig

        函数原型:

        void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter);

        函数讲解选择TIx捕获通道的时钟,第一个参数TIMx选择需要配置的定时器;第二个参数TIM_TIxExternalCLKSource,选择TIx具体的某个引脚;第三个参数TIM_ICPolarity输入的极性;第四个参数ICFilter,输入的滤波器。对于外部引脚的波形,一般都会有极性选择和滤波器,这样更灵活一些。

        函数定义

/**
  * @brief  Configures the TIMx Trigger as External Clock
  * @param  TIMx: where x can be  1, 2, 3, 4, 5, 9, 12 or 15 to select the TIM peripheral.
  * @param  TIM_TIxExternalCLKSource: Trigger source.
  *   This parameter can be one of the following values:
  *     @arg TIM_TIxExternalCLK1Source_TI1ED: TI1 Edge Detector
  *     @arg TIM_TIxExternalCLK1Source_TI1: Filtered Timer Input 1
  *     @arg TIM_TIxExternalCLK1Source_TI2: Filtered Timer Input 2
  * @param  TIM_ICPolarity: specifies the TIx Polarity.
  *   This parameter can be one of the following values:
  *     @arg TIM_ICPolarity_Rising
  *     @arg TIM_ICPolarity_Falling
  * @param  ICFilter : specifies the filter value.
  *   This parameter must be a value between 0x0 and 0xF.
  * @retval None
  */
void TIM_TIxExternalClockConfig(TIM_TypeDef* TIMx, uint16_t TIM_TIxExternalCLKSource,
                                uint16_t TIM_ICPolarity, uint16_t ICFilter)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST6_PERIPH(TIMx));
  assert_param(IS_TIM_TIXCLK_SOURCE(TIM_TIxExternalCLKSource));
  assert_param(IS_TIM_IC_POLARITY(TIM_ICPolarity));
  assert_param(IS_TIM_IC_FILTER(ICFilter));
  /* Configure the Timer Input Clock Source */
  if (TIM_TIxExternalCLKSource == TIM_TIxExternalCLK1Source_TI2)
  {
    TI2_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);
  }
  else
  {
    TI1_Config(TIMx, TIM_ICPolarity, TIM_ICSelection_DirectTI, ICFilter);
  }
  /* Select the Trigger source */
  TIM_SelectInputTrigger(TIMx, TIM_TIxExternalCLKSource);
  /* Select the External clock mode1 */
  TIMx->SMCR |= TIM_SlaveMode_External1;
}

2.9、TIM_ETRClockMode1Config

        函数原型:

        void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx,

                 uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter);

        函数原型选择ETR通过外部时钟模式1输入的时钟。第二个参数TIM_ExtTRGPrescaler,外部触发预分频器,可以对ETR的外部时钟再提前做一个分频,第三个参数TIM_ExtTRGPolarity输入的极性,第四个参数ExtTRGFilter输入的滤波器。

        函数定义

/**
  * @brief  Configures the External clock Mode1
  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
  *     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
  *     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
  *     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
  * @param  TIM_ExtTRGPolarity: The external Trigger Polarity.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
  *     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
  * @param  ExtTRGFilter: External Trigger Filter.
  *   This parameter must be a value between 0x00 and 0x0F
  * @retval None
  */
void TIM_ETRClockMode1Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                             uint16_t ExtTRGFilter)
{
  uint16_t tmpsmcr = 0;
  /* Check the parameters */
  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
  assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
  assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
  assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
  /* Configure the ETR Clock source */
  TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);
  
  /* Get the TIMx SMCR register value */
  tmpsmcr = TIMx->SMCR;
  /* Reset the SMS Bits */
  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_SMS));
  /* Select the External clock mode1 */
  tmpsmcr |= TIM_SlaveMode_External1;
  /* Select the Trigger selection : ETRF */
  tmpsmcr &= (uint16_t)(~((uint16_t)TIM_SMCR_TS));
  tmpsmcr |= TIM_TS_ETRF;
  /* Write to TIMx SMCR */
  TIMx->SMCR = tmpsmcr;
}

2.10、TIM_ETRClockMode2Config

        函数原型:

        void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx,

                 uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter);

        函数讲解

        选择ETR通过外部时钟模式2输入的时钟。参数同上。对于ETR输入的时钟而言,9和10两个函数是等效的,它们的参数也是一样的。如果不需要触发输入的功能,那两个函数可以互换。

        函数定义

/**
  * @brief  Configures the External clock Mode2
  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
  *     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
  *     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
  *     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
  * @param  TIM_ExtTRGPolarity: The external Trigger Polarity.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
  *     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
  * @param  ExtTRGFilter: External Trigger Filter.
  *   This parameter must be a value between 0x00 and 0x0F
  * @retval None
  */
void TIM_ETRClockMode2Config(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, 
                             uint16_t TIM_ExtTRGPolarity, uint16_t ExtTRGFilter)
{
  /* Check the parameters */
  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
  assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
  assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
  assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
  /* Configure the ETR Clock source */
  TIM_ETRConfig(TIMx, TIM_ExtTRGPrescaler, TIM_ExtTRGPolarity, ExtTRGFilter);
  /* Enable the External clock mode2 */
  TIMx->SMCR |= TIM_SMCR_ECE;
}

2.11、TIM_ETRConfig

        函数原型:

        void TIM_ETRConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,

                        uint16_t ExtTRGFilter);

        函数讲解单独用来配置ETR引脚的预分频器、极性、滤波器这些参数的

        函数定义

/**
  * @brief  Configures the TIMx External Trigger (ETR).
  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  TIM_ExtTRGPrescaler: The external Trigger Prescaler.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPSC_OFF: ETRP Prescaler OFF.
  *     @arg TIM_ExtTRGPSC_DIV2: ETRP frequency divided by 2.
  *     @arg TIM_ExtTRGPSC_DIV4: ETRP frequency divided by 4.
  *     @arg TIM_ExtTRGPSC_DIV8: ETRP frequency divided by 8.
  * @param  TIM_ExtTRGPolarity: The external Trigger Polarity.
  *   This parameter can be one of the following values:
  *     @arg TIM_ExtTRGPolarity_Inverted: active low or falling edge active.
  *     @arg TIM_ExtTRGPolarity_NonInverted: active high or rising edge active.
  * @param  ExtTRGFilter: External Trigger Filter.
  *   This parameter must be a value between 0x00 and 0x0F
  * @retval None
  */
void TIM_ETRConfig(TIM_TypeDef* TIMx, uint16_t TIM_ExtTRGPrescaler, uint16_t TIM_ExtTRGPolarity,
                   uint16_t ExtTRGFilter)
{
  uint16_t tmpsmcr = 0;
  /* Check the parameters */
  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
  assert_param(IS_TIM_EXT_PRESCALER(TIM_ExtTRGPrescaler));
  assert_param(IS_TIM_EXT_POLARITY(TIM_ExtTRGPolarity));
  assert_param(IS_TIM_EXT_FILTER(ExtTRGFilter));
  tmpsmcr = TIMx->SMCR;
  /* Reset the ETR Bits */
  tmpsmcr &= SMCR_ETR_Mask;
  /* Set the Prescaler, the Filter value and the Polarity */
  tmpsmcr |= (uint16_t)(TIM_ExtTRGPrescaler | (uint16_t)(TIM_ExtTRGPolarity | (uint16_t)(ExtTRGFilter << (uint16_t)8)));
  /* Write to TIMx SMCR */
  TIMx->SMCR = tmpsmcr;
}

2.12、6~11讲解

        上面这六个函数对应的就是时基单元的时钟选择部分,可以选择RCC内部时钟、ETR外部时钟、ITRx其他定时器、TIx捕获通道等。

2.13、TIM结构体讲解

typedef struct
{
  uint16_t TIM_Prescaler;         /*!< Specifies the prescaler value used to divide the TIM clock.
                                       This parameter can be a number between 0x0000 and 0xFFFF */

  uint16_t TIM_CounterMode;       /*!< Specifies the counter mode.
                                       This parameter can be a value of @ref TIM_Counter_Mode */

  uint16_t TIM_Period;            /*!< Specifies the period value to be loaded into the active
                                       Auto-Reload Register at the next update event.
                                       This parameter must be a number between 0x0000 and 0xFFFF.  */ 

  uint16_t TIM_ClockDivision;     /*!< Specifies the clock division.
                                      This parameter can be a value of @ref TIM_Clock_Division_CKD */

  uint8_t TIM_RepetitionCounter;  /*!< Specifies the repetition counter value. Each time the RCR downcounter
                                       reaches zero, an update event is generated and counting restarts
                                       from the RCR value (N).
                                       This means in PWM mode that (N+1) corresponds to:
                                          - the number of PWM periods in edge-aligned mode
                                          - the number of half PWM period in center-aligned mode
                                       This parameter must be a number between 0x00 and 0xFF. 
                                       @note This parameter is valid only for TIM1 and TIM8. */
} TIM_TimeBaseInitTypeDef;   

2.13.1、TIM_ClockDivision

        指定时钟分频,参数可以是TIM_Clock_Division_CKD中的一个值。

        时钟分频的作用:

        在定时器的外部信号输入引脚, 一般都会有滤波器用来过滤掉信号抖动的干扰

        工作原理是:在一个固定的时钟频率f下进行采样,如果连续N个采样点都为相同的电平,那就代表输入信号稳定了,就把这个采样值输出出去;如果这N个采样值不全都相同,那就说明信号有抖动,这时就保持上一次的输出或者直接输出低电平。这样就能保证输出信号在一定程度上的滤波

        这里的采样频率f和采样点数N都是滤波器的参数。频率越低,采样点数越多,滤波效果越好,不过相应的信号延迟就越大

         滤波器的采样频率f的来源:STM32手册中声明它可以由内部时钟直接而来,也可以是由内部时钟加一个时钟分频而来。分频多少就是由这个参数TIM_ClockDivision决定的。

        (这个参数和时基单元关系并不大)

 TIM_Clock_Division_CKD:

/** @defgroup TIM_Clock_Division_CKD 
  * @{
  */

#define TIM_CKD_DIV1                       ((uint16_t)0x0000)
#define TIM_CKD_DIV2                       ((uint16_t)0x0100)
#define TIM_CKD_DIV4                       ((uint16_t)0x0200)

        TIM_CKD_DIV1是1分频,即不分频;

        TIM_CKD_DIV2是2分频;

        TIM_CKD_DIV4是4分频;

2.13.2、TIM_CounterMode

        计数器模式。TIM_CounterMode可以是TIM_Counter_Mode中的一个值。

/** @defgroup TIM_Counter_Mode 
  * @{
  */

#define TIM_CounterMode_Up                 ((uint16_t)0x0000)
#define TIM_CounterMode_Down               ((uint16_t)0x0010)
#define TIM_CounterMode_CenterAligned1     ((uint16_t)0x0020)
#define TIM_CounterMode_CenterAligned2     ((uint16_t)0x0040)
#define TIM_CounterMode_CenterAligned3     ((uint16_t)0x0060)
#define IS_TIM_COUNTER_MODE(MODE) (((MODE) == TIM_CounterMode_Up) ||  \
                                   ((MODE) == TIM_CounterMode_Down) || \
                                   ((MODE) == TIM_CounterMode_CenterAligned1) || \
                                   ((MODE) == TIM_CounterMode_CenterAligned2) || \
                                   ((MODE) == TIM_CounterMode_CenterAligned3))

         从上到下分别是向上计数、向下计数、三种中央对齐模式。

2.13.3、TIM_Period

        周期,就是ARR自动重装器的值。时基单元中关键寄存器的参数之一。

        计算方法:

        注意:

        1.预分频器和计数器都有一个数的偏差,所以使用的时候要-1。、

        2.PSC和ARR的取值都要在0~65535之间,不要超出范围

        3.PSC和ARR的取值不是唯一的。可以预分频值给少一点、自动重装给多一点,这样就是以一个比较高的频率计比较多的数;也可以预分频值给多一点、自动重装给少一点,这样就是以一个比较低的频率计比较少的数。两种方法都可以达到目标的定时时间。

	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;

        在这里我们是对72MHz进行7200分频,得到的是10k的计数频率。 在10k的频率下计1w个数,正好是1s的时间。

2.13.4、TIM_Prescaler

        PSC预分频器的值。时基单元中关键寄存器的参数之一。

2.13.5、TIM_RepetitionCounter

        重复计数器的值。时基单元中关键寄存器的参数之一。是高级定时器才有的。

参数变更

2.14、TIM_PrescalerConfig 单独写入预分频值

        函数原型:

        void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler,

                uint16_t TIM_PSCReloadMode);

        函数讲解

        这个函数是用来单独写预分频值的。第一个参数Prescaler就是要写入的预分频值,第二个参数TIM_PSCReloadMode是指写入的模式。

        预分频器有一个缓冲器,写入的值是在更新时间发生后才有效的。所以这里有个写入的模式,可以选择听从安排,在更新事件生效,或者是在写入后手动产生一个更新事件,让这个值立刻生效。

        函数定义

/**
  * @brief  Configures the TIMx Prescaler.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  Prescaler: specifies the Prescaler Register value
  * @param  TIM_PSCReloadMode: specifies the TIM Prescaler Reload mode
  *   This parameter can be one of the following values:
  *     @arg TIM_PSCReloadMode_Update: The Prescaler is loaded at the update event.
  *     @arg TIM_PSCReloadMode_Immediate: The Prescaler is loaded immediately.
  * @retval None
  */
void TIM_PrescalerConfig(TIM_TypeDef* TIMx, uint16_t Prescaler, uint16_t TIM_PSCReloadMode)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_PRESCALER_RELOAD(TIM_PSCReloadMode));
  /* Set the Prescaler value */
  TIMx->PSC = Prescaler;
  /* Set or reset the UG Bit */
  TIMx->EGR = TIM_PSCReloadMode;
}

2.15、TIM_CounterModeConfig 改变计数器的计数模式

        函数原型:void TIM_CounterModeConfig(TIM_TypeDef* TIMx,

                uint16_t TIM_CounterMode);

        函数讲解:这个函数用于改变计数器的计数模式。参数TIM_CounterMode选择新的计数器模式。

        函数定义

/**
  * @brief  Specifies the TIMx Counter Mode to be used.
  * @param  TIMx: where x can be  1, 2, 3, 4, 5 or 8 to select the TIM peripheral.
  * @param  TIM_CounterMode: specifies the Counter Mode to be used
  *   This parameter can be one of the following values:
  *     @arg TIM_CounterMode_Up: TIM Up Counting Mode
  *     @arg TIM_CounterMode_Down: TIM Down Counting Mode
  *     @arg TIM_CounterMode_CenterAligned1: TIM Center Aligned Mode1
  *     @arg TIM_CounterMode_CenterAligned2: TIM Center Aligned Mode2
  *     @arg TIM_CounterMode_CenterAligned3: TIM Center Aligned Mode3
  * @retval None
  */
void TIM_CounterModeConfig(TIM_TypeDef* TIMx, uint16_t TIM_CounterMode)
{
  uint16_t tmpcr1 = 0;
  /* Check the parameters */
  assert_param(IS_TIM_LIST3_PERIPH(TIMx));
  assert_param(IS_TIM_COUNTER_MODE(TIM_CounterMode));
  tmpcr1 = TIMx->CR1;
  /* Reset the CMS and DIR Bits */
  tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
  /* Set the Counter Mode */
  tmpcr1 |= TIM_CounterMode;
  /* Write to TIMx CR1 register */
  TIMx->CR1 = tmpcr1;
}

2.16、TIM_ARRPreloadConfig自动重装器预装功能配置

        函数原型:void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx,

                FunctionalState NewState);

        函数讲解

                自动重装器预装功能配置。有无预装是可以自己选择的

                选择方法:第二个参数NewState赋值为使能or失能。

 

        函数定义

/**
  * @brief  Enables or disables TIMx peripheral Preload register on ARR.
  * @param  TIMx: where x can be  1 to 17 to select the TIM peripheral.
  * @param  NewState: new state of the TIMx peripheral Preload register
  *   This parameter can be: ENABLE or DISABLE.
  * @retval None
  */
void TIM_ARRPreloadConfig(TIM_TypeDef* TIMx, FunctionalState NewState)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_FUNCTIONAL_STATE(NewState));
  if (NewState != DISABLE)
  {
    /* Set the ARR Preload Bit */
    TIMx->CR1 |= TIM_CR1_ARPE;
  }
  else
  {
    /* Reset the ARR Preload Bit */
    TIMx->CR1 &= (uint16_t)~((uint16_t)TIM_CR1_ARPE);
  }
}

2.17、TIM_SetCounter 给计数器写入一个值

        函数原型:void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter);

        函数讲解给计数器写入一个值。如果想手动给一个计数值,就可以用这个函数。

        函数定义

/**
  * @brief  Sets the TIMx Counter Register value
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  Counter: specifies the Counter register new value.
  * @retval None
  */
void TIM_SetCounter(TIM_TypeDef* TIMx, uint16_t Counter)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  /* Set the Counter Register value */
  TIMx->CNT = Counter;
}

2.18、TIM_SetAutoreload 写入自动重装值

        函数原型:void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload);

        函数讲解给自动重装器写入一个值。如果想手动给一个自动重装值,就可以用这个函数。

        函数定义

/**
  * @brief  Sets the TIMx Autoreload Register value
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  Autoreload: specifies the Autoreload register new value.
  * @retval None
  */
void TIM_SetAutoreload(TIM_TypeDef* TIMx, uint16_t Autoreload)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  /* Set the Autoreload Register value */
  TIMx->ARR = Autoreload;
}

2.19、TIM_GetCounter 获取当前计数器的值

        函数原型:uint16_t TIM_GetCounter(TIM_TypeDef* TIMx);

        函数讲解获取当前计数器的值。如果想要查看当前计数器计到哪里了,就可以调用一下这个函数,返回当前计数器的值。

        函数定义

/**
  * @brief  Gets the TIMx Counter value.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @retval Counter Register value.
  */
uint16_t TIM_GetCounter(TIM_TypeDef* TIMx)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  /* Get the Counter Register value */
  return TIMx->CNT;
}

2.20、TIM_GetPrescaler 获取当前分频器的值

        函数原型:uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx);

        函数讲解获取当前的预分频器的值。如果想看预分频值,就调用一下这个函数。

        函数定义

/**
  * @brief  Gets the TIMx Prescaler value.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @retval Prescaler Register value.
  */
uint16_t TIM_GetPrescaler(TIM_TypeDef* TIMx)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  /* Get the Prescaler Register value */
  return TIMx->PSC;
}

2.21、TIM_GetFlagStatus 主程序标志位获取

        函数原型:FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

        函数讲解:主程序中获取标志位。

        函数定义

/**
  * @brief  Checks whether the specified TIM flag is set or not.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_FLAG: specifies the flag to check.
  *   This parameter can be one of the following values:
  *     @arg TIM_FLAG_Update: TIM update Flag
  *     @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag
  *     @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag
  *     @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag
  *     @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag
  *     @arg TIM_FLAG_COM: TIM Commutation Flag
  *     @arg TIM_FLAG_Trigger: TIM Trigger Flag
  *     @arg TIM_FLAG_Break: TIM Break Flag
  *     @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag
  *     @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag
  *     @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag
  *     @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag
  * @note
  *   - TIM6 and TIM7 can have only one update flag. 
  *   - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,
  *      TIM_FLAG_CC2 or TIM_FLAG_Trigger. 
  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.   
  *   - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. 
  *   - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    
  * @retval The new state of TIM_FLAG (SET or RESET).
  */
FlagStatus TIM_GetFlagStatus(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{ 
  ITStatus bitstatus = RESET;  
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_GET_FLAG(TIM_FLAG));
  
  if ((TIMx->SR & TIM_FLAG) != (uint16_t)RESET)
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

2.22、TIM_ClearFlag 主程序中清除标志位

        函数原型:void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG);

        函数讲解主程序中清除标志位。

        函数定义

/**
  * @brief  Clears the TIMx's pending flags.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_FLAG: specifies the flag bit to clear.
  *   This parameter can be any combination of the following values:
  *     @arg TIM_FLAG_Update: TIM update Flag
  *     @arg TIM_FLAG_CC1: TIM Capture Compare 1 Flag
  *     @arg TIM_FLAG_CC2: TIM Capture Compare 2 Flag
  *     @arg TIM_FLAG_CC3: TIM Capture Compare 3 Flag
  *     @arg TIM_FLAG_CC4: TIM Capture Compare 4 Flag
  *     @arg TIM_FLAG_COM: TIM Commutation Flag
  *     @arg TIM_FLAG_Trigger: TIM Trigger Flag
  *     @arg TIM_FLAG_Break: TIM Break Flag
  *     @arg TIM_FLAG_CC1OF: TIM Capture Compare 1 overcapture Flag
  *     @arg TIM_FLAG_CC2OF: TIM Capture Compare 2 overcapture Flag
  *     @arg TIM_FLAG_CC3OF: TIM Capture Compare 3 overcapture Flag
  *     @arg TIM_FLAG_CC4OF: TIM Capture Compare 4 overcapture Flag
  * @note
  *   - TIM6 and TIM7 can have only one update flag. 
  *   - TIM9, TIM12 and TIM15 can have only TIM_FLAG_Update, TIM_FLAG_CC1,
  *      TIM_FLAG_CC2 or TIM_FLAG_Trigger. 
  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_FLAG_Update or TIM_FLAG_CC1.   
  *   - TIM_FLAG_Break is used only with TIM1, TIM8 and TIM15. 
  *   - TIM_FLAG_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.   
  * @retval None
  */
void TIM_ClearFlag(TIM_TypeDef* TIMx, uint16_t TIM_FLAG)
{  
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_CLEAR_FLAG(TIM_FLAG));
   
  /* Clear the flags */
  TIMx->SR = (uint16_t)~TIM_FLAG;
}

2.23、TIM_GetITStatus 中断程序中获取标志位

        函数原型:ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT);

        函数讲解中断程序中获取标志位

        函数定义

/**
  * @brief  Checks whether the TIM interrupt has occurred or not.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_IT: specifies the TIM interrupt source to check.
  *   This parameter can be one of the following values:
  *     @arg TIM_IT_Update: TIM update Interrupt source
  *     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  *     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  *     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  *     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  *     @arg TIM_IT_COM: TIM Commutation Interrupt source
  *     @arg TIM_IT_Trigger: TIM Trigger Interrupt source
  *     @arg TIM_IT_Break: TIM Break Interrupt source
  * @note
  *   - TIM6 and TIM7 can generate only an update interrupt.
  *   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
  *      TIM_IT_CC2 or TIM_IT_Trigger. 
  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   
  *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. 
  *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.  
  * @retval The new state of the TIM_IT(SET or RESET).
  */
ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{
  ITStatus bitstatus = RESET;  
  uint16_t itstatus = 0x0, itenable = 0x0;
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_GET_IT(TIM_IT));
   
  itstatus = TIMx->SR & TIM_IT;
  
  itenable = TIMx->DIER & TIM_IT;
  if ((itstatus != (uint16_t)RESET) && (itenable != (uint16_t)RESET))
  {
    bitstatus = SET;
  }
  else
  {
    bitstatus = RESET;
  }
  return bitstatus;
}

2.24、TIM_ClearITPendingBit 中断程序中清除标志位

        函数原型:void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT);

        函数讲解中断程序中清除标志位

        函数定义

/**
  * @brief  Clears the TIMx's interrupt pending bits.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_IT: specifies the pending bit to clear.
  *   This parameter can be any combination of the following values:
  *     @arg TIM_IT_Update: TIM1 update Interrupt source
  *     @arg TIM_IT_CC1: TIM Capture Compare 1 Interrupt source
  *     @arg TIM_IT_CC2: TIM Capture Compare 2 Interrupt source
  *     @arg TIM_IT_CC3: TIM Capture Compare 3 Interrupt source
  *     @arg TIM_IT_CC4: TIM Capture Compare 4 Interrupt source
  *     @arg TIM_IT_COM: TIM Commutation Interrupt source
  *     @arg TIM_IT_Trigger: TIM Trigger Interrupt source
  *     @arg TIM_IT_Break: TIM Break Interrupt source
  * @note
  *   - TIM6 and TIM7 can generate only an update interrupt.
  *   - TIM9, TIM12 and TIM15 can have only TIM_IT_Update, TIM_IT_CC1,
  *      TIM_IT_CC2 or TIM_IT_Trigger. 
  *   - TIM10, TIM11, TIM13, TIM14, TIM16 and TIM17 can have TIM_IT_Update or TIM_IT_CC1.   
  *   - TIM_IT_Break is used only with TIM1, TIM8 and TIM15. 
  *   - TIM_IT_COM is used only with TIM1, TIM8, TIM15, TIM16 and TIM17.    
  * @retval None
  */
void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
{
  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx));
  assert_param(IS_TIM_IT(TIM_IT));
  /* Clear the IT pending Bit */
  TIMx->SR = (uint16_t)~TIM_IT;
}

三、定时中断完整代码

3.1、Timer.h

#ifndef _TIMER_H
#define _TIMER_H

void timer_init(void);

#endif

3.2、Timer.c

3.2.1、具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

	/*第一步:配置rcc时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

TIM_InternalClockConfig(TIM2);

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	/*中断通道*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

TIM_Cmd(TIM2,ENABLE); 

3.2.2、完整代码

#include "stm32f10x.h"                  // Device header

extern uint16_t num;

void timer_init(void)
{
	/*第一步:配置rcc时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	/*配置时基单元*/
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*使能更新中断*/
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	/*此时已经开启了更新中断到NVIC的通路*/
	
	/*配置NVIC通路*/
	/*NVIC优先级分组:*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	/*中断通道*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	/*启动定时器*/
	TIM_Cmd(TIM2,ENABLE); 
}

void TIM2_IRQHandler(void)
{
	/*检查中断标志位*/
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

3.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t num;
int main(void)
{
	OLED_Init();
	timer_init();/*初始化定时器*/
	
	OLED_ShowString(1, 1, "num:");
	
	while (1)
	{
		OLED_ShowNum(1,5,num,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5); 
	}
}

四、一个问题

        烧录代码观察现象,发现num是从1开始计数的。但是num的初始值为0,按理说应该是从0开始计数的,但是num一经上电就立刻变为1了,说明中断函数在初始化后就立刻进入了一次

        在TIM_TimeBaseInit的函数定义中:

/**
  * @brief  Initializes the TIMx Time Base Unit peripheral according to 
  *         the specified parameters in the TIM_TimeBaseInitStruct.
  * @param  TIMx: where x can be 1 to 17 to select the TIM peripheral.
  * @param  TIM_TimeBaseInitStruct: pointer to a TIM_TimeBaseInitTypeDef
  *         structure that contains the configuration information for the 
  *         specified TIM peripheral.
  * @retval None
  */
void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct)
{
  uint16_t tmpcr1 = 0;

  /* Check the parameters */
  assert_param(IS_TIM_ALL_PERIPH(TIMx)); 
  assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));
  assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));

  tmpcr1 = TIMx->CR1;  

  if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||
     (TIMx == TIM4) || (TIMx == TIM5)) 
  {
    /* Select the Counter Mode */
    tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR | TIM_CR1_CMS)));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode;
  }
 
  if((TIMx != TIM6) && (TIMx != TIM7))
  {
    /* Set the clock division */
    tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));
    tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision;
  }

  TIMx->CR1 = tmpcr1;

  /* Set the Autoreload value */
  TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ;
 
  /* Set the Prescaler value */
  TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;
    
  if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx == TIM16) || (TIMx == TIM17))  
  {
    /* Set the Repetition Counter value */
    TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter;
  }

  /* Generate an update event to reload the Prescaler and the Repetition counter
     values immediately */
  TIMx->EGR = TIM_PSCReloadMode_Immediate;           
}

        其中最后一行代码上面的注释:

           /* Generate an update event to reload the Prescaler and the Repetition counter values immediately */

        翻译为:立刻生成一个更新事件,来重新装载预分频器和重复计数器的值

        TIM_TimeBaseInit函数中有 “TIMx->EGR = TIM_PSCReloadMode_Immediate;”这句的原因是:

        预分频器是有一个缓冲寄存器的,我们写入的值只有在更新事件时才会真正起作用。所以这里为了让值立刻起作用,就在函数的最后手动生成了一个更新事件,这样,预分频器的值就有效了。

        但同时,它的副作用就是更新事件和更新中断是同时发生的,更新中断会置更新标志位。当我们之后一旦初始化结束,更新中断就会立刻进入。这就是我们刚一上电就立刻进入中断的原因

        解决方法

        在TIM_TimeBaseInit()的后面,开启中断的前面,调用一下TIM_ClearFlag()函数,手动将TIM_FLAG_Update更新标志位清除一下,就能避免刚初始化结束就立刻进入中断的问题了。

五、定时中断完整代码(调整后)

5.1、Timer.h

#ifndef _TIMER_H
#define _TIMER_H

void timer_init(void);

#endif

5.2、Timer.c

5.2.1、具体步骤

        第一步:RCC开启时钟。在这里打开时钟之后,定时器的基准时钟和整个外设的工作时钟就都会同时打开了。

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);

        第二步:选择时基单元的时钟源。对于定时中断,我们选择内部时钟源。

TIM_InternalClockConfig(TIM2);

        第三步:配置时基单元。包括这里的与分频器,计数器计数模式,自动重装器等等。这些参数用一个结构体就可以配置好了。

	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);

        第四步:配置输出中断控制,允许更行中断输出到NVIC。

	/*使能更新中断*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);

        第五步:配置NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	/*中断通道*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);

        整个模块配置完成之后我们还需要使能一下计数器,不然计数器是不会运行的。当定时器使能后,计时器就会开始报数了。当计时器更新时,触发中断。最后再写一个定时器的中断函数,这样这个中断函数每隔一段时间就能自动执行一次了。

TIM_Cmd(TIM2,ENABLE); 

5.2.2、完整代码

#include "stm32f10x.h"                  // Device header

extern uint16_t num;

void timer_init(void)
{
	/*第一步:配置rcc时钟*/
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2,ENABLE);
	
	/*配置时基单元*/
	TIM_InternalClockConfig(TIM2);
	
	TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;
	
	TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;
	TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;
	TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;
	TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1;
	TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
	TIM_TimeBaseInit(TIM2,&TIM_TimeBaseInitStructure);
	
	/*使能更新中断*/
	TIM_ClearFlag(TIM2,TIM_FLAG_Update);
	TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
	
	/*此时已经开启了更新中断到NVIC的通路*/
	
	/*配置NVIC通路*/
	/*NVIC优先级分组:*/
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	/*中断通道*/
	NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	/*启动定时器*/
	TIM_Cmd(TIM2,ENABLE); 
}

void TIM2_IRQHandler(void)
{
	/*检查中断标志位*/
	if(TIM_GetITStatus(TIM2,TIM_IT_Update) == SET)
	{
		num++;
		TIM_ClearITPendingBit(TIM2,TIM_IT_Update);
	}
}

5.3、main.c

#include "stm32f10x.h"                  // Device header
#include "Delay.h"
#include "OLED.h"
#include "Timer.h"

uint16_t num;
int main(void)
{
	OLED_Init();
	timer_init();/*初始化定时器*/
	
	OLED_ShowString(1, 1, "num:");
	
	while (1)
	{
		OLED_ShowNum(1,5,num,5);
		OLED_ShowNum(2,5,TIM_GetCounter(TIM2),5); 
	}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2093360.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

经典文献阅读之--ParkingE2E(基于摄像头的端到端停车网络:从图像到规划)

0. 简介 自动泊车是智能驾驶领域的一项关键任务。传统泊车算法通常采用基于规则的方案来实现。然而&#xff0c;由于算法设计的复杂性&#xff0c;这些方法在复杂的泊车场景中效果欠佳。相比之下&#xff0c;基于神经网络的方法往往比基于规则的方法更加直观且功能多样。通过收…

中国的铁路订票系统在世界上属于什么水平?

每到节假日&#xff0c;中国的铁路订票系统总会成为人们热议的焦点。无论是“抢票大战”还是“秒杀特价票”&#xff0c;这一系统似乎总是牵动着亿万乘客的心。那么&#xff0c;中国的铁路订票系统到底有多强大&#xff1f;在全球范围内&#xff0c;它处于什么水平&#xff1f;…

Java_ElasticSearch(ES)——分布式搜索引擎

介绍&#xff1a; Elasticsearch是一个开源的分布式搜索和分析引擎&#xff0c;最初由Elastic公司开发。它构建在Apache Lucene搜索引擎库之上&#xff0c;提供了一个强大的全文搜索和分析引擎&#xff0c; 它结合kibana、Logstash、Beats&#xff0c;是一整套技术栈&#xff0…

C语言——简单的do while循环找100~999之间的水仙花数(所有的三位水仙花数)

这道题的关键是如何把这个三位数的个位、十位、百位表示出来 这里用到了 / &#xff08;整除&#xff09;和 % &#xff08;取余&#xff09;这两个运算符 #include<stdio.h> int main() { int num 100; do { int a; int b; int …

手把手教你:用sentence-transformers库进行文本嵌入

在 Python 中使用 sentence-transformers 库进行实操&#xff0c;你可以按照以下步骤进行&#xff1a; 1. 安装 sentence-transformers 库 首先&#xff0c;确保你已经安装了 sentence-transformers。如果没有&#xff0c;可以通过 pip 安装&#xff1a; pip install sentenc…

图像去噪评论:从经典到最先进的方法

系列文章目录 文章目录 系列文章目录前言摘要1 引言1.1.噪声抑制 2. 空间域过滤2.1.局部滤波器2.2.非局部滤波器 3.变换域滤波3.1.阈值3.1.1. 通用阈值3.1.2. VISUShrink3.1.3.SURE收缩3.1.4.BayesShrink3.1.5.概率收缩3.1.6.SURELET3.1.7.Neigh Shrink Sure&#xff08;NSS&am…

十一头像红旗怎么弄的?3个方法轻松教会你!

国庆佳节渐行渐至&#xff0c;朋友圈里早已掀起了一股更换国庆主题头像的热潮&#xff01;那些五彩斑斓、光彩夺目的渐变国旗头像&#xff0c;既美观又富有节日气氛。如果你也想加入这个行列&#xff0c;那么如何动手制作呢&#xff1f;别担心&#xff0c;接下来我将为你介绍三…

求解组合优化问题的具有递归特征的无监督图神经网络

文章目录 ABSTRACT1 Introduction2 Related Work3 QRF-GNN方法4 数值实验4.1 MAX-CUTABSTRACT 介绍了一种名为QRF-GNN的新型算法,有效解决具有二次无约束二进制优化(QUBO)表述的组合问题。依赖无监督学习,从最小化的QUBO放松导出的损失函数。该架构的关键组成部分是中间GNN…

服务端之Node的QQ邮件发送功能、授权码申请流程、邮箱、createTransport、sendMail

MENU 前言邮箱授权码的申请流程Node连续发送邮件失败的原因 前言 1、代码段的主要功能是通过nodemailer模块从一个QQ邮箱发送电子邮件。 2、代码段实现从QQ邮箱1283077926qq.com发送一封邮件到2506562048qq.com&#xff0c;邮件主题为“微信公众号推广”&#xff0c;正文为“亲…

Docker私有镜像仓库Harbor安装并推拉镜像

1.环境信息 前置要求&#xff1a; linux&#xff1a;Oracle Linux Server release 7.9 docker&#xff1a;26.1.4 安装&#xff1a; docker-compose: Docker Compose version v2.29.2 harbor&#xff1a;v2.11.1 2.下载安装说明 docker-compose下载&#xff1a; https://githu…

Vue(八) localStorage、组件的自定义事件、Todo案例修改

文章目录 一、浏览器本地存储1. 相关API2. Todo案例中的应用 二、组件的自定义事件1. 回顾props传值方式2. 绑定自定义事件&#xff08;1&#xff09;方式一&#xff1a;v-on或&#xff08;2&#xff09;方式二&#xff1a; ref 3. 解绑自定义事件4. 注意点总结 三、Todo案例采…

【机器学习】在 scikit-learn 中,有哪些特征编码方法?分布详细举例列出

一、在scikit-learn中&#xff0c;有多种特征编码方法可以用来处理分类数据&#xff0c;以下是一些常见的编码方法及其示例&#xff1a; One-Hot Encoding (独热编码): 使用 OneHotEncoder 类将分类特征转换为二进制向量。例如&#xff0c;对于颜色特征 [red, blue, green]&…

day01项目概述、环境搭建

1 软件开发整体介绍 软件开发流程 角色分工 软件环境 2 苍穹外卖项目介绍 项目介绍 产品原型 技术选型 3 开发环境搭建 前端环境搭建 注意&#xff1a; - Nginx目录必须放在没有中文的目录中才能正常运行 - 当前Nginx的配置文件中已经配置了反向代理&#xff0c;通过此配置…

面试SQL题的水到底有多深?一文带你揭晓

不谋万世者&#xff0c;不足谋一时&#xff1b;不谋全局者&#xff0c;不足谋一域 目录 0 面试现状 1 面试SQL题目的难度及特点 1.1 题目场景化 1.2 题目算法化 1.3 方法多元化 2 破局之道 3 总结 数字化建设通关指南 主要内容&#xff1a; &#xff08;1&#xff09;SQL进阶实…

ChatTTS 长音频合成和本地部署2种方式,让你的“儿童绘本”发声的实战教程(文末有福利)

接上文&#xff08;GLM-4-Flash 大模型 API 免费了&#xff0c;手把手构建“儿童绘本”应用实战&#xff08;附源码&#xff09;&#xff09;&#xff0c;老牛同学通过 GLM-4-Flash 文生文和 CogView-3 文生图大模型&#xff0c;和大家一起编写了一个图文并茂的儿童绘本应用&am…

Claude3.5 Sonnet模型评测(附使用方法)

随着模型的发展&#xff0c;之前大家常用的鉴别模型能力的测试已经有很多过时现象&#xff0c;比如经典的喝水测试&#xff0c;目前国内的先进模型也已经可以答对&#xff0c;我们需要更复杂的问题来测试模型能力&#xff0c;最近有研究人员发现&#xff0c;大模型不会比较浮点…

操作符详细解析

操作符详解 文章目录 操作符详解1.操作符分类2.算数操作符3.移位操作符3.1整型二进制的表示3.1.1整数二进制的种类3.1.2二进制原码反码补码的表示 3.2移位运算符使用规则3.2.1正数的左移运算符 3.2.2负数的左移运算符3.2.3右移操作符3.2.3.1右移运算符的两种形式&#xff1a;3.…

使用WSL在Windows上安装Linux

文章目录 环境步骤参考 注&#xff1a;WSL是“Windows Subsystem for Linux”的缩写&#xff0c;即“适用于 Linux 的 Windows 子系统”&#xff0c;说白了就是在Windows系统里直接使用Linux&#xff0c;而不需要VMWare等虚拟软件。 环境 Windows 11 家庭中文版 步骤 首先&…

DORIS - DORIS简介

前言 本博文基于DORIS的2.1.5版本。apache-doris-2.1.5-bin-x64.tar.gz 是什么&#xff1f; DORIS官网 Apache Doris 是一款基于 MPP 架构的高性能、实时的分析型数据库&#xff0c;以高效、简单、统一的特点被人们所熟知&#xff0c;仅需亚秒级响应时间即可返回海量数据下的…

迅为2K1000开发板流畅运行Busybox、Buildroot、Loognix、QT5.12 系统

硬件配置 国产龙芯处理器&#xff0c;双核64位系统&#xff0c;板载2G DDR3内存&#xff0c;流畅运行Busybox、Buildroot、Loognix、QT5.12 系统! 接口全板载4路USB HOST、2路千兆以太网、2路UART、2路CAN总线、Mini PCIE、SATA固态盘接口、4G接口、GPS接口WIF1、蓝牙、Mini HD…