View Single Post
Old 26-05-2005, 10:54 PM   #6
falleaf
PIC Bang chủ
 
falleaf's Avatar
 
Tham gia ngày: May 2005
Bài gửi: 2,631
:
Send a message via Yahoo to falleaf
Hàm DELAY

Học vi điều khiển PIC trong 1 ngày

Qua bài học thứ nhất, chúng ta đã học về cách bật tắt một đèn LED. Bây giờ nếu muốn làm cho đèn LED nhấp nháy, có nghĩa là chúng ta bật đèn LED, sau đó chờ một khoảng thời gian, và tắt đèn led đó đi, sau đó lại chờ một khoảng thời gian nữa và lại bật đèn led lên. Muốn thực hiện việc này, chúng ta phải tìm cách làm một hàm delay (delay - tiếng Anh có nghĩa là trễ, chậm lại)

Hàm DELAY là một hàm rất thông dụng khi lập trình thời gian thực. Nguyên lý của hàm delay là dùng thời gian thực hiện các lệnh của vi điều khiển để làm thời gian trễ. Như các bạn đã biết (nếu chưa biết thì bây giờ biết.. hihi), mỗi lệnh của vi điều khiển, khi thực hiện, cần phải tốn một khoảng thời gian nào đó. Nếu một việc làm mà không tốn thời gian thì đúng là vô lý. Vậy thời gian thực hiện một lệnh của PIC là bao lâu?

Như trong bài học đầu tiên chúng ta đã đề cập, chúng ta sử dụng thạch anh từ 4MHz đến 10MHz và đến 20MHz. Thạch anh này tạo ra các dao động xung nhịp chính xác để duy trì những khoảng thời gian xác định cho vi điều khiển hoạt động.

Chúng ta xem hình sau để hiểu được nguyên lý tạo dao động bên trong vi điều khiển:

Hình 1:



Thạch anh tạo dao động trên các chân OSC, đưa vào bên trong PIC. PIC sẽ đếm 4 nhịp trên dao động thạch anh, và để thực hiện một lệnh. Như vậy, thời gian thực hiện một lệnh chính là 4 nhịp dao động của thạch anh.

Chúng ta thường gọi thời gian thực hiện một lệnh của PIC là một chu kỳ máy (đoạn số 2 trên hình). Vậy một chu kỳ máy bằng bao nhiêu, nếu chúng ta sử dụng thạch anh 10MHz cho PIC?

Code:
Tần số dao động của thạch anh:
F_osc = 10MHz
Chu kỳ của dao động thạch anh:
T_osc = 1/10.000.000 s
Chu kỳ máy
T_instruction = 4 * T_osc = 4/10.000.000 s = 0.0000004 s = 0.0004 ms = 0.4 us = 400 ns
Như vậy, một lệnh máy được thực hiện trong vòng 0.4 micro giây, hay 400 nano giây.

Tương tự, khi các bạn dùng thạch anh 4MHz, chu kỳ máy sẽ là 1us, và dùng thạch anh 20MHz, chu kỳ máy sẽ là 200 nano giây.

Quay trở lại với việc nếu chúng ta cần thực hiện một việc gì đó giống như nhấp nháy đèn LED, thì chúng ta cần PIC phải dừng lại, không làm gì cả để chờ chúng ta. Nếu như lệnh NOP (lệnh không làm gì) sẽ giúp chúng ta chờ 0.4 us, mà chúng ta cần chờ 1 giây, thì chúng ta viết bao nhiêu lệnh NOP cho đủ?

Thay vì như vậy, chúng ta viết một vòng lặp để cho vi điều khiển làm một việc vô thưởng vô phạt nào đó N lần, và mỗi lần như vậy nó tốn T chu kỳ máy. Như vậy, sau khi kết thúc việc làm vô thưởng vô phạt đó, vi điều khiển đã chờ chúng ta N * T chu kỳ máy.

Để viết một vòng lặp như vậy, trước tiên chúng ta học cách đặt biến.

Một biến được đặt trong PIC, thực chất là một tên gọi chung cho một hoặc nhiều thanh ghi các giá trị. Trong phần này, chúng ta chỉ đơn giản làm đặt biến có nghĩa là đặt tên cho một thanh ghi. Thực ra, chúng ta hoàn toàn không cần đặt tên, mà có thể gọi trực tiếp địa chỉ của thanh ghi, nhưng nếu làm như vậy, sau này, khi chương trình phức tạp dần lên, chúng ta sẽ dễ bị lẫn lộn các biến.

Khi đặt biến, thanh ghi này nằm ở đâu? Nó sẽ nằm trong bộ nhớ chương trình và cụ thể, nó sẽ nằm trong vùng nhớ dùng chung mà chúng ta đã đề cập trong bài học trước.

Vậy làm thế nào để đặt biến? Có rất nhiều cách đặt biến, và trong phần này, tôi sẽ hướng dẫn các bạn cách đặt biến mà tôi cho rằng rõ ràng nhất.

Code:
;==================================================================

			ORG 0x020
COUNT_L	RES	1
COUNT_H	RES	1
COUNT_N	RES	3

;==================================================================
Các bạn vừa làm gì?

Directive ORG dùng để xác định địa chỉ vùng nhớ. Các bạn lưu ý rằng, khi xác định địa chỉ vùng nhớ ở đây, chính là các bạn xác định địa chỉ vùng nhớ dữ liệu, chứ không phải địa chỉ vùng nhớ lập trình. Những gì các bạn viết phía bên dưới, sẽ giúp cho trình dịch hiểu được rằng các bạn đang làm việc trong vùng nhớ lập trình, hay vùng nhớ dữ liệu

Directive RES quy định việc đặt biến. Số 1 phía sau xác định rằng biến có tên COUNT_L chiếm 1 thanh ghi 8 bit, tức là 1 byte.

Tiếp theo, các bạn lại đặt biến tên là COUNT_H. Như vậy, biến COUNT_H cũng chiếm 1 byte.

Câu hỏi đặt ra là các thanh ghi này nằm ở đâu?

Các bạn lưu ý, khi các bạn dùng directive ORG, là các bạn đã xác định nơi bắt đầu đặt biến. Như vậy, biến COUNT_L sẽ có độ dài 1 byte, và được đặt ở địa chỉ 0x020 tức là địa chỉ đầu tiên của vùng nhớ dữ liệu dùng chung trong băng 0 (20h)

Vì COUNT_L đã chiếm 1 byte. Do đó, biến COUNT_H sẽ chiếm byte tiếp theo, và địa chỉ đầu tiên của COUNT_H sẽ là 21h, nhưng COUNT_H cũng chỉ có 1 byte, cho nên nó chính là thanh ghi ở địa chỉ 21h. Đến biến COUNT_N, tương tự, địa chỉ đầu tiên của nó sẽ là 22h. Biến COUNT_N chiếm 3 thanh ghi, như vậy, biến COUNT_N sẽ nằm từ 22h, 23h đến 24h. Nếu tiếp tục đặt thêm các biến khác, các biến đó sẽ bắt đầu từ địa chỉ 25h, cứ như thế.

Vậy muốn đặt biến ở các băng khác thì làm thế nào? Các bạn cứ lấy địa chỉ đầu của vùng nhớ dữ liệu dùng chung của băng đó và viết như sau:

Code:
;=================================================
			ORG	0x0A0h

COUNT_X	RES	10
;=================================================
Tóm lại, để chuẩn hoá một chương trình, các bạn chép đoạn code này vào, và sau đó không bao giờ còn phải viết lại nữa:

Code:
;=======================================================================

;-----------------------------------
; Bien nam o Bank0
;-----------------------------------
			ORG	0x020

COUNT_L	RES	1
COUNT_H	RES	1

;----------------------------------
; Bien nam o Bank1
;----------------------------------

			ORG	0x0A0

COUNT1_L	RES	1

;---------------------------------
; Bien nam o Bank2
;---------------------------------
			ORG	0x120

;========================================================================
Như vậy, một chương trình tổng quát bây giờ sẽ trở thành như thế nào?

Code:
;========================================================================
; Phần chú thích ban đầu
;
;========================================================================
; Phần khởi tạo vi điều khiển
			TITLE
			PROCESSOR
			INCLUDE
			__CONFIG

;========================================================================
; Phần đặt biến

;-------------------------------------
; Biến ở băng 0
;-------------------------------------
			ORG	0x020
;------------------------------------
; Biến ở băng 1
;------------------------------------
			ORG	0x0A0
;------------------------------------
; Biến ở băng 2
;------------------------------------
			ORG	0x120

;=========================================================================
; Phần chương trình chính
			ORG	0x0000
			GOTO	MAIN


			ORG	0x0005
MAIN
; 			những dòng lệnh được viết ở đây
			END
;==========================================================================
Như vậy, chúng ta đã biết cách viết một chương trình đầy đủ dành cho vi điều khiển PIC bằng ngôn ngữ MPASM.
falleaf vẫn chưa có mặt trong diễn đàn   Trả Lời Với Trích Dẫn