This is default featured slide 1 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 2 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 3 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 4 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

This is default featured slide 5 title

Go to Blogger edit html and find these sentences.Now replace these sentences with your own descriptions.

giới thiệu MSP430

Chương 1 : Giới thiệu qua họ vi điều khiển MSP430G2553.1.Giới thiệu tổng quát :
Các dòng vi điều khiển msp430 này do hãng TI ( Texas Instruments) sản xuất, ngoài ra thì TI còn sản xuất và cung cấp nhiều linh kiện điện tử và các module khác , để tìm hiểu thì các bạn có thể tham khảo ở địa chỉ : www.ti.com để biết rõ hơn .
Vi điều khiển( Micro controller unit – MCU ) là đơn vị xử lý nhỏ, nó được tích hợp toàn bộ các bộ nhớ như ROM , RAM , các port truy xuất , giao tiếp ngoại vi trực tiếp trên 1 con chip hết sức nhỏ gọn. Được thiết kế dựa trên cấu trúc
VON-NEUMAN , đặc điểm của cấu trúc này là chỉ có duy nhất 1 bus giữa CPU và bộ nhớ (data và chương trình) , do đó mà chúng phải có độ rộng bit tương tự nhau.

MSP430 có một số phiênbản như: MSP430x1xx, MSP430x2xx, MSP430x3xx,
MSP430x4xx, MSP430x5xx. Dưới đây là những đặc điểm tổng quát của họ vi điều khiển MSP430:
+ Cấu trúc sử dụng nguồn thấp giúp kéo dài tuổi thọ của Pin
-Duy trì 0.1µA dòng nuôi RAM.
-Chỉ 0.8µA real-time clock.
-250 µA/ MIPS.
+ Bộ tương tự hiệu suất cao cho các phép đo chính xác
-12 bit hoặc 10 bit ADC-200 kskp, cảm biến nhiệt độ, Vref ,
-12 bit DAC.
-Bộ giám sát điện áp nguồn.
+ 16 bit RISC CPU cho phép được nhiều ứng dụng, thể hiện một phần ở kích thước Code lập trình.
-Thanh ghi lớn nên loại trừ được trường hợp tắt nghẽn tập tin khi đang làm việc.
-Thiết kế nhỏ gọn làm giảm lượng tiêu thụ điện và giảm giá thành.
-Tối ưu hóa cho những chương trình ngôn ngữ bậc cao như C, C++
-Có 7 chế độ định địa chỉ.
-Khả năng ngắt theo véc tơ lớn.
+ Trong lập trình cho bộ nhớ Flash cho phép thay đổi Code một cách linh hoạt, phạm vi rộng, bộ nhớ Flash còn có thể lưu lại như nhật ký của dữ liệu.



1.Sơ đồ chân : Chip MSP430 có kích thước nhỏ gọn , chỉ với 20 chân đối với kiểu chân DIP.
Bao gồm 2 port I/O (hay GPIO general purprose input/ output : cổng nhập xuất chung).


1.
Ta thấy rằng mỗi port đều có 8 chân.
Port 1 : có 8 chân từ P1.0 đến P1.7 tương ứng với các chân từ 2-7 và 14 , 15.
Port 2 : cũng gồm có 8 chân P2.0 – P2.7 ứng với các chân 8 – 13 , 18,19.
Ngoài chức năng I/O thì trên mỗi pin của các port đều là những chân đa chức năng, ta thể thấy rõ trong bảng sau :
2.



3.


Trên bảng là chức năng của từng chân , ngoài ra đối với các MCU có kiểu chân SMD loại 28 chân thì nó có thêm port 3 nữa,nhưng ở đây chỉ xét đối với kiểu DIP 20 chân và kiểu TSSOP 20 chân , kiểu còn lại các bạn có thể tìm hiểu trên trang chủ của nhà sản xuất .


2.Giải thích sơ lược các chân :
- Chân số 1 là chân cấp nguồn Vcc( ký hiệu trên chip là DVcc ) , ở đây nguồn cho chip chỉ được cấp ở mức 3,3V , nếu cấp nguốn cao quá mức này thì chip có thể hoạt động sai hay cháy chip .
Để có được mức nguồn này thì ta phải dùng 1 IC ổn áp riêng có ký hiệu LM1117 hay AD1117 , IC này có kiểu chân SMD nhỏ gọn , cách mắc chip này thì cũng giống như với những IC nguồn như LM78xx , tuy nhiên lưu ý ở đây là thứ tự chân ở đây có hơi khác 1 chút.Các bạn có thể xem datasheet của IC mà mắc cho phù hợp.
-Chân 20 là chân nối cực âm (0V) , chân này thì không có gì đặc biệt.


Các bạn có thể tham khảo mạch nguồn ở đây để phục vụ cho việc thiết kế mạch học tập :

4.


Trên mạch các bạn có thể thấy là có thêm IC 7805 cấp 5V , với mục đích để sử dụng cho các ngoại vi khác cho ứng dụng của các bạn , mạch trên chỉ giúp các bạn tham khảo, nhưng các bạn yên tâm là mạch này không hề sai , các bạn có thể lấy đúng giá trị như mạch trên .
-Chân reset : Chính là chân số 16 RST , nếu các bạn đã từng học về PIC thì sẽ thấy chân reset có ký hiệu là MCLR , các bạn để ý thấy dấu gạch ngang trên có nghĩa là chân này tích cực ở mức thấp . Mục đích của việc reset là nhằm cho chương trình chạy lại từ đầu .


Mạch reset cho chip :

5.


Các bạn chú ý tụ ở đây là tụ pi và chính xác là tụ 102 nha, nếu thay đổi thì khi kết nỗi Jtag để nạp code cho chip sẽ không được.

-Mạch dao động : Cũng giống như những dòng vi điều khiển khác thì Msp430 cũng hỗ trợ người dùng thạch anh ngoài ( external crystal ), nhưng thạch anh ngoại vi cho phép chỉ có thể lên tới 32,768 kHz mà thôi, và tín hiệu này được mắc trên 2 chân 18 và 19. Nhưng msp430 lại hỗ trợ thạch anh nội có thể lên đến 16Mhz, tùy vào cách khai báo trong lập trình. Và mặc định của chip là thạch anh nội. Như vậy thì chúng ta không cần thiết phải sử dụng mạch dao động ngoại cho chip giống như những dòng khác.
- Port I/O :
Port 1 : có 8 chân từ P1.0 đến P1.7 tương ứng với các chân từ 2-7 và 14 , 15.
Port 2 : cũng gồm có 8 chân P2.0 – P2.7 ứng với các chân 8 – 13 , 18,19.
Trong chế độ nhập (input) thì cả 2 port đều có 1 mạch điều khiển điện trở kéo dương – gọi là PULL UP nhưng giá trị của điện trở này rất lớn khoảng 47K nên gọi là WEAK PULL UP RESISTAN. Việc điều khiển PULL UP sẽ được tiến hành thông qua lập trình tác động lên thanh ghi PxREN sẽ được đề cập ở chương sau .


Điều này cũng giống như việc thiết lập input ở port B của vi điều khiển PIC, ở port B cũng có điện trở kéo lên , và người lập trình phải thao tác qua thanh ghi OPTION_REG.


  • ðTóm tắt :
  • Qua chương này chúng ta phải nắm được các chân cơ bản trước của chip .
  • ðMạch reset và mạch dao động OSC của chip .
  • ðCác chân I/O của 2 port và PULL UP .
Chương 3 : Mạch nạp cho MCU.
1 . Kit Lanchpad :

Với bất kỳ 1 con MCU nào thì việc phải thiết kế 1 mạch nạp cho chip là điều không thể bỏ qua ! Và với Msp430 cũng không là ngoại lệ .
PIC hay 8051 thì có nhiều mạch nạp để nạp code cho chip , từ đơn giản đến phức tạp , nói chung cực kì đa dạng.Và nói chung thì các mạch nạp cũng đều khá đắt , thấp cũng phải mất 200k hay hơn.
Như đã nói thì Msp430 là dòng value line , power low, và low – cost . Chính vì vậy mà TI đã cung cấp cho người dùng 1 mạch nạp code + debug chỉ trên 1 mạch nhỏ gọn. Trong kit còn có hỗ trợ :

-1 mạch nạp code có cả debug
-1 dây cáp USB tốt để kết nối kit với máy tính.
-1 chip thạch anh 32,768kHz
-1 chip Msp430G2553
-1 chip Msp430G2453
-1 header female.

Tất cả chỉ có 9,8 USD – rất rẻ để học!

Đây chính là hình ảnh của Kit lanchpad :
6.



Các bạn có thể mua tại địa chỉ sau : HShopVN

Kit có thể nạp được code cho dòng Msp430G : như msp430g2231, 2553, 2452,…
Kit kết nối với máy tính thông qua cổng USB .


Chương 4 : Trình biên dịch

Bây giờ chúng ta sẽ tiến hành cài đặt chương trình để có thể tiến hành viết code , biên dịch và nạp code cho chip .

Không giống như chương trình của các dòng vi điều khiển khác , TI đã cung cấp cho người dùng những IDE đã được tích hợp trong 1 gói phần mềm. Các bạn chỉ cần cài đặt 1 chương trình là đã có thể vừa viết code , debug, và nạp code cho chip.
Chắc nhiều bạn sẽ thắc mắc cụm từ debug có nghĩa là gì?
Debug chỉ là việc cho chương trình chạy từng dòng lệnh để kiểm tra lỗi của chương trình cũng như kiểm tra được cả thanh ghi của chip khi nó thực hiện lệnh .
Có nhiều IDE được TI cung cấp cho người sử dụng , nhưng trong đó có 2 chương trình mạnh và được nhiều người ưa thích đó là CCS và IAR . Các bạn đừng có nhầm lẫn giữa CCS C cho PIC với CCS cho Msp430 nhé! Hai chương trình này là hoàn toàn khác nhau .


Sau đây , xin được giới thiệu cụ thể 2 chương trình trên :
1 . IAR (IAR Embedded Workbench ) :
Đây là chương trình biên dịch được cung cấp bởi IAR SYSTEMS. Có 3 phiên bản: Kickstart Version – Free , Baseline Version ~ $795 và Full Version ~ $2695.
Để tải chương trình , chúng ta có thể vào trang chủ : www.iar.com hoặc từ địa chỉ của TI : www.ti.com , sau đó gõ từ IAR trên mục tìm kiếm ,để download được thì các bạn phải tạo 1 tài khoản và đăng nhập để tải về , các bạn chỉ có thể tải được bản trial mà thôi .

2 . CCS (Code composer studio ) :
Đây là chương trình do TI cung cấp , có nhiều server đã được cung cấp .
Phiên bản mới nhất hiện nay là CCS 5.3 .

Các bạn có thể tải tại : www.ti.com
Đăng nhập vào (sau khi đã đăng ký tài khoản ) , CCS có hỗ trợ cho người dùng bản dùng thử nhưng bị giới hạn code (limited code ) , chúng ta chỉ được sử dụng 4kB bộ nhớ , nhưng với sinh viên chúng ta thì với 4 kB cũng đã đủ làm những dự án nhỏ .
Chính vì vậy mà tôi khuyên bạn nên tải bản CCS về , và trong tài liệu này cũng sử dụng CCS để viết code . CCS có rất nhiều tính năng hay mà sau này chúng ta sẽ cùng nhau nghiên cứu sau .Việc sử dụng phiên bản nào là tùy thuộc vào các bạn , các version cũng đều giống nhau , nếu CCS 5.3 thì yêu cầu máy của bạn phải có cấu hình đủ mạnh để dùng.

3 . Cài đặt và sử dụng CCS :
Sau khi tải CCS về , các bạn tiến hành cài đặt , cách cài đặt cũng rất đơn giản. Các bạn chỉ cần chạy file setup.exe .
Đối với phiên bản CCS 4.3 hay 4.2 thì các bạn cài đặt xong là có thể sử dụng được nhưng với CCS 5.3 thì các bạn còn phải làm 1 việc nữa đó là chọn : limit free code , thì mới viết code được . Cách làm như sau :
Sau khi cài đặt xong, các bạn khởi động chương trình :
Start -> all program -> Texas Instruments -> Chọn code ….
Hoặc chạy chương trình bằng cách click vào biểu tượng CCS trên desktop .
Sau đó , click chọn Help -> Code Composer code linsce -> upgrade -> active việc cài đặt và sử dụng cũng như tạo mới 1 project các bạn xem tại mục MSP430 này, đã có gần như đầy đủ các video minh họa việc học lập trình với msp430.


Phần 2 : Cách lập trình.

Phần này , sẽ giới thiệu cho các bạn cách lập trình trên MCU Msp430G2553 .
Ngôn ngữ lập trình ở đây chính là C (Language programing C).Đây là chủ đề chính của tài liệu .


Chương 1 : GPIO (General purpose input/ouput ) :

Đây sẽ là chương trình đầu tiên của các bạn , cũng tương tự như khi các bạn mới học C thì đầu tiên chúng ta phải học cách viết chương trình hiển thị dòng chữ “hello word” in ra màn hình .
Ở đây chúng ta sẽ tìm hiểu cách viết 1 chương trình đơn giản , để biết cách bật tắt 1 led trên chân P1.0 . Tại sao lại là trên chân P1.0 ? đơn giản là vì trên kit lanchpad đã có sẵn 2 chú led được hàn trên 2 chân là P1.0 và P1.6 .
Cũng giống như chức năng I/O của Pic thì chức năng GPIO cũng chỉ làm 1 việc đơn giản đó là việc xuất ra tín hiệu hay đọc vào tín hiệu . Tín hiệu ở đây hiểu đơn giản là những tín hiệu điện - tín hiệu số .
Tín hiệu số (Binary ) tín hiệu này chỉ có 2 trạng thái đó là 1 và 0 .
1 : Có điện , mức điện áp này bằng với điện áp nguốn cấp cho MCU .

00: không có điện .
1.Các thanh ghi cần thiết lập :
Msp430 có 2 port nhập xuất đó là :


Port1 : Từ chân P1.0 đến P1.7
Port2: 8 chân P2.0 đến P2.7
Để biết rõ các chân này trên MCU thì các bạn chịu khó đọc lại chương 1 trong phần 1 .



a. Thanh ghi PxSEL(x:1 , 2) và PxSEL2(x:1 , 2) :

Thanh ghi này qui định chế độ làm việc cho các chân bao gồm

PxSEL và PxSEL2 .
View attachment 5570
VD: Ta muốn port 1 là GPIO thì ta thực hiện lệnh như sau:
P1SEL = 0;
P1SEL2 = 0 ;
Nếu như muốn chân P1.2 làm chức năng I/O thì khai báo như sau :
P1SEL & = ~0x01 ; // sử dụng lệnh đảo bit , set về mức 0 .
P1SEL2 &= ~0x01;
Lưu ý: Interrupts P1 và P2 sẽ bị vô hiệu hóa khi PxSEL= 1 .

b. Thanh ghi PxDIR(x:1 , 2)
Thanh ghi này qui định loại ngõ vào ra cho các chân (I/O pins)
Mặc định các chân này là input, nên ta chỉ cần set output cho các chân này
VD: P1DIR = 0x01 // chân P1.0 là output.
Mức 1 : ouput ( xuất tín hiệu ) .
Mức 0 : input (đọc tín hiệu về) .


c. Thanh ghi PxREN(x:1 , 2)

Thanh ghi này cho phép tắt hoặc mở chế độ pullup/pulldown resistor cho các pins .
Bit = 0 : Tắt chức năng pull up /down (disable).
Bit= 1 : enable pull up/down.

d. Thanh ghi PxOUT(x: 1 , 2)
_Khi ta muốn xuất giá trị cho các chân I/O, ta sẽ đặt giá trị vào các thanh ghi PxOUT .
Bit = 1 : output mức cao.
Bit = 0 : output mức thấp.
_Khi ta config thanh ghi PxREN sang chế độ pullup/pulldown resistor thì
Bit = 1 : Pull up .
Bit = 0 : Pull down .


Lưu ý là ta phải chỉnh P1DIR trước khi xuất giá trị ra ngoài.


Tóm tắt:
Để thực hiện xuất / nhập trên 1 chân (Pin):
- Cài đặt đúng giá trị cho thanh ghi PxDIR
- Đặt kiểu tín hiệu của pin là GPIO hay các chức năng
khác qua thanh ghi PxSEL
- Xuất tín hiệu bằng cách ghi giá trị “0” hoặc “1” vào
port tương ứng (port P1OUT)


- Đọc giá trị của chân bằng cách đọc mức logic trên port tương ứng.


Code mẫu :


HTML:
#include <msp430g2231.h >
void  main(void)
{
WDTCTL = WDTPW + WDTHOLD;  // Stop watchdog timer
P1DIR |= 0x01;        // Set P1.0 to output  direction
P1SEL = 0;      // Set P1 GPIO function
P1SEL2 = 0;
while(1)
{
P1OUT ^= 0x01;      // Toggle P1.0 using exclusive-OR
_delay_cycles(100);  // Đối  với  CCS
} }
Tạm thời bài viết sẽ tạm dừng tại đây , mình sẽ viết tiếp và sẽ up lên sớm cho mọi người , mong các bạn ủng hộ mình ,hãy thể hiện việc làm của các bạn bằng cách thể hiện việc ấn like nhé!



Bài 1 : GPIO tiếp theo .

Bây giờ chúng ta sẽ viết về phần đọc tín hiệu cho msp430 , config chức năng input .

Các bạn lưu ý là trên kit lanchpad của chúng ta đã có sẵn 1 button được mắc vào chân P1.3 , vì vậy chúng ta sẽ tận dụng điều này để viết code , không cần phải lắp mạch để test .
Như đã nói ở phần đầu thì việc thiết lập chế độ input , có tích hợp sẵn 1 mạch điều khiển điện trở kéo dương - pull up , điện trờ tầm 47K , để bật được chức năng này , ta sẽ tác động đến thanh ghi PxREN
Code :
HTML:
// BAI 2 : doc button //

#include "msp430.h"
int main (void){
WDTCTL = WDTHOLD + WDTPW ;
P1SEL &= ~(BIT0 + BIT3);
P1SEL2 &= ~(BIT0 + BIT3) ;
P1DIR |= BIT0 ; // P1.0 : OUT
// BIT 3 : INPUT
P1DIR &= ~BIT3 ; // LENH XOA BIT 3
P1OUT |= BIT3 ;  //BIT3 = 1
P1REN = BIT3 ; //PULL UP BIT3

while(1) {
            if ((P1IN & BIT3)==0) {  // se tat khi p1.3 khong co bam nut.
                P1OUT |= BIT0 ;
              
            }
            else P1OUT &= ~ BIT0 ; // se sang
          
}


}
 
 
 
mẫu code:
 
 
 
Code:#includemain(void) {WDTCTL WDTPW WDTHOLD// Stop watchdog timerP1DIR |= 0XFF// set all the ports as output portsint x 0X01;long i=0;int j=1;int k=0;int l=0;
for(;;)
{
 
 
 


for(k=1;k<=5;k++){x=0×01;
for(j=1;j<=8;j++){
P1OUT x;x*=2;
for(i=0;i<=10000;i++)
{
}
}
}
for(k=1;k<=5;k++){x=0×80;
for(j=1;j<=8;j++){
P1OUT x;x/=2;
for(i=0;i<=10000;i++)
{
}
}
}

for(k=1;k<=5;k++){
P1OUT=0xAA;
for(l=0;l<=1;l++){
for(i=0;i<=64000;i++)
{}}P1OUT=0×55;
for(l=0;l<=1;l++){
for(i=0;i<=64000;i++)
{}}
}

for(k=1;k<=5;k++){
P1OUT=0×18;

for(i=0;i<=20000;i++)
{}P1OUT=0×24;

for(i=0;i<=20000;i++)
{}P1OUT=0×42;

for(i=0;i<=20000;i++)
{}P1OUT=0×81;

for(i=0;i<=20000;i++)
{}

}
for(k=1;k<=5;k++){
P1OUT=0×81;

for(i=0;i<=20000;i++)
{}P1OUT=0×42;

for(i=0;i<=20000;i++)
{}P1OUT=0×24;

for(i=0;i<=20000;i++)
{}P1OUT=0×18;

for(i=0;i<=20000;i++)
{}

}

}
} 
 
 
 
 
 
 
 
Chương 2 : Basic Clocks
 Phần này có thể hơi khó hiểu, nhưng các bạn cứ đọc kỹ trước, rồi sau này sẽ hiểu dần dần sau .
 Chế độ clock được cung cấp trong tất cả các dòng MCUs Msp430 của TI .Trong chương này sẽ giúp các bạn hiểu rõ về hoạt động các xung clocks cơ bản của  msp430.

1.  Giới thiệu về clock :

  Việc config xung clocks là vô cùng cần thiết đối với bất kỳ 1 con MCUs nào, có xung clock thì con mcu của chúng ta mới có thể hoạt động đúng được .

 Chúng ta có thể hiểu xung clocks chính là trái tim của 1 hệ thống xử lý số, và tốc độ xử lý lệnh phụ thuộc hoàn toàn vào nguồn xung .

 Vấn đề là làm sao chúng ta có thể thiết lập xung clocks này hoạt động .Chúng ta có thể có nhiều cách làm việc đó . Với dòng msp430 này thì nó 3 loại xung cơ bản như sau :

- Internal Oscillators

 - External Crystals 

 - External Oscillators

2.  Internal/External Oscillators :

a.  Internal :

Đây là nguồn dao động có sẵn bên trong chip , thông thường sử dụng các mạch RC được tích hợp sẵn với các hệ mạch .

-  Lợi ích của nguồn này đó là việc chúng ta có thể dễ dàng thay đổi được tần số hoạt động mà không cần phải sử dụng các linh kiện ngoại – làm chiếm diện tích board .

-  Trên chip Msp430  đã có sẵn nguồn xung DCO (Digitally Controller Oscillator) hỗ trợ tốc độ cao .

b.  External :

 Khác với những dòng vi điều khiển khác thì dòng Msp430 chỉ có thể hỗ trợ thạch anh có tần số lên đến 32.768khz ,việc sử dụng thạch anh ngoại nhằm đáp ứng nhu cầu về ứng dụng cần chạy thời gian thực và cần sự chính xác cao .

 Chính vì vậy mà chúng ta nên hạn chế sử dụng nếu có thể được , 1 mặt giảm việc thi công mạch in .

osc.		 

 Hình ảnh chỉ mang tính minh họa .

 Trong chương này , chúng ta sẽ nghiên cứu chi tiết việc thiết lập nguồn xung nội ,như vậy sẽ đơn giản cho việc thiết kế phần cứng .Và nguồn xung nội hỗ trờ dải tần làm việc tử 400-kHz to 16-MHz .

3.  Mode trong xung nội : 

 Trong nguồn xung nội thì chúng ta có tối đa là 4 mode chế độ hoạt động , các mode này lần lượt là :

LFXT1CLK : Low-frequency/high-frequency oscillator

 Module dao động hỗ trợ tần số thấp / cao , có thể được dung cho ứng dụng với bộ theo dõi tần số thấp thạch anh 32.768khz , hoặc từ các nguồn xung khác  có tần số từ 400khz đến 16Mhz .

XT2CLK: Optional high-frequency oscillator .

 Module lựa chọn làm việc ở tần số cao .

DCOCLK: Internal digitally controlled oscillator (DCO).

 Bộ dao động số được tích hợp sẵn trong chip, khi làm việc nếu không có thiết lập gì về nguồn xung thì msp430 sẽ hoạt động dưa trên bộ DCO này .

VLOCLK: Internal very low power, low frequency oscillator with 12-kHz typical frequency

 Module tích hợp , đây là mode hoạt động siêu tiết kiệm năng lượng .
 Sơ đồ khối clocks :
basic clocks.		  

Bộ đếm/ bộ định thời trong 8051

Bộ đếm/ bộ định thời trong 8051


Ø  Bộ đếm, bộ định thời là gì?
Ø  Các thanh ghi liên quan
Ø  Cách thức hoạt động của bộ đếm/bộ định thời
Ø  Các bước lập trình bộ đếm/bộ định thời

Giới thiệu

Bộ đếm/Bộ định thời: Đây là các ngoại vi được thiết kế để thực hiện một nhiệm vụ đơn giản: đếm các xung nhịp. Mỗi khi có thêm một xung nhịp tại đầu vào đếm thì giá trị của bộ đếm sẽ được tăng lên 01 đơn vị (trong chế độ đếm tiến/đếm lên) hay giảm đi 01 đơn vị (trong chế độ đếm lùi/đếm xuống).
Xung nhịp đưa vào đếm có thể là một trong hai loại:

Ø  Xung nhịp bên trong IC: Đó là xung nhịp được tạo ra nhờ kết hợp mạch dao động bên trong IC và các linh kiện phụ bên ngoài nối với IC. Trong trường hợp sử dụng xung nhịp loại này, người ta gọi là các bộ định thời (timers). Do xung nhịp bên loại này thường đều đặn nên ta có thể dùng để đếm thời gian một cách khá chính xác.
Ø  Xung nhịp bên ngoài IC: Đó là các tín hiệu logic thay đổi liên tục giữa 02 mức 0-1 và không nhất thiết phải là đều đặn. Trong trường hợp này người ta gọi là các bộ đếm (counters). Ứng dụng phổ biến của các bộ đếm là đếm các sự kiện bên ngoài như đếm các sản phầm chạy trên băng chuyền, đếm xe ra/vào kho bãi…

Một khái niệm quan trọng cần phải nói đến là sự kiện “tràn” (overflow). Nó được hiểu là sự kiện bộ đếm đếm vượt quá giá trị tối đa mà nó có thể biểu diễn và quay trở về giá trị 0. Với bộ đếm 8 bit, giá trị tối đa là 255 (tương đương với FF trong hệ Hexa) và là 65535 (FFFFH) với bộ đếm 16 bit.

            8051 có 02 bộ đếm/bộ định thời. Chúng có thể được dùng như các bộ định thờiđể tạo một bộ trễ thời gian hoặc như các bộ đếm để đếm các sự kiện xảy ra bên ngoài bộ VĐK. Trong bài này chúng ta sẽ tìm hiểu về cách lập trình cho chúng và sử dụng chúng như thế nào. Phần 1 là Lập trình bộ định thời, và phần 2 là Lập trình cho bộ đếm.

1. Các bộ định thời của 8051

            8051 có hai bộ định thời là Timer 0 và Timer 1, ở phần này chúng ta bàn về các thanh ghi của chúng và sau đó trình bày cách lập trình chúng như thế nào để tạo ra các độ trễ thời gian.

1.1 Các thanh ghi cơ sở của bộ định thời

            Cả hai bộ định thời Timer 0 và Timer 1 đều có độ dài 16 bit được truy cập như hai thanh ghi tách biệt byte thấp và byte cao. Chúng ta sẽ bàn riêng về từng thanh ghi.

1.1.1 Các thanh ghi của bộ Timer 0

            Thanh ghi 16 bit của bộ Timer 0 được truy cập như byte thấp và byte cao:

Ø  Thanh ghi byte thấp được gọi là TL0 (Timer0 Low byte).
Ø  Thanh ghi byte cao được gọi là TH0 (Timer0 High byte).

Các thanh ghi này có thể được truy cập, hoặc được đọc như mọi thanh ghi khác chẳng hạn như A, B, R0, R1, R2 v.v...


Hình 1: Các thanh ghi của bộ Timer 0

1.1.2 Các thanh ghi của bộ Timer 1

            Giống như timer 0, bộ định thời gian Timer 1 cũng dài 16 bit và thanh ghi 16 bit của nó cũng được chia ra thành hai byte là TL1 và TH1. Các thanh ghi này được truy cập và đọc giống như các thanh ghi của bộ Timer 0 ở trên.


Hình 2: Các thanh ghi của bộ Timer 1.

1.1.3 Thanh ghi TMOD

            Cả hai bộ định thời Timer 0 và Timer 1 đều dùng chung một thanh ghi được gọi là TMOD: để thiết lập các chế độ làm việc khác nhau của bộ định thời.

Thanh ghi TMOD là thanh ghi 8 bit gồm  có:

Ø  4 bit thấp để thiết lập cho bộ Timer 0.
Ø  4 bit cao để thiết lập cho Timer 1.

Trong đó:

Ø  2 bit thấp của chúng dùng để thiết lập chế độ của bộ định thời.
Ø  2 bit cao dùng để xác định phép toán.

  
Hình 3: Thanh ghi TMOD.

1.1.3.1 Các bit M1, M0

            Là các bit chế độ của các bộ Timer 0 và Timer 1. Chúng chọn chế độ của các bộ định thời: 012 và 3 như bảng dưới. Chúng ta chỉ tập chung vào các chế độ thường được sử dụng rộng rãi nhất là chế độ 1 và chế độ 2. Chúng ta sẽ sớm khám phá ra các đặc tính của các chế độ này sau khi khám phần còn lại của thanh ghi TMOD. Các chế độ được thiết lập theo trạng thái của M1 và M0 như sau:

M1
M0
Chế độ
Chế độ hoạt động
0
0
0
Bộ định thời 13 bit:8 bit  là bộ định thời/bộ đếm, 5 bit đặt trước.
0
1
1
Bộ định thời 16 bit: không có đặt trước.
1
0
2
Bộ định thời 8 bit: tự nạp lại.
1
1
3
Chế độ bộ định thời chia tách.
Bảng 1: Các chế độ hoạt động của bộ đếm/bộ định thời

1.1.3.2 Bit C/T (Counter/Timer)

            Bit này trong thanh ghi TMOD được dùng để quyết định xem bộ định thời được dùng như một máy tạo độ trễ hay bộ đếm sự kiện. Nếu bit C/T = 0 thì nó được dùng như một bộ định thời tạo độ trễ thời gian.

Ví dụ 1:
TMOD = 0000 0001 (01H) : chế độ 1 của bộ định thời Timer 0 được chọn.
TMOD = 0010 0000 (20H) : chế độ 2 của bộ định thời Timer 1 được chọn.
TMOD = 0001 0010 (12H) : chế độ 1 của bộ định thời Timer 1 và chế độ 2 của Timer 0 được chọn.

            Nguồn đồng hồ cho chế độ trễ thời gian là tần số thạch anh của 8051. Điều đó có nghĩa là độ lớn của tần số thạch anh đi kèm với 8051 quyết định tốc độ nhịp của các bộ định thời trên 8051. Tần số của bộ định thời luôn bằng 1/12 tần số của thạch anh gắn với 8051.


Hình 4: Tần số của bộ đếm/bộ định thời

Ví dụ 2:

Tần số thạch anh
Tần số bộ định thời
Chu kỳ bộ định thời
20MHz
20MHz/12=1,6666MHz
1/1,6666MHz=0,6us
12MHz
12MHz/12=1MHz
1/1MHz=1us
11,0592MHz
11,0592MHz/12=0,9216MHz
1/0,9216MHz=1,085us
Bảng 2: Một số tần số thông dụng

            Mặc dù các hệ thống 8051 có thể sử dụng tần số thạch anh từ 10 đến 40MHz, song ta chỉ tập trung vào tần số thạch anh 11,0592MHz. Lý do đằng sau một số lẻ như vậy là tốc độ baud đối với truyền thông nối tiếp của 8051. Tần số XTAL = 11,0592MHz cho phép hệ thống 8051 truyền thông với PC mà không có lỗi.

1.1.3.3 Bit cổng GATE

            Một bit khác của thanh ghi TMOD là bit cổng GATE. Để ý trên hình 3 ta thấy cả hai bộ định thời Timer0 và Timer1 đều có bit GATE. Vậy bit GATE dùng để làm gì? Mỗi bộ định thời thực hiện điểm khởi động và dừng. Một số bộ định thời thực hiện điều này bằng phần mềm, một số khác bằng phần cứng và một số khác vừa bằng phần cứng vừa bằng phần mềm. Các bộ định thời trên 8051 có cả hai:

Ø  Việc khởi động và dừng bộ định thời được khởi động bằng phần mềm bởi cácbit khởi động bộ định thời TR là TR0 và TR1. Điều này có được nhờ các lệnh Set bit TR0 lên 1 (khởi động bộ định thời) hoặc Clear bit TR0 (dừng bộ định thời) đối với Timer 0, và tương tự TR1 đối với Timer 1Các lệnh này có tác dụng khi bit GATE = 0 trong thanh ghi TMOD.
Ø  Việc khởi động và ngừng bộ định thời bằng phần cứng từ nguồn ngoài bằng cách đặt bit GATE = 1 trong thanh ghi TMOD.

Tuy nhiên, để tránh sự lẫn lộn ngay từ bây giờ ta đặt GATE = 0 có nghĩa là không cần khởi động và dừng các bộ định thời bằng phần cứng từ bên ngoài.

Ví dụ 3:
TMOD = 0000 0010: Bộ định thời là Timer0, chế độ 2, C/T = 0 dùng nguồn XTAL, GATE = 0 dùng phần mềm để khởi động và dừng bộ định thời.

            Như vậy, bây giờ chúng ta đã có hiểu biết cơ bản về vai trò của thanh ghi TMOD, chúng ta sẽ xét từng chế độ của bộ định thời và cách chúng được lập trình như thế nào để tạo ra một độ trễ thời gian.

1.2 Lập trình cho chế độ 1

            Dưới đây là những bước hoạt động của timer ở chế độ 1:

Ø  Đây là bộ định thời 16 bit, do vậy nó cho phép các giá trị 0000 đến FFFFHđược nạp vào các thanh ghi TL và TH của bộ định thời.
Ø  Sau khi TL và TH được nạp một giá trị khởi tạo 16 bit thì bộ định thời phải được khởi động. Điều này được thực hiện bởi việc SET bit TR0 đối vớiTimer 0 và SET bit TR1 đối với Timer 1.
Ø  Sau khi bộ định thời được khởi động, nó bắt đầu đếm lên. Nó đếm lên cho đến khi đạt được giới hạn FFFFH của nó. Sau đó, khi nó quay từ FFFFH về 0000thì nó bật lên bit cờ TF được gọi là cờ bộ định thời. Cờ bộ định thời này có thể được hiển thị. Khi cờ bộ định thời này được thiết lập, để dừng bộ định thời: ta thực hiện xóa các bit TR0 đối với Timer 0 hoặc TR1 đối với Timer 1. Ở đây cũng cần phải nhắc lại là đối với mỗi bộ định thời đều có cờ TF riêng của mình: TF0 đối với Timer 0 và TF1 đối với Timer 1.
Ø  Sau khi bộ định thời đạt được giới hạn của nó là giá trị FFFFH, muốn lặp lại quá trình thì các thanh ghi TH và TL phải được nạp lại với giá trị ban đầu và cờTF phải được xóa về 0.


Hình 5: Timer/counter chế độ 1

1.2.1 Các bước lập trình ở chế độ 1

            Để tạo ra một độ trễ thời gian dùng chế độ 1 của bộ định thời thì cần phải thực hiện các bước dưới đây:
1.      Nạp giá trị TMOD cho thanh ghi báo độ định thời nào (Timer0 hay Timer1) được sử dụng và chế độ nào được chọn.
2.      Nạp các thanh ghi TL và TH với các giá trị đếm ban đầu.
3.      Khởi động bộ định thời.
4.      Duy trì kiểm tra cờ bộ định thời TF bằng một vòng lặp để xem nó được bật lên 1 không. Thoát vòng lặp khi TF được lên cao.
5.      Dừng bộ định thời.
6.      Xoá cờ TF cho vòng kế tiếp.
7.      Quay trở lại bước 2 để nạp lại TL và TH.

Công thức tính toán độ trễ sử dụng chế độ 1 (16 bit) của bộ định thời đối với tần số thạch anh XTAL = f (MHz):

a) Tính theo số Hex
b) Tính theo số thập phân
(FFFF - YYXX + 1)*12/f (ms) trong đó YYXX là các giá trị khởi tạo của TH, TL tương ứng. Lưu ý rằng các giá trị YYXX là theo số Hex.
Chuyển đổi các giá trị YYXX của TH, TL về số thập phân để nhận một số thập phân NNNNN sau đó lấy (65536 – NNNNN)*12/f (ms).
Bảng 3: Công thức tính độ trễ thời gian theo tần số XTAL (f)

Ví dụ 4:
            Trong chương trình dưới đây ta tạo ra một sóng vuông với độ đầy xung 50% (cùng tỷ lệ giữa phần cao và phần thấp) trên chân P1.5. Bộ định thời Timer0 được dùng để tạo độ trễ thời gian:

#include<at89x51.h>                      //khai báo thư viện cho VĐK 89x51
void delay(void);                             //khi báo nguyên mẫu hàm con tạo trễ
main()
{
            P1_5=1;                                 //khởi tạo chân P1_5 ở mức cao
            while(1)                                 //vòng lặp vô hạn
            {
                        delay();                      //chương trình con tạo trễ
                        P1_5=~P1_5;            //đảo tín hiệu chân P1_5
            }
}
void delay(void)                              //định nghĩa hàm delay
{
                        TMOD=0x01;           //chọn timer0, chế độ 1, 16Bit
                        TL0=0xF2;                //nạp giá trị cho TL0
                        TH0=0xFF;                //nạp giá trị cho TH0
                        TR0=1;                       //khởi động timer0
                        while(!TF0){}           //vòng lặp kiểm tra cờ TF0
                        TR0=0;                       //ngừng timer0
                        TF0=0;                       //xóa cờ TF0
}

Trong chương trình chính (hàm main) thực hiện gọi hàm con delay() tạo trễ, và đảo liên tục tín hiệu đầu ra ở chân P1_5.
            Trong chương trình con delay() trên đây chú ý các bước sau:
1.      TMOD được nạp.
2.      Giá trị FFF2H được nạp và TH0 - TL0
3.      Bộ định thời Timer0 được khởi động bởi lệnh Set bit TR0.
4.      Bộ Timer0 đếm lên 01 sau mỗi chu kỳ của timer. Khi bộ định thời đếm tăng qua các trạng thái FFF3, FFF4 ... cho đến khi đạt giá trị FFFFH là nó quay về 0000H và bật cờ bộ định thời TF0 = 1. Tại thời điểm này vòng lặp kiểm tra cờ TF0 mới được thoát ra.
5.      Bộ Timer0 được dừng bởi lệnh clear bit TR0.
6.      Cờ TF0 cũng được xóa, sẵn sàng cho chu trình tiếp theo.

Lưu ý rằng để lặp lại quá trình trên ta phải nạp lại các thanh ghi TH và TL và khởi động lại bộ định thời (đơn giản là ta gọi lại hàm delay()).


Hình 6: Một chu trình đếm của timer0

Tính toán độ trễ tạo ra bởi bộ định thời ở chương trình trên với tần số XTAL=11,0592MHz:
            Bộ định thời làm việc với tần số đồng hồ bằng 1/12 tần số XTAL, do vậy ta có 11,0592MHz/12=0,9216MHz là tần số của bộ định thời. Kết quả là mỗi nhịp xung đồng hồ có chu kỳ T=1/0,9216MHz=1,085us. Hay nói cách khác, bộ Timer0 tăng 01 đơn vị sau 1,085ms để tạo ra bộ trễ bằng số_đếm´1,085ms.
            Số đếm bằng FFFFH - FFF2H = ODH (13 theo số thập phân). Tuy nhiên, ta phải cộng 1 vào 13 vì cần thêm  một nhịp đồng hồ để nó quay từ FFFFH về 0000H và bật cờ TF. Do vậy, ta có 14 ´ 1,085ms = 15,19ms cho nửa chu kỳ và cả chu kỳ là T = 2 ´ 15,19ms = 30, 38ms là thời gian trễ được tạo ra bởi bộ định thời.

            Tuy nhiên, trong tính toán độ trễ ở trên ta đã không tính đến tổng phí các lệnh cài đặt timer0, các lệnh kiểm tra trong vòng lặp, gọi hàm con… Chính các câu lệnh này làm cho độ trễ dài hơn, dẫn đến tần số của xung vuông ở đầu ra P1_5 không còn đúng như tính toán ở trên. Đây là nhược điểm của C trong lập trình VĐK. Tùy vào từng chương trình biên dịch, mỗi lệnh của C sẽ được biên dịch ra số lệnh ASM khác nhau, để tính toán chính xác ta phải tính cả tổng phí từng dòng lệnh ASM.

1.2.2 Tìm các giá trị cần được nạp vào bộ định thời

            Giả sử rằng chúng ta biết lượng thời gian trễ mà ta cần thì câu hỏi đặt ra là làm thế nào để tìm ra được các giá trị cần thiết cho các thanh thi TH và TL. Để tính toán các giá trị cần được nạp vào các thanh ghi TH và TL chúng ta hãy nhìn vào ví dụ sau với việc sử dụng tần số dao động XTAL = 11. 0592MHz đối với hệ thống 8051.

            Các bước để tìm các giá trị của các thanh ghi TH và TL:
1.      Chia thời gian trễ cần thiết cho 1.085ms
2.      Thực hiện 65536 - n với n là giá trị thập phân nhận được từ bước 1.
3.      Chuyển đổi kết quả ở bước 2 sang số Hex: ta có YYXX là giá trị Hexa ban đầu cần phải nạp vào các thanh ghi bộ định thời.
4.      Đặt TL = XX và TH = YY.

Ví dụ 5:
            Giả sử tần số XTAL = 11.0592MHz. Hãy tìm các giá trị cần được nạp vào các thanh ghi vào các thanh ghi TH và TL nếu ta muốn độ thời gian trễ là 5ms.
Lời giải:
            Vì tần số XTAL = 11.0592MHz nên bộ đếm tăng sau mỗi chu kỳ 1.085ms. Điều đó có nghĩa là phải mất rất nhiều khoảng thời gian 1,085ms để có được một xung 5ms. Để có được ta chia 5ms cho 1.085ms và nhận được số n = 4608 nhịp. Để nhận được giá trị cần được nạp vào TL và TH thì ta tiến hành lấy 65536 trừ đi 4608 bằng 60928. Ta đổi số này ra số hex thành EE00H. Do vậy, giá trị nạp vào TH là EE Và TL là 00.

void delay(void)                              //định nghĩa hàm delay
{
                        TMOD=0x01;           //chọn timer0 chế độ 1 16Bit
                        TL0=0x00;                //nạp giá trị cho TL0
                        TH0=0xEE;               //nạp giá trị cho TH0
                        TR0=1;                       //khởi động timer0
                        while(!TF0){}           //vòng lặp kiểm tra cờ TF0
                        TR0=0;                       //ngừng timer0
                        TF0=0;                       //xóa cờ TF0
}

Ví dụ 6:
            Giả sử ta có tần số XTAL là 11,0592MHz. Hãy tìm các giá trị cần được nạp vào các thanh ghi TH và TL để tạo ra một sóng vuông tần số 2kHz.
Xét các bước sau:
1. T = 1/f = 1/2KHz = 500us là chu kỳ của sóng vuông.
2.  Khoảng thời gian phần cao và phần thấp là: T/2 = 250ms.
3.      Số nhịp cần trong thời gian đó là:250us/1,085us = 230. Giá trị cần nạp vào các thanh ghi cần tìm là 65536 - 230 = 65306 và ở dạng hex là FF1AH.
4.      Giá trị nạp vào TL là 1AH, TH là FFH.
Chương trình cần viết là:

void delay(void)                              //định nghĩa hàm delay
{
                        TMOD=0x10;           //chọn timer1 chế độ 1 16Bit
                        TL1=0x1A;               //nạp giá trị cho TL1
                        TH1=0xFF;                //nạp giá trị cho TH1
                        TR1=1;                       //khởi động timer1
                        while(!TF1){}           //vòng lặp kiểm tra cờ TF1
                        TR1=0;                       //ngừng timer1
                        TF1=0;                       //xóa cờ TF1
}

1.3 Chế độ 0

            Chế độ 0 hoàn toàn giống chế độ 1 chỉ khác là bộ định thời 16 bit được thay bằng13 bit. Bộ đếm 13 bit có thể giữ các giá trị giữa 0000 đến 1FFFF trong TH - TL. Do vậy khi bộ định thời đạt được giá trị cực đại của nó là 1FFFH thì nó sẽ quay trở về 0000và cờ TF được bật lên.

1.4 Lập trình cho chế độ 2

            Dưới đây là những bước hoạt động của timer ở chế độ 2:

Ø  Nó là một bộ định thời 8 bit, do vậy nó chỉ cho phép các giá trị từ 00 đến FFHđược nạp vào thanh ghi TH của bộ định thời.
Ø  Sau khi 2 thanh ghi TH và TL được nạp giá trị ban đầu thì bộ định thời phải được khởi động.
Ø  Sau khi bộ định thời được khởi động, nó bắt đầu đếm tăng lên bằng cách tăng thanh ghi TL. Nó đếm cho đến khi đại giá trị giới hạn FFH của nó. Khi nó quay trở về 00 từ FFH, nó thiết lập cờ bộ định thời TF. Nếu ta sử dụng bộ định thời Timer0 thì đó là cờ TF0, còn Timer1 thì đó là cờ TF1.
Ø  Khi thanh ghi TL quay trở về 00 từ FFH, cờ TF được bật lên 1 thì thanh ghi TLđược tự động nạp lại với giá trị sao chép từ thanh ghi TH. Để lặp lại quá trình chúng ta đơn giản chỉ việc xoá cờ TF và để cho nó chạy mà không cần sự can thiệp của lập trình viên để nạp lại giá trị ban đầu. Điều này làm cho chế độ 2 được gọi là chế độ tự nạp lại so với chế độ 1 (phải nạp lại các thanh ghi TH và TL).


Hình 7: Timer/counter chế độ 2

Cần phải nhấn mạnh rằng: chế độ 2 là bộ định thời 8 bit. Tuy nhiên, nó lại có khả năng tự nạp, khi tự nạp lại thì giá trị ban đầu của TH được giữ nguyên, còn TL được nạp lại giá trị sao chép từ TH.

Chế độ này có nhiều ứng dụng, bao gồm việc thiết lập tần số baud trong truyền thông nối tiếp.

1.4.1 Các bước lập trình cho chế độ 2

Để tạo ra một thời gian trễ sử dụng chế độ 2 của bộ định thời cần thực hiện các bước sau:
1.      Nạp thanh ghi giá trị TMOD để báo bộ định thời gian nào (Timer0 hay Timer1) được sử dụng và chế độ làm việc nào của chúng được chon.
2.      Nạp lại thanh ghi TH và TL với giá trị đếm ban đầu.
3.      Khởi động bộ định thời.
4.      Duy trì kiểm tra cờ bộ định thời TF bằng cách sử dụng một vòng lặp để xem nó đã được bật chưa. Thoát vòng lặp khi TF lên cao.
5.      Dừng bộ định thời.
6.      Xoá cờ TF.
7.      Quay trở lại bước 3. Vì chế độ 2 là chế độ tự nạp lại.

Ví dụ 7 minh hoạ những điều này:

Ví dụ 7:
#include<at89x51.h>                      //khai báo thư viện cho VĐK 89x51        
void delay(void);                             //khi báo nguyên mẫu hàm con tạo trễ
main()
{
            TMOD=0x20;                       //chọn timer1, chế độ 2, 8Bit, tự nạp lại
            TH1=0x00;                            //nạp giá trị cho TH1
            TL1=0xFE;                            //nạp giá trị cho TL1
            P1_5=1;                                 //khởi tạo chân P1_5 ở mức cao
            while(1)                                 //vòng lặp vô hạn
            {
                        delay();                      //gọi chương trình con tạo trễ
                        P1_5=~P1_5;            //đảo tín hiệu chân P1_5
            }
}
void delay(void)                              //định nghĩa hàm delay
{
                        TR1=1;                       //khởi động timer1
                        while(!TF1){}           //vòng lặp kiểm tra cờ TF1
                        TR1=0;                       //ngừng timer1
                        TF1=0;                       //xóa cờ TF1
}

Hàm delay() trên sẽ tạo một độ trễ bằng 256 lần (FF - 00 + 1) chu kỳ của timer (không tính tổng phí các lệnh) kể từ chu trình thứ 2. Vì chu trình đầu tiên timer1 bắt đầu đếm ở vị trí 0xFE, kể từ chu trình sau thì thanh ghi TL1 mới sao chép được giá trị ở TH1.


2. Bộ đếm

            Ở phần trên đây ta đã sử dụng các bộ định thời của 8051 để tạo ra các độ trễ thời gian. Các bộ định thời này cũng có thể được dùng như các bộ đếm (counter) các sự kiện xảy ra bên ngoài 8051. Công dụng của bộ đếm sự kiện sẽ được tình bày ở phần này. Chừng nào còn liên quan đến công dụng của bộ định thời như bộ đếm sự kiện thì mọi vấn đề mà ta nói về lập trình bộ định thời ở phần trước cũng được áp dụng cho việc lập trình như là một bộ đếm ngoại trừ nguồn tần số.
Đối với bộ định thời/bộ đếm khi dùng nó như bộ định thời thì nguồn tần số là tần số thạch anh của 8051. Tuy nhiên, khi nó được dùng như một bộ đếm thì nguồn xung để tăng nội dung các thanh ghi TH và TL là từ bên ngoài 8051.
Ở chế độ bộ đếm, hãy lưu ý rằng các thanh ghi TMOD và THTL cũng giống như đối với bộ định thời được bàn ở phần trước, thậm chí chúng vẫn có cùng tên gọi. Các chế độ của các bộ đếm cũng giống nhau.

2.1 Bit C/T trong thanh ghi TMOD

            Xem lại phần trên về bit C/T trong thanh ghi TMOD: ta thấy rằng nó quyết định nguồn xung đồng hồ cho bộ đếm:

Ø  Nếu bit C/T = 0 thì  bộ định thời nhận các xung đồng hồ từ bộ giao động thạch anh của 8051.
Ø  Nếu bit C/T  = 1 thì bộ định thời được sử dụng như bộ đếm và nhận các xung đồng hồ từ nguồn bên ngoài của 8051.

Do vậy, nếu bit C/T = 1 thì bộ đếm tăng lên khi các xung được đưa đến chân P3.4 (T0) đối với counter0 và chân P3.5 (T1) đối với counter1.

Chân
Chân cổng
Chức năng
Mô tả
14
P3.4
T0
Đầu vào ngoài của bộ đếm 0
15
P3.5
T1
Đầu vào ngoài của bộ đếm 1
Bảng 4: Các chân cổng P3 được dùng cho bộ đếm 0 và 1

Ví dụ 8:
            Chương trình sau sử dụng bộ đếm 1, đếm các xung ở chân P3.5 và hiển thị số đếm được (trong thanh ghi TL1) lên cổng P2:

#include<at89x51.h>          //khai báo thư viện 89x51
main()                                                //chương trình chính
{
            TMOD=0x60;           //0x60=0110 000 : C/T=1, bộ đếm 1, chế độ 2 tự nạp
            TH1=0x00;                //xóa bộ đếm ban đầu

            P3_5=1;                     //set chân vào cho bộ đếm
            TR1=1;                       //khởi động bộ đếm 1

            while(1)                     //vòng lặp vô hạn
            {
                        P2=TL1;         //hiển thị số đếm được ra cổng P2
            }
}

            Trong ví dụ 8 chúng ta sử dụng bộ  counter1 như bộ đếm sự kiện để nó đếm lên mỗi khi các xung đồng hồ được cấp đến chân P3.5. Các xung đồng hồ này có thể biểu diễn số người đi qua cổng hoặc số vòng quay hoặc bất kỳ sự kiện nào khác mà có thể chuyển đổi thành các xung.

2.2 Thanh ghi TCON

            Trong các ví dụ trên đây ta đã thấy công dụng của các cờ TR0 và TR1 để bật/tắt các bộ đếm/bộ định thời. Các bit này là một bộ phận của thanh ghi TCON. Đây là thanh ghi 8 bit, như được chỉ ra trong hình 2:

Ø  4 bit trên được dùng để lưu cất các bit TF và TR cho cả Timer/counter 0 và Timer/counter 1.
Ø  4 bit thấp được thiết lập dành cho điều khiển các ngắt mà ta sẽ bàn ở các bài sau.


Hình 8: Thanh ghi TCON – Điều khiển bộ đếm/bộ định thời

2.3 Trường hợp khi bit GATE = 1 trong TMOD

            Trước khi kết thúc bài này ta cần bàn thêm về trường hợp khi bit GATE = 1 trong thanh ghi TMOD. Tất cả những gì chúng ta vừa nói trong bài này đều giả thiết GATE = 0. Khi GATE = 0 thì bộ đếm/bộ định thời được khởi động bằng các lệnh Set bit TR0 hoặcTR1. Vậy điều gì xảy ra khi bit GATE = 1?
Nếu GATE = 1 thì việc khởi động và dừng bộ đếm/bộ định thời được thực hiện từ bên ngoài qua chân P3.2 (INT0) và P3.3 (INT1) đối với Timer/counter 0 và Timer/counter 1 tương ứng. Phương pháp điều khiển bằng phần cứng để dừng và khởi động bộ đếm/bộ định thời này có thể có rất nhiều ứng dụng.
Ví dụ: chẳng hạn 8051 được dùng trong một sản phẩm phát báo động mỗi giây dùng bộ Timer0 theo nhiều việc khác. Bộ Timer0 được bật lên bằng phần mềm qua lệnh Set bit TR0 và nằm ngoài sự kiểm soát của người dùng sản phẩm đó. Tuy nhiên, khi nối một công tắc chuyển mạch tới chân P2.3 ta có thể dừng và khởi động bộ định thời, bằng cách đó ta có thể tắt báo động.