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

当 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 定时器中调用上面的显示函数就可以了。
三:实物演示如下所示:

我要赚赏金
