这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 嵌入式开发 » 国产MCU » 学习AI8051开发板例程:03AI8051定时器的功能调试(二)

共1条 1/1 1 跳转至

学习AI8051开发板例程:03AI8051定时器的功能调试(二)

高工
2025-11-07 18:56:05     打赏

在之前的帖子中,介绍过使用ST公司的芯片实现外部电平的持续时间,今天尝试在STC的芯片上面测试一下。

一:定时器的模式:

1107-1.png

当 GATE=0(TMOD.7)时,如 TR1=1,则定时器计数。GATE=1 时,允许由外部输入 INT1 控制定时器 1,这样可实现脉宽测量。TR1为TCON 寄存器内的控制位,TCON 寄存器各位的具体功能描述见上节 TCON 寄存器的介绍。

当 CT=0 时,多路开关连接到系统时钟的分频输出,T1 对内部系统时钟计数,T1 工作在定时方式。当C/T=1 时,多路开关连接到外部脉冲输入 P3.5/T1,即 T1 工作在计数方式。

单片机的定时器1有两种计数速率:一种是 12T模式,每 12 个时钟加 1,与传统 8051单片机相同:另外一种是 1T 模式,每个时钟加 1,速度是传统 8051 单片机的 12 倍。T1 的速率由特殊功能寄存器 AUXR 中的 T1x12 决定,如果 T1x12=0,T1 则工作在 12T 模式:如果 T1x12=1,T1 则工作在 1T 模式

定时器1有两个隐藏的寄存器RL TH1和 RI TL1。RL TH1与TH1 共有同一个地址,RL TL1与 TL1共有同一个地址。当 TR1=0 即定时器/计数器1被禁止工作时,对 TL1 写入的内容会同时写入 RL TL1,对TH1 写入的内容也会同时写入 RL TH1。当 TR1=1 即定时器/计数器1被允许工作时,对 TL1 写入内容,实际上不是写入当前寄存器 TL1 中,而是写入隐藏的寄存器 RL TL1中,对 TH1 写入内容,实际上也不是写入当前寄存器 TH1 中,而是写入隐藏的寄存器 RL TH1,这样可以巧妙地实现 16 位重装载定时器。当读 TH1和 TL1 的内容时,所读的内容就是 TH1 和 TL1 的内容,而不是 RL TH1 和 RL TL1 的内容。

当定时器1工作在模式1(TMOD[5:4]/[M1.M0]=00B)时,[TH1,TL1]的溢出不仅置位 TF1,而且会自动将[RL TH1.RL IL1]的内容重新装入[TH1,IL1]。

当 T1CLKO/NT CLKO.1=1 时,P3.4/T0 管脚配置为定时器1的时钟输出 T1CLKO。输出时钟频率为 T1溢出率/2。

如果 C/T=0,定时器/计数器 T1对内部系统时钟计数,则:

T1 工作在 1T 模式(AUXR.6/T1x12=1)时的输出时钟频率=(SYSclk)/(TM1PS+1)/(65536-[RL TH1,RL TL1])/2T1工作在 12T 模式(AUXR.6/T1x12=0)时的输出时钟频率=(SYScIk)/(TMIPS+1)/12/(65536-RL TH1.RL TL1])/2

如果 C/T=1,定时器/计数器 T1 是对外部脉冲输入(P3.5/T1)计数,则:输出时钟频率=(T1 Pi CLK)/(65536-[RL TH1,RL TL1])/2

二:软件代码编写:

2.1:定时器1的初始化过程:

定义一下,定时器1 进入的中断时间,这里我配置为0.1s。

#define Timer1_Reload   (MAIN_Fosc / 10000)     //Timer 1 中断频率, 10000次/秒

定时器1初始化:

void Timer1_init(void)
{
        TR1 = 0;    //停止计数

    #if (Timer1_Reload < 64)    // 如果用户设置值不合适, 则不启动定时器
        #error "Timer1设置的中断过快!"

    #elif ((Timer1_Reload/12) < 65536UL)    // 如果用户设置值不合适, 则不启动定时器
        ET1 = 1;    //允许中断
    //  PT1 = 1;    //高优先级中断
        TMOD &= ~0x30;
        TMOD |= (0 << 4);   //工作模式, 0: 16位自动重装, 1: 16位定时/计数, 2: 8位自动重装
    //  T1_CT = 1;  //计数
        T1_CT = 0;  //定时
    //  T1CLKO = 1; //输出时钟
        T1CLKO = 0; //不输出时钟

        #if (Timer1_Reload < 65536UL)
            T1x12 = 1;  //1T mode
            TH1 = (u8)((65536UL - Timer1_Reload) / 256);
            TL1 = (u8)((65536UL - Timer1_Reload) % 256);
        #else
            T1x12 = 0;  //12T mode
            TH1 = (u8)((65536UL - Timer1_Reload/12) / 256);
            TL1 = (u8)((65536UL - Timer1_Reload/12) % 256);
        #endif

        TR1 = 1;    //开始运行

    #else
        #error "Timer1设置的中断过慢!"
    #endif
}

2.2:定时器1的中断函数:

软件读取P3.3 IO口电平,然后计算低电平的持续时间:

void timer1_int (void) interrupt 3
{
   if(!P33)
   {
      Temp_cnt++;
   }
   else
   {
      if(Temp_cnt>10)		//有效信号 > 1ms
      {
         Test_cnt = Temp_cnt;
      }
      Temp_cnt = 0;
   }
}

2.3 :上电数码管显示,当前监测低电平的持续时间。

void Display(void)
{
    u8  i;
    
    LED8[3] = Test_cnt / 10000;
    LED8[4] = (Test_cnt % 10000) / 1000;
    LED8[5] = (Test_cnt % 1000) / 100;
    LED8[6] = (Test_cnt % 100) / 10;
    LED8[7] = Test_cnt % 10;
    
    for(i=3; i<7; i++)  //消无效0
    {
        if(LED8[i] > 0) break;
        LED8[i] = DIS_BLACK;
    }
}

在主函数的1ms 定时器中调用上面的显示函数就可以了。

三:实物演示如下所示:

1107-2.jpg





关键词: AI8051     定时器     外部中断监测低电平    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]