深入浅出地理解STM32中的定时器工作原理

  • 一、如何实现延时
    • 1 纯硬件电路
    • 2 纯软件编程
    • 3 可编程定时/计数器
  • 二、可编程定时/计数器有哪些功能?
  • 三、STM32F103 的定时器有哪些
    • 1 基本定时器 TIM6 和 TIM7
      • 1.1 概述
      • 1.2 内部结构
        • (1)定时器时钟源
        • (2)计数器时钟
        • (3)计数器
        • (4)自动重装载计数器
      • 1.3 工作过程
      • 1.4 库函数文件
      • 1.5
    • 2 通用定时器 TIM2 ~ TIM5
      • 2.0 总体结构
      • 2.1 时钟源选择模块
        • (1)内部时钟源
        • (2)外部时钟模式 1
          • ① 时钟信号输入引脚
          • ② 滤波器
          • ③ 边沿检测
          • ④ 触发选择
          • ⑤ 从模式选择
        • (3)外部时钟模式 2
          • ①:时钟信号输入引脚
          • ②:外部触发极性
          • ③:外部触发预分频器
          • ④:滤波器
          • ⑤:从模式选择
          • ⑥:使能计数器
        • (4)内部触发输入(ITRx)
      • 2.1 计数方式
        • (1)向上计数
        • (2)向下计数
        • (3)双向计数
    • 4 定时中断的实现
      • 4.1 工作流程
        • (1)第 1 步
        • (2)第 2 步
        • (3)第 3 步
        • (4)第 4 步
        • (5)第 5 步
        • (6)第 6 步
      • 4.2 实验准备
      • 4.3 keil中实现
      • 4.3 实验效果
    • 5 定时中断-外部时钟源
    • 6 PWM 实现呼吸灯
      • 6.1 什么是 PWM
        • (1)高级定时器的输出比较电路

一、如何实现延时

  延时在嵌入式应用中是常用操作,嵌入式应用中的延时通常可以用以下3种方式实现:

1 纯硬件电路

  在早期仪器仪表中,经常使用模拟或数字电路来实现定时/计数功能。 例如,模拟电
路中555集成芯片,辅以少量的电阻和电容,即可实现一个定时器。

  由千硬件电路结构固定,由其产生的延时时间无法改变

  因此,使用纯硬件电路实现的延时主要应用于无微控制器的简单应用系统或是有特殊要求的应用系统中。

  目前,嵌入式系统中使用纯硬件方式来实现延时已经越来越少了。

2 纯软件编程

  微控制器基于一定的时钟条件运行,因此,可以根据代码执行所需的时钟周期来完成延时操作。

  通常,在基千微控制器的嵌入式系统中,对千短时延时,可以通过执行一定数量的空指令来实现,空指令每执行一次需要一个周期;对于长时延时,可以通过循环结构来实现。

  例如,可以使用循环语句for (nCount = 0xFFFFFF; nCount != 0; nCount--)实现LED点亮和熄灭时间的延迟。

  延时的纯软件方式实现起来非常简单,但 具有以下缺点:
(1) 对于不同的微控制器, 每条指令的执行时间不同,很难做到精确延时。
 例如,在上面讲到的LED闪烁应用案例 中,如果要使LED点亮和熄灭的时间精确到各为500ms,
对应软件实现的循环语句中决定延时时间的变量 nCount 的具体取值很难由计算准确得出。

(2) 延时过程中 CPU 始终被占用, CPU利用率不高
  虽然纯软件定时/计数方式有以上缺点,但由千其简单方便、易于实现等优点,在当今的嵌入式应用中,尤其在短延时和不 精确延时中,被频繁地使用。 例如,高速ADC的转换时间可能只需要几个时钟周期,这种情况下,使用软件延时反而效率更高。

3 可编程定时/计数器

  当前的微控制器往往内置一个或多个定时/计数器,以代替CPU 计数,克服纯硬件和纯软件方式的缺点,并结合它们各自的优点实现延时。

  并且,这些定时/计数器都是用户可编程的, 其时钟源、预分频系数、工作模式和启动/停止等参数均可由软件配置。

  由此可见, 微控制器内置的定时/计数器具有通用性强、用户可编程、可重复利用、不占用CPU、成本低等特点,是目前使用最多的一种定时/计数的实现方式。

二、可编程定时/计数器有哪些功能?

  可编程定时/计数器(简称定时器)是当代微控制器标配的片上外设和功能模块。

  它不仅可以实现延时,而且还完成其他功能:
(1) 如果时钟源来自内部系统时钟,那么可编程定时/计数器可以实现精确的定时。此时的定时器工作于普通模式、比较输出或PWM输出模式,通常用千延时 、输出指定波形、驱动电机等应用中。

(2) 如果时钟源来自外部输入信号,那么可编程定时/计数器可以完成对外部信号的计数。 此时的定时器工作于输入捕获模式,通常用千测戴输入信号的频率和占空比、测量外部事件的发生次数和时间间隔等应用中。

在嵌入式系统应用中,使用定时器可以完成以下功能:
(3) 在多任务的分时系统中用作中断来实现任务的切换。
(4) 周期性执行某个任务,如每隔固定时间完成一次AD采集。
(5) 延时一定时间执行某个任务,如交通灯信号变化。
(6) 显示实时时间,如万年历。
(7) 产生不同频率的波形,如MP3播放器。
(8) 产生不同脉宽的波形,如驱动伺服电机。
(9) 测拭脉冲的个数,如测县转速。
(10) 测量脉冲的宽度,如测最频率。

三、STM32F103 的定时器有哪些

1 基本定时器 TIM6 和 TIM7

1.1 概述

  STM32Fl03 基本定时器 TIM6 和 TIM7 只具备最基本的定时功能,即累计时钟脉冲数超过预定值时,产生定时器溢出事件。 如果使能了中断或者 DAC 操作,则将产生中断或者 DAC 操作。

  TIM6 和 TIM7 还可以作为通用定时器提供时间基准。 特别地,它们可以为数模转换器 DAC 提供时钟。 实际上,在 STM32Fl03 微控制器内部 TIM6 和 TIM7 直接连接到 DAC 并通过触发输出直接驱动 DAC。

  DAC也是一种片内外设功能电路,其功能就是将数字信号转换为模拟信号,以输出特定的波形。

  正常来说,我们如果要用DAC输出特定的波形,那么就要每隔一段时间就触发DAC,让其输出下一个电压点。这样的话,可以设置一个定时器,每隔一段时间,触发中断,启动中断程序,程序中触发DAC转换,然后DAC输出。

  这样做,可以,但是,主程序处于被频繁中断的状态,这会影响主程序的运行,以及其他中断的响应。

  在参考手册中,对于该功能的描述如下:

   原话是:they are also specifically used to drive the digital-to-analog converter (DAC). In fact, the timers are internally connected to the DAC and are also able to drive it through their trigger outputs (触发输出)。

   它们还专门用于驱动数模转换器(DAC)。事实上,定时器内部连接到DAC,也能够通过其 触发输出 驱动DAC。

再看下面这个图:

   这里定时器产生的更新事件,可以映射到TRGO的位置,TRGO就是 trigger outputs (触发输出)。TRGO直接接到DAC的触发转换引脚上。

1.2 内部结构

  STM32Fl03基本定时器 TIM6 和 TIM7 的内部结构较为简单,由触发控制器、一个16位预分频器、一个带自动重装载寄存器的16位计数器等构成。其中,由可编程的16位预分频器驱动的具有自动重装载功能的16位计数器TIMx_CNT是STM32Fl03基本定时器的核心。

基本定时器,基本由四部分组成:

(1)定时器时钟源

  下面画圈 的部分,就是 定时器时钟源在时钟树上的位置。

  从STM32Fl03基本定时器TIM6和TIM7的内部结构可以看出,基本定时器TIM6 和 TIM7只有一种时钟源一一内部时钟CK_INT。对于STM32Fl03 所有的定时器 ,内部时钟CK_INT都来自 RCC(Reset and Clock Control,复位和时钟控制)的TIMxCLK。

  TIMxCLK根据APBl的预分频系数分为两种情况:
(1)若APBl预分频系数等于1,TIMxCLK等于APBl时钟频率PCLK1
(2)若 APBl 预分频系数不等千1,TIMxCLK 等千 APBl 时钟频率PCLK1X2。

  通常情况下,STM32Fl03 上电复位后,APB1 的预分频系数为 2, APB1 时钟频率PCLKl 为 36MHz。

  因此 如上所述,基本定时器 TIM6 和 TIM7 的时钟 TIMxCLK,是APBl 时钟频率PCLKl 的 2 倍,即 72MHz

(2)计数器时钟


  小知识点: 什么是预分频器?

  A prescaler is an electronic counting circuit used to reduce a high frequency electrical signal to a lower frequency by integer division.

  预分频器是一种电子计数电路,用于通过整数除法将高频电信号降低到较低频率。

(3)计数器


  所谓向上计数,就是从0开始,不断增大。计数器CNT是16位 的寄存器,那么计数的范围就是0000H到FFFFH0000H 到 FFFFH0000HFFFFHFFFFH=15×163+15×162+15×16+15=61440+3840+240+15=61440+4080+15=61440+4095=65535FFFFH=15 \times16^{3}+15 \times16^{2}+15 \times16+15=61440+3840+240+15=61440+4080+15=61440+4095=65535FFFFH=15×163+15×162+15×16+15=61440+3840+240+15=61440+4080+15=61440+4095=65535,所以CNT的最大计数值是655356553565535

(4)自动重装载计数器

1.3 工作过程

  STM32F103 基本定时器中的 16位计数器 TIMx_CNT 只能工作在向上计数模式,自动重装载寄存器中保存的是定时器的溢出值。

  基本定时器工作时,脉冲计数器 TIMx_CNT 从 0 开 始,在时钟 CK_CNT触发下不断累加计数。

  当脉冲计数器 TIMx_CNT的计数值等千自动重装载寄存器 TIMx_ARR ( Auto Reload Register) 中保存的预设值时, 产生溢出事件,可以触发中断或 DAC请求。 然后,脉冲计数器TIMx_CNT的计数值被清零,重新开始向上计数。

延时时间=(ARR+1)×(PSC+1)/TIMxCLK延时时间=(ARR+1)\times(PSC+1)/TIMxCLK延时时间=(ARR+1)×(PSC+1)/TIMxCLK

1.4 库函数文件

在定时器头文件 tim.h中,声明了四个定时器初始化的函数,基本定时器只用其中的一个,

void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);

tim.c文件,找到函数

  这个函数要传入两个参数变量,一个是指定是哪个定时器,第二个是结构体变量TIM_TimeBaseInitStruct,是用TIM_TimeBaseInitTypeDef结构体定义的,TIM_TimeBaseInitTypeDef的定义如下(在 tim.h中):

typedef struct
{uint16_t TIM_Prescaler;   // 设置 预分频器的值,可以是0000H到FFFFHuint16_t TIM_CounterMode; // 设置 计数方式,基本定时器只能是向上计数方式uint16_t TIM_Period;      // 定时器周期,其实就是自动重载寄存器的值,可以是0~65535uint16_t TIM_ClockDivision;  // 时钟分频,基本定时器没有这个功能,不用设置uint8_t TIM_RepetitionCounter;  // 重复计数器,基本定时器没有这个功能,不用设置
} TIM_TimeBaseInitTypeDef;

1.5

2 通用定时器 TIM2 ~ TIM5

2.0 总体结构

  通用定时器的结构如下所示:


下面按模块分别讲解:

2.1 时钟源选择模块

(1)内部时钟源

  红色框内的是内部时钟源,内部时钟 CK_INT 即来自于芯片内部,等于 72M,一般情况下,我们都是使用内部时钟。

  当从模式控制寄存器 TIMx_SMCR 的 SMS 位等于 000 时,则使用内部时钟。

(2)外部时钟模式 1


  除了内部时钟,还可以选择外部时钟,一个外部时钟,就是来自TIMx_ETR引脚上的时钟,TIMx_ETR引脚的位置,可以通过引脚定义表查看


① 时钟信号输入引脚

  当使用外部时钟模式 1 的时候,时钟信号来自于定时器的输入通道,总共有 4 个,分别为 TI1/2/3/4,即 TIMx_CH1/2/3/4

  具体使用哪一路信号,由 TIM_CCMRx 的位CCxS[1:0]配置,其中 CCMR1 控制 TI1/2,CCMR2 控制 TI3/4。

② 滤波器

  如果来自外部的时钟信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对信号重新采样,来达到降频或者去除高频干扰的目的,具体的由 TIMx_CCMRx的位 ICxF[3:0]配置。

③ 边沿检测

  边沿检测的信号来自于滤波器的输出,在成为触发信号之前,需要进行边沿检测,决定是上升沿有效还是下降沿有效,具体的由 TIMx_CCER 的位 CCxP 和 CCxNP 配置。

④ 触发选择

  当使用外部时钟模式 1 时,触发源有两个,一个是滤波后的定时器输入 1(TI1FP1)和滤波后的定时器输入 2(TI2FP2),具体的由 TIMxSMCR 的位 TS[2:0]配置。

⑤ 从模式选择

  选定了触发源信号后,最后我们需把信号连接到 TRGI 引脚,让触发信号成为外部时钟模式 1 的输入,最终等于 CK_PSC,然后驱动计数器 CNT 计数。具体的配置TIMx_SMCR 的位 SMS[2:0]为 000 即可选择外部时钟模式 1。

(3)外部时钟模式 2

①:时钟信号输入引脚

  当使用外部时钟模式 2 的时候,时钟信号来自于定时器的特定输入通道 TIMx_ETR,只有 1 个。

②:外部触发极性

   来自 ETR 引脚输入的信号可以选择为上升沿或者下降沿有效,具体的由 TIMx_SMCR 的位 ETP 配置。

③:外部触发预分频器

  由于 ETRP 的信号的频率不能超过 TIMx_CLK(72M)的 1/4,当触发信号的频率很高的情况下,就必须使用分频器来降频,具体的由 TIMx_SMCR 的位 ETPS[1:0]配置。

④:滤波器

  如果 ETRP 的信号的频率过高或者混杂有高频干扰信号的话,我们就需要使用滤波器对 ETRP 信号重新采样,来达到降频或者去除高频干扰的目的。具体的由 TIMx_SMCR 的 位 ETF[3:0]配置,其中的 fDTS是由内部时钟 CK_INT 分频得到,具体的由 TIMx_CR1 的位CKD[1:0]配置。

⑤:从模式选择

  经过滤波器滤波的信号连接到 ETRF 引脚后,触发信号成为外部时钟模式 2 的输入,最终等于 CK_PSC,然后驱动计数器 CNT 计数。具体的配置 TIMx_SMCR 的位 ECE 为 1即可选择外部时钟模式 2。

⑥:使能计数器

  经过上面的 5 个步骤之后,最后我们只需使能计数器开始计数,外部时钟模式 2 的配置就算完成。使能计数器由 TIMx_CR1 的位 CEN 配置。

(4)内部触发输入(ITRx)

2.1 计数方式

  首先,通用定时器,计数器的计数方式被扩展成了三种方式:向上计数、向下计数、双向计数。具体区别,截图如下:

(1)向上计数


(2)向下计数

(3)双向计数

4 定时中断的实现

4.1 工作流程

(1)第 1 步

  RCC开启时钟,这样,定时器的基准时钟和整个外设的工作时钟就同时打开了。

(2)第 2 步

  选择时基单元的时钟源,对于定时中断,这里我就选择内部时钟源。

(3)第 3 步

  配置时基单元,包括预分频器、自动重装载寄存器、计数器的计数方式。

(4)第 4 步

  配置输出中断控制,允许更新中断输出到 NVIC。

(5)第 5 步

  配置 NVIC,在NVIC中打开定时器中断的通道,并分配一个优先级。

(6)第 6 步

  运行控制
  整个模块配置完成后,还需要使能一下计数器
  使能之后,计数器就开始计数了,当计数器更新时,触发中断,执行中断函数。

4.2 实验准备

4.3 keil中实现

  在keil中,对于建立 定时器设置的 C 文件 和 h 文件:

/********************* Timer.c ********************/
#include "stm32f10x.h"                  // Device headerextern uint16_t Num;void Timer_Init(void)
{/* 第一步:打开定时器时钟 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);/* 第二步:选择时基单元的时钟 */TIM_InternalClockConfig(TIM2); // 这里选择的是内部时钟// 这样,TIM2的时基单元就// 是由内部时钟来驱动了// 实际上,定时器上电后,// 默认的就是用内部时钟驱动时基单元/* 第三步:配置时基单元 */TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1; // TIM_ClockDivision用于指定时钟分频,这里TIM_CKD_DIV1 代表1分频,也就是不分频TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up; //  TIM_CounterMode用于设置计数方式,TIM_CounterMode_Up代表向上计数TIM_TimeBaseInitStructure.TIM_Period = 10000 - 1;     // 这里设置的是ARR的值,也就是自动重装载寄存器(Auot-reload register)的值,可以是 0~65535TIM_TimeBaseInitStructure.TIM_Prescaler = 7200 - 1; // 这里是预分频器的值,可以是0~65535TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0; // 设置重复计数器的值,高级定时器时会用到,这里不用,设置为0即可TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);/* 第四步:使能更新中断 */TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);/* 第五步:配置NVIC */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/* 第六步:启动定时器 */TIM_Cmd(TIM2, ENABLE);/** 写到这里,定时中断的初始化工作就已经完成了 **/
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}
/********************* Timer.h ********************/
#ifndef __TIMER_H
#define __TIMER_Hvoid Timer_Init(void);
void TIM2_IRQHandler(void);#endif

  再看一下下面关于延时时间计算公式:
  延时时间=(ARR+1)×(PSC+1)/TIMxCLK延时时间=(ARR+1)\times(PSC+1)/TIMxCLK延时时间=(ARR+1)×(PSC+1)/TIMxCLK

  TIMxCLK一般就是72MHZ72 MHZ72MHZ,也就是72×106HZ72\times10^{6}HZ72×106HZ,这里我们向延时1秒种,那么凑数就可以了,ARRARRARR可以是10000−110000 - 1100001PrescalerPrescalerPrescaler设置为 7200−17200-172001,那么带入公式之后,得到
  (10000−1+1)×(7200−1+1)/(72×106)=(104×72×102)/(72×106)=1秒(10000 - 1+1)\times(7200-1+1)/(72\times10^{6})=(10^{4}\times72\times10^{2})/(72\times10^{6})=1 秒(100001+1)×(72001+1)/(72×106)=(104×72×102)/(72×106)=1

4.3 实验效果

定时中断现象

5 定时中断-外部时钟源

定时器中断-外部时钟

#include "stm32f10x.h"                  // Device headerextern uint16_t Num;void Timer_Init(void)
{/* 第一步:打开时钟 */RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);/* 第二步:选择时基单元的时钟 */TIM_ETRClockMode2Config(TIM2, TIM_ExtTRGPSC_OFF, TIM_ExtTRGPolarity_NonInverted, 0x00); ///* 第三步:配置时基单元 */TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;TIM_TimeBaseInitStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseInitStructure.TIM_CounterMode = TIM_CounterMode_Up;TIM_TimeBaseInitStructure.TIM_Period = 10 - 1;TIM_TimeBaseInitStructure.TIM_Prescaler = 1 - 1;TIM_TimeBaseInitStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM2, &TIM_TimeBaseInitStructure);/* 第四步:使能更新中断 */TIM_ITConfig(TIM2, TIM_IT_Update, ENABLE);/* 第五步:配置NVIC */NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;NVIC_Init(&NVIC_InitStructure);/* 第六步:启动定时器 */TIM_Cmd(TIM2, ENABLE);/** 写到这里,定时中断的初始化工作就已经完成了 **/}uint16_t Timer_GetCounter(void)
{return TIM_GetCounter(TIM2);
}void TIM2_IRQHandler(void)
{if (TIM_GetITStatus(TIM2, TIM_IT_Update) == SET){Num++;TIM_ClearITPendingBit(TIM2, TIM_IT_Update);}
}

6 PWM 实现呼吸灯

6.1 什么是 PWM

  PWM = Pulse Width Modulation = 脉冲宽度调制
  在具有惯性的系统中,可以通过对一系列脉冲的宽度进行调制,来等效地获得所需要地模拟参量,常应用于电机控制速度等领域。

PWM 参数有哪些:
  (1) 频率 1/Ts1/T_{s}1/Ts
  (2) 占空比 TON/TsT_{ON}/T_{s}TON/Ts
  (3) 分辨率,占空比变化步距

  按理说,LED灯只有亮和灭两种状态。怎么控制它的亮度呢?

  就用PWM,利用PWM,让LED灯不断地点亮、熄灭,当亮灭的频率足够大时,LED灯就不闪烁了,呈现一个中等亮度。

  当我们调整点亮和熄灭时间的比例时,就能让LED灯呈现不同的亮度。

  这个思想,就跟电机调速一样,给电机通电,断电,通电,断电,那么电机的速度就维持在一个中等速度,通过调节通电和断电时间的比例,就可以调节电机的速度。

定时器的输出比较功能:
(1) OC(Output Compare)= 输出比较
(2) 输出比较可以通过比较计数器 CNT 和 “捕获/比较寄存器(Capture/Compare register, CCR)”值的关系,来对输出电平进行置1、置0或翻转的操作,用于输出一定频率和占空比的PWM波形。(注意:PWM = Pulse Width Modulation = 脉冲宽度调制)
(3) 每个高级定时器和通用定时器都拥有4个输出比较通道。
(4) 高级定时器的前3个通道额外拥有死区生成和互补输出的功能。

这里再说明一点:
   要知道,高级定时器和通用定时器,具有输入捕获和输出比较,这两个功能,CCR这个寄存器,是具有两重功能的,在输入捕获中,它就是捕获寄存器,在输出比较中,它就是输出比较器,所以,综上,我们就叫它“捕获/比较寄存器”。就是这么简单。

(1)高级定时器的输出比较电路


要理解这个电路的作用,要结合它的外接电路,一般是这样的:

黄色的是MOS管
① 上管导通,下管断开,输出的就是高电平
② 上管断开,下管导通,输出就是低电平
③ 上管和下管都断开,输出呈现高阻态
④ 不能同时导通,会烧掉的。
这就是推挽电路的工作流程,

  有两个这样的推挽电路,就构成了H桥电路,就能控制电机的正反转了。

  有三个这个推挽电路,就能够驱动三相无刷电机了。

  OC1和OC1N的输出电平必须是相反的,也就是互补的。

  but,这里会存一个安全性问题,比如说,现在是上管导通,下管断开,下一个状态是上管断开,下管导通。这个状态之间的转换,是瞬间立刻,干干净净地完成吗?不能,极有可能出现这种情况:
  上管还没完全断开,下管就导通,两种MOS管都处于导通状态,啪!!! 烧了!!!

ST公司为了避免这种情况,设计了死区电路,

上管开始关闭时,延迟一小段时间,再导通下管!哈哈哈,没有复杂的理论推导,就是这么直接!!!

深入浅出地理解STM32中的定时器工作原理相关推荐

  1. 深入浅出地理解STM32中的中断系统——从原理到简单工程示例——保姆级教程

    深入浅出地理解STM32中的中断系统 一.什么是中断?什么是异常? 二.如何管理中断? 三.NVIC 1 NVIC 特点 2 中断优先级 (1) 优先级分组 3 中断向量表 4 中断服务函数 (1)中 ...

  2. 再次理解STM32中的堆栈机制

    再次理解STM32中的堆栈机制 刚拿到STM32时,你只编写一个死循环 void main() { while(1); }BUILD://Program Size: Code=340 RO-data= ...

  3. lwip协议栈中超时定时器实现原理

    lwip协议栈中超时定时器实现原理 1,超时定时器存在的目的: tcpip协议中存在很多需要定时处理的任务,包括一次性超时处理和周期性超时处理. 以tcp传输为例,每条连接总共需要建立七个定时器,依次 ...

  4. java中session的作用_java中session的工作原理是什么?和Cookies有何区别?

    现在大家学习的东西和以前大不相同了,越来越多的人倾向于去学习高新技术以获得更好的发展.java是很多人的第一选择.java中的知识还是很多的,今天就来为大家介绍一下. 首先来说一下java中sessi ...

  5. 深入解析Android中View的工作原理

    Android中的任何一个布局.任何一个控件其实都是直接或间接继承自View实现的,当然也包括我们在平时开发中所写的各种炫酷的自定义控件了,所以学习View的工作原理对于我们来说显得格外重要,本篇博客 ...

  6. 理解 JSON 的数据储存工作原理及对象和文本间的转换方法

    目标: 理解 JSON 的数据储存工作原理及对象和文本间的转换方法. 什么是 JSON? JSON 是一种按照JavaScript对象语法的数据格式.虽然它是基于 JavaScript 语法,但它独立 ...

  7. 一文带你理解Java中Lock的实现原理

    转载自   一文带你理解Java中Lock的实现原理 当多个线程需要访问某个公共资源的时候,我们知道需要通过加锁来保证资源的访问不会出问题.java提供了两种方式来加锁,一种是关键字:synchron ...

  8. Linux中LVM的工作原理是什么?优缺点有哪些?

    在Linux操作系统中,LVM全称Logical Volume Manager,中文意思为逻辑卷管理.之前文章为大家介绍过什么是LVM.LVM名词解释.LVM写入模式等内容,本篇文章为大家介绍一下LV ...

  9. STM32控制步进电机:工作原理及库函数(标准库) / HAL库控制程序(不定期更新)

    STM32控制步进电机:工作原理并附带库函数/HAL库程序 一.步进电机的基本工作原理 1.步进电机工作原理 2.混合式步进电机工作原理 二.步进电机参数解析(后续学习会继续补充此处内容

最新文章

  1. lua5.2调用c函数成功的例子
  2. nginx 如何处理请求系列1-Nginx安装
  3. Intellij IDEA 2019 自动生成 serialVersionUID
  4. [2018/11/13]图像处理
  5. MPC实现自动驾驶轨迹跟踪
  6. 2019.03.06 22.25
  7. python可以操作word吗_python实现在windows下操作word的方法
  8. 3d激光雷达开发(voxel滤波)
  9. mysql jar包下载(直接链接下载)
  10. 求大佬解决0x00881340 处有未经处理的异常(在 ConsoleApplication1.exe 中): 0xC0000005: 写入位置 0x00993B8C 时发生访问冲突。
  11. 学习平面设计有哪些优势?
  12. 基于ABP的应用执行Update-Database出现异常的解决办法
  13. 高德地图实现的数据统计切换街景地图
  14. 英雄联盟无法开始第二局(已解决,亲测有效)
  15. VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences
  16. 人工智能为教育创新赋能,开启教学新模式
  17. java写猴子偷桃问题_猴子偷桃是什么意思
  18. java双端加密操作 vue+springboot+AES(CBC-ECB) ------------------前传后
  19. 什么才是社交APP该有的样子
  20. 说服力——工作型PPT该这样做

热门文章

  1. java获取电脑配置_使用Java获取cao作系统和硬件信息
  2. Java多线程示例:4个售票员卖1000张火车票
  3. 轩逸车联网功能怎么用_2020款轩逸中控屏幕按键功能介绍
  4. Java——查找里程
  5. IOS后台运行 之 后台播放音乐
  6. 转型并非放弃 诺基亚年底宣布MeeGo1.1
  7. 使用window.print()方法分页打印
  8. Linux 杀毒软件clamav的yum 安装
  9. 耶鲁大学《博弈论》课程——混合策略
  10. 【最全的】JPEG Toolbox代码及使用方式详解