定时器中断_定时器中断实验 - CSDN
精华内容
参与话题
  • STM32学习笔记一一定时器中断

    千次阅读 2020-07-21 23:04:16
    1.STM32 通用定时器简介 STM32 的通用定时器是一个通过可编程预分频器( PSC)驱动的 16 位自动装载计数器( CNT)构成。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个...

    前言:

    为了方便查看博客,特意申请了一个公众号,附上二维码,有兴趣的朋友可以关注,和我一起讨论学习,一起享受技术,一起成长。

    在这里插入图片描述


    1. STM32 通用定时器简介

    STM32 的通用定时器是一个通过可编程预分频器( PSC)驱动的 16 位自动装载计数器( CNT)构成。使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。 STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。

    TIMER主要是由三部分组成:

    时基单元; 输入捕获;输出比较。

    2. STM32 的通用定时器功能

    通用定时器有TIMx (TIM2、 TIM3、 TIM4 和 TIM5),具体功能如下:

    1. 16 位向上、向下、向上/向下自动装载计数器( TIMx_CNT);

    2. 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。

    3. 4 个独立通道( TIMx_CH1~4),这些通道可以用来作为:

    A.输入捕获;

    B.输出比较;

    C. PWM 生成(边缘或中间对齐模式);

    D.单脉冲模式输出;

    1. 可使用外部信号( TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。

    2. 如下事件发生时产生中断/DMA:

    A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发);

    B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数);

    C.输入捕获;

    D.输出比较;

    E.支持针对定位的增量(正交)编码器和霍尔传感器电路;

    F.触发输入作为外部时钟或者按周期的电流管理.

    3. 定时器相关的寄存器

    (1)控制寄存器 1( TIMx_CR1),各个位介绍如下:

    这里写图片描述

    这里写图片描述

    这里写图片描述

    (2)DMA/中断使能寄存器( TIMx_DIER):16位如下图

    这里写图片描述

    它的第 0 位,该位是更新中断允许位,设置为 1,来允许由于更新事件所产生的中断。

    (3)预分频寄存器( TIMx_PSC)

    这里写图片描述

    定时器的时钟来源有 4 个:

    1) 内部时钟( CK_INT)

    2) 外部时钟模式 1:外部输入脚( TIx)

    3) 外部时钟模式 2:外部触发输入( ETR)

    4) 内部触发输入( ITRx):使用 A 定时器作为 B 定时器的预分频器( A 为 B 提供时钟)。

    注:

    a. 具体选择通过 TIMx_SMCR 寄存器的相关位来设置。CK_INT 时钟是从 APB1 倍频的来的,STM32 中除非 APB1 的时钟分频数设置为 1,否则通用定时器 TIMx 的时钟是 APB1 时钟的 2 倍,当 APB1 的时钟不分频的时候,通用定时器 TIMx 的时钟就等于 APB1 的时钟。

    b. 高级定时器的时钟来自 APB2 。

    (3)TIMx_CNT 寄存器

    该寄存器是定时器的计数器,该寄存器存储了当前定时器的计数值。

    3.1 计数模式

    a. 向上计数模式:

    在向上计数模式中,计数器从0计数到自动加载值 ( TIMx_ARR 计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。

    b. 向下计数模式:

    在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。

    c. 中央对齐模式:

    在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器) - 1,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。

    d. 重复计数器功能

    如果使用了重复计数器功能,在向上计数达到设置的重复计数次数(TIMx_RCR)时,产生更新事件(UEV);否则每次计数器溢出时才产生更新事件。

    (4)自动重装载寄存器( TIMx_ARR),各位如下图:

    这里写图片描述

    此寄存器在物理上实际对应着 2 个寄存器。一个是程序员可以直接操作的,另外一个是程序员看不到的,这个看不到的寄存器被叫做影子寄存器。事实上,真正起作用的是影子寄存器。 根据 TIMx_CR1 寄存器中 APRE 位的设置: APRE=0 时,预装载寄存器的内容可以随时传送到影子寄存器,此时 2者是连通的;而 APRE=1 时,在每一次更新事件( UEV)时,才把预装在寄存器的内容传送到影子寄存器。

    (6)状态寄存器( TIMx_SR)

    该寄存器用来标记当前与定时器相关的各种事件/中断是否发生。

    这里写图片描述

    4.定时器中断的配置步骤

    1) TIM3 时钟使能。

    TIM3 是挂载在 APB1 之下,所以我们通过 APB1 总线下的时钟使能函数来使能 TIM3。调用的函数是:

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //时钟使能
    

    2)初始化定时器参数,设置自动重装值, 分频系数,计数方式等。

    在库函数中,定时器的初始化参数是通过初始化函数 TIM_TimeBaseInit 实现的:

    voidTIM_TimeBaseInit(TIM_TypeDef*TIMx,TIM_TimeBaseInitTypeDef* TIM_TimeBaseInitStruct);
    第一个参数:确定是哪个定时器
    第二个参数:定时器初始化参数结构体指针,结构体类型为 TIM_TimeBaseInitTypeDef。
    

    结构体的定义:

     typedef struct
     {
      uint16_t TIM_Prescaler;
      uint16_t TIM_CounterMode;
      uint16_t TIM_Period;
      uint16_t TIM_ClockDivision;
      uint8_t TIM_RepetitionCounter;
    } TIM_TimeBaseInitTypeDef;
    

    注:对于通用定时器只有前面四个参数有用,最后一个参数 TIM_RepetitionCounter 是高级定时器才有用的。

    第一个参数 TIM_Prescaler:设置分频系数;

    第二个参数 TIM_CounterMode:设置计数方式,可以设置为向上计数,向下计数方式还有中央对齐计数方式,比较常用的是向上计数模式 TIM_CounterMode_Up 和向下计数模式 TIM_CounterMode_Down;

    第三个参数TIM_Period:设置自动重载计数周期值;

    第四个参数TIM_ClockDivision:设置时钟分频因子。

    TIM3 初始化:

    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_TimeBaseStructure.TIM_Period = 5000;
    TIM_TimeBaseStructure.TIM_Prescaler =7199;
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
    

    3)设置 TIM3_DIER 允许更新中断。

    因为我们要使用 TIM3 的更新中断,寄存器的相应位便可使能更新中断。在库函数里面定时器中断使能是通过 TIM_ITConfig 函数来实现的:

    void TIM_ITConfig(TIM_TypeDef* TIMx, uint16_t TIM_IT, FunctionalState NewState)

    第一个参数:选择定时器号,取值为 TIM1~TIM17;

    第二个参数:用来指明我们使能的定时器中断的类型,定时器中断的类型有很多种,包括更新中断 TIM_IT_Update,触发中断 TIM_IT_Trigger,以及输入捕获中断等等;

    第三个参数:失能还是使能;

    使能 TIM3 的更新中断,格式为:

    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE );
    

    4) TIM3 中断优先级设置

    在定时器中断使能之后,因为要产生中断,必不可少的要设置 NVIC 相关寄存器,设置中断优先级。

    5)允许 TIM3 工作,也就是使能 TIM3

    在配置好定时器后边要开启定时器,通过 TIM3_CR1 的 CEN 位来设置。在固件库里面使能定时器的函数是通过 TIM_Cmd 函数来实现的:

    void TIM_Cmd(TIM_TypeDef* TIMx, FunctionalState NewState)
    

    使能定时器 3,方法为:

    TIM_Cmd(TIM3, ENABLE); //使能 TIMx 外设
    

    6) 编写中断服务函数。

    最后,编写定时器中断服务函数,通过该函数来处理定时器产生的相关中断。在中断产生后,通过状态寄存器的值来判断此次产生的中断属于什么类型。然后执行相关的操作,这里使用的是更新(溢出)中断,所以在状态寄存器 SR 的最低位。在处理完中断之后应该向 TIM3_SR 的最低位写 0,来清除该中断标志。

    a. 在固件库函数里面,用来读取中断状态寄存器的值判断中断类型的函数是:

    ITStatus TIM_GetITStatus(TIM_TypeDef* TIMx, uint16_t)
    

    该函数的作用:判断定时器 TIMx 的中断类型 TIM_IT 是否发生中断。比如,我们要判断定时器 3 是否发生更新(溢出)中断,方法为:

    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET){}
    

    b. 固件库中清除中断标志位的函数是:

    void TIM_ClearITPendingBit(TIM_TypeDef* TIMx, uint16_t TIM_IT)
    

    该函数的作用:清除定时器 TIMx 的中断 TIM_IT 标志位。比如在 TIM3 的溢出中断发生后,我们要清除中断标志位,方法是:

    TIM_ClearITPendingBit(TIM3, TIM_IT_Update );
    

    注:固件库还提供了两个函数用来判断定时器状态以及清除定时器状态标志位的函数 TIM_GetFlagStatus 和 TIM_ClearFlag,他们的作用和前面两个函数的作用类似。只是在 TIM_GetITStatus 函数中会先判断这种中断是否使能,使能了才去判断中断标志位,而TIM_GetFlagStatus 直接用来判断状态标志位。

    5. 实例学习

    功能; 通过 TIM3 的中断来控制 DS1 的亮灭.

    定时器基本配置*******

    #include "timer.h"
    #include "led.h"
    //通用定时器 3 中断初始化
    //这里时钟选择为 APB1 的 2 倍,而 APB1 为 36M
    //arr:自动重装值。
    //psc:时钟预分频数
    //这里使用的是定时器 3!
    void TIM3_Int_Init(u16 arr,u16 psc)
    {
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    NVIC_InitTypeDef NVIC_InitStructure;
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE); //①时钟 TIM3 使能
    //定时器 TIM3 初始化
    TIM_TimeBaseStructure.TIM_Period = arr; //设置自动重装载寄存器周期的值
    TIM_TimeBaseStructure.TIM_Prescaler =psc; //设置时钟频率除数的预分频值
    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //设置时钟分割
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //TIM 向上计数
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure); //②初始化 TIM3
    TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE ); //③允许更新中断
    //中断优先级 NVIC 设置
    NVIC_InitStructure.NVIC_IRQChannel = TIM3_IRQn; //TIM3 中断
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级 0 级
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 3; //从优先级 3 级
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //IRQ 通道被使能
    NVIC_Init(&NVIC_InitStructure); //④初始化 NVIC 寄存器
    TIM_Cmd(TIM3, ENABLE); //⑤使能 TIM3
    }
    

    //定时器 3 中断服务程序⑥

    定时器中断服务函数的实现****

    void TIM3_IRQHandler(void) //TIM3 中断
    {
    if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) //检查 TIM3 更新中断发生与否
    {
    TIM_ClearITPendingBit(TIM3, TIM_IT_Update ); //清除 TIM3 更新中断标志
    LED1=!LED1;
    }
    }
    

    时钟系统初始化的时候在默认的系统初始化函数 SystemInit 函数里面已经初始化 APB1 的时钟为 2 分频,所以 APB1 的时钟为 36M,而从 STM32 的内部时钟树图得知:当 APB1 的时钟分频数为 1 的时候, TIM2~7 的时钟为 APB1 的时钟,而如果 APB1 的时钟分频数不为 1,那么 TIM2~7 的时钟频率将为 APB1 时钟的两倍。因此, TIM3 的时钟为 72M,再根据我们设计的 arr 和 psc 的值,就可以计算中断时间了。

    计算公式如下:

    Tout= ((arr+1)*(psc+1))/Tclk;

    其中:

    Tclk: TIM3 的输入时钟频率(单位为 Mhz)。

    Tout: TIM3 溢出时间(单位为 us)。

    *主函数实现

    int main(void)
     {	
    	delay_init();	    	 //延时函数初始化
    	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);// 设置中断优先级分组2
    	LED_Init();		  	//初始化与LED连接的硬件接口
    	TIM3_Int_Init(4999,7199);//10Khz的计数频率,计数到5000为500ms  
       	while(1)
    	{
    		LED0=!LED0;
    		delay_ms(200);		   
    	}
    }
    

    参考:

    1.正点原子STM32库函数手册
    2.STM32通用定时器
    3.STM32之定时器
    4. STM32 定时器浅谈_1

    展开全文
  • 51单片机第二讲(定时器中断

    千次阅读 2018-01-28 19:03:34
    1.中断的概念 CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断产生);...51单片机里一共有5个中断源,分别是外部中断0,定时器0,外部中断1,定时器1,串口中断中断优先级从大到

    1.中断的概念
    CPU在处理某一事件A时,发生了另一事件B请求CPU迅速去处理(中断产生);
    CPU暂时中断当前的工作,转去处理事件B(中断响应和中断服务);
    待CPU将事件B处理完毕后,再回到原来事件A中断的地方继续处理事件A(中断返回),这一过程称为中断。
    这里写图片描述
    2.中断的优先级
    51单片机里一共有5个中断源,分别是外部中断0,定时器0,外部中断1,定时器1,串口中断,中断优先级从大到小分别是0,1,2,3,4。

    3.中断的优点
    分时操作。CPU可以分时为多个I/O设备服务,提高了计算机的利用率;
    实时响应。CPU能够及时处理应用系统的随机事件,系统的实时性大大增强;
    可靠性高。CPU具有处理设备故障及掉电等突发性事件能力,从而使系统可靠性提高。

    4.外部中断
    外部中断0是定义在P3.2口,外部中断1是定义在P3.3口
    TCON的中断标志(控制寄存器):
    这里写图片描述
    IT0(TCON.0),外部中断0触发方式控制位。
    当IT0=0时,为电平触发方式。
    当IT0=1时,为边沿触发方式(下降沿有效)。
    IE0(TCON.1),外部中断0中断请求标志位。
    IT1(TCON.2),外部中断1触发方式控制位。
    IE1(TCON.3),外部中断1中断请求标志位。
    TR0(TCON.4):T0运行控制位,其功能与TR1类同。
    TF0(TCON.5),定时/计数器T0溢出中断请求标志位。
    TR1(TCON.6):T1运行控制位。TR1置1时,T1开始工作;TR1置0时,T1停止工作。TR1由软件置1或清0。所以,用软件可控制定时/计数器的启动与停止
    TF1(TCON.7),定时/计数器T1溢出中断请求标志位。

    外部中断初始化:

    void bsp_Int0_Init(void)//外部中断0
    {
         IT0 = 1;    //设置边沿触发方式 等于0是电平触发方式
         EX0 = 1;    //开外部中断,在中断寄存器里
         EA = 1;     //开总中断
    }
    
    void bsp_Int1_Init(void)//外部中断1
    {
         IT1 = 1;
         EX1 = 1;
         EA = 1;
    }
    
    void ISR_INT0(void) interrupt 0//中断处理函数
    {
        P1 = 0x55;
    }
    
    void ISR_INT1(void) interrupt 2
    {
        P1 = 0xaa;
    }

    5.定时器中断
    工作方式寄存器TMOD:
    这里写图片描述
    GATE:门控位。GATE=0时,只要用软件使TCON中的TR0或TR1为1,就可以启动定时/计数器工作;GATA=1时,要用软件使TR0或TR1为1,同时外部中断引脚或也为高电平时,才能启动定时/计数器工作。即此时定时器的启动多了一条件。(默认情况下等于0不要设置)。
    C/T:定时/计数模式选择位。=0为定时模式;=1为计数模式。
    M1M0:工作方式设置位。定时/计数器有四种工作方式,由M1M0进行设置。(正常情况旋方式1,即M1M0=01)。
    中断寄存器:
    这里写图片描述
    EA是总中断
    ET0是定时器0中断
    EX0是外部中断0
    ET1是定时器1中断
    EX1是外部中断1

    void Timer0_Init(void)
    {
        TMOD |= 0x01;//设置定时器为工作方式1  C/T位为1的时候是计数器模式,为0的时候是定时器模式,前四位是定时器1,后四位是定时器0
        TL0 = (65536 - 1000)%256;    //装初值,低8位
        TH0 = (65536 - 1000)/256;   //高8位
        ET0 = 1;    //开定时器的中断
        TR0 = 1;    //开定时器
        EA = 1;     //开总中断
    }
    
    void Timer0(void) interrupt 1
    {
        TL0 = (65536 - 1000)%256;    //装初值,低8位//初值是1000即1ms
        TH0 = (65536 - 1000)/256;   //高8位
        count++;
        if(count == 1000)
        {
            count = 0;
            LED = ~LED;//LED一秒钟闪烁一次
        }
    }
    展开全文
  • 51单片机定时器中断

    万次阅读 2019-06-08 23:58:02
    51定时器中断 1.定时器/计数器 51单片机有2个16位定时器/计数器:定时器0(T0为P3.4) 和定时器1(T1为P3.5) 这里所说的16位是指定时/计数器内部分别有16位的计数寄 存器。当工作在定时模式时,每经过一个机器...

    51定时器中断

    1.定时器/计数器

    51单片机有2个16位定时器/计数器:定时器0(T0为P3.4) 和定时器1(T1为P3.5)
    这里所说的16位是指定时/计数器内部分别有16位的计数寄 存器。当工作在定时模式时,每经过一个机器周期内部的16位计数 寄存器的值就会加1,当这个寄存器装满时溢出。 我们可以算出工作在定时模式时最高单次定时时间为 65535*1.085us=时间(单位us)
    当工作在计数器模式时,T0(P3.4引脚),T1(P3.5引脚)每 来一个脉冲计数寄存器加1
    在这里插入图片描述
    定时器作用:定时计数器可以用于精确事件定时,PWM脉宽调 制,波形发生,信号时序测量的方面。

    使用51定时/计数器步骤:

    (1)启动定时/计数器(通过TCON控制器)
    (2)设置定时/计数器工作模式(通过TMOD控制器)
    (3)查询定时/计数器是否溢出(读TCON内TF位
    在这里插入图片描述
    在这里插入图片描述

    3.代码片:

    (1)定时器定时:

    #include <reg52.h>
    #include <intrins.h>
    #define uint unsigned int
    #define uchar unsigned char
    sbit DU = P2^6;
    sbit WE = P2^7;
    uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
    void delay(uint z)
    {
     uint x,y;
     for(x = z; x > 0; x--)
      for(y = 114; y > 0 ; y--);   
    } 
    void display(uchar i)
    {
     uchar bai, shi, ge;
     bai = i / 100; //236 / 100  = 2
     shi = i % 100 / 10; //236 % 100 / 10 = 3
     ge  = i % 10;//236 % 10 =6   
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFE; //1111 1110
     WE = 0; 
     DU = 1;
     P0 = tabel[bai];//
     DU = 0;
     delay(5);
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFD; //1111 1101
     WE = 0; 
     DU = 1;
     P0 = tabel[shi];//
     DU = 0;
     delay(5);
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFB; //1111 1011
     WE = 0; 
     DU = 1;
     P0 = tabel[ge];//
     DU = 0;
     delay(5);
    }
    void timer0Init()
    {
     TR0 = 1; 
     TMOD = 0X01; 
     TH0 = 0x4b;
     TL0 = 0xfd; 
    }
    void main()
    { 
     uchar mSec, Sec;
     timer0Init();
     while(1)
     {
      if(TF0 == 1)
      {
       TF0 = 0;
       TH0 = 0x4b;
       TL0 = 0xfd; 
       mSec++;
       if(mSec == 20)
       {
        mSec = 0;
        Sec++;
       }     
      }
      display(Sec); 
      if(Sec > 10)
       Sec = 0;
     } 
    } 
    

    (2)定时器计数:

    #include <reg52.h>
    #include <intrins.h>
    #define uint unsigned int
    #define uchar unsigned char
    sbit DU = P2^6;
    sbit WE = P2^7;
    sbit LED1 = P1^0;
    uchar  code tabel[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
    void delay(uint z)
    {
     uint x,y;
     for(x = z; x > 0; x--)
      for(y = 114; y > 0 ; y--);   
    } 
    void display(uchar i)
    {
     uchar bai, shi, ge;
     bai = i / 100;
     shi = i % 100 / 10;
     ge  = i % 10;   
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFE; //1111 1110
     WE = 0;
     DU = 1;
     P0 = tabel[bai];//
     DU = 0;
     delay(5);
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFD; 
     WE = 0;
     DU = 1;
     P0 = tabel[shi];
     DU = 0;
     delay(5);
     P0 = 0XFF;
     WE = 1;
     P0 = 0XFB; //1111 1011
     WE = 0;
     DU = 1;
     P0 = tabel[ge];//
     DU = 0;
     delay(5);
    }
    void timer0Init()
    {
     TR0 = 1;  
     TMOD |= 0X05; 
     TH0 = 0;
     TL0 = 0; 
    }
    void timer1Init()
    {
     TR1 = 1;  
     TMOD |= 0X10; 
     TH1 = 0x4b;
     TL1 = 0xfd; 
    }
    void main()
    { 
     uchar mSec, Sec;
     timer0Init();
     timer1Init();
     while(1)
     {
      if(TF1 == 1)
      {
       TF1 = 0;
       TH1 = 0x4b;
       TL1 = 0xfd; 
       mSec++;
       if(mSec == 10) 
       {
        mSec = 0;
        LED1 = ~LED1;
       }     
      }
      display(TL0); 
     } 
    } 
    

    (3)定时器中断:

    #include <reg52.h>
    #include <intrins.h>
    #define uint unsigned int
    #define uchar unsigned char
    sbit DU = P2^6;
    sbit WE = P2^7;
    sbit key_s2 = P3^0;
    sbit key_s3 = P3^1;
    uchar num;
    uchar mSec, Sec;
    uchar code SMGduan[]= {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F,};
    uchar code SMGwei[] = {0xfe, 0xfd, 0xfb};
    void delay(uint z)
    {
     uint x,y;
     for(x = z; x > 0; x--)
      for(y = 114; y > 0 ; y--);   
    } 
    void display(uchar i)
    {
     static uchar wei;   
     P0 = 0XFF;
     WE = 1;
     P0 = SMGwei[wei];
     WE = 0;
     switch(wei)
     {
      case 0: DU = 1; P0 = SMGduan[i / 100]; DU = 0; break;
      case 1: DU = 1; P0 = SMGduan[i % 100 / 10]; DU = 0; break; 
      case 2: DU = 1; P0 = SMGduan[i % 10]; DU = 0; break;  
     }
     wei++;
     if(wei == 3)
      wei = 0;
    }
    void timer0Init()
    {
     EA = 1; 
     ET0 = 1;
     TR0 = 1; 
     TMOD = 0X01; 
     TH0 = 0xED;
     TL0 = 0xFF; 
    }
    void main()
    { 
     timer0Init();
     while(1)
     {
      if(key_s2 == 0)
      {
       delay(20);
       if(key_s2 == 0)
       {
        if(num != 120)
        num++;
        while(!key_s2);
       } 
      }
      if(key_s3 == 0)
      {
       delay(20);
       if(key_s3 == 0)
       {
        if(num > 0)
         num--;
        while(!key_s3);
       } 
      }
     } 
    } 
    void timer0() interrupt 1
    {
     TH0 = 0xED;
     TL0 = 0xFF; 
     display(num);  
    }
    
    展开全文
  • 外部中断和定时器中断

    万次阅读 多人点赞 2018-11-20 14:14:26
    1.什么是中断 2.中断有什么用 3.双重功能的P3引脚 4.8051的 中断体系 5.中断特殊寄存器 6.中断的优先级 7.中断服务程序的编写 8.外部中断实现代码 9.定时器/计数器中断工作原理 10.定时器/计数器定时值的...

    1.什么是中断

    2.中断有什么用

    3.双重功能的P3引脚

    4.8051的 中断体系

    5.中断特殊寄存器

    6.中断的优先级

    7.中断服务程序的编写

    8.外部中断实现代码

    9.定时器/计数器中断工作原理

    10.定时器/计数器定时值的计算

    11.定时器/计数器实现代码

    1.什么是中断

    中断就是指CPU正在执行一项任务A,然后突然停止任务A去执行任务B,执行完任务B再回来继续执行任务A的过程。

    例如:你正在看电视,然后电话响了,你就停止看电视,跑去接电话,接完电话后由回来继续看电视。这个过程叫中断。


    中断跟硬件有关。可以说是硬件来让单片机中断。

    2.中断有什么用 

    1.中断能让CPU同时执行多项任务,例如CPU在执行流水灯程序,就无法执行 按下按键时,蜂鸣器发声了。

    2.当然上面的例子可以用软件轮询检擦案件是否按下来实现,但这样就消耗了CPU一部分资源来轮询检测 按键是否有按下了,所以中断的另一个优点就是

       节省CPU资源

    3.双重功能的P3引脚

    由最小系统板的原理图可知,P3.0~P3.7的引脚对应着RXD,TXD,INTO,INT1,T0,T1等,说明P3引脚既是 I/O口,由有别的功能,这个功能就是中断功能。

    4.8051中断体系

    8051的单片机有5个中断源,2个优先级

    由上图可知,INT0是通过引脚P3.2,INI1时通过引脚P3.3,定时器T0和T1是分别通过引脚P3.4和P3.5的


    中断源:INT0(外部中断0),INT1(外部中断1),T0(定时器0),T1(定时器1),RXD和TXD(同属串口中断)

    中断相关的特殊寄存器:

    (1)中断允许控制寄存器(IE)--------控制各中断的开放和屏蔽

    (2)定时器/计数器控制寄存器(TCON)-------定时器和外部中断的控制

    (3)串行口控制寄存器(SCON)-------串行中断的控制

    (4)中断优先级控制寄存器(IP)-------设置各中断的优先级


    各寄存器的控制范围如下图:

    从上图可看出从中断源产生请求到请求进入CPU的过程:

    以INT0为例,INT0产生中断源,经过TCON寄存器中的IT0为选择是下边沿触发的还是低电平触发的中断请求(当然IT0是程序人工设置的),当中断请求到达IE0的时候,

    IE0会被硬件置1(当CPU响应此中断请求时,IE0被硬件置0),然后就到 IE寄存器的地方了,EX0是外部中断INT0的开关,而 EA 是所有中断的总开关,这都由 IE寄存器

    控制,最后经过 IP寄存器 设置优先级,这个一般比较少用,默认的优先级为,INT0 > T0 > INT1 > T1 >串口中断。最后把中断请求传给CPU。

    5.中断特寄存器

    TCON寄存器

    IE寄存器

    EA:中断的总开关,EA=1才能允许中断传给CPU

    ES:串行口中断开关

    ET1:定时器1中断开关

    EX1:外部中断1开关

    ET0:定时器0中断开关

    EX0:外部中断0开关

    IP优先级寄存器(对应为设置成1说明优先级设置成高,8051只有高低两种优先级)

    6.中断的优先级

    8051只有高低两种优先级,默认下优先级从高到低:INT0 > T0 > INT1 > T1 > 串行中断。

    1.高优先级的中断可以打断低优先级的中断。

    2.正在响应的中断,不能被同级或者低级的中断打断。

    3.同时发生几个中断,先响应优先级高的中断

    7.中断服务程序的编写

    中断服务程序就是中断发生后,CPU去执行的函数。

    1.中断服务函数没有返回值

    2.中断服务函数不能传入参数


    例如:

    void  函数名 (void)  interrupt  x  using  y

    {

    }

    x 范围为0~4,分别代表5个中断源,例如外部中断INT0就是0,T0就是1,INT1就是2,T1就是3,串行中断就是4

    y 的范围为0~3,分别表示4组工作寄存器,不写就用0. 不写也可以

    8.外部中断实现代码

    ##includeinclude<reg52.h><reg52.h>
    sbit LED=P1^sbit LED=P 0;
    void main()
    {
        IT0=0;  //中断触发方式为低电平触发,IT0=1则为下边沿触发
        EX0=1;  //打开外部中断0
        EA=1;    //打开中断总开关
        while(1)
        {
            LED=1;   //在没有中断发生时,LED关闭
        }
    }
     
    void INTERR(void) interrupt 0
    {
        LED=0;//有中断发生时,LED亮起
    }

    把开发板的P3.2用杜邦线接到GND上,就会触发中断,发现LED亮起来了。(为什么是P3.2?因为由最上面的原理图可知道INT0的引脚是P3.2)

    9.定时器/计数器中断工作原理

    1.由最上面的最小系统原理图可以看出,定时器T0和T1分别对应的引脚是P3.4和P3.5

    2.定时器/计数器 的计数脉冲来源可以有两个,一个是芯片内部晶振振荡器输出脉冲12分频后的脉冲,一个是从外部接入的外部脉冲


    3.TLx和THx寄存器,x=0,1。

    以TL0和TH0为例,TL0和TH0 都是8位寄存器(8051的寄存器都是8位),所以TL0和TH0形成高八位和低八位寄存器,用于计数,一共16位。

    2^16=65536,所以 TL0和TH0加一起最大能计数的值是0~65536,一共65536.


    4.定时器/计数器的两个寄存器:TCON和TMOD,其中TCON用于开启定时器/计数器中断,TMOD用于设置定时器/计数器的工作方式(TCON上面 已经说过了)

    TMOD寄存器:

    (由图:低八位为定时器T0,高八位为定时器T1)

    GATE:门控制。

    当GATE=1:INTx引脚为高电平且TRx 要同时为1,定时器Tx才启动。

    当GATE=0:只要TRx =1,定时器Tx就启动,不用理会INTx引脚的电平高低。


    C/T:决定是使用 定时功能,还是 计数功能

    当C/T=0:定时功能。加1计数器对芯片晶振12分频的脉冲计数,一个脉冲过来,就加一,直到 TFx 加满了溢出。(TFx在TCON寄存器中)
    当C/T=1:计数功能。加1计数器对来自输入引脚T0(P3.4)或T1(P3.5)的外部脉冲进行计数,一个脉冲加一,直到TFx加满溢出。

    M1和M0:工作方式选择位


    M0    M1    工作方式    功能说明
    0    0    方式0    13位定时器/计数器,最大计数为2^13 = 8192
    0    1    方式1    16位定时器/计数器,最大计数为2^16 = 65536
    1    0    方式2    自动重载8位定时器/计数器,最大计数为 2^8 = 256
    1    1    方式3    T0分为2个独立的8位独立计数器,T1停止工作

    10.定时器/计数器定时数值的计算

    例:我要定时10ms。晶振频率是12M,工作模式在方式1

    f = 12M/12 =1M   (因为要12分频),也就是说 1秒 1000000个机器周期,10ms有10000个机器周期。

    65536 - 10000 = 55536 ,意思是 计数器从65536 一直减到 55536 所用的时间就是10ms。

    55536的十六进制是0xD8F0

    所以设置 TH0 = 0XD8,TL0=0XF0

    下面给出代码

    或者直接下载一个C51定时器计算器:

    11.定时器/计数器代码

    #include<reg52.h>
    sbit LED0=P1^0;
    unsigned char i;
     
    void main()
    {
        TMOD=0X01;  //设置使用定时器0,16位的定时/计数寄存器
        TL0=0xD8;    //低八位赋初值
        TH0=0XF0;    //高八位赋初值
        ET0=1;          //开启定时器0中断
        TR0=1;         //运行定时器0
        EA=1;          //开启中断总开关
        while(1);
    }
     
    void Delay(void) interrupt 1 using 0
    {
        i++;
        TR0=0;           //进入中断函数时,关闭定时器
        TL0=0XD8;    //重新赋初值
        TH0=0XF0;
        if(i==20)        //因为10ms一次处罚看不出明显结果,所以让20次触发才让灯变一次
        {
            LED0=~LED0;
        }
        TR0=1;     //重新开启定时器
    }


     

    展开全文
  • 单片机中断原理及定时器详解

    万次阅读 多人点赞 2018-04-22 17:20:21
    中断的概念什么是中断:CPU在处理某一事件A时,发生的另外某一事件B请求CPU去处理(产生了中断),随后CPU暂时中断当前正在执行的任务,去对事件B进行处理,CPU处理完事件B后再返回之前中断的位置继续执行原来的事件...
  • STM32复习笔记(七)定时器&定时器中断

    千次阅读 多人点赞 2018-09-11 07:16:28
    声明:本篇文章只是个人知识盲区、知识弱点、重点部分的归纳总结,望各位大佬不喜勿喷。梳理顺序是按照正点原子的视频和文档的实际顺序梳理,转载请注明出处。...定时器中断   一、STM32定时器: STM32F10x系列...
  • 定时器中断

    2017-06-21 22:43:52
    TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%6; EA=1; ET0=1; TR0=1;   void timer0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%6;...//开总中断允许  ET0=1
  • stm32f103定时器中断

    千次阅读 2018-11-04 20:52:33
    stm32为我们提供了8个定时器,分为:通用是定时器(TIM2~TIM5),高级定时器(TIM1和TIM8),基本定时器(TIM6和TIM7)。 至于三者之间的区别可以参考以下博客:https://blog.csdn.net/dukai392/article/details/72058041...
  • 定时器中断实验

    千次阅读 2019-07-29 10:58:59
    STM32的通用定时器是一个通过可编程预分频器(PSC)驱动的16位自动装载计数器(CNT)构成。STM32的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和PWM)。使用定时器预分频...
  • stm32中定时器中断的套路

    万次阅读 2018-10-11 18:12:09
    首先要提到的是,在stm32中,定时器相关的库函数主要集中在固件库文件 stm32f10x_tim.h 和 stm32f10x_tim.c 文件中,所以在进行定时器方面的处理时,需要加载这两个文件进来。在进行定时器操作时,一般按如下步骤来...
  • 51单片机中断系统(定时器、计数器)

    万次阅读 多人点赞 2017-11-21 00:17:12
    一、中断 中断是指计算机运行过程中,出现某些意外情况需主机干预时,机器能自动停止正在运行的程序并转入处理新情况的程序,处理完毕后又返回原被暂停的程序继续运行。 (*以上解释来自于百度百科-中断)   二...
  • 定时器系统是单片机内部一个独立硬件部分,与CPU和晶振之间通过内部某些控制线连接并相互作用,CPU一旦启动定时功能,定时器便会在晶振的作用下自动计时,当定时器计数器积满之后就会产生中断,通知CPU接下来做什么...
  • 【STM32】HAL库 STM32CubeMX教程六----定时器中断

    万次阅读 多人点赞 2020-03-26 10:10:44
    是我们学习STM32最频繁使用到的外设之一,所以一定要掌握好,这节我们讲解定时器中断,本系列教程将对应外设原理,HAL库与STM32CubeMX结合在一起讲解,使您可以更快速的学会各个模块的使用 所用工具: 1、芯片:...
  • 串口1每1秒给32发一串数据,通过...串口而是被动的,只有32给他发送数据0x01,它才给32回一串数据,定时器中断产生定时时长,用来发送那个0x01,现在的问题是32在定时器和串口同时工作的情况下,接收到的串口数据有错。
  • 虽然有很多库可以直接用,但是据说精度只有ms级,也不知道为什么只到ms级。 类似51程序中的定时器配置。
  • 定时器的实现依赖的是CPU时钟中断,时钟中断的精度就决定定时器精度的极限。一个时钟中断源如何实现多个定时器呢?对于内核,简单来说就是用特定的数据结构管理众多的定时器,在时钟中断处理中判断哪些定时器超时,...
  • STM32HAL库定时器中断关闭的方法

    千次阅读 2019-03-07 18:00:02
    本文可以用于解决这个问题:定时器中断上电后莫名其妙开启,或者首先触发一次。 STM32HAL库在定时器初始化并开启以后,也是会默认开启中断。如不需要默认就开启中断可以用一下代码关闭: __HAL_TIM_CLEAR_FLAG(&...
  • 单片机MSP430 - Timer_A 定时器中断程序

    万次阅读 2016-11-21 11:18:35
    一、利用定时器定时功能,实现定时器单个溢出中断,实现 P3.0 方波输出 #include "cc430x613x.h" void main() { WDTCTL = WDTPW + WDTHOLD; // 停止看门狗定时器 P3DIR |= 0x04; // P3口初始化,设置为输出模式
  • STM32定时器中断时间计算

    万次阅读 2019-06-04 10:39:56
    关于STM32定时器,TIMx(1-8),在库设置默认的情况下,都是72M的时钟; 名为TIMx的有八个,其中TIM1和TIM8挂在APB2总线上,而TIM2-TIM7则挂在APB1总线上。其中TIM1&TIM8称为高级控制定时器(advanced control ...
  • 定时器中断,单片机中断处理时间大于定时器定时时间会怎样? 如果是不同的中断类型是可以根据优先级嵌套,如果是同一中断类型(如题), 有三种结果:1、马上进入新的中断处理(中断嵌套) 2、等待中断处理完再...
1 2 3 4 5 ... 20
收藏数 61,639
精华内容 24,655
关键字:

定时器中断