Technologieaustausch

04: Timer

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina


Wenn der Timer verwendet wird, ist er zum Zählen auf die interne Oszillatorschaltung angewiesen. Bei der Konfiguration für Timer-Nutzung wird der Wert des Zählerspeichers bei jedem Maschinenzyklus um 1 erhöht.

1. So stellen Sie den Timer ein

1. Der Quarzoszillator (Kristalloszillator) sendet Impulse aus und zeichnet die Anzahl der Impulse zur Zeitmessung auf.
2. Die Frequenz des Impulses ist die Taktfrequenz, und der Kehrwert dieser Frequenz ist die Schwingungsperiode (Taktzyklus), die auch die kleinste Zeiteinheit im Computer ist.
Fügen Sie hier eine Bildbeschreibung ein

Wie in der Abbildung gezeigt: Die Frequenz des Quarzoszillators beträgt 11,0592 MHz, dann beträgt sein Taktzyklus 1/11,0592 MHz (Sekunde), d. h. ein Impulszyklus dauert so viele Sekunden.

3. Der Maschinenzyklus ist der CPU-Zyklus, und die für eine Grundoperation erforderliche Zeit wird als Maschinenzyklus bezeichnet. Im Allgemeinen besteht ein Maschinenzyklus aus mehreren Taktzyklen. Normalerweise ist es 12-mal/6-mal.
Fügen Sie hier eine Bildbeschreibung ein

Fügen Sie hier eine Bildbeschreibung ein

  • Wie viel Zeit ist seit dem Hinzufügen von 1 vergangen?
    Wenn die Quarzoszillatorfrequenz 11,0592 MHz beträgt, entspricht sie 11059,2 kHz = 11059200 Hz
    Maschinenzyklen = 12 x Taktzyklen = 12 x (1/Taktfrequenz) Sekunden = 12 / Taktfrequenz Sekunden = 12 / 11059200 Sekunden = 12 000 000 / 11059200 Mikrosekunden = 1,085 (us)
    Das heißt: Wenn ein Vielfaches von 12 verwendet wird, erhöht der Zähler alle 1,085 us den Wert um 1

2. Wie implementiert man das Zählen?

Durch Konfiguration der relevanten Register: Die folgende Abbildung zeigt die relevanten Register des Timers.
Fügen Sie hier eine Bildbeschreibung ein

  • Wie in der Abbildung gezeigt, gibt es zwei Register: das erste ist TCON und das zweite ist TCOM, beide sind jeweils 8 Bit.
  • Wie in der Abbildung gezeigt, gibt es zwei Arten von Timern: Der erste ist der Bit-Timer T0 und der zweite ist der Timer T1. Beide haben jeweils 16 Bit.

2.1. Steuerregister TCON

Fügen Sie hier eine Bildbeschreibung ein

TF0:定时器T0溢出中断标志,当定时器0开始计数时,计数到规定的时间时,定时器产生了溢出。TF0自动由0变位1(由硬件置1)。
如果不用中断,需要手动清零。

TR0:定时器T0的控制位,当为1时,定时器T0才能计数,相当于T0的开关(由软件控制)。
  • 1
  • 2
  • 3
  • 4

2.2. Arbeitsmodusregister TCOM

Fügen Sie hier eine Bildbeschreibung ein

GATE:门控制位,当GATE=0时:计数条件只有TR1一个(TR1=1就计数,TR1=0就不计数)。
			   当GATE=1时:是否计数不仅取决于TR1还取决于INT1引脚
C/T :时钟输入选择为,为1时,时钟从外部引脚P3.5口输入;为0时,时钟从内部输入
M1      M0
0        0        :13位定时器,使用高8位和低5位
0        1        :16位定时器,全用
1        0        :8位自动重装载定时器,当溢出时将TH1存放的值自动重装入TL1.
1        1        :定时器无效
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

2.3. Timer T0

Fügen Sie hier eine Bildbeschreibung ein

Der Timer T0 hat insgesamt 16 Bits, aufgeteilt in die oberen 8 Bits TH0 und die niedrigen 8 Bits TL0. Daher können insgesamt 2 ^ 16 Zahlen (65536) gezählt werden, und der Zyklus zum Zählen einer Zahl beträgt 1,085 us. Daher wird standardmäßig mit dem Zählen bei 0 begonnen und die kumulative Zeit beträgt etwa 71 ms.

3. Fall: Verwenden Sie den Timer T0, um die LED so zu steuern, dass sie sich in Intervallen von 1 Sekunde ein- und ausschaltet.

Code ①:

#include <REGX52.H>

sbit LED1 = P3^7;
void main(void)
{
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	
/*1、选择定时器T0,并配置为16位定时器*/
	TMOD =0x01;							// 0000 0001
	
/*
	2、定一个10ms的时间,数1下需要1.085us
	10ms需要数则需要数9216下,那从65536-9126=56320
	从56320这里开始数,数9216下就到了65536。当超过了
	65536时就报表了,控制寄存器TCON的TF0由0变为1	
*/
	TL0 = 0x00; //0000 0000
	TH0 = 0xDC;//1101 1100
	
/*3、打开定时器T0*/
	TR0 = 1;
	
	TF0 = 0;//先个溢出标志清零
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

【Notiz】

  • Nach jeder Meldung muss dem Timer ein neuer Anfangswert zugewiesen werden.
  • cnt erhöht sich alle 10 Millisekunden um 1. Wenn cnt auf 100 steigt, bedeutet dies, dass 1 Sekunde vergangen ist.

Codeoptimierung②:

#include <REGX52.H>

sbit LED1 = P3^7;

void Timer0_Init_10ms(void)//定时器初始化10ms
{
	TMOD =0x01;							
	
	TL0 = 0x00; //0000 0000
	TH0 = 0xDC;//1101 1100
	
	TR0 = 1;
	TF0 = 0;
}

void main(void)
{ 
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	Timer0_Init_10ms();
	
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
			
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

Kapseln Sie die Timer-T0-Initialisierung in eine Funktion und rufen Sie sie bei Bedarf direkt auf.
Aber die Verwendung von TMOD = 0x01; eine solche Initialisierung weist auch Mängel auf:

假如定时器T1正在使用,且为16位定时器。则TMOD的高4位应该为:0x1(0001)
而我们使用定时器T0时TMOD初始为0x01,则TMOD的高4位为0x0(0000),则把定时器T1变为一个13位定时器了。所以还需要改进
  • 1
  • 2

Codeoptimierung ③:

#include <REGX52.H>

sbit LED1 = P3^7;

void Timer0_Init_10ms(void)		//10毫秒@11.0592MHz
{
	//AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0xDC;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void main(void)
{ 
	int cnt = 0;
	LED1 = 1;//先让灯熄灭的状态
	Timer0_Init_10ms();
	
	while(1)
	{
		if(TF0 == 1)//10ms报表了
		{	
			TF0 = 0;//软件清零,现在不使用中断
			TL0 = 0x00; //重新给初值
			TH0 = 0xDC;
			cnt++;
			if(cnt == 100)//数100次,相当于1s
			{
				cnt = 0;
				LED1 = !LED1;
			}
			
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

Wir finden, dass die Initialisierung von TMOD ist:

TMOD &= 0xF0;		//设置定时器模式
TMOD |= 0x01;		//设置定时器模式
  • 1
  • 2

Welche Vorteile bietet eine solche Initialisierung?

假如定时器T1正在使用,且为16位定时器。则TMOD的高4位应该为:0x1(0001),而要使用定时器T0,且也为16位定时器,则TMOD =  0x11;
TMOD &= 0xF0;表示TMOD = TMOD & 0xf0,则与出来的TMOD = 0x10,由此可见,这一步就是让TMOD的高4位不变,低4位清零。
TMOD |= 0x01;表示TMOD = TMOD | 0x01,则或出来的TMOD = 0x11,由此可见,这一步就是让TMOD的高4位不变,低4位初始化。
通过这样初始化,既保证了TMOD的高4位不变(不改变定时器T1的初始化),由对低4位进行了改变(对定时器T0初始化)。
当然:也可以直让TMOD = 0x11;
  • 1
  • 2
  • 3
  • 4
  • 5