Chương trình delay

Một phần của tài liệu Nghiên cứu ứng dụng điều khiển pic (Trang 87 - 96)

2. MOVWF PORTB

3.1.1 Chương trình delay

Chương trình trên giúp ta đưa giá trị ra các PORT của vi điều khiển và các LED sẽ sáng hay tắt tùy theo mức logic đưa ra các PORT. Bây giờ ta lại muốn các LED sẽ chớp tắt sau một khoảng thời gian định trước. Muốnvậy ta dùng thêm một đoạn chương trình DELAY. Thực chất của chương trình DELAY là cho vi điều khiển làm một cơng việc vơ nghĩa nào đĩ trong một khoảng thời gian định trước. Khoảng thời gian này được tính tốn dựa trên quá trình thực thi lệnh, hay cụ thể hơn là dựa vào thời gian của một chu kì lệnh. Cĩ thể viết chương trình DELAY dựa trên đoạn chương trình sau:

MOVLW 0X20 ; giá trị 20h

MOVWL delay-reg ; đưa vào thanh ghi delay

loop DECFSZ delay-reg ; giảm giá trị thanh ghi delay-reg 1 đơn vị

GOTO loop ; nhảy tới label “loop” nếu thanh ghi delay-reg ; sau khi giảm 1 đơn vị chứa giá trị khác 0.

……… ; lệnh này được thực thi khi delay-reg bằng 0 Nếu dùng đoạn chương trình này thì thời gian delay được tính gần đúng như sau: td= 3(1+tv)ti

Trong đĩ tdlà thời gian delay, tvlà giá trị đưa vào thanh ghi delay-reg và ti là thời gian của một chu kì lệnh và được tính theo cơng thức:

Với f0 là tần số của oscillator. Sở dĩ cĩ cơng thức này là vì một chu kì lệnh bao gồm 4 xung clock. Cơng thức này chỉ gần đúng vì ta đã bỏ qua thời gian thực thi các lệnh trước label “loop” và một chu kì lệnh phát sinh khi thanh ghi delay-reg mang giá trị 0 (trường hợp này cần hai chu kì lệnh để thực thi lệnh DECFSZ).

Do thanh ghi delay-reg chỉ mang giá trị lớn nhất là FFh nên thời gian delay chỉ giới hạn ở một khoảng thời gian nhất định tùy thuộcvào xung clock sử dụng để cấp cho vi điều khiển. Muốn tăng thời gian delay ta cĩ thể gọi chương trình delay nhiều lần hoặc tăng số lượng vịng lặp của chương trình delay như sau:

MOVLW 0Xff MOVWF delay-reg1 loop DECFSZ delay-reg1

GOTO loop1 ; thưc thi dìng lệnh này nếu delay-reg khác 0

GOTO exit ; thưc thi dìng lệnh này nếu delay-reg bằng 0

Loop1 MOVLW 0Xff MOVWF delay-reg2 DECFSZ delay-reg2

MOVWF loop1 ; thưc thi dừng lệnh này nếu delay-reg khác 0

GOTO loop ; thưc thi dừng lệnh này nếu delay-reg khác 0

Exit……….. ; lệnh tiếp theo sau thời gian delay

Với đoạn chương trình trên thời gian delay chỉ kết thúc khi cả hai thanh ghi delay- reg1 và delay-reg2 đều mang giá trị 0.

Sau đây là một ví dụ cụ thể. Yêu cầu đặtra là cho các LED trong chương trình 3.1 chớp tắt sau mỗi 100 miligiây. Giả sử ta đang sử dụng oscillator 4MHz. Khi đĩ thời gian của một chu kì lệnh là:

ti= 4/4 MHz = 1 uS.

Với thời gian cần delay là tdbằng 1s thì giá trị cần đưa vào thanh ghi delay-reg là: tv= (td/3ti) – 1 = 33332.

Như vậy ta đưa vào thanh ghi delay-reg2 giá trị 255 (FFh) và thanh ghi delay-reg1 giá trị 33332/255 = 131 (83h).

Chương trình được viết như sau:

;chương trình 2

;PORTBTESTANDDELAY.ASM ;Version 1.1

processor 16f877a ; khai báo vi điều khiển include <p16f877a.inc> ; header file đính kèm __CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF

; khai báo các “Configuration bits”

delay_reg1 EQU ; khai báo địa chỉ các ơ nhớ chứa các thanh ghi delay_reg2 EQU 0x21 ; delay-reg1 và delay-reg2

ORG 0x000 ; địa chỉ bắt đầu chương trình GOTO start

start ; chương trình chính bắt đầu tại đây BCF STATUS,RP1

CLRF PORTB ; xĩa PORTB BSF STATUS,RP0 ; chọn BANK1 MOVLW 0x00

MOVWF TRISB ; PORTB <- outputs BCF STATUS,RP0 ; chọn BANK0

loop MOVLW 0x8F ; giá trị cần đưa ra PORTB MOVWF PORTB ; PORTB <- 8Fh

MOVLW 0x83

MOVWF delay_reg1 MOVLW 0xFF MOVWF delay_reg2 loop1 DECFSZ delay_reg1 GOTO loop2 GOTO exit1

loop2 DECFSZ delay_reg2 GOTO loop2

GOTO loop1 ; delay 100 ms exit1 CLRF PORTB ; xĩa PORTB MOVLW 0x83

MOVWF delay_reg1 MOVLW 0xFF MOVWF delay_reg2 loop3 DECFSZ delay_reg1 GOTO loop4 GOTO exit2

GOTO loop4

GOTO loop3 ; delay 100 ms exit2

GOTO loop ; vịng lặp vơ hạn END ; kết thúc chương trình

Với chương trình này các pin của PORTB sẽ thay đổi trạng thái sau mỗi khoảng thời gian delay là 100 ms. Điều này cho phép ta nhận thấy bằng mắt thường vì trong một giây các pin của PORTB sẽ thay đổi trạng thái 10 lần.

Tuy nhiên ta dễ dàng nhận thấy một nhược điểm của chương trình trên là cần tới hai đoạn chương trình delay với cấu trúc chương trình, thuật tốn và chứcnăng hồn tồn giống nhau. Điều này làm cho chương trình trở nên phức tạp và tốn nhiều dung lượng bộ nhớ của vi điều khiển. Điều này cần được chú trọng vì dung lượng bộ nhớ chương trình của một vi điều khiển thường nhỏ (đối với PIC16F877A dung lượng bộ nhớ chương trình là 8K word với một word là 14 bit). Một phương pháp để khắc phục nhược điểm này là sử dụng chương trình con và dùng lệnh “CALL” để gọi chương trình con đĩ. Chương trình con cĩ thể đựơc đặt tại bất cứ vị trí nào trong chương trình chính. Chương trình 2 khi đĩ được viết lại như sau:

;chương trình 3

;PORTBTESTANDDELAY.ASM ;Version 1.2

processor 16f877a ; khai báo vi điều khiển include <p16f877a.inc> ; header file đính kèm

__CONFIG _CP_OFF & _WDT_OFF & _BODEN_OFF & _PWRTE_ON & _XT_OSC & _WRT_OFF & _LVP_OFF & _CPD_OFF

; khai báo các “Configuration ; bits”

delay_reg1 EQU 0x20 ; khai báo địa chỉ các ơ nhớ chứa ; các thanh ghi delay-reg1

delay_reg2 EQU 0x21 ; và delay-reg2

ORG 0x000 ; địa chỉ bắt đầu chương trình GOTO start

start ; chương trình chính bắt đầu tại ; đây

BCF STATUS,RP1

BCF STATUS,RP0 ; chọn BANK0

CLRF PORTB ; xĩa PORTB BSF STATUS,RP0 ; chọn BANK1

MOVLW 0x00

MOVWF TRISB ; PORTB <- outputs

BCF STATUS,RP0 ; chọn BANK0

loop MOVLW 0x8F ; giá trị bất kì cần đưa ra ; PORTB

MOVWF PORTB ; PORTB <- 8Fh

CALL delay100ms ; gọi chương trình con ; delay100ms

CLRF PORTB ; xĩa PORTB CALL delay100ms

GOTO loop ; vịng lặp vơ hạn Delay100ms

MOVLW 0x83

MOVWF delay_reg1 MOVLW 0xFF MOVWF delay_reg2

loop1 DECFSZ delay_reg1 GOTO loop2 GOTO exit

loop2 DECFSZ delay_reg2 GOTO loop2

GOTO loop1 ; delay 100 ms Exit

RETURN ; trở về chương trình chính

Với cách viết chương trình sử dụng chương trình con, cấu trúc chương trình sẽ trở nên gọn gàng dễ hiểu hơn, linh hoạt hơn và tiết kiệm được nhiều dung lượng bộ nhớ chương trình.

Bây giờ ta sẽ bàn đến một thuật tốn khác để viết chương trình delay. Về nguyên tắc thì thuật tốn mới này khơng cĩ nhiều khác biệt so với thuật tốn cũ, tuy nhiên lệnh sử dụng trong chương trình và cách tính tốn thời gian delay thì khác nhau. Chương trình con delay100ms với oscillator 4 MHz cĩ thể được viết lại như sau: delay100ms MOVLW d’100’ MOVWF count1 d1 MOVLW 0xC7 MOVWF counta MOVLW 0x01 MOVW countb delay_0 DECFSZ counta,1 GOTO $+2 DECFSZ countb,1 GOTO delay_0 DECFSZ count1,1 GOTO d1 RETLW 0x00

END

Trước tiên ta xét đoạn chương trình kể từ label “delay_0”. Lệnh DECFSZ mất một chu kì lệnh (trừ trường hợp thanh ghi counta mang giá trị 0 thì cần 2 chu kì lệnh), lệnh GOTO $+2 mất hai chu kì lệnh. Lệnh này cĩ tác dụng cộng vào bộ đếm chương trình giá trị 2, khi đĩ chương trình sẽ nhảy tới lệnh cĩ địa chỉ (PC+2), tức là lệnh GOTO delay_0, lệnh này cũng tốn hai chu kì lệnh. Như vậy ta cần tổng cộng 5 chu kì lệnh để giảm giá trị trong thanh ghi counta 1 đơn vị. Thanh ghi counta mang giá trị 199 (C7h), do đĩ đoạn chương trình này sẽ tạo ra một khoảng thời gian delay:

td= 5(counta+1)*ti = 5(199+1)*1 uS = 1 mS

Muốn tạo ra thời gian delay 100 mS, ta chỉ việc đưa giá trị 100 vào thanh ghi count1. Bên cạnh đĩ ta cĩ thể viết một chương trình con cĩ tác dụng delay một khoảng thời gian bất kì là bội số của 1 mS một cách dễ dàng.

Trong chương trình trên ta cịn sử dụng thêm một lệnh khá lạ là lệnh RETLW. Lệnh này cĩ tác dụng trở về vị trí mà chương trình con được gọi và thanh ghi W khi đĩ mang giá trị là tham số của lệnh RETLW (00h). Trong trường hợp này thanh ghi W khơng cần mang một giá trị cụ thể khi quay trở về chương trình chính nên lệnh RETLchỉ cĩ tác dụng như lệnh RETURN.

Một phần của tài liệu Nghiên cứu ứng dụng điều khiển pic (Trang 87 - 96)

Tải bản đầy đủ (DOCX)

(125 trang)
w