Professional Documents
Culture Documents
Nhìn vào Hình 2, chúng ta có thể liên hệ vai trò của Gate bit C/T trên thanh ghi TMOD.
Đây là định nghĩa về các bit đó:
Gate: Khi bit này thiết lập (nghĩa là: ‘1’), timer có thể được điều khiển bên ngoài bởi
INT1 đối với timer 1 và INT0 đối với timer 0. Timer bắt đầu khi chân này cao. Khi bit
Gate là ‘0’, thì counter bắt đầu không lệ thuộc các chân ngoài.
C/T: Bit này định nghĩa có sử dụng đồng hồ bộ dao động bên trong hoặc đồng hồ bên
ngoài từ T1 đối với timer 1 hoặc T0 đối với timer 0 hày không. M1 & M0 định nghĩa chế
độ của timer như sau:
Bảng 1: Bốn chế độ của từng timer
M1 M0 Diến giải
0 0 Mode 0: 13-bit Timer
0 1 Mode 1: 16-bit Timer
1 0 Mode 2: 8-bit Auto-reload
1 1 Mode 3: Split Timer
Mode 0
Đặt hoặc Timer vào trong Mode 0 làm cho nó trông giống 8048 Timer, đó là Counter 8-
bit có mạch đếm gộp trước (prescaler) chia-theo-32. Hình 7 trình bầy hoạt động của
Mode 0 khi nó áp dụng vào Timer 1. Trong chế độ này, thanh ghi Timer được định hình
là thanh ghi 13-bit. Khi sự đếm cuốn qua từ mọi 1s đến mọi 0s, thì nó thiết lập cờ hiệu
ngắt Timer TF1. Đầu vào được đến được Timer cho phép khi TR1 = 1và hoặc GATE = 0
hoặc INT1 = 1. (Cách thiết lập GATE = 1 cho phép Timer điều khiển đầu vào bên ngòi
INT1, để dễ đo chiều rộng xung). TR1 điều khiển bit trong Special Function Register
TCON. GATE là trong TMOD.
Thanh ghi 13-bit có tất cả 8 bit của TH1 và 5 bit thấp hơn của TL1. 3 bit thấp của TL1 là
vô định và nên lờ đi. Cách thiết lập chạy cớ hiệu (TR1) không làm xoá các thanh ghi.
Mode 0 hoạt động giống như Timer 0 như đối với Timer 1. Có hai bit GATE khác nhau,
một cho Timer1 (TMOD.7) và một cho Timer 0 (TMOD.3).
Mode 1
Mode 1 giống như Mode 0, trừ thanh ghi Timer đang chạy với toàn bộ 16 bits.
Mode 2
Mode 2 đinh cấu hình thanh ghi Timer như Counter (TL1) 8-bit có nạp lại tự động. Sự
tràn bộ nhớ khỏi TL1 không chỉ thiết lập TF1, mà còn làm nạp lại TL1 bằng những nội
dung của TH1, cái đó do phần mềm định trước. Sự nạp lại cho phép TH1 không bị thay
đổi. Mode 2 hoạt động giống như Timer/Counter 0.
Mode 3
Timer 1 trong Mode 3 đơn giản là chứa sự đếm của nó. Hiệu lực giống như cách thiết lập
TR1 = 0. Timer 0 trong Mode 3 thiết lập TL0 và TH0 như hai bộ đếm riêng rẽ. TL0 sử
dụng Timer 0 kiểm soát các bit: C/T, GATE, TR0, INT0, và TF0.TH0 ghìm lại vào trong
chức năng timer (đếm chu kỳ máy) và dẫn tới (takes over) sử dụng TR1 và TF1 từ Timer
1. Như vậy, TH0 bây giờ điều khiển “Timer 1” ngắt. Mode 3 được cung cấp cho những
ứng dụng yêu cầu timer phụ 8-bit vào counter. Với Timer 0 trong Mode 3, 80C51 có thể
trông giống như nó có ba Timer/Counters. Khi Timer 0 trong Mode 3, Timer 1 có thể
được bật và tắt bằng chuyển mạch cho nó ra và vào Mode 3 riêng của nó, hoặc có thể vẫn
sử dụng bởi hàng loạt cổng như máy phát tốc độn baud, hoặc thực tế, trong mọi ứng dụng
không yêu cầu ngắt.
Bảng 2
Bit Ký hiệu Diễn giải
Phần mềm có thể lự đối với timer 0
TCON.0 IT0
Nó chỉ rõ cách tụt xuống mức edge/Low đã gây ra sự ngắt bên ngoài
Ngắt cờ hiệu Edge đối với timer 0. Việc này đặt khi ngắt mép ngoài
TCON.1 IE0
được tìm thấy. Nó được xoá khi Interrupt đã tiến hành
Phần mềm có thể lựa đối với timer 1
TCON.2 IT1
Nó chỉ rõ cách tụt xuống mức edge/Low đã gây ra sự ngắt bên ngoài
TCON.3 IE1
Cờ hiệu Interrupt Edge đối với timer 1. Việc này đặt khi ngắt mép ngoài
được tìm thấy. Nó được xoá khi Interrupt đã tiến hành
TCON.4 TR0 Phần mềm có thể lựa. Bắt đầu và dừng timer 0
Cờ hiệu tràn bộ nhớ Timers 0.
TCON.5 TF0 Nó đặt tự động khi timer / counter tràn bộ nhớ. Nó được xoá khi dịch vụ
ngắt đã xảy ra.
TCON.6 TR1 Phần mềm có thể lựa. Bắt đầu và dừng timer 1
Cờ hiệu tràn bộ nhớ Timers 1.
TCON.7 TF1
Nó đặt tự động khi timer / counter tràn bộ nhớ. Nó được xoá khi dịch vụ
ngắt đã xảy ra.
Note:
Chúng ta giả thiết rằng bộ vi xử lý đang chạy với tinh thể (crystal) Fc=12 MHz.
Điều này gợi ý là đồng hồ thời gian đang chạy tại Ft = 1MHz. Kể kể từ đây thời
gian mỗi tích tắc là 1 giây.
Bộ đếm theo thời gian luôn luôn tính tăng. TL0 và TH0 là những thanh ghi đối với
timer0, TL1 và TH1 là những thanh ghi đối với timer 1. Khi timer khởi động, nó
bắt đầu tăng cho đến khi đạt tới cực đại của nó, rồi nó sinh ra cờ hiệu TF0 hoặc
TF1.
Những ví dụ dưới đâu minh hoạ việc sử dụng và những ứng dụng của timers.
Ví dụ [1]: Time Delays
Tiến trình phát sinh chức năng chừng 100 μ s bằng cách dùng timer 0.
Thủ tục để lập trình timer như sau:
Khởi tạo thanh ghi TMOD
Khởi tạo thanh ghi TL0 và TH0
Khởi động timer
Theo rõi TF0 cho đến khi ổn định
Đối với nhiều ứng dụng thời gian trễ, chế độ 0 của các timer là sử dụng thích hợp nhất.
Bước thứ nhất là quyết định nội dung của thanh ghi TMOD. Các thanh ghi này như đã
nói trên, định nghĩa chế độ/timer nào được sử dụng. Định dạng của các thanh ghi này
được nhắc lại ở đây cho thuận tiện:
Hình 5:
Ở đây chúng ta dùng timer 0 trong chế độ 1 (nghĩa là timer 16 bit). Chúng ta sử dụng
đồng hộ nội tại đối với timer (nghĩa là C/T=0), chúng ta muốn khởi động timer bằng phần
mềm mà nó hàm ý Gate=0. Chế độ là 0, kể từ đây là M1 M0 = 01. Nội dung của thanh
ghi bởi vậy là:
Hình 6
Đối với tinh thể 12MHz, timer sẽ được khoá tại 1MHz tương ứng với 1 μ s mỗi cú đếm.
Kể từ đây đối với 100 μ s, counter cần thiết tính 100 xung. Chúng ta biết rằng TL0 và
TH0 có thể có giá trị cực đại chừng FFFF (in Hex) hoặc (65535). Nếu chúng ta đặt số 0-
100=-100 (nghĩa là FFC9), thì khi sự đếm bắt đầu, thì timer tính tăng lên cho đến FFFF
trước khi nó phát sinh TF0=1. Như từ FFC9 tới 0000 có 100 xung, bởi vậy điều này sẽ
nói chung là 100 μ s khi TF0 đặt là 1.
Thường trình con được viết theo ngôn ngữ assembly (ngôn ngư lập trình bậc thấp) vì vậy:
void Delay(void)
{
TMOD=0X01;
TL0=0X9C;
TH0=0X0FF;
TR0=1;
while(!TF0);
TR0=0;
TF0=0;
}
Triển khai chương trình để phát sinh sóng vuông từ P 1.0 như sau:
Bằng cách áp dụng timer 0, và giả thiết rằng bộ vi xử lý là đang chạy với tinh thể 12MHz
chúng ta có thể bắt đầu thiết kế bằng cách trước tiên quyết định như thế nào số ban đầu
trong TL0 và TH0 cần cung cấp sự chậm trễ chừng 0.5 ms (nghĩa là 500 μ s). Bằng cách
dùng tinh thể 12 MHz cung cấp tần số cơ sở thuận tiện để phát sinh thời gian trễ như thể
được chia bên trong bởi 12 tới tần số cho trước 1MHz và kể từ đây tần số máy là 1 μ s.
Kể từ đây 500 μ s trễ yêu cầu timer đếm 500 xung. Điều này thành lập nên biểu thức sau:
0 – 500 = -500 = FE0CH
Bit thấp (nghĩa là 0C) là giá trị ban đầu của TL0 và bit cao hơn là giá trị ban đầu của TH0
(nghĩa là FE). Tiếp theo, chúng ta cần định nghĩa các bit tương ứng trong thanh ghi
TMOD như sau:
Hình 8
Chúng ta giả thiết rằng timer 1 không được dùng trong chương trình này. Timer 0 được
dùng trong chế độ 1, sử dụng đồng hồ bên trong.
Cả hai chương trình toàn bộ và ‘C’ được cho dưới đây:
Chương trình nói trên có thể được thực hiện đầy đủ trong ‘C’ như sau:
#include <reg51.h>
void Delay(void);
sbit Pulse = P1^0;
void main(void)
{
for(;;)
{
Pulse = 1;
Delay();
Pulse = 0;
Delay();
}
}
void Delay(void)
{
TMOD=0X01;
TL0=0X0C;
TH0=0X0FE;
TR0=1;
while(!TF0);
TR0 =0;
TF0 =0;
}
Hình 9: Đo chiều rộng xung bằng cách dùng các timer bên trong
Ở đây, chúng ta đặt cả hai TL0 và TH0 thành 0. Khi xung tới mức cao, bộ đếm sẽ bắt đầu
đếm tăng lên từ 0. Khi xung xuống mức thấp, nó dừng đếm. Giá trị đếm trong TH0 và
TL0 miêu tả chiều rộng theo μ s.
Chú ý rằng, trong sơ đồ trên chân INT0 không phục vụ như đầu vào gián đoạn mà đơn
giản là đầu vào bit. Điều này trình bầy trong Hình 10.
Hình 10: INT0 có thể được sử dụng để khởi động và dừng timer
được cung cấp bên ngoài Gate tại 1 và TR1=1
Chức năng dưới đây trả về chiều rộng xung trong thanh ghi R0 (Least Significant Byte)
và R1 (Most Significant Byte).
#include <reg51.h>
sbit Width = P3^2;
void main(void)
{
unsigned char Width_Low, Width_High;
TMOD=0X09;
while(1)
{
TL0=0X00;
TH0=0X00;
while(Width==1);
while(Width==0);
TR0 =1;
while(Width==1);
TR0=0;
TF0 =0;
Width_Low=TL0;
Width_High=TH0;
}
#include <reg51.h>
sbit Width = P3^2;
void main(void)
{
unsigned int Width_Low, Width_High;
unsigned int Count=0;
TMOD=0X09;
while(1)
{
TL0=0X00;
TH0=0X00;
while(Width==1);
while(Width==0);
TR0 =1;
while(Width==1)
{
if(TF0==1)
{
Count++;
TF0=0;
}
}
TR0 =0;
TF0 =0;
Width_Low=TL0 + ( Count & 0X00FF);
Width_High=TH0 + ( Count & 0XFF00);
}
Fc 11.0592
Ftimer = = = 0.9216MHz= 92MHz
12 12
1
Bởi vậy, Thời gian mỗi đếm, Tcount = = 1.285 μ s
0.9216
Td
Con số (Number) được yêu cầu để nạp vào trong TL0 và TH0 Ö N =
Tcount
50x1000
Ví dụ về thời gian trễ của Td=50mS: N = = 486080
1.085
Chú ý rằng counter cần phải đếm số này để sinh ra thời gian trễ 50ms. Nhưng vì bộ đếm
luôn luôn đếm tăng lên đến FFFF (hoặc 65535) trước khi nó phát sinh cờ hiệu tràn bộ
nhớ (nghĩa là TF0 hoặc TF1) chúng ta cần nạp thanh ghi counter (TLx và THx) với:
Đây là con số để được nạp vào trong TL0 và TH0 đối với timer 0 và TL1 và TH1 đối với
timer 1.
Bước tiếp theo là xác định 8-bits trong thanh ghi TMOD. Thanh ghi này yêu cầu
xác định chiều rộng timer và chế nào được đòi hỏi. Sự định dạng thanh ghi này
như sau:
Ví dụ sử dụng đồng hồ bên trong (C/T =0 ), để dừng và khởi động timer ở bên
trong (Gate = 0), thì sử dụng timer 0 trong Mode 1 (nghĩa là M1 M0 = 0 1 ), thời
gian cần được khởi tạo như: 00000001 đã cung cấp timer 1 không được sử dụng.
Đôi khi một trong các timer có thể được sử dụng bởi phần khác của chương trình
và bởi vậy sự khởi tạo của thanh ghi TMOD cần phải được thực hiện mà không
tác động đến các bit đó, điều đó có lẽ đã đặt trong hoạt động trước. Trong trường
hợp này, nó là thực tiễn tốt để initialise TMOD như sau:
Thao tác thực hiện hoạt động logical của mã đang có trong TMOD và mã mới.
Điều này bảo đảm rằng chỉ những bit tương ứng với timer 0 là đã ảnh hưởng và sự
tương ứng đó với timer 1 là không bị thay đổi.
Và trong ‘C’:
void Delay50(void)
{
TMOD |=0X01;
TH0=0X4C;
TL0=0X00;
TF0=0;
TR0=1;
while(TF0==0);
TR0=0;
}
Nếu bội số của 50ms được yêu cầu, hàm trên có thể được gọi bằng tham số mà nó xác
định số lần 50ms trễ cần được thi hành. Điều đó được trình bầy như sau:
void Delay50(unsigned char N)
{
unsigned char i;
for(i=0; i<N; i++)
{
TMOD |=0X01;
TH0=0X4C;
TL0=0X00;
TF0=0;
TR0=1;
while(TF0==0);
TR0=0;
}
}
Hàm nói trên có thể được gọi từ chương trình chính như sau:
#include <reg51.h>
void Delay50(unsigned char N);
void main(void)
{
/* To generate 200 mS delay using repeated 50ms
*/
Delay50(4);
}