Technologieaustausch

Mikrocontroller Puzhong 51: Ausführliche Erklärung und Anwendung von Timern und Zählern (7)

2024-07-12

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

Fügen Sie hier eine Bildbeschreibung ein

Einführung

Timer und Zähler sind Hardwaremodule, mit denen Zeitintervalle gemessen oder Ereignisse gezählt werden. Sie können in vielen Anwendungen eingesetzt werden, z. B. zum Erzeugen präziser Zeitverzögerungen, zum Messen von Frequenzen, zum Zählen externer Ereignisse usw. Der Timer des 51-Mikrocontrollers gehört zu den internen Ressourcen des Mikrocontrollers, und die Verbindung und der Betrieb seiner Schaltung werden innerhalb des Mikrocontrollers abgeschlossen. In diesem Artikel werden das Funktionsprinzip, die Konfigurationsmethode und die Anwendung von Timern und Zählern im 51-Mikrocontroller ausführlich vorgestellt.

In diesem Kapitel werden Kenntnisse im Zusammenhang mit Interrupts behandelt. Weitere Informationen finden Sie unter:Erklärung des Unterbrechungssystems

Hinweis: Die Timer-Ressourcen hängen vom Modell des Mikrocontrollers ab. Verschiedene Modelle von Mikrocontrollern können eine unterschiedliche Anzahl von Timern und Betriebsmethoden haben, aber im Allgemeinen sind die Betriebsmethoden von T0 und T1 allen 51 Mikrocontrollern gemeinsam.

So funktioniert der Timer

Der Timer ist wie ein kleiner Wecker im Mikrocontroller. Entsprechend dem Ausgangssignal der Uhr erhöht sich der Wert der Zähleinheit jede „Sekunde“. Wenn der Wert der Zähleinheit auf die „eingestellte Alarm-Erinnerungszeit“ ansteigt, sendet die Zähleinheit eine Interrupt-Anfrage an das Interrupt-System, generiert eine „Ring-Erinnerung“ und veranlasst das Programm, zur Ausführung zur Interrupt-Service-Funktion zu springen .

Das Funktionsprinzip des Timers/Zählers basiert auf Taktimpulsen. Im Timer-Modus verwenden sie eine interne Taktquelle zum Zählen; im Zählermodus verwenden sie eine externe Impulsquelle zum Zählen. Jeder Timer/Zähler verfügt über ein Register, das den aktuellen Zählwert speichert.

TMOD Timer-/Zähler-Betriebsartregister

Die Zeit- und Zählfunktionen werden durch die Steuerbits des Sonderfunktionsregisters TMOD gesteuert. CT Csqrt{T}CT Zur Auswahl sind die Informationen des TMOD-Registers in der folgenden Tabelle aufgeführt. Es ist ersichtlich, dass die beiden Timer/Zähler über vier Betriebsmodi verfügen, die über M1 und M0 von TMOD ausgewählt werden. Die Modi 0, 1 und 2 der beiden Timer/Zähler sind gleich, aber Modus 3 ist unterschiedlich. Die Funktionen in jedem Modus sind wie folgt:
Fügen Sie hier eine Bildbeschreibung ein

Timer-Arbeitsmodus

Durch Setzen von M1 und M0 im Register TMOD haben Timer/Zähler 0 und 1 vier verschiedene Betriebsarten.

Modus 0 (13-Bit-Timer/Zähler)

Fügen Sie hier eine Bildbeschreibung ein
Das Arbeitsmodusdiagramm sieht wie folgt aus:
Fügen Sie hier eine Bildbeschreibung ein

Modus 1 (16-Bit-Timer/Zähler)

Modus 1 ist genau derselbe wie Modus 0, außer dass alle 16 Bits von TH0 und TL0 verwendet werden. In diesem Modus wird der 8-Bit-Überlauf von TL0 an TH0 übertragen, und der Überlauf von TH0 setzt das Überlaufflag TF0 in TCON.

Wenn GATE=0(TMOD.3) und TR0=1, zählt der Timer. Wenn GATE=1, darf der externe Eingang INTO den Timer 0 steuern, sodass eine Impulsbreitenmessung erreicht werden kann. TRO ist das Steuerbit im TCON-Register. Die spezifische Funktionsbeschreibung jedes Bits des TCON-Registers finden Sie in der Einführung des TCON-Registers im vorherigen Abschnitt.

Hinweis: Der Timer des Mikrocontrollers der Serie STC89C51RC/RD+ verfügt über zwei Zählraten: eine ist der 12T-Modus, der alle 12 Takte 1 hinzufügt, genau wie der herkömmliche 8051-Mikrocontroller; der andere ist der 6T-Modus, der alle 6 Takte 1 hinzufügt, die Geschwindigkeit Die T0-Rate, die doppelt so hoch ist wie die des herkömmlichen 8051-Mikrocontrollers, wird beim Brennen des Benutzerprogramms im STC-ISP-Programmierer eingestellt.

Modus 2 (8-Bit-Auto-Reload-Modus)

In diesem Modus kann der Timer/Zähler den 8-Bit-Zähler automatisch neu laden. Der Überlauf von TL0 setzt nicht nur TF0, sondern lädt auch den Inhalt von TH0 in TL0 neu. (TH0 kann zuerst festgelegt werden und der Inhalt von TH0 bleibt während der Neuinstallation unverändert.)
Fügen Sie hier eine Bildbeschreibung ein

Modus 3 (zwei 8-Bit-Zähler)

Für Timer 0 hört Timer 1 in diesem Modus auf zu zählen, und der Effekt ist derselbe, als würde man TR1 auf 0 setzen.


Für Timer 0 fungieren in diesem Modus TL0 und TH0 von Timer 0 als zwei unabhängige 8-Bit-Zähler. Die folgende Abbildung zeigt das Logikdiagramm von Timer 0 im Modus 3. TL0 belegt das Steuerbit von Timer 0: CT Csqrt{T}CT , GATE, TRO, INTO und TFO. THO ist auf die Timerfunktion (Zählerperiode) beschränkt und belegt TR1 und TF1 von Timer 1. Zu diesem Zeitpunkt steuert TH0 den Timer 1-Interrupt.

Modus 3 ist vorgesehen, um einen zusätzlichen 8-Bit-Timer/Zähler hinzuzufügen, wodurch der Mikrocontroller drei Timer/Zähler erhält. Modus 3 gilt nur für Timer/Zähler 0. Wenn sich Timer T1 im Modus 3 befindet, entspricht er TR1-0 und stoppt den Zählvorgang, und T0 kann als zwei Timer verwendet werden.
Fügen Sie hier eine Bildbeschreibung ein

Timer-Konfigurationsprozess

  1. Weisen Sie TMOD Werte zu, um zu bestimmen, wie T0 und T1 funktionieren.
  2. Berechnen Sie den Anfangswert entsprechend der zu messenden Zeit und schreiben Sie ihn in TH0, TL0 oder TH1, TL1.
  3. Wenn Interrupts verwendet werden, weisen Sie EA einen Wert zu und öffnen Sie den Timer-Gesamtinterrupt.
  4. Stellen Sie TR0 oder TR1 ein, um die Zeitmessung oder Zählung des Timers/Zählers zu starten.

Hinweis: Das STC-ISP-Programmiertool enthält den Anfangswert der zu berechnenden Zeit. Sie können den Code entsprechend dem von Ihnen gewählten Modus kopieren.
Fügen Sie hier eine Bildbeschreibung ein

Codedemonstration – LED1 blinkt im 1-Sekunden-Takt

Die LED1-Anzeigeleuchte wird durch den Timer-0-Interrupt so gesteuert, dass sie in Intervallen von einer Millisekunde blinkt. Das physikalische Diagramm ist mit dem P2_0-Pin verbunden Jedes Mal wird die Interrupt-Trigger-Funktion zum Zählen verwendet. Wenn es 1000 ist, ist es eine Sekunde.

#include <REGX52.H>

sbit LED1 = P2^0;

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		LED1 = !LED1;
	}
	count++;
}


void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}


void main()
{
	Timer0_Init();
	while(1)
	{
		
	}	
}
  • 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

Code-Demonstration – Taste 1 steuert den Status des LED-Lauflichts

In dieser Demonstration werden die Shift-Funktionen _crol_left und _cror_right in der INTRINS.H-Bibliothek verwendet. Wenn die Taste KEY1 gedrückt wird, wechselt das LED-Lauflicht den Richtungsstatus und blinkt. Physische Bildverbindung: K1 ist mit dem P0_0-Pin verbunden und die acht LED-Leuchten werden in den P2-Pin eingefügt.

  • kro(unsigned char val, unsigned char n): Rotieren Sie Zeichen nach rechts und rotieren Sie val um n Bits nach rechts.
  • crol(unsigned char val, unsigned char n): Zeichen nach links drehen, Wert um n Bits nach links drehen
#include <REGX52.H>
#include <INTRINS.H>

sbit KEY1 = P0^0;
sbit KEY2 = P0^1;
unsigned char LEDMode;

void DelayXms(unsigned int xms)	//@12.000MHz
{
	unsigned char data i, j;
	
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		if(LEDMode == 0)
			P2 = _crol_(P2,1);
		if(LEDMode == 1)
			P2 = _cror_(P2,1);

	}
	count++;
}

unsigned char Getkey()
{
	unsigned char keyNumber = 0;
	if(KEY1 == 0)
	{
		DelayXms(5);
		while(KEY1 == 0);
		DelayXms(5);
		keyNumber = 1;
	}
	if(KEY2 == 0)
	{
		DelayXms(5);
		while(KEY2 == 0);
		DelayXms(5);
		keyNumber = 2;
	}
	return keyNumber;
}


void main()
{
	unsigned char keyNum = 0;
	P2 = 0xfe;
	Timer0_Init();
	while(1)
	{
		keyNum = Getkey();
		if(keyNum)
		{
			if(keyNum == 1)
			{
				LEDMode++;
				if(LEDMode>=2)
				{
					LEDMode = 0;	
				}
			}
		}
	}
}
  • 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
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95

Code-Demonstration – LCD1602-Timer-Uhr-Anzeige

Dieser Demonstrationscode verwendet das LCD1602-Modul als Anzeige. Das LCD1602-Modul wird nicht im Detail erklärt und spezielle Kapitelanweisungen werden später bereitgestellt. Wenn Sie die LCD1602-Bibliothek benötigen, können Sie mir eine private Nachricht senden. Physischer Bildanschluss: Stecken Sie einfach das LCD1602-Modul auf die Platine.

#include <REGX52.H>
#include "LCD1602.h"

unsigned char Sec=55,Min=59,Hour;//秒分时

void DelayXms(unsigned int xms)	//@12.000MHz
{
	unsigned char data i, j;
	
	while(xms)
	{
		i = 2;
		j = 239;
		do
		{
			while (--j);
		} while (--i);
		xms--;
	}
}

void Timer0_Init(void)		//1毫秒@12.000MHz
{
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x18;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	ET0 = 1;//打开T0中断
	EA = 1;//打开总中断
	TR0 = 1;				//定时器0开始计时
}

void External0_ISR(void) interrupt 1
{
	static unsigned int count = 0;
	TL0 = 0x18;	//需要手动复原			
	TH0 = 0xFC;	//需要手动复原
    // 中断处理代码
	if(count == 1000)
	{
		count = 0;
		Sec++;
		if(Sec == 60)
		{
			Sec = 0;
			Min++;
			if(Min == 60)
			{
				Min = 0;
				Hour++;
				if(Hour == 24)
				{
					Hour = 0;
				}
			}

		}
	}
	count++;
}

void main()
{
	Timer0_Init();
	LCD_Init();
	LCD_ShowString(1,1,"Time:");
	LCD_ShowString(2,1,"00:00:00");
	while(1)
	{
		LCD_ShowNum(2,1,Hour,2);
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowNum(2,7,Sec,2);
	}	
}
  • 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
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75