前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >蓝桥杯嵌入式之Time和PWM输出讲解

蓝桥杯嵌入式之Time和PWM输出讲解

作者头像
用户5935416
发布2019-08-01 10:07:42
1.3K0
发布2019-08-01 10:07:42
举报
文章被收录于专栏:IT界的小白帽

开发板内置有四个16位可同步运行定时器(TIM1、TIM2、TIM3和TIM4)。不过在比赛时一般可以使用SysTick滴答定时器代替Time定时器,所以Time定时器可以简单了解。接下来以TIM3为例讲解Time定时器,其它的使用方法相似。

TIM3初始化代码

TIM3的初始化代码需要用到stm32f10x_tim.c里定义的函数。所以需要包含stm32f10x_tim.c和stm32f10x_tim.h文件。

TIM3初始化的代码为

代码语言:javascript
复制
/**
  * @说明     通用定时器TIM3配置函数
  * @参数     none
  * @返回值   None
  */
void TIM_Config(void)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  
  /* TIM3 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
  
  //中断向量配置
  NVIC_Configuration();    
  
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 50000;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
  //TIM3预分频设置:1MHZ,APB1分频系数2,TIM3时钟为36MHzx2 = 72MHz  
  TIM_PrescalerConfig(TIM3,71, TIM_PSCReloadMode_Immediate);  
  
  //通用定时器TIM3中断配置
  TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);  
  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);
}

首先是对时钟的使能。可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\TIM1_Synchro中的main.c文件的时钟初始化代码。源代码为

代码语言:javascript
复制
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3 | RCC_APB1Periph_TIM4, ENABLE);

其次是中断的设置。中断设置函数为

代码语言:javascript
复制
/**
  * @说明     中断向量配置函数
  * @参数     none
  * @返回值   None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM3 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

  NVIC_Init(&NVIC_InitStructure);
}

可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\TIM9_OCToggle中的main.c文件。源代码为

代码语言:javascript
复制
/**
  * @brief  Configure the nested vectored interrupt controller.
  * @param  None
  * @retval None
  */
void NVIC_Configuration(void)
{
  NVIC_InitTypeDef NVIC_InitStructure;

  /* Enable the TIM9 global Interrupt */
  NVIC_InitStructure.NVIC_IRQChannel =  TIM1_BRK_TIM9_IRQn;
  NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
  NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStructure);
}

只需将TIM1_BRK_TIM9_IRQn替换成TIM3_IRQn。TIM3_IRQn定义在stm32f10x.h中的第211行。结构体NVIC_InitStructure的元素NVIC_IRQChannelSubPriority 的值改为1。

最后是TIM3的模式设置。可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\TIM1_Synchro中的main.c文件中的代码。源代码为

代码语言:javascript
复制
  /* TIM3 Peripheral Configuration ----------------------------------------*/
  /* TIM3 Slave Configuration: PWM1 Mode */
  TIM_TimeBaseStructure.TIM_Period = 2;
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

  TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

只需将结构体TIM_TimeBaseStructure的元素TIM_Period的值改为50000即可。

其中以下的代码需要自己组织。

代码语言:javascript
复制
//TIM3预分频设置:1MHZ,APB1分频系数2,TIM3时钟为36MHzx2 = 72MHz  
  TIM_PrescalerConfig(TIM3,71, TIM_PSCReloadMode_Immediate);  
  
  //通用定时器TIM3中断配置
  TIM_ITConfig(TIM3,TIM_IT_Update, ENABLE);  
  /* TIM3 enable counter */
  TIM_Cmd(TIM3, ENABLE);

函数TIM_PrescalerConfig定义在stm32f10x_tim.c中的第1176行,声明在stm32f10x_tim.h中的第1083行。参数TIM_PSCReloadMode_Immediate定义在stm32f10x_tim.h中的第804行。函数TIM_ITConfig定义在stm32f10x_tim.c中的第872行,声明在stm32f10x_tim.h中的第1069行。参数TIM_IT_Update定义在stm32f10x_tim.h中的第601行。函数TIM_Cmd定义在stm32f10x_tim.c中的第806行,声明在stm32f10x_tim.h中的第1067行。

TIM3中断函数

TIM3的中断函数为

代码语言:javascript
复制
void TIM3_IRQHandler(void)
{
  if(TIM_GetFlagStatus(TIM3,TIM_FLAG_Update) == SET){
    //清除标志位
    TIM_ClearFlag(TIM3,TIM_FLAG_Update);
    //
    if(++_50ms == 20){
      _50ms = 0;
      if(++leds == 9){
        leds = 1;
      }
    }
  }
}

其内容可以自己改写。该函数定义在stm32f10x_it.c文件中。

函数TIM_GetFlagStatus定义在stm32f10x_tim.c中的第2556行,声明在stm32f10x_tim.h中的第1142行。

PWM_Out讲解

PWM_Out是输出脉冲宽度调制,用来模拟模拟信号量的输出。由于大多数考生在备考时没有示波器,考场每人提供一台示波器有不太理想,所以该部分的内容几乎没有考过。往届的比赛考过,但是有点失败,没有示波器的同学无法测试,只能凭感觉提交代码。该部分的知识可以简单了解。

PWM_Out初始化函数为

代码语言:javascript
复制
/**
  * @说明     PWM输出模式 PA1(TIM2-CH2)、PA2(TIM2-CH3)引脚配置
  * @参数     None 
  * @返回值   None
  */
void PWM_IO_Config(void)
{
    GPIO_InitTypeDef  GPIO_InitStructure;
  
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
  
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
}

利用PA1、PA2来模拟波形输出。

由于PWM_Out的输出是改变占空比来模拟模拟信号的输出。所以需要一个Timer定时器来对高低电平的时长进行定时。本例利用TIM2进行输出时间的控制。TIM2的初始化代码为

代码语言:javascript
复制
/**
  * @说明     通用定时器TIM2配置函数,PWM输出工作模式
  * @参数     none
  * @返回值   None
  */
void TIM_Config(uint16_t Channel2Pulse, uint16_t Channel3Pulse)
{
  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
  TIM_OCInitTypeDef  TIM_OCInitStructure;
  
  /* TIM2 clock enable */
  RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);    
  
  /* Time base configuration */
  TIM_TimeBaseStructure.TIM_Period = 999;  //1KHz
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
  //TIM2预分频设置:1MHZ,APB1分频系数2,输入到TIM3时钟为36MHzx2 = 72MHz  
  TIM_PrescalerConfig(TIM2,71, TIM_PSCReloadMode_Immediate);

  /* Channel 2 and 3 Configuration in PWM mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;  
  
  TIM_OC2Init(TIM2, &TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;
  TIM_OC3Init(TIM2, &TIM_OCInitStructure);

  //使能TIM2定时计数器
  TIM_Cmd(TIM2, ENABLE);
  //使能TIM2 PWM输出模式
  TIM_CtrlPWMOutputs(TIM2, ENABLE);
}

参数Channel2Pulse、Channel3Pulse决定两个端口输出波形的占空比。

可以参考CT117E嵌入式竞赛板\STM32_MCU\stm32f10x_stdperiph_lib\STM32F10x_StdPeriph_Lib_V3.5.0\Project\STM32F10x_StdPeriph_Examples\TIM\7PWM_Output的main.c文件,源代码为

代码语言:javascript
复制
 /* Time Base configuration */
  TIM_TimeBaseStructure.TIM_Prescaler = 0;
  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
  TIM_TimeBaseStructure.TIM_Period = TimerPeriod;
  TIM_TimeBaseStructure.TIM_ClockDivision = 0;
  TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;

  TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

  /* Channel 1, 2,3 and 4 Configuration in PWM mode */
  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;
  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
  TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;
  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_Low;
  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;

  TIM_OC1Init(TIM1, &TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;
  TIM_OC2Init(TIM1, &TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;
  TIM_OC3Init(TIM1, &TIM_OCInitStructure);

  TIM_OCInitStructure.TIM_Pulse = Channel4Pulse;
  TIM_OC4Init(TIM1, &TIM_OCInitStructure);

  /* TIM1 counter enable */
  TIM_Cmd(TIM1, ENABLE);

  /* TIM1 Main Output Enable */
  TIM_CtrlPWMOutputs(TIM1, ENABLE);

需要将结构体TIM_OCInitStructure中的元素TIM_Period 的值改成999。通道选择两个,一个为12,另一个为13,可以尝试其它通道。

如果想输出一个占空比为50%,一个为70%的话,代码为

代码语言:javascript
复制
TIM_Config(998/2,998*7/10);
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-17,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 IT界的小白帽 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档