[N32G43x] 如何使用定时器输出指定数量的脉冲

[复制链接]
805|3
 楼主| sy12138 发表于 2022-12-30 10:15 | 显示全部楼层 |阅读模式
#每日话题# #技术资源#

目前我们有两种方式来实现定时器输出指定数量的脉冲
方法1:定时器级联
方法2:高级定时器
接下来给大家简单讲一下两种方式具体的实现原理

定时器级联:这里我们用到的是TIM2和TIM3,是两个通用定时器;然后我们TIM2从模式配置为外部时钟模式1,触发源选择TIM3,即利用TIM3来驱动TIM2,TIM3每更新一次,TIM2计数器+1,所以TIM3输出PWM的个数 = TIM2的计数值,这里如果我们选择输出10个PWM,就需要配置TIM2_ARR = 10-1,然后使能TIM2的更新中断,当TIM3输出指定数量的PWM之后,进入TIM2更新中断,在中断中关闭TIM3,停止PWM输出。
  1. void TIM3_Master_Config(void)
  2. {
  3.     GPIO_InitType GPIO_InitStructure;
  4.     TIM_TimeBaseInitType TIM_TimeBaseStructure;
  5.     OCInitType TIM_OCInitStructure;

  6.     /** RCC Config */
  7.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOA, ENABLE);
  8.     RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM3, ENABLE);

  9.     /** GPIO Config */
  10.     GPIO_InitStruct(&GPIO_InitStructure);
  11.     GPIO_InitStructure.Pin            = GPIO_PIN_6 ;
  12.     GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
  13.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM3;
  14.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

  15.     /** Time Base Config */
  16.     TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
  17.     TIM_TimeBaseStructure.Period    = 1000 - 1;
  18.     TIM_TimeBaseStructure.Prescaler = 108 - 1;
  19.     TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;
  20.     TIM_TimeBaseStructure.ClkDiv    = TIM_CLK_DIV1;
  21.     TIM_InitTimeBase(TIM3, &TIM_TimeBaseStructure);

  22.     /** PWM Config */
  23.     TIM_InitOcStruct(&TIM_OCInitStructure);
  24.     TIM_OCInitStructure.OcMode       = TIM_OCMODE_PWM2;
  25.     TIM_OCInitStructure.OutputState  = TIM_OUTPUT_STATE_ENABLE;
  26.     TIM_OCInitStructure.Pulse        = 500;
  27.     TIM_OCInitStructure.OcPolarity   = TIM_OC_POLARITY_LOW;
  28.     TIM_InitOc1(TIM3, &TIM_OCInitStructure);

  29.     TIM_ConfigOc1Preload(TIM3, TIM_OC_PRE_LOAD_ENABLE);
  30.     TIM_ConfigArPreload(TIM3, ENABLE);

  31.     TIM_SelectOutputTrig(TIM3, TIM_TRGO_SRC_OC1REF);               // 选择OC1REF作为主定时器的TRGO信号
  32. }
  1. void TIM2_Slave_Config(uint32_t countpluse)
  2. {
  3.     NVIC_InitType NVIC_InitStructure;
  4.     TIM_TimeBaseInitType TIM_TimeBaseStructure;

  5.     /** RCC Config */
  6.     RCC_EnableAPB1PeriphClk(RCC_APB1_PERIPH_TIM2, ENABLE);

  7.     /** NVIC Config */
  8.     NVIC_InitStructure.NVIC_IRQChannel                   = TIM2_IRQn;
  9.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  10.     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
  11.     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  12.     NVIC_Init(&NVIC_InitStructure);

  13.     /** Time Base Config */
  14.     TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
  15.     TIM_TimeBaseStructure.Period    = (countpluse - 1);
  16.     TIM_TimeBaseStructure.Prescaler = 0;
  17.     TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;
  18.     TIM_TimeBaseStructure.ClkDiv    = TIM_CLK_DIV1;
  19.     TIM_InitTimeBase(TIM2, &TIM_TimeBaseStructure);

  20.     TIM_SelectInputTrig(TIM2, TIM_TRIG_SEL_IN_TR2);
  21.     TIM_SelectSlaveMode(TIM2, TIM_SLAVE_MODE_EXT1);

  22.     TIM_ConfigInt(TIM2, TIM_INT_UPDATE, DISABLE);
  23.     TIM_ClearFlag(TIM2, TIM_FLAG_UPDATE);
  24.     TIM_ConfigInt(TIM2, TIM_INT_UPDATE, ENABLE);

  25.     TIM_Enable(TIM2, ENABLE);
  26. }
  27. TIM_Enable(TIM3, ENABLE);
  1. void TIM2_IRQHandler(void)
  2. {
  3.         if(TIM_GetIntStatus(TIM2, TIM_INT_UPDATE) != RESET)
  4.         {
  5.                 TIM_Enable(TIM3, DISABLE);
  6.                 TIM_ConfigInt(TIM2, TIM_INT_UPDATE, DISABLE);
  7.                   TIM_ClrIntPendingBit(TIM2, TIM_INT_UPDATE);
  8.         }
  9. }
然后我们来看一下TIM3输出的PWM波形:
1fba19aaaac3cf77fc2d26e549bc93f.png
其实定时器级联还有一种配置也可以达到这种效果,我们主定时器TIM3选择更新事件触发,TIM2从模式选择门控模式;

接下来讲一下第二种实现方式,高级定时器
高级定时器:N32高级定时器独有一个重复计数器的模块,每次计数器更新都会让重复计数器-1,当重复计数器=0时,触发更新事件,在更新中断中关闭定时器,停止PWM输出。
  1. void TIM1_PWM_Config(uint8_t num)
  2. {
  3.     GPIO_InitType GPIO_InitStructure;
  4.     NVIC_InitType NVIC_InitStructure;
  5.     TIM_TimeBaseInitType TIM_TimeBaseStructure;
  6.     OCInitType TIM_OCInitStructure;

  7.     /** RCC Config */
  8.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_AFIO | RCC_APB2_PERIPH_GPIOA, ENABLE);
  9.     RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_TIM1, ENABLE);

  10.     TIM_EnableCtrlPwmOutputs(TIM1, ENABLE);

  11.     /** GPIO Config */
  12.     GPIO_InitStruct(&GPIO_InitStructure);
  13.     GPIO_InitStructure.Pin            = GPIO_PIN_8;
  14.     GPIO_InitStructure.GPIO_Mode      = GPIO_Mode_AF_PP;
  15.     GPIO_InitStructure.GPIO_Alternate = GPIO_AF2_TIM1;
  16.     GPIO_InitPeripheral(GPIOA, &GPIO_InitStructure);

  17.     /** NVIC Config */
  18.     NVIC_InitStructure.NVIC_IRQChannel                   = TIM1_UP_IRQn;
  19.     NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  20.     NVIC_InitStructure.NVIC_IRQChannelSubPriority        = 1;
  21.     NVIC_InitStructure.NVIC_IRQChannelCmd                = ENABLE;
  22.     NVIC_Init(&NVIC_InitStructure);

  23.     /** Time Base Config */
  24.     TIM_InitTimBaseStruct(&TIM_TimeBaseStructure);
  25.     TIM_TimeBaseStructure.Period    = 1000 - 1;
  26.     TIM_TimeBaseStructure.Prescaler = 108 - 1;
  27.     TIM_TimeBaseStructure.CntMode   = TIM_CNT_MODE_UP;
  28.     TIM_TimeBaseStructure.ClkDiv    = TIM_CLK_DIV1;
  29.     TIM_TimeBaseStructure.RepetCnt  = (num - 1);
  30.     TIM_InitTimeBase(TIM1, &TIM_TimeBaseStructure);

  31.     /** PWM Config */
  32.     TIM_InitOcStruct(&TIM_OCInitStructure);
  33.     TIM_OCInitStructure.OcMode       = TIM_OCMODE_PWM1;
  34.     TIM_OCInitStructure.OutputState  = TIM_OUTPUT_STATE_ENABLE;
  35.     TIM_OCInitStructure.Pulse        = 500;
  36.     TIM_OCInitStructure.OcPolarity   = TIM_OC_POLARITY_LOW;
  37.     TIM_OCInitStructure.OcIdleState  = TIM_OC_IDLE_STATE_SET;
  38.     TIM_InitOc1(TIM1, &TIM_OCInitStructure);

  39.     TIM_ConfigOc1Preload(TIM1, TIM_OC_PRE_LOAD_ENABLE);
  40.     TIM_ConfigArPreload(TIM1, ENABLE);

  41.     TIM_ConfigInt(TIM1, TIM_INT_UPDATE, DISABLE);
  42.     TIM_ClearFlag(TIM1, TIM_FLAG_UPDATE);
  43.     TIM_ConfigInt(TIM1, TIM_INT_UPDATE, ENABLE);

  44.     TIM_Enable(TIM1, ENABLE);
  45. }
  1. void TIM1_UP_IRQHandler(void)
  2. {
  3.         if(TIM_GetIntStatus(TIM1, TIM_INT_UPDATE) != RESET)
  4.         {
  5.                 TIM_Enable(TIM1, DISABLE);
  6.                 TIM_ConfigInt(TIM1, TIM_INT_UPDATE, DISABLE);
  7.                 TIM_ClrIntPendingBit(TIM1, TIM_INT_UPDATE);
  8.         }
  9. }
输出PWM波形展示:
aece35757b30b92f2521f9eea7a1859.png
zhouchen605768 发表于 2023-1-1 21:05 | 显示全部楼层
这种波形图是用逻辑分析仪抓出来的嘛
 楼主| sy12138 发表于 2023-1-3 09:47 | 显示全部楼层
zhouchen605768 发表于 2023-1-1 21:05
这种波形图是用逻辑分析仪抓出来的嘛

是的,用逻辑分析仪
zhouchen605768 发表于 2023-1-4 22:02 | 显示全部楼层
sy12138 发表于 2023-1-3 09:47
是的,用逻辑分析仪

逻辑分析仪采样率可以推荐下不?就当前国民的MCU这块100M的采样率完全够用不?打算买一个逻辑分析仪
您需要登录后才可以回帖 登录 | 注册

本版积分规则

92

主题

404

帖子

19

粉丝
快速回复 在线客服 返回列表 返回顶部