zoukankan      html  css  js  c++  java
  • STM32F4 定时器TIM1输出七路PWM信号【使用库函数】

    【实验目的】

    输出7路占空比不同的PWM信号是各个版本ST库必备的例子。本实验的主要目的不是表现ST芯片PWM功能的强大,而是要完成输出的精确计算。

    【实验内容】

    输出7路PWM信号,并用示波器测量输出。

    【实验原理】

    1、时基单元初始化

    TIM1和TIM8使用内部时钟时,时钟由APB2提供。但是定时器的时钟并不是直接由APB2提供,而是来自于输入为APB2的一个倍频器。当APB2的与分频系数为1时,这个倍频器不起作用,定时器时钟频率等于APB2时钟。当APB2预分频系数为其他时这个倍频器起作用。定时器的输入频率等于APB2的2倍。本实验中,APB2时钟被设置成了84M是对系统时钟进行2分频。因此定时器的输入时钟是84M×2 = 168M = SYSCLK。(PS:这个倍频我在ST的手册上边没有找到,是网上搜索得到的结果,与实际结果对比是正确的)

    TIM_Prescaler 为预分频值,为0时分频系数为1.

    TIM_Period 为每个周期计数值,从0开始计数所以其值应为计数次数减去1。

    TIM_RepetitionCounter是F4新增的一个东西,只有高级定时器TIM1和TIM8有效,对应寄存器RCR。意思就是每TIM_RepetitionCounter+1个技术周期产生一次中断。

    我定义的时基如下,将产生频率为20K的即使基准:

    TimerPeriod = (SystemCoreClock / 20000 ) - 1;

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
    //时基初始化
    TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //死区控制用。
    TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数器方向
    TIM_TimeBaseInitStructure.TIM_Prescaler = 0;   //Timer clock = sysclock /(TIM_Prescaler+1) = 168M
    TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
    TIM_TimeBaseInitStructure.TIM_Period = TimerPeriod - 1;    //Period = (TIM counter clock / TIM output clock) - 1 = 20K
    TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);

    2、计时输出

    ccr1、2、3、4为各个技术周期的TIM_Pulse。即每当计数到这些个值的时候,PWM波形就会反转。

    ccr1 = TimerPeriod / 2;  //占空比1/2 = 50%
    ccr2 = TimerPeriod / 3;  //占空比1/3 = 33%
    ccr3 = TimerPeriod / 4;  //占空比1/4 = 25%
    ccr4 = TimerPeriod / 5;  //占空比1/5 = 20%

    定义输出部分:

    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
    TIM_OCInitStructure.TIM_Pulse = ccr1;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
    TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_Low;//输出同相,TIM_OCNPolarity_High时输出反相
    TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
    TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;

    TIM_OC1Init(TIM1,&TIM_OCInitStructure);

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

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

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

    TIM_Cmd(TIM1,ENABLE);
    TIM_CtrlPWMOutputs(TIM1,ENABLE);

    3、到这里就完成了定时器的配置,下边是GPIO引脚的配置

    使用GPIOE的8、9、10、11、12、13、14引脚进行PWM输出。配置如下:

    void TIM1_GPIO_Config(void)
    {
      //PE 8 9 10 11 12 13 14输出
      GPIO_InitTypeDef GPIO_InitStructure;
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11
                                    | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_Init(GPIOE,&GPIO_InitStructure);

      GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1);
    }

    输出波形图:

    同相输出时候:

    OC1/OC1N

    IMAG2200

    OC2/OC2N

    IMAG2201

    OC3/OC3/N

    IMAG2202

    OC4

    IMAG2203

    反相输出

    OC1/OC1N

    IMAG2204

    OC2/OC2N

    IMAG2205

    OC3/OC3/N

    IMAG2206

    OC4

    IMAG2207

    完整的应用代码:

    使用时只主要两行即可

    //主函数调用

       TIM1_GPIO_Config();
       Tim1_Config();

    //定时器输出引脚初始化

    void TIM1_GPIO_Config(void)
    {
      //PE 8 9 10 11 12 13 14输出
      GPIO_InitTypeDef GPIO_InitStructure;
      RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE,ENABLE);
      GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
      GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
      GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11
                                    | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14;
      GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
      GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
      GPIO_Init(GPIOE,&GPIO_InitStructure);
     
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource8,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource9,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource10,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource11,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource12,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource13,GPIO_AF_TIM1);
      GPIO_PinAFConfig(GPIOE,GPIO_PinSource14,GPIO_AF_TIM1);
       
    }

    //TIM1做PWM输出
    void Tim1_Config(void)
    {
      TimerPeriod =  (SystemCoreClock / 20000 ) - 1;
      ccr1 = TimerPeriod / 2;  //占空比1/2 = 50%
      ccr2 = TimerPeriod / 3;  //占空比1/3 = 33%
      ccr3 = TimerPeriod / 4;  //占空比1/4 = 25%
      ccr4 = TimerPeriod / 5;  //占空比1/5 = 20%
     
      RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
      //时基初始化
      TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; //死区控制用。
      TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;  //计数器方向
      TIM_TimeBaseInitStructure.TIM_Prescaler = 0;   //Timer clock = sysclock /(TIM_Prescaler+1) = 168M
      TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;
      TIM_TimeBaseInitStructure.TIM_Period = TimerPeriod - 1;    //Period = (TIM counter clock / TIM output clock) - 1 = 20K
      TIM_TimeBaseInit(TIM1,&TIM_TimeBaseInitStructure);

     
      TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
      TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
      TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;
      TIM_OCInitStructure.TIM_Pulse = ccr1;
      TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
      TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;
      TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;
      TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
     
      TIM_OC1Init(TIM1,&TIM_OCInitStructure);

      TIM_OCInitStructure.TIM_Pulse = ccr2;
      TIM_OC2Init(TIM1,&TIM_OCInitStructure);
     
      TIM_OCInitStructure.TIM_Pulse = ccr3;
      TIM_OC3Init(TIM1,&TIM_OCInitStructure);
     
      TIM_OCInitStructure.TIM_Pulse = ccr4;
      TIM_OC4Init(TIM1,&TIM_OCInitStructure);
     
      TIM_Cmd(TIM1,ENABLE);
      TIM_CtrlPWMOutputs(TIM1,ENABLE);
    }

  • 相关阅读:
    yii2 gii 命令行自动生成控制器和模型
    控制器中的方法命名规范
    Vue Property or method "" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based
    IDEA插件:GsonFormat
    Spring Boot : Access denied for user ''@'localhost' (using password: NO)
    Typora添加主题
    Git基础命令图解
    Java Joda-Time 处理时间工具类(JDK1.7以上)
    Java日期工具类(基于JDK1.7版本)
    Oracle SQL Developer 连接Oracle出现【 状态: 失败 -测试失败: ORA-01017: invalid username/password; logon denied】
  • 原文地址:https://www.cnblogs.com/zyqgold/p/3100377.html
Copyright © 2011-2022 走看看