第一章 系统定时器
1.1
系统定时器(SysTick系统),属于CM3内核,内嵌在NVIC(中断处理器)中。 系统定时器是一个24bit的向下递减的计数器,计数器每计数一次时间为1/SYSCLK,一般设为72M。
为72MHz。后面根据情况走不同分支。
当重装载数值寄存器值递减到0时,系统定时器就产生一次中断,以此往复。
1.2 对系统定时器进行配置 (延迟方式)
目录4.5
此值等同于
而load等同于
我们的值在
发生变化,计数完成一次后,重新放回
该寄存器中,COUNTFLAG为:如果自上次读取以来计时器计数为0,则返回1。
倒计时结束时返回1,就结束此语句
1.3 系统滴答定时器中断功能实现LED灯闪烁(1s)
|=:赋1操作
重复触发:每100个时钟周期触发一次中断,就设置reload为99; 单一触发:若400个时钟周期后触发中断,则设置reload为400。
所以
第二章 基本定时器
和TIM8.
STM32F1数据手册中
二分频导致内部时钟发两个脉冲,定时器时钟只发一次脉冲。
两种情况
当real=50时,此时要将real改为100,此100需先存到buffer中,此时30->50之后从0->100;real已经改为了100,从30->100之后从0->100.
2.1 TIM6和TIM7寄存器
ARPE:影子寄存器能否直接使用。可直接设置使用0,没有缓冲。
OPM:无需管理。因为脉冲非单脉冲,源源不断过来
URS:产生更新事件时,来源是什么即发出的什么请求使事件更新
UDIS:禁止更新。我们要更新
CEN:计数器使能。设为1.
主模式:定时器控制其他定时器时采用,此处用不上
UIE:此处只使用UIE,设为1,使能
UIF:硬件在更新中断时会设置该位,自动从0变成1.需要代码清除。代码设为0
此为事件产生,我们用中断,与事件关系不大
该寄存器里的值自动放入,无需看
PSC:有加一过程。赋值时需要减一
2.2 软件实现定时器控制LED灯闪烁
2.2.1 定时器基本配置
2.2.2 逻辑实现
2.3 HAL库
2.3.1 单灯闪烁HAL库滴答定时器
创建项目即可
重新点击项目创建
HAL库中有SysTick中断服务函数
uwTickFreq使每1ms+1
在不清零情况下,每500次触发一次
2.3.2 定时器6触发单灯闪烁
stm32f1xx_it.c中
已经包含复位,只需写自己逻辑即可
周期结束中断回调函数
ctrl+f搜一下
此时烧录下载后灯不闪烁。
因为HAL库中定时器未启动
此时有现象了
双灯闪烁 但交替闪烁并不同时闪烁
第三章 通用定时器
3.1 通用定时器介绍
三种可选的时钟源
上半部分专门计时,下半部分与其他功能融合起来。称不同引脚为不同的通道
3.2 PWM
占空比:高电平在一个周期上所占比例
信号来源路径
3.2.1 输出比较部分
计数器从0-59共60个数为低电平,从60-99共40个数为高电平。占空比为40%
3.2.2 TIMx寄存器描述
3.3 软件实现
3.3.1 呼吸灯
#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库实现呼吸灯
依然配置