51单片机的定时计数器

定时/计数器的核心部件是一个加法(或减法)计数器;若计数脉冲来自零碎时钟,则为定时形式;若计数脉冲来自单片机内部引脚,则为计数形式。

根本介绍

定时器:

  • 定时器是SOC的外部外设。
  • 定时器就是CPU的闹钟。

计数器:

  • 单片机实现定时器其实质是用计数器来实现的。
  • 计数器能够计算内部脉冲的个数。
  • 当单片机计算外部脉冲个数时就相当于定时器,当计算内部脉冲个数就相当于计数器。

加法计数器和减法计数器:(51单片机是加法计数器)

  • 加法计数器:从咱们给定的值开始加,加到溢出,而后触发中断。

    • 例如:16位定时器最大计数65535次,如果咱们想计数50000次,那么设置的TH和TL应设为65535-50000 = 15535。
  • 减法计数器;从咱们给定的值开始减,减到0就溢出,而后触发中断。

    • 例如:16位定时器最大计数65535次,如果咱们想计数50000次,那么设置的TH和TL应设为50000。
  • 计算TL和TH:

    • 首先确定定时工夫,time(例如50ms)。
    • 确定外部时钟周期,因为是12T模式,晶振12MHz,所以外部频率1MHz,周期1us。
    • 定时计个数 = time ÷ 周期。(50000)
    • TL1 = 个数 % 256(取余);TH1 = 个数 / 256(取整)。

工作流程

  1. 设置定时器时钟源(作定时器应用时,须要外部的脉冲,这个脉冲来源于时钟源)
  2. 初始化定时器相干寄存器。
  3. 设置定时工夫(计数个数)
  4. 设置中断处理程序。
  5. 关上定时器。
  6. 运行时:定时器计数到设置值后产生中断,执行中断处理程序。

定时/计数器相干寄存器。

管制寄存器TCON

  • TF1:定时器/计数器T1溢出标记位。T1被容许计数后,从初值开始加一,计数实现后由硬件置位,收回中断请求;中断响应后硬件主动复位。
  • TR1:定时器T1容许管制位,由软件置位和清零。GATE(TMOD.7)= 0,TR1 = 1时才容许T1开始计数。
  • IE1:内部中断1申请源标记。IE1 = 1,内部中断向CPU申请中断,CPU响应后由硬件清零。、
  • IT1:内部中断1触发形式管制位。IT1 = 0时,内部中断1为低电平触发形式;IT1 = 1时,内部中断1为高电平触发形式。

工作模式寄存器TMOD

  • GATE(TMOD.7):与TCON.6(TR1)配合管制定时器运行
  • C/T(TMOD.6):管制定时器1用作定时器还是计数器。清零用作定时器,置一用作计数器。
  • M1/M0(TMOD.5/TMOD4):定时计数器模式抉择位。
  • (00)模式0(13位定时器/计数器); (01)模式1(16位定时器/计数器模式); (10)模式2(8位主动重装模式); (11)模式3(两个8位定时器/计数器)。

示例代码

//TIM1定时器初始化void TIM1_Init(){    TMOD = 0x10;           // T0设置工作在定时器模式下,模式一 16位定时器    TL1 = (65535 - 50000) % 256;        TH1 = (65535 - 50000) / 256;    TR1 = 1;            // 开启计数器,开始计数了    ET1 = 1;            // 开启T1中断    EA = 1;                // 开启中断总开关    count = 10;            // 10次,对应500ms}//TIM1中断处理程序;定时500msvoid timer1_isr(void) interrupt 1 using 1{       TL1 = (65535 - 50000) % 256;        TH1 = (65535 - 50000) / 256;            // 手工重装载计数值    //因为模式一不能主动重装载,所以要手工重装载计数值。    if (count-- == 0)    {        // 阐明曾经中断了10次了,500ms到了,该干活了        LED = !LED;                // LED取反        count = 10;    }}

STM32单片机的定时/计数器

独立看门狗(IWDG)

  • 当计数器达到给定的超时值时会产生零碎复位。
  • 独立看门狗(IWDG)由专用的低速时钟(LSI)驱动,即便主时钟产生故障它也依然无效。
  • 独立看门狗(IWDG)是减法计数器。
  • 看门狗被激活后,则在计数器计数至0x000时产生复位(复位的意思是指从0xfff开始递加)
  • 独立看门狗能够在任何时候进行喂狗操作。喂狗后,计数器从设定的值开始计数。
  • IWDG最适宜利用于那些须要看门狗作为一个在主程序之外(次要是为了避免程序跑飞),可能齐全独立工作,并且对工夫精度要求较低的场合。

窗口看门狗(WWDG)

  • 当计数器达到给定的超时值时会产生零碎复位或触发一个中断。
  • 窗口看门狗由从APB1时钟分频后失去的时钟驱动。
  • 窗口看门狗(WWDG)是减法计数器。
  • 窗口看门狗(WWDG)喂狗工夫有严格控制。必须要在规定的工夫内(窗口)喂狗才无效。如果在其余工夫喂狗则会产生复位,如果在窗口没有喂狗,则计数完后也会产生复位。
  • WWDG最适宜那些要求看门狗在准确计时窗口起作用的应用程序。

通用定时器(TIMx)((TIM2、TIM3、TIM4、TIM5)

TIMx简介

  • 16位向上(加法计数)、向下(减法计数)、向上/向下主动装载计数器。
  • 向上/向下计数(地方对齐模式):计数器从0加到(设定值-1)触发溢出中断,再从(设定值-1)减到1触发下溢中断。
  • 加法计数和减法计数:例如想计数500次,加法计数器是从0开始计数到500,而减法计数器是从500减到0。
  • 性能:输出捕捉、输入比拟、PWM。
  • 16位可编程(能够实时批改)预分频器,计数器时钟频率的分频系数为1~65536之间的任意数值。(计数器的时钟频率是由下级频率通过预分频器分频失去的,下级频率每个定时器可能不同,可能是APB1或APB2,下级频率设置办法请查看另外一篇文章“STM32时钟体系”)
  • 计数器、主动装载寄存器和预分频器寄存器能够由软件读写,在计数器运行时仍能够读写。
  • 计数器由预分频器的时钟输入CK_CNT驱动,仅当设置了计数器TIMx_CR1寄存器中的计数器使能位(CEN)时,CK_CNT才无效。
  • 主动重装载寄存器、预装载寄存器、影子寄存器、计数器关系:(集体了解,不肯定对)

    • ARPE:管制寄存器 1(TIMx_CR1)中预装载寄存器容许位。(0:不应用预装载寄存器)
    • 计数器是计算次数的,而影子寄存器则是用来与计数器做比拟的。(实用于加法计数中)
    • 例如:以后计数值为500,当初想将计数个数改为1000。
    • 当APRE为0时:先将1000写入主动重装载寄存器,主动重装载寄存器立马将1000装入影子寄存器中。以后计数到1000后才触发中断,而不是500。
    • 当APRE为1时:先将1000写入主动重装载寄存器,主动重装载寄存器将1000写入预装载寄存器中,当此次计数实现即计数到500后触发中断,预装载寄存器才将1000写入影子寄存器中。下次计数到1000触发中断。

TIMx寄存器形容

管制寄存器 1(TIMx_CR1)

  • 复位值:0x0000
  • CKD: 时钟分频因子
  • ARPE:主动重装载预装载容许位(1:容许预装载)
  • CMS:抉择地方对齐模式。
  • DIR:抉择计数方向(0上1下)
  • URS:URS:更新申请源(1:如果使能了更新中断或DMA申请,则只有计数器溢出/下溢才产生更新中断或DMA申请)
  • UDIS:禁止更新(1:禁止更新,不触发任何中断或事件)
  • CEN:使能计数器(1:使能计数器)

DMA/中断使能寄存器(TIMx_DIER)

  • 复位值:0x0000
  • TDE:容许触发DMA申请(1:容许)
  • UDE:容许更新的DMA申请(1:容许)
  • TIE:触发中断使能(1:使能触发中断)
  • UIE:容许更新中断(1:容许更新中断)
  • 中断服务程序程序执行完当前,要把中断关上(即把标记地位位),以便下一次还能触发该中断。 这就是更新中断。

状态寄存器(TIMx_SR)

  • 复位值:0x0000
  • TIF:触发器中断标记(当产生触发事件时由硬件对该地位一,它由软件清零)(1:触发器中断期待响应)
  • UIF:更新中断标记(当产生更新事件时该位由硬件置一。它由软件清零)(1:更新中断期待响应)

事件产生寄存器(TIMx_EGR)

  • 复位值:0x0000
  • TG:产生触发事件,由软件置一硬件清零(1:当TIMx_SR寄存器的TIF=1,若开启对应的中断和DMA,则产生相应的中断和DMA。)
  • UG:产生更新事件,由软件置一硬件清零(1:从新初始化计数器,并产生一个更新事件。)

示例

/******************************************************************************** 函 数 名         : TIM4_Init* 函数性能           : TIM4初始化函数* 输    入         : per:重装载值                     psc:分频系数* 输    出         : 无*******************************************************************************/void TIM4_Init(u16 per,u16 psc){    TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;    NVIC_InitTypeDef NVIC_InitStructure;        RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4,ENABLE);//使能TIM4时钟        TIM_TimeBaseInitStructure.TIM_Period=per;   //主动装载值    TIM_TimeBaseInitStructure.TIM_Prescaler=psc; //分频系数    TIM_TimeBaseInitStructure.TIM_ClockDivision=TIM_CKD_DIV1;            //设置CKD时钟分频因子    TIM_TimeBaseInitStructure.TIM_CounterMode=TIM_CounterMode_Up; //设置向上计数模式    TIM_TimeBaseInit(TIM4,&TIM_TimeBaseInitStructure);        TIM_ITConfig(TIM4,TIM_IT_Update,ENABLE); //开启定时器中断    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);    //革除中断挂起位        NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn;//定时器中断通道    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority=2;//抢占优先级    NVIC_InitStructure.NVIC_IRQChannelSubPriority =3;        //子优先级    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;            //IRQ通道使能    NVIC_Init(&NVIC_InitStructure);            TIM_Cmd(TIM4,ENABLE); //使能定时器    }/******************************************************************************** 函 数 名         : TIM4_IRQHandler* 函数性能           : TIM4中断函数* 输    入         : 无* 输    出         : 无*******************************************************************************/void TIM4_IRQHandler(void){    if(TIM_GetITStatus(TIM4,TIM_IT_Update))    {        led2=!led2;    }    TIM_ClearITPendingBit(TIM4,TIM_IT_Update);    }