MS51FB9AE – Giới thiệu về Timer 0 / 1

Ở ví dụ trước mình đã viết code Blink led, tạo delay bằng vòng lặp.
Nhưng như vậy khó tính toán thời gian delay.
Mình tiếp tục giới thiệu về Timer / Counter và ứng dụng để tạo Delay chính xác.
Timer / Counter (T/C) về cơ bản là bộ đếm. Nếu được cấu hình để đếm xung bên trong chip thì được gọi là Timer, còn khi được cấu hình đếm xung từ bên ngoài chip thì được gọi là Counter vì vậy gọi chung là Timer / Counter (mình sẽ viết tắt là T/C).
Như đã nói ở trên T/C sẽ đếm xung, mỗi khi nhận được xung thì nó sẽ tăng giá trị chứa lên 1, chỉ đơn giản như vậy thôi. 🙂
Sơ qua về T/C 0 và T/C 1 của con MS51, nó khá giống nhau nên mình sẽ nói về T/C 0
– Các chế độ hoạt động:
* Chế độ 0

* Chế độ 1

Chế độ 2

Chế độ 3

Phân tích một chút ở chế độ 1: (chế độ 0 và chế độ 1 hoạt động rất giống nhau chỉ khác nhau về số bit)

* Xung đầu vào bộ đếm:
Có 2 trường hợp tùy thuộc vào bit C/T nếu bit C/T bằng 0 thì lúc này sẽ đếm xung từ trong chip và được gọi là Timer
Nếu bit C/T bằng 1 thì lúc này sẽ đếm xung từ chân T0 (đếm xung từ bên ngoài chip), lúc này gọi là Counter.
Trong trường hợp chế độ Timer thì có 2 tùy chọn:
Nếu T0M = 0 thì xung đầu vào bằng xung hệ thống Fsys / 12
Nếu T1M = 1 thì xung đầu vào sẽ bằng xung hệ thống Fsys
* Timer 0 sẽ đếm khi bit TR0 = 1 và dừng khi TR0 = 0
* Bit GATE: khi bit này = 0 thì Timer 0 sẽ đếm miễn là khi TR0 =  1, bất chấp mức logic tại chân INT0
Khi bit này = 1 thì Timer 0 sẽ chỉ đếm khi TR0 = 1 và chân INT0 ở mức logic 1.
Các thanh ghi

Như đã giới thiệu ở trên, giờ mình sẽ dùng Timer 0 chế độ 16 bit để tạo thời gian delay 1ms chính xác.
Fsys sử dụng 16MHz giao động nội.
Mình sẽ cấu hình xung đầu vào Timer 0  bằng Fsys (T0M = 1)
=> muốn đếm được 1ms thì cần 16.000.000 / 1.000 = 16.000 xung.
Hàm delay 1 ms sẽ như sau

void delay_1ms(void)
{
	TH0 = 0;
	TL0 = 0;
	TR0 = 1;
	while (TH0 * 256 + TL0 < 16000) {
	}
	TR0 = 0;
}

Hàm delay sẽ như thế này

void Delay_Ms(uint16_t u16Delay)
{
	while (u16Delay) {
		--u16Delay;
		delay_1ms();
	}
}

Chương trình chính

int main(void)
{
	
	P1M1 &= ~(1 << 5);
	P1M2 |= (1 << 5);
	Delay_Init();
	
	while (1) {
		P15 = 0;
		Delay_Ms(50);
		P15 = 1;
		Delay_Ms(100);
	}
}

Led trên mạch sẽ nháy, đo tại chân P15

Link project
http://vidieukhien.org/blink_tim0