1. stm32f103xx高级定时器/通用定时器、基本定时器比较:

2.  IC: 输入捕获

  OC: 输出比较

  TIMx_CCRx: 捕获/比较寄存器

  

 

3. OC(output compare)输出比较

  • 输出比较可以通过比较CNT与CCR寄存器值的关系,来对输出电平进行置1、置0或翻转的操作。用于输出一定频率和占空比的PWM波形
  • 每个高级定时器和通用定时器都有4个输出比较通道
  • 高级定时器的前3个通道额外拥有死区生成和互补输出的功能

4. CNT: 时基单元的计数器

时基单元包含:
● 计数器寄存器(TIMx_CNT)
● 预分频器寄存器 (TIMx_PSC)
● 自动装载寄存器 (TIMx_ARR)
● 重复次数寄存器 (TIMx_RCR)

 

 

模式 描述
冻结 CNT=CCR时,REF保持为原状态
匹配时置有效电平 CNT=CCR时,REF置有效电平
 匹配时置无效电平 CNT=CCR时,REF置无效电平 
 匹配时电平翻转 CNT=CCR时,REF电平翻转 
 强制为无效电平  CNT与CCR无效,REF强制为无效电平
强制为有效电平  CNT与CCR无效,REF强制为有效电平 
PWM1模式 

 向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置无效电平

向下计数: CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置有效电平

PWM2模式   

向上计数:CNT<CCR时,REF置有效电平,CNT≥CCR时,REF置有效电平

向下计数: CNT>CCR时,REF置无效电平,CNT≤CCR时,REF置无效电平

有效电平:高电平

冻结:暂停PWM

无效电平:低电平

5. PWM控制流程

  • PWM频率:Freq = CK_PSC / (PSC+1)(ARR+1)
  • PWM占空比: Duty = CCR / (ARR + 1)
  • PEM分辨率: Reso = 1 / (ARR + 1)

例如:PWM: 1kHz, 占空比50, 分辨率1% => ARR = 100, CCR=50, PSC=720

  • PWM频率:Freq = 72M / (PSC+1)(ARR+1) = 1000
  • PWM占空比: Duty = CCR / (ARR + 1) = 50%
  • PEM分辨率: Reso = 1 / (ARR + 1) = 1%

6. 舵机控制

  • 利用PWM占空比控制角度
  • 输入PWM信号: 周期20ms, 高电平宽度0.5ms~2.5ms
  • 20ms = 50Hz
  • 舵机驱动程序 
  • void pwm_init()
    {
        GPIO_InitTypeDef                       GPIO_InitStructure;   //声明初始化定时器GPIO的结构体变量
        TIM_TimeBaseInitTypeDef              TIM_TimeBaseInitStructure;//声明初始化定时器时基的结构体变量
        TIM_OCInitTypeDef                     TIM_OCInitStructure;//根据TIM_OCInitStruct中指定的参数初始化外设TIMx
    
        //开启时钟
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC,ENABLE);
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE);
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);
    
        //  配置GPIO的模式和IO口
        GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;// PC6
        GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用推挽输出
        GPIO_Init(GPIOC,&GPIO_InitStructure);
        
        //TIM3定时器初始化
        TIM_TimeBaseInitStructure.TIM_Period = 199; //PWM 频率=72000/(199+1)=36Khz//设置自动重装载寄存器周期的值
        TIM_TimeBaseInitStructure.TIM_Prescaler = 7199;//设置用来作为TIMx时钟频率预分频值
        TIM_TimeBaseInitStructure.TIM_ClockDivision = 0;//设置时钟分割:TDTS = Tck_tim
        TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;    //TIM向上计数模式
        TIM_TimeBaseInit(TIM3, & TIM_TimeBaseInitStructure);
    
        GPIO_PinRemapConfig(GPIO_FullRemap_TIM3,ENABLE);//改变指定管脚的映射 规则在F103参考手册里。
    
        //PWM初始化
        TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable;//PWM输出使能
        TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_Low;
    
        TIM_OC1Init(TIM3,&TIM_OCInitStructure);  //配置TIM1时基单元
        TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);//使能或者失能TIMx在CCR1上的预装载寄存器
        TIM_Cmd(TIM3,ENABLE);//使能或者使能TIMx外设
    }

     

  •  

    通过RCC实现PWM值的变化,需要用到配置比较单元的函数

  • void PWM_SerCompare1(u16 Compare)
    {
       TIM_SetCompare1(TIM2, Compare);  
    }

     

  • 主函数不断更新RCC值

  • for (i=0; i<=100; i++)
    {
      PWM_SetCompare1(i);
      Delay_ms(10);  
    }
    
    for (i=0; i<1=100; i++)
    {
      PWM_SetCompare1(100-i);
      Delay_ms(10);  
    }

     

  • Delay_ms

  • //毫秒级的延时
            void delay_ms(u16 time)
            {    
               u16 i=0;  
               while(time--)
               {
                  i=12000;  //自己定义
                  while(i--) ;    
               }
            }

  • 同时使用两个通道输出PWM, 频率必须是一样的,RCC占空比可以不一样;
  • Freq=50Hz = 20ms = 72M / (72) / 20k
  • ARR = 20k = 20ms = CCR / 20k
  • CCR = 500 = 0.5ms

6. TB6612FNG电机驱动模块

  •  

  •  

    电机驱动程序 bsp_AdvanceTim.c

    #include "bsp_AdvanceTim.h"
    
    //TP6612 GPIO驱动函数代码
    /*驱动6112 的AIN1 AIN2
    AIN1    PB13    置高电平
    AIN2    PB12    置低电平
    */
    void TB6612_GPIO_Init(void)
    {
        GPIO_InitTypeDef    GPIO_InitStructure;
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);        /*使能PB端口时钟*/
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;            /*PB12 PB13端口配置*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12|GPIO_Pin_13;    /*推挽输出*/
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;            /*IO口速度设置为50MHz*/
        GPIO_Init(GPIOB, &GPIO_InitStructure);                            /*根据设定参数初始化*/
        //电机正转
        GPIO_SetBits(GPIOB, GPIO_Pin_13);            /*PB13输出高*/
        GPIO_ResetBits(GPIOB, GPIO_Pin_12);        /*PB12输出低*/    
        
        //电机反转
    //    GPIO_SetBits(GPIOB, GPIO_Pin_12);            /*PB13输出高*/
    //    GPIO_ResetBits(GPIOB, GPIO_Pin_13);        /*PB12输出低*/    
        
        //电机停止
    //    GPIO_SetBits(GPIOB, GPIO_Pin_12);            /*PB13输出高*/
    //    GPIO_SetBits(GPIOB, GPIO_Pin_13);        /*PB12输出低*/    
    }
    
    //TIM1 PWM部分初始化
    /*
    PWM输出初始化
    arr: 自动重装值
    psc: 时钟预分频数
    */
    
    void TIM1_PWM_Init(u16 arr, u16 psc)
    {
        GPIO_InitTypeDef                    GPIO_InitStructure;
        TIM_TimeBaseInitTypeDef        TIM_TimeBaseStructure;
        TIM_OCInitTypeDef                    TIM_OCInitStructure;
        //使能对应定时器
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1, ENABLE);    /*使能定时器1时钟*/
    
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);    /*使能GPIO外设和AFIO复用功能模块*/
        //配置对应引脚功能,设置该引脚为复用输出功能,输出TIM1, CH1, CH4
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;        /*复用推挽输出*/
        GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8|GPIO_Pin_11;    /*TIM_CH1        TIM_CH4*/
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;        /**/
        GPIO_Init(GPIOA, &GPIO_InitStructure);    /*初始化GPIO口*/
        
        //初始化TIM1
    //    TIM_TimeBaseStructure.TIM_ClockDivision = 0;        /*设置时钟分割:TDTS = TCK_TIM*/
        TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;        /*设置时钟分割:TDTS = TCK_TIM*/
        TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;        /*TIM向上计数模式*/
        TIM_TimeBaseStructure.TIM_Period = arr;    /*设置在下一个更新事件装入活动的自动重装载寄存器周期的值*/
        TIM_TimeBaseStructure.TIM_Prescaler = psc;    /*设置用来作为TIMx时钟频率除数的预分频值*/
        //TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;    /**/
        TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);    /*根据TIM_TimeBaseInitStructure中指定的参数初始化TIMx的时间基数单位*/
        
        //初始化TIM1 Channel1 PWM模式
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;    /*选择定时器模式:TIM脉冲宽度调制模式2*/
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;        /*输出极性:TIM输出比较极性高*/
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;        /*比较输出使能*/
        TIM_OC1Init(TIM1, &TIM_OCInitStructure);    /*根据TIM_OCInitStructure指定的参数初始化外设TIM3*/
        TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);    /*使能TIM3在CCR2上的预装载寄存器*/
        TIM_CtrlPWMOutputs(TIM1,ENABLE);    /*MOE主输出使能,高级定时器必须开启这个*/
        
        //初始化TIM1 Channel4 PWM模式
        TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
        TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
        TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
        TIM_OC4Init(TIM1, &TIM_OCInitStructure);
        TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);
        
        TIM_Cmd(TIM1, ENABLE);    /*使能TIM1*/
        
    }
    
    
    void ADVANCE_TIM_Init(void)
    {
        TB6612_GPIO_Init();
        //TIM1挂载APB2为72MHz,故72000000/(359+1)/(1999+1) = 100Hz;
        /*故设置频率为100Hz,自动重装载值1999*/
    //TIM1_PWM_Init(1999, 359);
        TIM1_PWM_Init(120-1, 10-1);
    //    TIM1_PWM_Init(110, 100);
    }

     

  • bsp_AdvanceTim.h
    #ifndef __bsp_AdvanceTim_h
    #define __bsp_AdvanceTim_h
    #include "stm32f10x.h"
    
    //配置高级定时器1(Timer1)
    #define ADVANCE_TIM                                            TIM1
    #define ADVANCE_TIM_APBxClock_FUN                RCC_APB2PeriphClockCmd
    #define ADVANCE_TIM_CLK                                    RCC_APB2Periph_TIM1
    
    //PWM信号的频率F = TIM_CLK/{(ARR+1) * (PSC+1)}
    #define ADVANCE_TIM_PERIOD                            (8-1)
    #define ADVANCE_TIM_PSC                                    (9-1)
    #define ADVANCE_TIM_PULSE                                 4
    
    ////中断相关宏定义
    #define ADVANCE_TIM_IRQ                                    TIM1_CC_IRQn
    #define ADVANCE_TIM_IRQHandler                    TIM1_CC_IRQHandler
    
    ////TIM1输出比较通道
    #define ADVANCE_TIM_CH1_GPIO_CLK                RCC_APB2Periph_GPIOA
    #define ADVANCE_TIM_CH1_PORT                        GPIOA
    #define ADVANCE_TIM_CH1_PIN                            GPIO_Pin_8
    
    //TIM1输出比较通道的互补通道
    #define ADVANCE_TIM_CH1N_GPIO_CLK                    RCC_APB2Periph_GPIOB
    #define ADVANCE_TIM_CH1N_PORT                            GPIOB
    #define ADVANCE_TIM_CH1N_PIN                            GPIO_Pin_13
    
    //TIM1输出比较通道的刹车通道
    #define ADVANCE_TIM_BKIN_GPIO_CLK                    RCC_APB2Periph_GPIOB
    #define ADVANCE_TIM_BKIN_PORT                            GPIOB
    #define ADVANCE_TIM_BKIN_PIN                            GPIO_Pin_12
    
    
    //#define ADVANCE_TIM_IC1PWM_CHANNEL            TIM_Channel_1
    //#define ADVANCE_TIM_IC2PWM_CHANNEL            TIM_Channel_2
    
    
    #define AIN1            GPIO_Pin_13
    #define AIN2            GPIO_Pin12
    
    //void TIM1_PWM_Init(u16 arr, u16 psc);
    void ADVANCE_TIM_Init(void);
    
    //void ADVANCE_TIM_Init(void);
    #endif /*__bsp_AdvanceTim_h*/

     

  • 主函数main.c
    #include "stm32f10x.h"            //相当于51单片机中的     
    #include "bsp_AdvanceTim.h"
    
    int main()
    {
        while(1)
        {
            TIM_SetCompare1(TIM1, 30);//设置马达转速
        }
    }
        

     

原文地址:http://www.cnblogs.com/kevin-hou1991/p/16884619.html

1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长! 2. 分享目的仅供大家学习和交流,请务用于商业用途! 3. 如果你也有好源码或者教程,可以到用户中心发布,分享有积分奖励和额外收入! 4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解! 5. 如有链接无法下载、失效或广告,请联系管理员处理! 6. 本站资源售价只是赞助,收取费用仅维持本站的日常运营所需! 7. 如遇到加密压缩包,默认解压密码为"gltf",如遇到无法解压的请联系管理员! 8. 因为资源和程序源码均为可复制品,所以不支持任何理由的退款兑现,请斟酌后支付下载 声明:如果标题没有注明"已测试"或者"测试可用"等字样的资源源码均未经过站长测试.特别注意没有标注的源码不保证任何可用性