zoukankan      html  css  js  c++  java
  • N76E003的定时器/计数器 0和1

    定时器/计数器 0和1
    N76E003系列定时器/计数器 0和1是2个16位定时器/计数器。每个都是由两个8位的寄存器组成的16位计数寄存器。

    对于定时器/计数器0,高8位寄存器是TH0、 低8位寄存器是TL0。

    同样定时器/计数器1也有两个8位寄存器, TH1 和TL1。

     

     TCON 和 TMOD 可以配置定时器/计数器0和1的工作模式。

    通过TMOD中的 位来选择定时器或计数器功能。

    每个定时器/计数器都有选择位,TMOD的第2位选择定时器/计数器0功能,TMOD的第6位选择定时器/计数器1功能。

    将它们设置为定时器后,定时器将对系统时钟周期计数。

    定时器0通过设置T0M(CKCON.3)位,定时器1通过设置T1M(CKCON.4)位,来选择定时器时钟是系统时钟(FSYS)的12分频或直接是系统时钟。

     

    在计数器模式下,每当检测到外部输入脚T0上的下降沿,计数寄存器的内容就会加一。如果在一个时钟周期采样到高电平,在下一个时钟周期采样到低电平,那么T0或T1引脚就会确认为一个由高到低的跳变。

    当有定时器溢出发生,定时器0和1能配置引脚T0/T1自动翻转输出。

    这个功能通过设P2S寄存器的T0OE和T1OE来设置,分别对应于定时器0和定时器1。当打开这个功能,输出端口在第一个定时溢出之前输出逻辑1。为确保此模式功能, 位应该被清除并且选择系统时钟作为定时器的时钟源。

    注意:TH0(TH1)和TL0(TL1)是独立分开访问。需要特别注意,在模式0或模式1下时,当读/写TH0(TH1)和TL0(TL1)之前,必须清除TR0(TR1)来停止计时。否则将产生不可预料的结果。

    模式0(13位定时器)
    在模式 0, 定时器/计数器是13位的计数器。13位的计数器由TH0 (TH1) 和TL0 (TL1)的低五位组成。TL0 (TL1)的高三位被忽略。当TR0 (TR1)置位且GATE是0或 是1时,定时器/计数器使能。GATE设置为1可以通过定时器来计算外部输入引脚上输入脉冲的宽度。当13位的定时器计数值从1FFFH变为0000H后,定时器溢出标志TF0 (TF1) 置位,如果中断打开,此时会产生一个定时器中断。

     

    #define TH0_INIT        0xFC 
    #define TL0_INIT        0x0F
    #define TH1_INIT        0xE0 
    #define TL1_INIT        0x00
        TMOD = 0XFF;
        Set_All_GPIO_Quasi_Mode;
        TIMER0_MODE0_ENABLE;                        //Timer 0 and Timer 1 mode configuration
        TIMER1_MODE0_ENABLE;
        
        clr_T0M;
        clr_T1M;
        
        TH0 = TH0_INIT;
        TL0 = TL0_INIT;
        TH1 = TH1_INIT;
        TL1 = TL1_INIT;
        
        set_ET0;                                    //enable Timer0 interrupt
        set_ET1;                                    //enable Timer1 interrupt
        set_EA;                                     //enable interrupts
        
        set_TR0;                                    //Timer0 run
    //    set_TR1;                                    //Timer1 run
    TMOD = 0XFF;

     

    Set_All_GPIO_Quasi_Mode; 设置引脚模式

    #define   P14_OpenDrain_Mode   P1M1|=SET_BIT4;P1M2|=SET_BIT4

    
    
        TIMER0_MODE0_ENABLE;                        //Timer 0 and Timer 1 mode configuration

    #define TIMER0_MODE0_ENABLE TMOD&=0xF0

     

    //-------------------- Timer1 function define --------------------
    #define        TIMER0_MODE0_ENABLE        TMOD&=0xF0
    #define        TIMER0_MODE1_ENABLE        TMOD&=0xF0;TMOD|=0x01
    #define        TIMER0_MODE2_ENABLE        TMOD&=0xF0;TMOD|=0x02
    #define        TIMER0_MODE3_ENABLE        TMOD&=0xF0;TMOD|=0xF3
        clr_T0M;
        clr_T1M;
    #define clr_PWMCKS  CKCON   &= ~SET_BIT6
    #define clr_T1M     CKCON   &= ~SET_BIT4
    #define clr_T0M     CKCON   &= ~SET_BIT3
    #define clr_CLOEN   CKCON   &= ~SET_BIT1

        TH0 = TH0_INIT;
        TL0 = TL0_INIT;
        TH1 = TH1_INIT;
        TL1 = TL1_INIT;
    #define TH0_INIT        0xFC //
    #define TL0_INIT        0x0F
    #define TH1_INIT        0xE0 //
    #define TL1_INIT        0x00

     set_TR0;                                    //Timer0 run

     

    
    

    由于定时器方式0位13为计数器,即最多能装载2的13次方个(8192),当TH0与TL0初始值为零时最多经过8192个机器周期该计数器就会溢出一次,,向CPU申请中断。
    时钟周期

    时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12M的晶振,它的时间周期就是1/12 us),是计算机中最基本的、最小的时间单位。

    在一个时钟周期内,CPU仅完成一个最基本的动作。对于某种单片机,若采用了1MHZ的时钟频率,则时钟周期为1us;若采用4MHZ的时钟频率,则时钟周期为250us。由于时钟脉冲是计算机的基本工作脉冲,它控制着计算机的工作节奏(使计算机的每一步都统一到它的步调上来)。显然,对同一种机型的计算机,时钟频率越高,计算机的工作速度就越快。但是,由于不同的计算机硬件电路和器件的不完全相同,所以其所需要的时钟周频率范围也不一定相同。我们学习的8051单片机的时钟范围是1.2MHz-12MHz。

    8051单片机中把一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示)。

    机器周期

    在计算机中,为了便于管理,常把一条指令的执行过程划分为若干个阶段,每一阶段完成一项工作。例如,取指令、存储器读、存储器写等,这每一项工作称为一个基本操作。完成一个基本操作所需要的时间称为机器周期。一般情况下,一个机器周期由若干个S周期(状态周期)组成。8051系列单片机的一个机器周期同6个S周期(状态周期)组成。前面已说过一个时钟周期定义为一个节拍(用P表示),二个节拍定义为一个状态周期(用S表示),8051单片机的机器周期由6个状态周期组成,也就是说一个机器周期=6个状态周期=12个时钟周期。

    指令周期

    指令周期是执行一条指令所需要的时间,一般由若干个机器周期组成。指令不同,所需的机器周期数也不同。对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。
    通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。
    1T、6T、12T这个原本叫 机械周期,现在更多人称为 指令周期;以前标准51单片机,是12T模式的。后来大量单片机厂家的介入,开始对单片机进行提速,于是就出现了 6T、1T模式的单片机。
    时钟周期:是指振荡源的周期,如 外部晶振 10MHz(假设有),那么它的时钟周期就是 1/10MHz=0.1us;(N76E003)
    机械周期:单片机执行一单位指令所需要的 时钟周期 个数,如 1T,就表示,需要 1个时钟周期;12T(AT89C51) 即为 12个时钟周期。这些都只是一单位指令的时间(如自增、自减等),多单位指令时间进行倍乘(如赋值语句需要2个机械周期,即乘以2倍)
    指令周期:早期更多的是用来描述 某条指令执行 需要多少个机械周期,(如自增、自减为 1个机械周期,赋值 2个机械周期,判断 4个机械周期)。随着C语言的大量普及,现在,更多的人用它来代替 机械周期 这个名词,而 指令本身的 周期被人们所忽略,不再深讨了。
    13位的计数器由TH0 (TH1) 和TL0 (TL1)的低五位组成。也就是说先将TH0向左移五位,在或上TL0,即(0xFC<<5)|0X0F=((11111100)<<5)|00001111=1111110000000|00001111=0001 1111 1000 1111=1F8F(8079)
    当13位的定时器计数值从1FFFH变为0000H后(这地方需要仔细理解,我花费了好长时间),定时器溢出标志TF0 (TF1) 置位(定时器溢出标志溢出),如果中断打开,此时会产生一个定时器中断。N76E003例程里选用了16M,选用16MHZ,然后16/12(clr_t0m,可以不选)=1.3MHZ,也就是1/1300000s,
    即(8192-8079)*1/1300000=0.000086923s(即86us)

    这里需要说明的是示波器高电平计一次数低电平计一次数所以,周期需要除以二就是定时器的正确计时时间


    其实也可以按照这种方法来写
    TH0=(8192-X)/32; TL0=(8192-x)%32 这种好处就是更方便计数。
    方式0为13位的定时器/计数器,对定时器T0来说是分成两个寄存器(可以形象地比作容器吧,网上有比我更形象的比喻,我就不多写了,请自行查阅):TH0和TL0的低五位,组成了13位的定时器,当低位TL0计满就向高位TH0移一个数,然后清零。
    以内置16MHZ的晶振来说,经过clr_T0M12分频 ,也就是16/12=1.3MHZ,对于N76E003 这种1T 8051内核来说,一个指令周期就是一个机器周期,就是一个时钟周期,如果从0开始计数,计数到8192时(即0X1FFF)再来一个数就“溢出”产生中断,一次溢出也就是8192/1300000,约等于6.3ms,如果要定时1ms的话就要给他们装一个预装值(初值),总值-需要值=预装值,(8192-(0.001s*1300000(MHZ))=6892
    也就预装值(8192-6892),预装后,定时器从预装值开始加值,定时器溢出中断后,会重新从预装值开始加值加到我们想要的时间就再产生中断,从而达到了定时的目的。如果要定时1s就可以让定时器中断1000ms/1ms=1000次。
    另外一点,TH0和TL0中应该装入的总数是6892,然后把6892对32求模:6892/32装入TH0中,把6892对32求余:6892%32装入TL0中,因为这是两个八位28*28的容器。
    所以就有了
    TH0=(8192-6892)/32
    TL0=(8192-6892)%32
     
    当用定时器的方式0时,为13位计数器,机最多能装载2的13次方,当TL0和TH0的初始值为零时最多经过8192个机器周期,该计数器就会溢出一次,向CPU申请中断。
    总结如下:
    当使用定时器的方式0时,设机器周期为Tcy,定时器产生一次中断的时间为t,那么需要计数的个数为N=t/Tcy,装入THX和TLX中的数分别为
    THX=(8192-N)/32,TLX=(8192-N)%32
    先计算机器周期Tcy,时钟频率为内置的16MHZ,历程中clr——T0M是对其进行了12分频,则为16/12=1.3MHZ,若t=1ms,则需要计数N=t/TCY(即5/1/1300000),这就是在16MHZ12分频下初值的计算方法,如果不进行分频,算法与上述相同。
    这里对32求模是因为定时器1方式0是13为计数器,,技术只是用了TL0的低五位,这五位最多可装载32个数,再加一便会进位,与16位计数器装载256个数有所不同,因此这里在这里是对32求模,求余同理。
    
    
        set_ET1;                                    //enable Timer1 interrupt

               #define set_ET1 ET1 = 1

        set_EA;                                     //enable interrupts

        set_TR0;                                    //Timer0 run
     

    中断服务函数:

    void Timer0_ISR (void) interrupt 1          //interrupt address is 0x000B
    {
        TH0 = TH0_INIT;
        TL0 = TL0_INIT;    
        P12 = ~P12;                                                            // GPIO toggle when interrupt
    }

    模式1(16位定时器)

    模式1与模式0 非常相似,只是模式1下定时器/计数器为16位的,就是说是用THx和TLx的全部16位用来计数。当
    计数值由FFFFH向0000H翻转后,定时器相应的溢出标志TF0(TF1)置1,如果中断使能则将产生中断。

    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_define.h"
    
    //*****************  The Following is in define in Fucntion_define.h  ***************************
    //****** Always include Function_define.h call the define you want, detail see main(void) *******
    //***********************************************************************************************
    #if 0
    //#define        TIMER0_MODE0_ENABLE        TMOD&=0x0F
    //#define        TIMER0_MODE1_ENABLE        TMOD&=0x0F;TMOD|=0x10
    //#define        TIMER0_MODE2_ENABLE        TMOD&=0x0F;TMOD|=0x20
    //#define        TIMER0_MODE3_ENABLE        TMOD&=0x0F;TMOD|=0x3F
    
    //#define        TIMER1_MODE0_ENABLE        TMOD&=0xF0
    //#define        TIMER1_MODE1_ENABLE        TMOD&=0xF0;TMOD|=0x01
    //#define        TIMER1_MODE2_ENABLE        TMOD&=0xF0;TMOD|=0x02
    //#define        TIMER1_MODE3_ENABLE        TMOD&=0xF0;TMOD|=0xF3
    #endif
    
    #define TH0_INIT        50000 
    #define TL0_INIT        50000
    #define TH1_INIT        25000 
    #define TL1_INIT        25000
    
    UINT8 u8TH0_Tmp,u8TL0_Tmp,u8TH1_Tmp,u8TL1_Tmp;
    /************************************************************************************************************
    *    TIMER 0 interrupt subroutine
    ************************************************************************************************************/
    void Timer0_ISR (void) interrupt 1  //interrupt address is 0x000B
    {
        TH0 = u8TH0_Tmp;
        TL0 = u8TL0_Tmp;    
        
        P12 = ~P12;                     // GPIO1 toggle when interrupt
    }
    
    /************************************************************************************************************
    *    TIMER 1 interrupt subroutine
    ************************************************************************************************************/
    void Timer1_ISR (void) interrupt 3  //interrupt address is 0x001B
    {
        TH1 = u8TH1_Tmp;
        TL1 = u8TL1_Tmp;   
    
        P03 = ~P03;                     //P0.3 toggle when interrupt
    }
    /************************************************************************************************************
    *    Main function 
    ************************************************************************************************************/
    void main (void)
    {
       
        Set_All_GPIO_Quasi_Mode;
            TIMER0_MODE1_ENABLE;
            TIMER1_MODE1_ENABLE;
    
        clr_T1M;
        //set_T1M;
    
        u8TH0_Tmp = (65536-TH0_INIT)/256;
        u8TL0_Tmp = (65536-TL0_INIT)%256;    
        u8TH1_Tmp = (65536-TH1_INIT)/256;
        u8TL1_Tmp = (65536-TL1_INIT)%256;
        
        TH0 = u8TH0_Tmp;
        TL0 = u8TL0_Tmp;
        TH1 = u8TH1_Tmp;
        TL1 = u8TL1_Tmp;
        
        set_ET0;                                    //enable Timer0 interrupt
        set_ET1;                                    //enable Timer1 interrupt
        set_EA;                                     //enable interrupts
        set_TR0;                                    //Timer0 run
        set_TR1;                                    //Timer1 run
        while(1);
    }

    u8TH0_Tmp = (65536-TH0_INIT)/256; u8TL0_Tmp = (65536-TL0_INIT)%256;
        u8TH1_Tmp = (65536-TH1_INIT)/256;
        u8TL1_Tmp = (65536-TL1_INIT)%256;
        
        TH0 = u8TH0_Tmp;
        TL0 = u8TL0_Tmp;
        TH1 = u8TH1_Tmp;
        TL1 = u8TL1_Tmp;
    只是模式1下定时器/计数器为16位的,就是说是用THx和TLx的全部16位用来计数。当
    计数值由FFFFH向0000H翻转后,定时器相应的溢出标志TF0(TF1)置1,如果中断使能则将产生中断。

    方式1为16位的定时器/计数器,对定时器T0来说是分成两个寄存器(可以形象地比作容器吧,网上有比我更形象的比喻,我就不多写了,请自行查阅):TH0为高八位,TL0为低八位,组成了16位的定时器,当低位TL0计满就向高位TH0移一个数,然后清零。
    以16Mhz的内置晶振来说,机器周期是(1/16000000)s(1T 8051),当一次溢出也就是65536*1/16 us,约等于4.096ms,如果要定时50ms的话就要给他们装一个预装值(初值),总值-需要值=预装值,
    也就是65536-65536=0,预装后,定时器从预装值(0)开始加值,定时器溢出中断后,会重新从预装值开始加值加到4(约为)ms就再产生中断,从而达到了定时的目的。如果要定时1s就可以让定时器中断1000ms/4ms=500次。
    另外一点,TH0和TL0中应该装入的总数是0,然后把0对256求模:0/256=00装入TH0中,把0对256求余:0%256=0装入TL0中,因为这是两个八位2^8*2^8的容器。
    所以就有了
    TH0=(65535-65535)/256
    TL0=(65535-65535)%256
      

    模式2(8位自动重装载定时器)
    模式2下定时器/计数器为自动重装模式。此模式下TL0(TL1)是一个8位的计数器,TH0(TH1)保存重装计数
    值。当TL0(TL1)溢出后,TCON中的TF0(TF1)标志置位且TH0 (TH1)中内容重装至TL0(TL1),然后继续计数过
    程。重装过程中TH0(TH1)内的值保持不变.该特征最好地适用于UART波特率发生器,不需要连续软件介入。

    void InitialUART0_Timer1(UINT32 u32Baudrate)    //T1M = 1, SMOD = 1
    {
            P06_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
            P07_Quasi_Mode;        //Setting UART pin as Quasi mode for transmit
        
        SCON = 0x50;         //UART0 Mode1,REN=1,TI=1
        TMOD |= 0x20;        //Timer1 Mode2
        
        set_SMOD;            //UART0 Double Rate Enable
        set_T1M;
        clr_BRCK;            //Serial port 0 baud rate clock source = Timer1
     
    #ifdef FOSC_160000
        TH1 = 256 - (1000000/u32Baudrate+1);               /*16 MHz */
    #endif        
    #ifdef FOSC_166000
        TH1 = 256 - (1037500/u32Baudrate);                      /*16.6 MHz */
    #endif
        set_TR1;
            set_TI;                        //For printf function must setting TI = 1
    }
     SCON = 0x50;         //UART0 Mode1,REN=1,TI=1


    TMOD |= 0x20; //Timer1 Mode2

    #define set_SMOD    PCON    |= SET_BIT7

    #define set_T1M     CKCON   |= SET_BIT4

    clr_BRCK;

    #define clr_BRCK T3CON &= ~SET_BIT5

    #ifdef FOSC_160000
    TH1 = 256 - (1000000/u32Baudrate+1); /*16 MHz */
    #endif
    #ifdef FOSC_166000
    TH1 = 256 - (1037500/u32Baudrate); /*16.6 MHz */
    #endif

    已知串口0通信方式1下,波特率为115200bps,系统晶振频率为16MHz,求TL1,TH1中装入的初值(定时器1方式2) 
    解:设初值X,则定时器每计256-X个数溢出一次,每计一个数的时间为一个机器周期,因为是1T 8051架构,所以一个机器周期等于1个时钟周期,由于设置了SMOD 所以计一个数的时间为(1/16MHZ) us(即1/16000000s),则定时器溢出一次的时间为[256-X]/16MHZ
    通常都是固定的,一般都是根据所使用的波特率来求定时器初值。方式1的波特率=      即   (2^smod /32)*T1的溢出率,即  ((2^smod /32)*16000000)/(256-x)

    通常都是固定的,一般都是根据所使用的波特率来求定时器初值。

    TH1 = 256 - (1000000/u32Baudrate+1); 
    256-TH1-1=1000000/u32Baudrate

    u32Baudrate=1000000/(256-TH1-1)
    
    
     set_T1M;
    
        clr_BRCK;            //Serial port 0 baud rate clock source = Timer1

        set_TR1;

            set_TI;                        //For printf function must setting TI = 1
     

    模式3(两组独立8位定时器)
    定时器0和定时器1的模式3有着不同的工作方式。对定时器/计数器1来说模式3会将其停用;

    对定时器/计数器0来说,模式3下TL0和TH0是2个独立的8位计数寄存器。模式3下TL0使用定时器0的控制位:如  GATE, TR0,TL0也可以用来对T0 脚上的1到0 跳变计数,由 计数。TH0 只能对时钟周期计数,并使用定时器/计数器1的控制位(TR1和TF1)。

    当需要额外的8位定时器时可以使用模式3 。

    当定时器0配置为模式3时,定时器1可以通过配置其进入或离开模式3的方式来打开或关闭自己。

    定时器1依然可以工作在模式0、1、2下,但它的灵活性受到限制。虽然基本功能得以维持,但已不能对TF1和TR1进行控制(由上文可知在该模式下该位由定时器0控制)。此时定时器1依然可以使用GATE脚、T1M。它同样可以用作串行口的波特率发生器或其他不需要中断的应用。也就是说当定时器工作在模式3时,定时器1模式依然可以选择但是灵活性受限,不能对TF1和TR1进行控制。

    /*---------------------------------------------------------------------------------------------------------*/
    /*                                                                                                         */
    /* Copyright(c) 2016 Nuvoton Technology Corp. All rights reserved.                                         */
    /*                                                                                                         */
    /*---------------------------------------------------------------------------------------------------------*/
    
    //***********************************************************************************************************
    //  Nuvoton Technoledge Corp. 
    //  Website: http://www.nuvoton.com
    //  E-Mail : MicroC-8bit@nuvoton.com
    //  Date   : Apr/21/2016
    //***********************************************************************************************************
    
    //***********************************************************************************************************
    //  File Function: N76E003 Timer0/1 Mode3 demo code
    //***********************************************************************************************************
    #include "N76E003.h"
    #include "Common.h"
    #include "Delay.h"
    #include "SFR_Macro.h"
    #include "Function_define.h"
    
    //*****************  The Following is in define in Fucntion_define.h  ***************************
    //****** Always include Function_define.h call the define you want, detail see main(void) *******
    //***********************************************************************************************
    #if 0
    //#define        TIMER0_MODE0_ENABLE        TMOD&=0x0F
    //#define        TIMER0_MODE1_ENABLE        TMOD&=0x0F;TMOD|=0x10
    //#define        TIMER0_MODE2_ENABLE        TMOD&=0x0F;TMOD|=0x20
    //#define        TIMER0_MODE3_ENABLE        TMOD&=0x0F;TMOD|=0x3F
    
    //#define        TIMER1_MODE0_ENABLE        TMOD&=0xF0
    //#define        TIMER1_MODE1_ENABLE        TMOD&=0xF0;TMOD|=0x01
    //#define        TIMER1_MODE2_ENABLE        TMOD&=0xF0;TMOD|=0x02
    //#define        TIMER1_MODE3_ENABLE        TMOD&=0xF0;TMOD|=0xF3
    #endif
    
    #define TH0_INIT        (256-100)
    #define TL0_INIT        (256-50)
    #define TH1_INIT        0x00
    #define TL1_INIT        0x00
    
    /************************************************************************************************************
    *    TIMER 0 interrupt subroutine
    ************************************************************************************************************/
    void Timer0_ISR (void) interrupt 1              // interrupt address is 0x000B
    {              
        TL0 = TL0_INIT;                             // reload by software    
        P12 = ~P12;                                 // GPIO1 toggle when interrupt
    }
    
    /************************************************************************************************************
    *    TIMER 1 interrupt subroutine
    ************************************************************************************************************/
    void Timer1_ISR (void) interrupt 3              //interrupt address is 0x001B
    {           
        TH0 = TH0_INIT;
            Send_Data_To_UART0(0x54);                                        //print charater "T" means timer interrupt
            P12 = ~ P12;                                                    //Mark UART output to find the real timer interrupt timming.
    }
    
    /************************************************************************************************************
    *    Main function 
    ************************************************************************************************************/
    void main (void)
    {
        Set_All_GPIO_Quasi_Mode;
            InitialUART0_Timer3(115200);
        
            TIMER0_MODE3_ENABLE;
            TIMER1_MODE3_ENABLE;
        
        TH0 = TH0_INIT;                             //initial counter values 
        TL0 = TL0_INIT;    
        TH1 = TH1_INIT;
        TL1 = TL1_INIT;    
        
        set_ET0;                                    //enable Timer0 counter interrupt
        set_ET1;                                    //enable Timer1 counter interrupt
        set_EA;                                     //enable interrupts
        set_TR0;                                    //Timer0 run
        set_TR1;                                    //Timer1 run
        
        while(1);
    }
    #define        TIMER1_MODE3_ENABLE        TMOD&=0xF0;TMOD|=0xF3
    #define TH0_INIT        (256-100)
    #define TL0_INIT        (256-50)
    #define TH1_INIT        0x00
    #define TL1_INIT        0x00
    
    /************************************************************************************************************
    *    TIMER 0 interrupt subroutine
    ************************************************************************************************************/
    void Timer0_ISR (void) interrupt 1              // interrupt address is 0x000B
    {              
        TL0 = TL0_INIT;                             // reload by software    
        P12 = ~P12;                                 // GPIO1 toggle when interrupt
    }
    
    /************************************************************************************************************
    *    TIMER 1 interrupt subroutine
    ************************************************************************************************************/
    void Timer1_ISR (void) interrupt 3              //interrupt address is 0x001B
    {           
        TH0 = TH0_INIT;
        P11 = ~P11;                                 //P1.1 toggle when interrupt
    }
    
    /************************************************************************************************************
    *    Main function 
    ************************************************************************************************************/
    void main (void)
    {
       
        Set_All_GPIO_Quasi_Mode;
            TIMER0_MODE3_ENABLE;
            TIMER1_MODE3_ENABLE;
        
        TH0 = TH0_INIT;                             //initial counter values 
        TL0 = TL0_INIT;    
        TH1 = TH1_INIT;
        TL1 = TL1_INIT;    
        
        set_ET0;                                    //enable Timer0 counter interrupt
        set_ET1;                                    //enable Timer1 counter interrupt
        set_EA;                                     //enable interrupts
        set_TR0;                                    //Timer0 run
        set_TR1;                                    //Timer1 run
        
        while(1)
        {
            P1 = TH1;                               //for Timer 1 has no interrupt while Timer 0 in mode 3, show on ports
            P2 = TL1;
        }
    }

    对定时器/计数器0来说,模式3下TL0和TH0是2个独立的8位计数寄存器。

    模式3下TL0使用定时器0的控制位:如  ,GATE, TR0,,TL0也可以用来对T0 脚上的1到0 跳变计数,由TMOD.2()来决定。TH0 只能对时钟周期计数,并使用定时器/计数器1的控制位(TR1和TF1)

    模式三情况如下表所示:

    TH0 TL0 TH1 TL1
    8位计数 8位计数 停用,其他模式可选择但受限 停用,其他模式可选择但受限
    定时器1的控制位(TR1,TF1) 定时器0的控制位 其他模式可以控制GATE、、T1M 其他模式可以控制GATE、、T1M

     当定时器0配置为模式3时,定时器1可以通过配置其进入或离开模式3的方式来打开或关闭自己。定时器1依然可以工作在模

    式0、1、2下,但它的灵活性受到限制。虽然基本功能得以维持,但已不能对TF1和TR1进行控制

    它同样可以用作串行口的波特率发生器或其他不需要中断的应用。

     
  • 相关阅读:
    Linux 安装SonarQube
    Linux 安装postgresql
    如何为chrome浏览器设置socks5代理
    echarts tab切换宽度变为100px解决方案
    将url参数转为对象
    一行js代码实现时间戳转时间格式
    解决问题的方法论
    李笑来的幻灯课
    随便写写(最近更新于2021/07/18早)
    谈谈装系统这件事
  • 原文地址:https://www.cnblogs.com/zhugeanran/p/9180609.html
Copyright © 2011-2022 走看看