「STM32入门」TIM输出比较

Posted 正在黑化的KS

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「STM32入门」TIM输出比较相关的知识,希望对你有一定的参考价值。

输出比较的简介

  • 输出比较英文写作OC (Output Compare) 
  • 输出比较可以通过比较CNT和CCR寄存器值的关系,来对输出电平进行置高或者置低或者翻转的操作,用于输出一定频率和占空比的PWM波形
  • 常见应用例子如:呼吸灯,调速电机等
  • CCR(Capture/Compare Register的缩写,及捕获/比较寄存器) 

CNT与CCR之间的逻辑关系

  • CNT计数自增,CCR是我们给定的一个值

PWM简介 

  • Pulse Width Modulation 脉冲宽度调制
  • 在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要的模拟参量,常应用于电机控速领域
  • PWM的参数:
  • 频率 =  
  • 占空比 = 
  • 分辨率 = 占空比变化步距

如何理解上述所说的:PWM可用于等效获得模拟参量呢?

在我们通常点亮LED实验中,我们只能给LED置1或者置0,也就是亮或者灭。但是当我们以一个很高的频率点亮熄灭,点亮熄灭,点亮熄灭...的时候,LED就会呈现出中等亮度,具体的亮暗程度就取决于亮的时间的占空比。

同理:我们不断地给电机通电断电,通电断电,通电断电...就可以让电机的速度维持在一个中等速度。

定时器的输出比较模块输出PWM

根据上面这张图,我们关注输出模式控制器这一模块。它的输入端是CNT和CCR的大小关系,输出则是oc1ref的高低电平。

在输出模式控制器中有许多输出比较模式,一般来说最常用也是这里要介绍的是PWM模式

 其中具体选模式1还是模式2,向上计数还是向下计数都是可以在代码中进行配置的,这两个模式可以输出频率和占空比都可调的波形。


接下来重点介绍PWM基本结构(该图对应PWM模式1)

我们首先关注右上角的图,其中黄线代表ARR的值,蓝线代表CNT的值,红线代表CCR的值

CNT从0开始自增,一直增到ARR,也就是99,之后清0,再继续自增...一直循环下去

可以看到,我们设置CCR为30,当蓝线在红线下面时,输出高电平;当蓝线在红线上面时,输出低电平,对应PWM模式1的执行逻辑。

在这里我们发现:当我们将CCR的值设高,高电平的时间就延长,占空比升高。对应回我们的两个例子的现象就是,灯变得更亮,电机转的更快。

流程图中的REF指的就是一个频率可调,占空比也可调的PWM波形。最终再经过极性选择和输出使能,通向GPIO口。

参数计算 

PWM频率:Freq = CK_PSC / (PSC + 1) / (ARR + 1) 

PWM占空比:Duty = CCR / (ARR + 1) 

PWM分辨率:Reso = 1 / (ARR + 1) 

其中CK_PSC是系统频率72MHz,PSC是预分频系数

由于个人项目需要,这里补充简介一下直流电机及其驱动,权当笔记。 

直流电机及其驱动

电机(左)

驱动电路(右) 

  • 直流电机有两个电极,当电极正接时,电机正转;反接则反转。
  • 直流电机属于大功率器件,GPIO口无法直接驱动,需要配合驱动电路来操作
  • 查表控制电机正转或反转

stm32-TIM之基本定时器

TIM:

  STM32F1 系列中,除了互联型的产品,共有8 个定时器,分为基本定时器,通用定时器和高级定时器。基本定时器TIM6 TIM7 是一个16 位的只能向上计数的定时器,只能定时,没有外部IO。通用定时器TIM2/3/4/5 是一个16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,每个定时器有四个外部IO。高级定时器TIM1/8是一个16 位的可以向上/下计数的定时器,可以定时,可以输出比较,可以输入捕捉,还可以有三相电机互补输出信号,每个定时器有8个外部IO

 

TIM分类:

 技术分享图片

 

 

基本定时器框图:

 技术分享图片

 

 

1.  时钟源

    定时器时钟TIMxCLK,即内部时钟CK_INT,经APB1 预分频器后分频提供,如果APB1预分频系数等于1,则频率不变,否则频率乘以2,库函数中APB1  预分频的系数是2,即PCLK1=36M,所以定时器时钟TIMxCLK=36*2=72M

2.  计数器时钟

    定时器时钟经过PSC 预分频器之后,即CK_CNT,用来驱动计数器计数。PSC 是一个16 位的预分频器,可以对定时器时钟TIMxCLK 进行1~65536 之间的任何一个数进行分频。 具体计算方式为:CK_CNT=TIMxCLK/(PSC+1)

3.  计数器

    计数器CNT 是一个16 位的计数器,只能往上计数,最大计数值为65535。当计数达到自动重装载寄存器的时候产生更新事件,并清零从头开始计数。

4.  自动重装载寄存器

自动重装载寄存器ARR 是一个16 位的寄存器,这里面装着计数器能计数的最大数值。当计数到这个值的时候,如果使能了中断的话,定时器就产生溢出中断。

5.  定时时间的计算

定时器的定时时间等于计数器的中断周期乘以中断的次数。计数器在CK_CNT 的驱动下,计一个数的时间则是CK_CLK  的倒数,等于:1/TIMxCLK/(PSC+1) ),产生一次中断的时间则等于:1/ CK_CLK * ARR)。如果在中断服务程序里面设置一个变量time,用来记录中断的次数,那么就可以计算出我们需要的定时时间等于:1/CK_CLK                                   * (ARR+1)*time

 bsp_timbase.h文件:

#ifndef __BSP_TIMEBASE_H
#define __BSP_TIMEBASE_H


#include "stm32f10x.h"

#define BASIC_TIM6 // 使用TIM7时,注释掉该行即可 

#ifdef  BASIC_TIM6 
#define            BASIC_TIM                   TIM6
#define            BASIC_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            BASIC_TIM_CLK               RCC_APB1Periph_TIM6
//定时周期(从0开始计数) ,得出一次中断的事件为1000/1M=1ms,
#define            BASIC_TIM_Period            1000-1    
//预分频,72MHz/(71+1)= 1MHz,(0时,为1分频)   
#define            BASIC_TIM_Prescaler         71         
#define            BASIC_TIM_IRQ               TIM6_IRQn
#define            BASIC_TIM_IRQHandler        TIM6_IRQHandler

#else 
#define            BASIC_TIM                   TIM7
#define            BASIC_TIM_APBxClock_FUN     RCC_APB1PeriphClockCmd
#define            BASIC_TIM_CLK               RCC_APB1Periph_TIM7
#define            BASIC_TIM_Period            1000-1
#define            BASIC_TIM_Prescaler         71
#define            BASIC_TIM_IRQ               TIM7_IRQn
#define            BASIC_TIM_IRQHandler        TIM7_IRQHandler

#endif
/**************************oˉêyéù?÷********************************/

void BASIC_TIM_Init(void);


#endif

bsp_timbase.c文件:

#include "bsp_timbase.h" 
static void BASIC_TIM_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure; 
    NVIC_PriorityGroupConfig(NVIC_PriorityGroup_0);        
    NVIC_InitStructure.NVIC_IRQChannel = BASIC_TIM_IRQ ;    
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;     
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3;    
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

static void BASIC_TIM_Mode_Config(void)
{
    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
    BASIC_TIM_APBxClock_FUN(BASIC_TIM_CLK, ENABLE);
    TIM_TimeBaseStructure.TIM_Period = BASIC_TIM_Period;    
    TIM_TimeBaseStructure.TIM_Prescaler= BASIC_TIM_Prescaler;
    
    //TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;

    //TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; 

    //TIM_TimeBaseStructure.TIM_RepetitionCounter=0;
    

    TIM_TimeBaseInit(BASIC_TIM, &TIM_TimeBaseStructure);
    //?????????ж???λ 
    TIM_ClearFlag(BASIC_TIM, TIM_FLAG_Update);
    TIM_ITConfig(BASIC_TIM,TIM_IT_Update,ENABLE);
    TIM_Cmd(BASIC_TIM, ENABLE);    
}

void BASIC_TIM_Init(void)
{
    BASIC_TIM_NVIC_Config();
    BASIC_TIM_Mode_Config();
}

中断处理函数:

void SysTick_Handler(void)
{
}
void  BASIC_TIM_IRQHandler (void)
{
    if ( TIM_GetITStatus( BASIC_TIM, TIM_IT_Update) != RESET ) 
    {    
        time++;
        TIM_ClearITPendingBit(BASIC_TIM , TIM_FLAG_Update);           
    }             
}

main.c文件:

#include"stm32f10x.h"
#include"bsp_led.h"
#include"bsp_timbase.h" 
volatile uint32_t time = 0; 

int main(void)
{

    LED_GPIO_Config();
    BASIC_TIM_Init();
  while(1)
  {
    if ( time == 1000 ) //1000 * 1 ms = 1s 
    {
          time = 0;    
        red_TOGGLE; 
    }        
  }
}

 

以上是关于「STM32入门」TIM输出比较的主要内容,如果未能解决你的问题,请参考以下文章

怎么解决用stm32 发射2m方波,求大神!!!!!

stm32输出pwm,怎么控制直流电机的正反转?

STM32单片机使用定时器中断产生1khz的方波

STM32基本定时器

求一stm32产生spwm波的程序

STM32使用TIM闪烁LED——输出比较方式