技術共有

Puzhong 51 マイクロコントローラー: タイマーとカウンターの詳細な説明と応用 (7)

2024-07-12

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

ここに画像の説明を挿入します

導入

タイマーとカウンターは、時間間隔の測定やイベントのカウントに使用されるハードウェア モジュールです。これらは、正確な時間遅延の生成、周波数の測定、外部イベントのカウントなど、多くのアプリケーションで使用できます。 51 マイクロコントローラーのタイマーはマイクロコントローラーの内部リソースに属し、その回路の接続と動作はマイクロコントローラー内で完了します。この記事では、51 マイクロコントローラーのタイマーとカウンターの動作原理、設定方法、応用について詳しく紹介します。

この章では、割り込み関連の知識について説明します。具体的な内容については、以下を参照してください。割り込みシステムの説明

注: タイマ リソースはマイコンのモデルに関連しており、マイコンのモデルによってタイマの数と動作方法が異なる場合がありますが、一般的に言えば、T0 と T1 の動作方法は 51 個のマイコンすべてに共通です。

タイマーの仕組み

タイマーはマイコン内部にある小さな目覚まし時計のようなもので、時計の出力信号に従って「1秒」ごとにカウント単位の値が1ずつ増えていきます。カウントユニットの値が「設定されたアラームリマインダ時間」まで増加すると、カウントユニットは割り込みシステムに割り込み要求を発行し、「リングリマインダ」を生成し、プログラムを実行のために割り込みサービス関数にジャンプさせます。 。

タイマー/カウンターの動作原理はクロック パルスに基づいています。タイマ モードでは内部クロック ソースを使用してカウントし、カウンタ モードでは外部パルス ソースを使用してカウントします。各タイマー/カウンターには、現在のカウント値を保存するレジスタがあります。

TMODタイマ/カウンタ動作モードレジスタ

タイミングおよびカウント機能は、特殊機能レジスタ TMOD の制御ビットによって制御されます。 CT Csqrt{T}T 選択するには、TMOD レジスタの情報を次の表に示します。 2 つのタイマー/カウンターには 4 つの動作モードがあり、TMOD の M1 および M0 によって選択されることがわかります。 2 つのタイマ/カウンタのモード 0、1、2 は同じですが、モード 3 は次のように異なります。
ここに画像の説明を挿入します

タイマー動作モード

TMOD レジスタの M1 と M0 を設定することにより、タイマ/カウンタ 0 と 1 は 4 つの異なる動作モードを持ちます。

モード0(13ビットタイマ/カウンタ)

ここに画像の説明を挿入します
動作モード図は次のとおりです。
ここに画像の説明を挿入します

モード1(16ビットタイマ/カウンタ)

モード 1 は、TH0 と TL0 の 16 ビットすべてが使用されることを除いて、モード 0 とまったく同じです。このモードでは、TL0 の 8 ビット オーバーフローが TH0 にキャリーされ、TH0 のオーバーフローによって TCON のオーバーフロー フラグ TF0 がセットされます。

GATE=0(TMOD.3)のとき、TR0=1 の場合、タイマーがカウントします。 GATE=1 のとき、外部入力 INTO によるタイマ 0 の制御が許可され、パルス幅測定が可能になります。 TRO は TCON レジスタの制御ビットです。TCON レジスタの各ビットの具体的な機能の説明については、前のセクションの TCON レジスタの概要を参照してください。

注: STC89C51RC/RD+ シリーズ マイクロコントローラのタイマーには 2 つのカウント レートがあります。1 つは 12T モードで、従来の 8051 マイクロコントローラと同じように 12 クロックごとに 1 を加算します。もう 1 つは 6T モードで、6 クロックごとに 1 を加算します。従来の 8051 マイクロコントローラーの 2 倍である T0 レートは、ユーザー プログラムを書き込むときに STC-ISP プログラマーで設定されます。

モード 2 (8 ビットオートリロードモード)

このモードでは、タイマー/カウンタは 8 ビット カウンタを自動的にリロードできます。TL0 のオーバーフローは、TF0 を設定するだけでなく、TH0 の内容を TL0 にリロードします。 (TH0 を最初に設定しても、TH0 の内容は再インストール時に変更されません)
ここに画像の説明を挿入します

モード 3 (2 つの 8 ビット カウンタ)

タイマ 0 の場合、このモードではタイマ 1 がカウントを停止し、その効果は TR1 を 0 に設定したのと同じになります。


タイマ 0 の場合、このモードでは、タイマ 0 の TL0 と TH0 が 2 つの独立した 8 ビット カウンタとして機能します。以下の図は、モード 3 のタイマ 0 のロジック図を示しています。 TL0 はタイマー 0 の制御ビットを占有します。 CT Csqrt{T}T 、GATE、TRO、INTO、TFO。 THO はタイマ機能(カウンタ周期)に限定されており、タイマ 1 の TR1 と TF1 を占有します。このとき、TH0はタイマ1割り込みを制御します。

モード 3 は、8 ビット タイマー/カウンターを追加するために提供されており、マイクロコントローラーに 3 つのタイマー/カウンターを与えます。モード 3 はタイマ/カウンタ 0 にのみ適用されます。タイマ T1 がモード 3 の場合、TR1-0 と同等になりカウントが停止し、T0 を 2 つのタイマとして使用できます。
ここに画像の説明を挿入します

タイマー設定プロセス

  1. TMOD に値を割り当てて、T0 と T1 がどのように機能するかを決定します。
  2. 計時する時間に応じて初期値を計算し、TH0、TL0またはTH1、TL1に書き込みます。
  3. 割り込みを使用する場合は、EA に値を割り当て、タイマー合計割り込みを開きます。
  4. TR0 または TR1 を設定すると、タイマ/カウンタの計時またはカウントが開始されます。

注: STC-ISP プログラミング ツールには、計算する時間の初期値が付属しています。選択したモードに応じてコードをコピーできます。
ここに画像の説明を挿入します

コードのデモ - LED1 が 1 秒間隔で点滅

LED1 インジケータライトは、タイマー 0 割り込みによって 1 秒間隔で点滅するように制御されます。 物理図は次のとおりです。 D1 は P2_0 ピンに接続され、割り込みは 1 ミリ秒間隔でトリガーされます。 1000回ごとに割り込みトリガ機能を使用してカウントします。

#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

コードのデモ - ボタン 1 は LED ランニング ライトのステータスを制御します

このデモでは、INTRINS.H ライブラリの _crol_left シフト関数と _cror_right シフト関数を使用します。KEY1 ボタンを押すと、LED ランニング ライトが方向の状態を切り替えて点滅します。物理画像接続: K1 は P0_0 ピンに接続され、8 つの LED ライトが P2 ピンに挿入されます。

  • クロル(unsigned char val, unsigned char n): 文字を右に回転し、val を右に n ビット回転します。
  • クロル(unsigned char val, unsigned char n): 文字を左に回転し、val を n ビット左に回転します。
#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

コードデモ - LCD1602 タイマークロック表示

このデモ コードでは、LCD1602 モジュールをディスプレイとして使用します。LCD1602 モジュールの詳細については説明しません。特別な章の説明は後ほど説明します。 LCD1602 ライブラリが必要な場合は、個人的に私にメッセージを送ってください。物理的な画像接続: LCD1602 モジュールをボードに接続するだけです。

#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