Lập trình bộ định thời-bộ đếm (Timer-Counter) với 8051 (Phần 1)

Lập trình bộ định thời-bộ đếm (Timer-Counter) với 8051 (Phần 1)

Timer trong vi điều khiển là gì

I. Giới thiệu

Chào các bạn!

Bộ định thời/bộ đếm (Timer/Counter) là một trong những tính năng ngoại vi thông dụng mà bất cứ dòng vi điều khiển nào cũng có .Timer/Counter được sử dụng rất nhiều trong các ứng dụng như quét led, tạo xung pwm, đo tần số, định thời…

Trước khi sử dụng Timer/Counter thì ta cần hiểu rõ và đi sau vào nó trên các dòng vi điều khiển cấp thấp như 8051 .Đây sẽ là bước tiếp cho việc sử dụng trên các dòng chíp cao cấp sau này.

1.Timer/Counter là gì và hoạt động như thế nào?

  • Timer/Counter là một bộ đếm xung nhịp (xung clock).
  • Nó chứa các thanh ghi chứa giá trị đếm và thanh ghi điều khiển hoạt động đếm này.
  • Xung nhịp có 2 loại:
    • Xung nhịp nội (bên trong vi điều khiển)
    • Xung nhịp bên ngoài (đưa vào trên một chân nào đó).
  • Người dùng có thể lập trình cho Timer/Counter bắt đầu đếm từ 1 giá trị nào đó bằng cách ghi giá trị đó vào thanh ghi chứa giá trị đếm. Khi giá trị đếm vượt quá giá trị tối đa mà thanh ghi chứa giá trị của Timer/Counter thì xuất hiện hiện tượng gọi là “tràn (over flow)”.

2.Timer/Counter trên 8051

Trong 8051 có 2 bộ Timer/Counter đó là:

  • Timer/Counter 0
  • Timer/Counter 1.

Đối với dòng 8052 thì sẽ có thêm 1 bộ Timer/Counter 2 nữa.

Trong phạm vi bài học này, mình sẽ hướng dẫn các bạn lập trình điều khiển 2 bộ Timer/Counter của 8051. Timer/Counter 2 các bạn có thể tự tìm hiểu, hoặc có thời gian mình sẽ viết trong 1 bài viết khác. Nào, chúng ta hãy cùng bắt đầu tiềm hiểu về Timer/Counter trong 8051 nhé!

II. Các thanh ghi điều khiển Timer/Counter trong 8051.

2.1. Thanh ghi chứa giá trị đếm.

Mỗi bộ Timer/Counter trong 8051 có 1 thanh ghi 16 bit chứa giá trị đếm, được truy cập (đọc/ghi) dưới 2 thanh ghi 8 bit độc lập gọi là byte thấp (TLx), byte cao (THx).

  • Thanh ghi chứa giá trị đếm của Timer/Counter 0.

  • Thanh ghi chứa giá trị đếm của Timer/Counter 1.

2.2. Thanh ghi cài đặt chế độ hoạt động: TMOD.

Cả 2 bộ Timer/Counter 0 và Timer/Counter 1 đều dùng chung 1 thanh ghi TMOD để thiết lập các chế độ hoạt đông. TMOD là thanh ghi 8 bit. 4 bit thấp sử dụng để thiết lập chế độ cho Timer/Counter 0, còn 4 bit cao được sử dụng để thiết lập chế độ hoạt động cho Timer 1.

Các bit M1, M0 được dùng để thiết lập chế độ hoạt động cho các bộ Timer/Counter.

Các chế độ hoạt động của Timer/Counter được mô tả như trong bảng sau.

  • Bit C/T được sử dụng để chon xung clock.
  • Khi bit C/T = 0. Bộ Timer/Counter hoạt động dựa vào xung clock nội bên trong chip. Tần số của xung clock này được tính bằng 1/12 của tần số thạch anh. Ví dụ nếu sử dụng thạch anh 12MHz, thì tần số của Timer/Counter sẽ là (1/12)*12MHz = 1MHz.
  • Khi bit C/T = 1. Bộ Timer/Counter hoạt động dựa vào xung clock cấp từ bên ngoài đưa vào trên chân T0 (sử dụng cho Timer/Counter 0), chân T1 (sử dụng cho Timer/Counter 1).
  • Bit GATE được sử dụng để xác định việc điều khiển khởi động/dừng hoạt động của bộ Timer.
  • Nếu GATE = 0. Bộ Timer/Counter được khởi động bằng cách set bit TRx lên 1. (TR0 cho Timer/Counter 0, TR1 cho Timer/Counter 1). Bộ Timer/Counter dừng hoạt động nếu bit TRx được xóa về 0.
  • Nếu GATE = 1. Bộ Timer/Counter được khởi động bằng cách set bit TRx lên 1 và chân INTx được set lên mức 1. Ngược lại nếu TRx không được set lên 1 hoặc chân INTx không được set lên 1 thì bộ Timer/Counter dừng hoạt động.

Trong phạm vi bài học này, chúng ta sẽ viết các chương trình với bit 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.

2.3. Thanh ghi điều khiển và trạng thái: TCON.

Thanh ghi TCON đã được đề cập tròng bài 5 với các bit sử dụng để thiết lập chế độ cho ngắt ngoài. Tròng bài này chúng ta tiếp tục tìm hiểu thanh ghi TCON với các bit sử dụng cho Timer/Counter.

  • Có 4 bit trong thanh ghi TCON được sử dụng cho bộ Timer/Counter.
  • Có 2 bit để điều khiển khởi động/dừng hoạt động của Timer/Counter. Đó là:
  • Bit TR0 dùng để khởi động/dừng Timer/Counter 0. TR0 =1: khởi động. TR0 = 0: dừng
  • Bit TR1 dùng để khởi động/dừng Timer/Counter 1. TR1 =1: khởi động. TR1 = 0: dừng
  • Có 2 bit cờ báo trạng thái tràn của bộ Timer/Counter. Đó là:
  • Bit TF0 báo tràn cho bộ Timer/Counter 0. Khi giá trị trong thi ghi chứa giá trị đếm TL0, TH0 bị tràn, thì bit TF0 sẽ được bật lên 1.
  • Bit TF1 báo tràn cho bộ Timer/Counter 1. Khi giá trị trong thi ghi chứa giá trị đếm TL1, TH1 bị tràn, thì bit TF1 sẽ được bật lên 1.
  • Cả hai bit TF0, TF1 được bật bằng phần cứng, và phải xóa bằng phần mềm.

III. Các bước thiết lập cho Timer/Counter trong 8051.

Để sử dụng bộ Timer/Counter trong 8051, chúng ta khởi tạo theo các bước sau.

  1. Ghán giá trị cho thanh ghi TMOD để thiết lập chế độ hoạt động cho bộ Timer/Counter. Ví dụ, mình muốn sử dụng Timer/Counter 0 ở chế độ 16 bit (M1 = 0, M0 = 1), sử dụng nguồn clock nội (C/T = 0), mình sẽ ghán cho thanh ghi TMOD giá trị: 0x01. (TMOD = 0x01).
  2. Khởi tạo giá trị cho thanh ghi chứa giá trị đếm TLx, THx.
    • Mặc định giá trị của 2 thanh ghi TLx, THx sẽ là bằng 0. Nghĩa là khi Timer/Counter hoạt động, bộ đếm sẽ đếm từ 0 cho đến 65535 (với chế độ 16 bit) thì xảy ra tràn. Nghĩa là bộ đếm đếm được (65535 – 0 + 1 =65536 lần) thì xảy ra tràn. Nhưng bây giờ mình chỉ muốn cho bộ đếm đếm 100 lần thì tràn. Vậy mình phải ghán giá trị cho thanh ghi TLx, THx để nó bắt đầu đếm từ giá trj mà mình gán, cho tới khi tràn (=65535) là được 100 lần đếm. Vậy mình sẽ phải gán cho TLx, THx giá trị: 65536 -100 = 65436. Do phải gán cho các thanh ghi 8 bit, nên mình phải đổi số 65436 ra thành 2 byte thấp vào cao để gán cho TLx, THx. 65436 đổi sang dạng hexa ta được: 0xFF9C. Do vậy mình sẽ gán TLx = 0x9C và THx = 0xFF.
    • Việc tính toán giá trị gán cho thanh ghi TLx, THx rất quan trọng. Nó yêu cầu bạn phải biết tần số hoạt động của Timer/Counter, thời gian bạn muốn xảy ra sự kiện tràn. Từ đó các bạn tính ra số lần bộ Timer/Counter cần đếm (gọi là n) để giá trị bị tràn. Sau đó lấy 65536 – n (với chế độ 16 bit), được giá trị cần gán cho TLx, THx.
    • Lấy 1 ví dụ thế này: Mình cần cài đặt Timer/Counter 0 hoạt động để cứ 10ms thì sẽ xảy ra tràn. Biết thạch anh là 12MHz. Tính giá trị cần gán cho thanh ghi TL0, TH0.
    • Với thạch anh 12MHz, ==>tần số hoạt động của Timer/Counter là: (1/12)*12 = 1MHz. nghĩa là cứ 1 xung nhịp (1us) thì bộ đếm tăng thêm 1 giá trị.
    • ==> Để 10ms = 10000us xảy ra tràn thì cần cho bộ đếm đếm 10000 lần (n=10000).
    • ==>giá trị gán cho TL0, TH0: 65536 -10000 = 55536 = 0xD8F0
    • ==> TL0 = 0xF0, TH0 = 0xD8.

3.Bật bit TRx để khởi động bộ Timer/Counter.

Như vậy là trong các phần trên, chúng ta đã tìm hiểu về Timer/Counter, các thanh ghi, cũng như cách thiết lập cho các thanh ghi của bộ Timer/Counter. Tiếp theo chúng ta sẽ tìm hiểu hoạt động của Timer/Counter trong các ví dụ cụ thể để hiểu rõ hơn về nó.

IV. Một số ví dụ

Tạo xung có tần số 2KHz trên chân P2.0, trong đó độ rộng mức 1 chiếm 70%, độ rộng mức 0 chiếm 30%. Biết mạch sử dụng thạch anh có tần số 12MHz.

  • Do mạch sử dụng thạch anh có tần số 12MHz => tần số xung nhịp cấp cho bộ timer/counter là (1/12)*12=1MHz (Mỗi xung clock mất 1us).
  • Do yêu cầu xung có tần số f = 2KHz =>T = 1/f = 0.5ms = 500us. =>Cần cho bộ timer/counter đếm 500 lần.
  • Độ rộng mức 1 chiếm 70% => mình sẽ set chân P2.0 lên 1 timer/counter và cho đếm 350 lần.
  • Độ rộng mức 0 chiếm 30% => tiếp theo, clear chân P2.0 về 0 và cho timer/counter đếm 150 lần.

Các bạn có thể hình dung qua hình vẽ dưới đây.

  • Ở đây mình sẽ chọn timer/counter 0, để thực hiện bài toán này. Do giá trị gán cho thanh ghi đếm vượt quá 255 nên mình sẽ sử dụng timer/counter 0 ở mode 16 bit (TMOD = 0x01)
  • Đoạn code thực việc tạo xung.

  • Trong comment mình đã viết rõ ý nghĩa các lệnh, nên mình sẽ không giải thích lai nữa. Bạn nào còn chưa rõ ở điểm nào vui lòng comment phía dưới.
  • Kết quả mô phỏng.

Bộ định thời gian. (Continue…)