定时器

73 阅读6分钟

第一章 系统定时器

1.1

系统定时器(SysTick系统),属于CM3内核,内嵌在NVIC(中断处理器)中。 系统定时器是一个24bit的向下递减的计数器,计数器每计数一次时间为1/SYSCLK,一般设为72M。

image.png为72MHz。后面根据情况走不同分支。

当重装载数值寄存器值递减到0时,系统定时器就产生一次中断,以此往复。

1.2 对系统定时器进行配置 (延迟方式)

image.png 目录4.5image.png


image.png 此值等同于

image.png


而load等同于

image.png

我们的值在

image.png发生变化,计数完成一次后,重新放回


image.png

image.png

该寄存器中,COUNTFLAG为:如果自上次读取以来计时器计数为0,则返回1。

image.png 倒计时结束时返回1,就结束此语句


image.png

image.png

1.3 系统滴答定时器中断功能实现LED灯闪烁(1s)

image.png |=:赋1操作 image.png

重复触发:每100个时钟周期触发一次中断,就设置reload为99; 单一触发:若400个时钟周期后触发中断,则设置reload为400。

所以

image.png


image.png

image.png

image.png

第二章 基本定时器

image.png和TIM8.

STM32F1数据手册中 image.png

image.png image.png

image.png

image.png

image.png

image.png 二分频导致内部时钟发两个脉冲,定时器时钟只发一次脉冲。

两种情况

image.png 当real=50时,此时要将real改为100,此100需先存到buffer中,此时30->50之后从0->100;real已经改为了100,从30->100之后从0->100.

image.png

image.png

2.1 TIM6和TIM7寄存器

image.png

image.png ARPE:影子寄存器能否直接使用。可直接设置使用0,没有缓冲。

OPM:无需管理。因为脉冲非单脉冲,源源不断过来

URS:产生更新事件时,来源是什么即发出的什么请求使事件更新

UDIS:禁止更新。我们要更新

CEN:计数器使能。设为1.

image.png

主模式:定时器控制其他定时器时采用,此处用不上

image.png

UIE:此处只使用UIE,设为1,使能 image.png

UIF:硬件在更新中断时会设置该位,自动从0变成1.需要代码清除。代码设为0

image.png 此为事件产生,我们用中断,与事件关系不大

image.png 该寄存器里的值自动放入,无需看

image.png

PSC:有加一过程。赋值时需要减一

image.png

2.2 软件实现定时器控制LED灯闪烁

2.2.1 定时器基本配置

image.png

image.png

2.2.2 逻辑实现

image.png

image.png

2.3 HAL库

2.3.1 单灯闪烁HAL库滴答定时器

image.png

image.png

image.png

image.png 创建项目即可

image.png 重新点击项目创建 HAL库中有SysTick中断服务函数

image.png uwTickFreq使每1ms+1

image.png 在不清零情况下,每500次触发一次

2.3.2 定时器6触发单灯闪烁

image.png

image.png

image.png

image.png

stm32f1xx_it.c中 image.png

image.png 已经包含复位,只需写自己逻辑即可

image.png 周期结束中断回调函数 ctrl+f搜一下

image.png 此时烧录下载后灯不闪烁。 因为HAL库中定时器未启动

image.png 此时有现象了

双灯闪烁 但交替闪烁并不同时闪烁

image.png

第三章 通用定时器

3.1 通用定时器介绍

image.png

image.png

三种可选的时钟源

image.png

image.png

image.png 上半部分专门计时,下半部分与其他功能融合起来。称不同引脚为不同的通道

image.png

image.png

image.png

image.png

image.png

image.png

image.png

3.2 PWM

占空比:高电平在一个周期上所占比例

image.png

image.png

信号来源路径

image.png image.png

image.png

image.png

image.png

3.2.1 输出比较部分

image.png

image.png

image.png

image.png

image.png

计数器从0-59共60个数为低电平,从60-99共40个数为高电平。占空比为40%

image.png

image.png

image.png

image.png

image.png

image.png

3.2.2 TIMx寄存器描述

image.png image.png

image.png

image.png

image.png

image.png

3.3 软件实现

3.3.1 呼吸灯

image.png image.png

#include "Delay.h"
/****
 * 
 * 通用定时器 - 输出PWM方波信号,让LED灯闪烁
 * 
 ****/
int main(void)
{
    TIM5_Init();
    TIM5_Start();

    uint8_t dutyCycle =50;
    uint8_t dir = 0;

    while (1)
    {
        if(dir == 0)
        {
            dutyCycle++;
            if(dutyCycle>99)
            {
                dir = 1;
            }
        }
        else
        {
            dutyCycle--;
            if(dutyCycle<1)
            {
                dir = 0;
            }

        }
        //dutyCycle++;
        TIM5_SetDutyCycle(dutyCycle);
        Delay_ms(20); 
    }
    
}

3.3.2 呼吸屏幕

```#include "TIM3.h"
#include "Delay.h"
/****
 * 
 * 通用定时器 - 输出PWM方波信号,让LED灯闪烁
 * 
 ****/
int main(void)
{
    TIM3_Init();
    TIM3_Start();
    uint8_t dutyCycle =50;
    uint8_t dir = 0;

    while (1)
    {
        if(dir == 0)
        {
            dutyCycle++;
            if(dutyCycle>99)
            {
                dir = 1;
            }
        }
        else
        {
            dutyCycle--;
            if(dutyCycle<1)
            {
                dir = 0;
            }

        }
        //dutyCycle++;
        TIM3_SetDutyCycle(dutyCycle);
        Delay_ms(20); 
    }
    
}

//main函数中
#include "TIM3.h"

void TIM3_Init(void)
{
    RCC->APB2ENR |=RCC_APB2ENR_IOPBEN;
    RCC->APB1ENR |=RCC_APB1ENR_TIM3EN;
    //PB0
    GPIOB->CRL |=GPIO_CRL_MODE0;
    GPIOB->CRL |=GPIO_CRL_CNF0_1;
    GPIOB->CRL &=~GPIO_CRL_CNF0_0;

    TIM3->PSC=7199;
    TIM3->ARR=99;
    TIM3->CR1 &=~TIM_CR1_DIR;

    //输出(00):PWM(110)
    TIM3->CCMR2 &=~TIM_CCMR2_CC3S;
    TIM3->CCMR2 |=TIM_CCMR2_OC3M_2;
    TIM3->CCMR2 |=TIM_CCMR2_OC3M_1;
    TIM3->CCMR2 &=~TIM_CCMR2_OC3M_0;

    TIM3->CCR3=50;

    TIM3->CCER &=~TIM_CCER_CC3P;//高电平有效
    TIM3->CCER |=TIM_CCER_CC3E;//使能输出
}

void TIM3_Start(void)
{
    TIM3->CR1 |=TIM_CR1_CEN;//使能计数器
}

void TIM3_End(void)
{
    TIM3->CR1 &=~TIM_CR1_CEN;//禁止计数器
}

void TIM3_SetDutyCycle(uint8_t dutyCycle)
{
    TIM3->CCR3 = dutyCycle;
}



```js

3.3.3 交叉呼吸灯

即定时器开启两个灯,改变其中一个灯电平

TIM5.c中

```#include "TIM5.h"

void TIM5_Init(void)
{
    //1.开启时钟
    RCC->APB2ENR |=RCC_APB2ENR_IOPAEN;
    RCC->APB1ENR |=RCC_APB1ENR_TIM5EN;
    //2.配置引脚
    // PA0:MODE[11],CNF[10]
    GPIOA->CRL |= GPIO_CRL_MODE0;
    GPIOA->CRL |= GPIO_CRL_CNF0_1;
    GPIOA->CRL &= ~GPIO_CRL_CNF0_0;
    // PA1:MODE[11],CNF[10]
    GPIOA->CRL |= GPIO_CRL_MODE1;
    GPIOA->CRL |= GPIO_CRL_CNF1_1;
    GPIOA->CRL &= ~GPIO_CRL_CNF1_0;
    
    //3.配置定时器(PWM)
    //  100Hz
    TIM5->PSC = 7199 ;//7200
    TIM5->ARR = 99 ;

    TIM5->CR1 &= ~TIM_CR1_DIR;//DIR清零默认向上计数

    //4.配置通道
    //4.1 配置工作模式
    TIM5->CCMR1 &= ~TIM_CCMR1_CC2S;
    TIM5->CCMR1 |= TIM_CCMR1_OC2M_2;
    TIM5->CCMR1 |= TIM_CCMR1_OC2M_1;
    TIM5->CCMR1 &= ~TIM_CCMR1_OC2M_0;

    TIM5->CCMR1 &= ~TIM_CCMR1_CC1S;
    TIM5->CCMR1 |= TIM_CCMR1_OC1M_2;
    TIM5->CCMR1 |= TIM_CCMR1_OC1M_1;
    TIM5->CCMR1 &= ~TIM_CCMR1_OC1M_0;
    //4.2 配置比较寄存器
    TIM5->CCR1 = 50 ; //改变该值使占空比随时间改变,0-49为高电平,50-99为低电平
    TIM5->CCR2 = 50 ; //改变该值使占空比随时间改变,0-49为高电平,50-99为低电平

    //4.3 配置输出的有效电平(极性)
    TIM5->CCER &=~TIM_CCER_CC2P;//CC2P清零,输出高电平有效
    TIM5->CCER |= TIM_CCER_CC2E;//输入/捕获1使能

    TIM5->CCER |= TIM_CCER_CC1P;//CC1P赋1,输出低电平有效
    TIM5->CCER |= TIM_CCER_CC1E;//输入/捕获1使能
    //(9900:1)(100:0)

}

void TIM5_Start(void)
{
    TIM5->CR1 |= TIM_CR1_CEN;//开始计数
}

void TIM5_End(void)
{
    TIM5->CR1 &= ~TIM_CR1_CEN;//禁止计数
}
void TIM5_SetCH1_DutyCycle(uint8_t dutyCycle)
{
    TIM5->CCR1 = dutyCycle;
}
void TIM5_SetCH2_DutyCycle(uint8_t dutyCycle)
{
    TIM5->CCR2 = dutyCycle;
}


```js

main.c中

```#include "TIM5.h"
#include "Delay.h"
/****
 * 
 * 通用定时器 - 交叉呼吸灯
 * 
 ****/
int main(void)
{
    TIM5_Init();
    TIM5_Start();

    uint8_t dutyCycle = 50;
    uint8_t dir = 0;

    while (1)
    {
        if(dir == 0)
        {
            dutyCycle++;
            if(dutyCycle>99)
            {
                dir = 1;
            }
        }
        else
        {
            dutyCycle--;
            if(dutyCycle<1)
            {
                dir = 0;
            }

        }
        //dutyCycle++;
        TIM5_SetCH1_DutyCycle(dutyCycle);
        TIM5_SetCH2_DutyCycle(dutyCycle);
        Delay_ms(20); 
    }
    
}
```js

3.3.4 HAL库实现呼吸灯

image.png 依然配置

image.png image.png

image.png image.png image.png