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

0
65
Rate this post
Video timer trong vi điều khiển là gì

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 đèn LED, tạo xung PWM, đo tần số và định thời. Trước khi sử dụng Timer/Counter, ta cần hiểu rõ và đi sâu 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 chip cao cấp sau này.

I. Giới thiệu

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ừ một 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 (overflow)”.

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, 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 tì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 0

  • Thanh ghi chứa giá trị đếm của Timer/Counter 1:
    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.

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

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:

Các chế độ hoạt động của Timer/Counter

  • Bit C/T được sử dụng để chọn 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. Điều này 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 trong bài 5 với các bit sử dụng để thiết lập chế độ cho ngắt ngoài. Trong 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 thanh 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 thanh 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. Gá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ẽ gá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 gán giá trị cho thanh ghi TLx, THx để nó bắt đầu đếm từ giá trị 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.
    • Ví dụ: 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.

Hình vẽ minh hoạ ví dụ

Ở đâ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.

Đoạn code 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 lại 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…)

Dnulib