21.07.2013 Views

THỰC HÀNH VI XỬ LÝ - Khoa Khoa học và Kỹ thuật Máy tính

THỰC HÀNH VI XỬ LÝ - Khoa Khoa học và Kỹ thuật Máy tính

THỰC HÀNH VI XỬ LÝ - Khoa Khoa học và Kỹ thuật Máy tính

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

ĐẠI HỌC QUỐC GIA TP.HCM<br />

TRƯỜNG ĐẠI HỌC BÁCH KHOA<br />

KHOA KHOA HỌC VÀ KỸ THUẬT MÁY TÍNH<br />

<strong>THỰC</strong> <strong>HÀNH</strong> <strong>VI</strong> <strong>XỬ</strong> <strong>LÝ</strong><br />

BM <strong>Kỹ</strong> <strong>thuật</strong> <strong>Máy</strong> <strong>tính</strong><br />

2009


Giới thiệu


Mục Lục<br />

Mục Lục.............................................................................................................................. 1<br />

Bài 1 : Giới thiệu MPLAB IDE <strong>và</strong> KIT PIC .................................................................. 1<br />

1.1 Môi trường phát triển MPLAB ................................................................................. 1<br />

1.2 Nạp file hex <strong>và</strong>o vi điều khiển PIC........................................................................... 8<br />

1.3 Debug dùng MpLab SIM........................................................................................ 12<br />

1.4 Debug onchip dùng Mplab ICD2............................................................................ 15<br />

1.5 Bài tập ..................................................................................................................... 15<br />

Bài 2 : Khảo sát cổng xuất nhập................................................................................... 16<br />

2.1 Kiến thức liên quan................................................................................................. 16<br />

2.1.1 Các thanh ghi điều khiển cổng xuất nhập ........................................................ 16<br />

2.1.2 Kết nối mạch.................................................................................................... 16<br />

2.2 Các bước hiện thực yêu cầu 1................................................................................. 18<br />

2.3 Chương trình mẫu yêu cầu 1................................................................................... 20<br />

2.4 Các bước hiện thực yêu cầu 2................................................................................. 21<br />

2.5 Chương trình mẫu yêu cầu 2................................................................................... 22<br />

2.6 Bài tập ..................................................................................................................... 23<br />

Bài 3 : Khảo sát cơ chế ngắt quãng, giao tiếp LCD ký tự ............................................ 24<br />

3.1 Kiến thức liên quan................................................................................................. 24<br />

3.1.1 Tóm tắt các thanh ghi điều khiển ngắt............................................................. 24<br />

3.2 Các bước hiện thực yêu cầu 1................................................................................. 25<br />

3.3 Chương trình mẫu yêu cầu 1................................................................................... 28<br />

3.4 LCD ký tự 2x16 ...................................................................................................... 31<br />

3.4.1 Hình dạng <strong>và</strong> ý nghĩa các chân: ....................................................................... 31<br />

3.4.2 Tổ chức vùng nhớ của LCD............................................................................. 32<br />

3.4.3 Các lệnh giao tiếp với LCD ............................................................................. 34<br />

3.4.4 Khởi tạo LCD................................................................................................... 35<br />

3.5 Các bước hiện thực yêu cầu 2................................................................................. 36<br />

3.6 Bài tập ..................................................................................................................... 41<br />

Bài 4 : Khảo sát bộ định thời........................................................................................ 42<br />

4.1 Các bước hiện thực yêu cầu 1................................................................................. 42<br />

4.2 Chương trình mẫu ................................................................................................... 46<br />

4.3 Bài tập ..................................................................................................................... 48<br />

Bài 5 : <strong>Kỹ</strong> <strong>thuật</strong> quét ma trận phím .............................................................................. 49<br />

5.1 Kết nối mạch ma trận phím..................................................................................... 49<br />

5.2 Các bước hiện thực ................................................................................................. 50<br />

5.3 Bài tập ..................................................................................................................... 54<br />

Bài 6 : <strong>Kỹ</strong> <strong>thuật</strong> quét LED............................................................................................ 56<br />

6.1 Cấu tạo LED 7 đoạn <strong>và</strong> LED ma trận..................................................................... 56<br />

6.2 Kết nối mạch........................................................................................................... 58<br />

6.3 Các thanh ghi liên quan <strong>và</strong> cách điều khiển............................................................ 59<br />

6.4 Các bước hiện thực. ................................................................................................ 62<br />

6.5 Bài tập ..................................................................................................................... 65<br />

Bài 7 : Khảo sát bộ truyền nhận nối tiếp ...................................................................... 66<br />

7.1 Các bước hiện thực. ................................................................................................ 66


7.2 Chương trình mẫu ................................................................................................... 68<br />

7.3 Bài tập ..................................................................................................................... 70<br />

Bài 8 : Khảo sát khối chuyển đổi A-D.......................................................................... 71<br />

8.1 Các bước hiện thực ................................................................................................. 71<br />

8.2 Bài tập ..................................................................................................................... 72<br />

Bài 9 : Khảo sát các khối chức năng đặc biệt khác ...................................................... 73<br />

9.1 Các bước hiện thực PWM....................................................................................... 73<br />

9.2 Chương trình mẫu ................................................................................................... 74<br />

9.3 Bài tập ..................................................................................................................... 75


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 1 : Giới thiệu MPLAB IDE <strong>và</strong> KIT PIC<br />

Nội dung :<br />

Tạo project trên MPLAB IDE.<br />

Viết chương trình ASM.<br />

Dịch <strong>và</strong> nạp chương trình <strong>và</strong>o vi điều khiển PIC.<br />

Chạy <strong>và</strong> gỡ rối chương trình.<br />

1.1 Môi trường phát triển MPLAB<br />

Double Click <strong>và</strong>o biểu tượng MPLAB trên Desktop hoặc theo cách sau: Start -><br />

All Programs -> Microchip -> MPLAB IDE v76.2 -> MPLAB IDE.<br />

Từ thanh Menu, click chọn tab Project -> Project Wirazd…<br />

Cửa sổ Welcome hiện lên <strong>và</strong> bạn chọn Next.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 1 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Chọn PIC cần sử dụng tại khung Device >> Click Next:<br />

Chọn tool Microchip C18 Toolsuite tại Active Toolsuite.<br />

Chọn MPLAB C18 C Compiler tại Tollsuite contents.<br />

Nếu lập trình bằng assembly thì ta chon Active Toolsuite theo hình sau:<br />

Click Next<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 2 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Chọn Browse…. Để chọn thư mục lưu project.<br />

Đánh <strong>và</strong>o tên Project muốn tạo. Save, sau đó chúng ta chọn Next thì hiện ra của<br />

sổ như sau:<br />

Đây là nơi để các bạn add thư viện cho project.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 3 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bạn nên add hết các file cần thiết cho việc lập trình trước khi bắt đầu viết chương<br />

trình gồm file .lib <strong>và</strong> file .lkr. Nếu viết chương trình cho con chip nào thì ta lấy file .lib<br />

<strong>và</strong> file .lkr của chíp tương ứng, như hình trên chung ta đang sử dụng chip 18f4550.<br />

Click Next.<br />

Click Finish. Ta sẽ được một project như hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 4 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Một project đơn giản nhất phải gồm có 2 thành phần Source files <strong>và</strong> Hearder<br />

Files. Thư mục Source files chứa file text *.asm hoặc file *.c chứa code lâp trình. Thư<br />

mục Hearder Files chứa file *.h hoặc *.INC: file có sẵn của microchip. User khai báo<br />

dùng loại chip gì => add <strong>và</strong>o thư mục này.<br />

Nếu bạn quên không add các file cần có <strong>và</strong>o thì làm theo hướng dẫn sau.<br />

ADD header file: ( Copy header file <strong>và</strong>o thư mục chứa project để tiện cho việc sử dụng<br />

sau này).<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 5 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Chọn header file phù hợp với PIC mình đã chọn. Open.<br />

ADD source file: Click chọn New trên toolbar:<br />

Cửa sổ hiện lên như sau: Từ Menu bar chọn File >> Save để lưu.<br />

Đặt tên <strong>và</strong> Save với đuôi .c nếu bạn lập trình trên c18 của maplab hoặc .asm nếu<br />

bạn lập trình trên assembly.<br />

Nhấp phải <strong>và</strong>o Source Files chọn Add file >>> chọn file chúng ta vừa tạo xong.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 6 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Cửa sổ hiện lên như sau:<br />

Chúng ta đã hoàn tất việc add file <strong>và</strong>o các thư mục Source files <strong>và</strong> header files.<br />

Công việc tiếp theo là viết code ( ở cửa sổ text editor :D:\MAPLAB\Untiled.asm).<br />

Ðối với project mà sử dụng cùng 1 loại chip, cùng loại ngôn ngữ lập trình ( ASM hay C)<br />

thì chỉ cần tạo 1 lần. Những lần sau, chỉ cần add/ remove file text (*.asm hoặc *.c) <strong>và</strong>o<br />

thư mục Source files.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 7 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

1.2 Nạp file hex <strong>và</strong>o vi điều khiển PIC<br />

Sau khi tạo được một project, ta tiến hành build nó để tạo ra *.hex. Có thể mô tả<br />

công việc như sau:<br />

Ví dụ, ta có một chương trình cho PIC như sau:<br />

;=====================================;<br />

; Name: nut_nhan.asm<br />

; Project: Nhap du lieu tu nút nhan RA4.<br />

; Khi nút RA4 du?c nh?n thì led don RB0 sáng,<br />

; Khi không nh?n RA4 thì led don RB0 t?t<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 7 - 31 - 2009<br />

;======================================;<br />

list p=18f4520<br />

#include p18f4520.inc<br />

org 0<br />

goto start<br />

start<br />

call INIT<br />

main<br />

BTFSC PORTA,4 ;Wait for SW1 to be pressed<br />

GOTO main<br />

BSF<br />

SWOFF<br />

PORTB,0 ;Turn on LED1.<br />

BTFSS PORTA,4 ;Wait for SW1 to be released.<br />

GOTO SWOFF<br />

BCF PORTB,0 ;Switch off LED1.<br />

GOTO main ;Repeat sequence.<br />

INIT<br />

clrf PORTB ; setup portb for outputs<br />

bcf TRISB,0<br />

bsf PORTA,4 ; setup porta.4 for input<br />

bsf TRISA,4<br />

return<br />

END<br />

Bây giờ chúng ta lưu chương trình vừa viết thành nut_nhan.asm <strong>và</strong>o một thư mục<br />

đã tạo project phía trên. Để compile chương trình ta <strong>và</strong>o menu Project -> Build All như<br />

hình bên dưới.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 8 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Nếu việc build thất bại, nhưng việc này thì không mong muốn, ta có thấy kết quả<br />

như hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 9 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Nếu thành công, ta sẽ thấy hình sau:<br />

Nếu việc build đã thành công, chương trình sẽ dịch nut_nhan.asm thành<br />

nut_nhan.hex trong cùng thư mục chương trình nut_nhan.asm.<br />

Sau khi đã có được file hex, công việc tiếp theo là làm thế nào để nạp được file<br />

Hex xuống board. Đầu tiên là chọn mạch nạp bằng cách <strong>và</strong>o menu Programmer -><br />

Select Programmer -> Mplab ICD2 như hình sau :<br />

Sau khi chọn Mplab ICD2 xong thì ta sẽ thấy giao diện như sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 10 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Lúc này để nạp chương trình ta chỉ cần <strong>và</strong>o menu Programmer -> Program như<br />

hình sau là có thể nạp được chương trình.<br />

Sau khi nhấn Program nếu download xuống chip thành công thì ta sẽ thấy hiển thị<br />

ra cửa sổ Output như sau:<br />

MPLAB ICD 2 Ready<br />

Programming Target...<br />

...Validating configuration fields<br />

...Erasing Part<br />

...Programming Program Memory (0x0 - 0x3F)<br />

Verifying...<br />

...Program Memory<br />

...Verify Succeeded<br />

Programming Configuration Bits<br />

.. Config Memory<br />

Verifying configuration memory...<br />

...Verify Succeeded<br />

...Programming succeeded<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 11 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

04-Aug-2009, 14:23:39<br />

MPLAB ICD 2 Ready<br />

Để bắt đầu chạy chương trình ta phải rút dây kết nối mạch nạp <strong>và</strong> kit ra. Khi đó<br />

chương trình mới có thể chạy được.<br />

Trên đây là toàn bộ các bước để tạo một project, viết assembly cho Pic trên Mplab<br />

cũng như làm thế nào để compile <strong>và</strong> download chương trình xuống chip để thực thi. Đây<br />

là trường hợp lý tưởng là khi viết code không có lỗi nào xảy ra. Nếu có lỗi nào xảy ra thì<br />

ta phải debug nó như thế nào. Trong chương này sẽ hướng dẫn các bạn hai cách debug.<br />

1.3 Debug dùng MpLab SIM<br />

Bước 1: Để sử dụng MpLab SIM ta <strong>và</strong>o menu Debugger -> Select Debugger -><br />

Mplab SIM như hình vẽ sau:<br />

Bước 2: Khi đã chọn Mplab SIM xong thì trên menu Debugger có thêm nhiều<br />

chức năng khác để hỗ trợ cho việc debug như hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 12 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Từ đây ta đã có thể mô phỏng được chương trình của mình một cách dễ dàng.<br />

Ví dụ như Run (F9) dùng để chạy chương trình, chương trình sẽ chạy liên tục đến<br />

khi nào có breakpoint thì dừng. Vậy làm thế nào để tạo Breakpoint, ta sử dụng lệnh<br />

Breakpoints (F2) như trên hình để tạo ra breakpoint tại vị trí hiện tại của con trỏ hoặc<br />

double click <strong>và</strong>o hàng code mình mong muốn đặt con trỏ. Hay sử dụng Step Into (F7) để<br />

chạy từng lệnh một, gặp lời gọi hàm thì nó sẽ <strong>và</strong>o bên trong lời gọi hàm chạy từng lệnh<br />

trong đó. Khác với Step Over (F8) một tí là khi có lời gọi hàm thì Step Over xem như đó<br />

là một lệnh bình thường, không đi <strong>và</strong>o hàm chi tiết như Step Into.<br />

Reset: trở về đầu chương trình.<br />

Bước 3: Khi debug thì ta cũng cần phải biết giá trị của các thanh ghi cũng như bộ<br />

nhớ của chip như thế nào, để xem được các giá trị này thì chúng ta qua menu View.<br />

Để xem được giá trị của các thanh ghi trong PIC ta chọn View -> File registers sẽ xuất<br />

hiện cửa sổ như hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 13 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Để xem được giá trị của các thanh ghi SFR thì ta chọn View -> Special Function<br />

Registers sẽ xuất hiện của sổ như hình sau:<br />

Hay để xem một <strong>và</strong> thanh ghi mà ta quan tâm thì có thể dùng Watch để xem bằng<br />

cách <strong>và</strong>o View -> Watch thì hình sau sẽ xuất hiện:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 14 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Muốn xem thanh ghi nào, ta chỉ việc chọn thanh ghi tương ứng trong combobox<br />

bên trên, sau đó nhấn Add SFR.<br />

1.4 Debug onchip dùng Mplab ICD2.<br />

Cũng giống như debug trên Mplab SIM, Mplab ICD2 cũng có những <strong>tính</strong> năng<br />

tương tự, nhưng khi sử dụng Mplab ICD2 thì cần phải có mạch debug, <strong>và</strong> các hiện tượng<br />

xảy ra giống như khi chạy thực tế.<br />

1.5 Bài tập<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 15 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 2 : Khảo sát cổng xuất nhập<br />

Nội dung:<br />

Khảo sát hoạt động của nút nhấn, LED.<br />

Khảo sát các thanh điều khiển cổng xuất nhập.<br />

Tính toán thời gian thực thi lệnh, viết chương trình con làm nhiệm vụ delay.<br />

Viết chương trình đọc giá trị của tổ hợp nút nhấn <strong>và</strong> điều khiển giá trị hiển thị<br />

LED.<br />

Yêu cầu:<br />

Viết chương trình xuất dữ liệu ra 4 led đơn đếm từ 0 -> 15 -> 0. Thời gian giữa<br />

các lần đếm lên 1 đơn vị là 1s.<br />

Nhập dữ liệu từ nút nhấn RA4. Khi nút RA4 được nhấn thì led đơn RB0 sáng,<br />

khi không nhấn RA4 thì led đơn RB0 tắt.<br />

2.1 Kiến thức liên quan<br />

2.1.1 Các thanh ghi điều khiển cổng xuất nhập<br />

Mỗi Port có ba thanh ghi điều khiển hoạt động chính:<br />

Các bit trong thanh ghi TRIS: thiết lập chân tương ứng là ngõ <strong>và</strong>o (logic 1) hoặc<br />

ngõ ra (logic 0).<br />

Các bit trong thanh ghi PORT: đọc mức logic từ chân tương ứng.<br />

Các bit trong thanh ghi LAT: ghi mức logic ra chân tương ứng.<br />

2.1.2 Kết nối mạch<br />

Vị trí LED hiển thị <strong>và</strong> nút nhấn trên board như hình dưới đây:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 16 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

LED hiển thị có kết nối như sau:<br />

D2<br />

D3<br />

D4<br />

D5<br />

LED<br />

LED<br />

LED<br />

LED<br />

J6<br />

1 2<br />

R21 470<br />

R22 470<br />

R23 470<br />

R24 470<br />

Để LED sáng, J6 phải được nối lại <strong>và</strong> chân điều khiển tương ứng được thiết lập là<br />

ngỏ ra <strong>và</strong> ở mức logic 1.<br />

Các nút nhấn có kết nối như sau:<br />

VCC<br />

R1<br />

10K<br />

D401<br />

4007<br />

S1<br />

RESET<br />

VCC<br />

R3<br />

10K<br />

C1<br />

104<br />

RB0<br />

RB1<br />

RB2<br />

RB3<br />

VCC<br />

R7<br />

10K<br />

MCLR RA4<br />

RB0<br />

S2<br />

SW RA4<br />

S3<br />

SW RB0<br />

Nút nhấn RESET dùng để reset vi điều khiển<br />

Nút nhấn RA4, RB0 khi được nhấn sẽ làm cho chân tương ứng ở mức logic 0.<br />

Cần thiết lập các chân RA4 <strong>và</strong> RB0 là ngõ <strong>và</strong>o.<br />

Hiện tượng rung phím:<br />

VCC<br />

R7<br />

10K<br />

S3<br />

SW RB0<br />

RB0<br />

C2<br />

104<br />

Khi phím được nhấn, do tác động của hiện tượng rung cơ <strong>học</strong>, tín hiệu điện tại<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 17 Thực hành Vi xử lý<br />

C2<br />

104


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

ngõ ra bị chuyển trạng thái giữa logic 0 <strong>và</strong> logic 1. Khi phím được thả, hiện tượng rung<br />

cũng xảy ra tương tự.<br />

Bộ dao động chính có kết nối như sau:<br />

C4<br />

22pF<br />

C5<br />

VCC<br />

22pF<br />

OSC1<br />

Y1<br />

4MHz<br />

OSC2<br />

R4<br />

4.7K<br />

1 2<br />

J7<br />

C3<br />

1<br />

2<br />

Y2<br />

NC/OE<br />

GND<br />

4MHz<br />

VCC 4<br />

22pF<br />

Trên kit thí nghiệm, thạch anh Y2 được sử dụng cho tất cả các bài thí nghiệm.<br />

2.2 Các bước hiện thực yêu cầu 1<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Led_don, tạo file led_don.asm <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

OUT<br />

3<br />

VCC<br />

OSC1<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file led_don.asm.<br />

Bước 3: Khởi tạo PortB là output sử dụng các lệnh clrf, bcf.<br />

INIT<br />

clrf PORTB ; setup portb for outputs<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 18 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

bcf TRISB,0 ; clear trisb.0<br />

bcf TRISB,1 ; clear trisb.1<br />

bcf TRISB,2 ; clear trisb.1<br />

bcf TRISB,3 ; clear trisb.1<br />

return<br />

Bước 4: Tạo hàm delay1ms sử dụng các lệnh CLRF, NOP, DECFSZ,<br />

GOTO.<br />

delay equ 0ch ; declare variable “delay”<br />

Delay1ms ;Approxiamtely at 4Mhz<br />

clrf delay ; clear variable “delay”<br />

Delay_1<br />

nop<br />

decfsz delay<br />

goto Delay_1<br />

return<br />

Bước 5: Từ đây ta có thể tạo ra được hàm delay1s:<br />

Delay1s<br />

Movwf .4<br />

Movlw delay_1sa<br />

Delay1s_1<br />

Movwf .250<br />

Movlw delay_1sb<br />

Delay1s_2<br />

Call Delay1ms<br />

decfsz delay_1sb<br />

goto Delay1s_2<br />

decfsz delay_1sa<br />

goto Delay1s_1<br />

return<br />

Bước 6: Viết chương trình cho hàm main thực hiện các yêu cầu của<br />

đề bài sử dụng lệnh INCF:<br />

begin<br />

INCF PORTB<br />

call Delay1s<br />

goto begin<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 19 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

2.3 Chương trình mẫu yêu cầu 1<br />

;=====================================;<br />

; Name: led_don.asm<br />

; Project: Xuất dữ liệu ra 4 led đơn đếm từ 0 -> 15 -> 0.<br />

; Thời gian giữa các lần đếm lên 1 đơn vị là 1s.<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 7 - 31 - 2009<br />

;======================================;<br />

list p=18f4520<br />

#include p18f4520.inc<br />

delay res 1<br />

delay_1sa res 1<br />

delay_1sb res 1<br />

org 0<br />

goto start<br />

start<br />

call INIT<br />

begin<br />

INCF PORTB<br />

call Delay1ms<br />

goto begin<br />

INIT<br />

clrf PORTB ; setup portb for outputs<br />

bcf TRISB,0<br />

bcf TRISB,1<br />

bcf TRISB,2<br />

bcf TRISB,3<br />

return<br />

Delay1ms ;Approxiamtely at 4Mhz<br />

clrf delay<br />

Delay_1<br />

nop<br />

decfsz delay<br />

goto Delay_1<br />

return<br />

Delay1s<br />

movwf .4<br />

movlw delay_1sa<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 20 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Delay1s_1<br />

movwf .250<br />

movlw delay_1sb<br />

Delay1s_2<br />

call Delay1ms<br />

decfsz delay_1sb<br />

goto Delay1s_2<br />

decfsz delay_1sa<br />

goto Delay1s_1<br />

return<br />

END<br />

Sau khi có chương trình mẫu ta thực hiện việc compile chương trình <strong>và</strong> nạp<br />

xuống mạch để chạy chương trình như hướng dẫn ở chương 1.<br />

2.4 Các bước hiện thực yêu cầu 2<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Nut_nhan <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file nut_nhan.asm.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 21 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bước 3: Khởi tạo PortB là output <strong>và</strong> PortA là input sử dụng các lệnh clrf,<br />

bcf, bsf<br />

INIT<br />

CLRF PORTB ;setup portb for outputs<br />

BCF TRISB,0<br />

BCF TRISB,1<br />

BCF TRISB,2<br />

BCF TRISB,3<br />

BSF PORTA,4 ; setup porta.4 for input<br />

BSF TRISA,4<br />

RETURN<br />

Bước 4: Viết chương trình cho hàm main thực hiện yêu cầu của đề bài<br />

MAIN<br />

BTFSC PORTA,4 ;Wait for SW1 to be pressed<br />

GOTO MAIN<br />

BSF<br />

SWOFF<br />

PORTB,0 ;Turn on LED1.<br />

BTFSS PORTA,4 ;Wait for SW1 to be released.<br />

GOTO SWOFF<br />

BCF PORTB,0 ;Switch off LED1.<br />

GOTO MAIN ;Repeat sequence.<br />

2.5 Chương trình mẫu yêu cầu 2<br />

;=====================================;<br />

; Name: nut_nhan.asm<br />

; Project: Nhập dữ liệu từ nút nhấn RA4.<br />

; Khi nút RA4 được nhấn thì led đơn RB0 sáng,<br />

; Khi không nhấn RA4 thì led đơn RB0 tắt<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 7 - 31 - 2009<br />

;======================================;<br />

list p=18f4520<br />

#include p18f4520.inc<br />

ORG 0<br />

GOTO START<br />

START<br />

CALL INIT<br />

MAIN<br />

BTFSC PORTA,4 ;Wait for SW1 to be pressed<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 22 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

GOTO MAIN<br />

BSF PORTB,0 ;Turn on LED1.<br />

SWOFF<br />

BTFSS PORTA,4 ;Wait for SW1 to be released.<br />

GOTO SWOFF<br />

BCF PORTB,0 ;Switch off LED1.<br />

GOTO MAIN ;Repeat sequence.<br />

INIT<br />

CLRF PORTB ; setup portb.0 for outputs<br />

BCF TRISB,0<br />

BSF PORTA,4 ; setup porta.4 for input<br />

BSF TRISA,4<br />

RETURN<br />

END<br />

Sau khi có chương trình mẫu ta thực hiện việc compile chương trình <strong>và</strong> nạp<br />

xuống mạch để chạy chương trình như hướng dẫn ở chương 1.<br />

2.6 Bài tập<br />

Viết chương trình để khi nhấn RA4 thì các led sẽ sáng đếm lên, mỗi lần<br />

nhấn đếm lên 1 đơn vị.<br />

Viết chương trình sao cho mỗi lần nhấn RA4 thì 2 led trái <strong>và</strong> 2 led phải<br />

thay nhau sáng.<br />

Tạo hiệu ứng light river trên 4 led của board mạch starter kit. Nhấn RA4 để<br />

thay đổi chiều của light river.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 23 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 3 : Khảo sát cơ chế ngắt quãng, giao tiếp LCD ký<br />

tự<br />

Nội dung:<br />

Khảo sát các nguyên nhân gây ngắt quảng, cách xử lý ngắt quãng, <strong>tính</strong> ưu tiên<br />

giữa các ngắt của vi điều khiển PIC16F877.<br />

Khảo sát ngắt ngoài của vi điều khiển PIC16F877.<br />

Điều khiển LCD ký tự 2x16.<br />

Yêu cầu:<br />

1. Viết chương trình khởi tạo 2 ngắt:<br />

Ngắt ngoài 0 với độ ưu tiên cao.<br />

Ngắt timer 0 với độ ưu tiên thấp.<br />

Trong chương trình ngắt ngoài 0 bật 3 led đơn RB1, RB2, RB3sáng<br />

cùng lúc.<br />

Trong chương trình timer 0 sau 1s khi 3 led được bật ở trong ngắt ngoài<br />

thì tắt 3 led đơn RB1, RB2, RB3 cùng lúc.<br />

2. Viết chương trình hiển thị kí tự lên LCD.<br />

3.1 Kiến thức liên quan<br />

3.1.1 Tóm tắt các thanh ghi điều khiển ngắt<br />

Thanh ghi INTCON:<br />

Thanh ghi PIE1:<br />

Thanh ghi PIE2:<br />

Thanh ghi PIR1:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 24 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Thanh ghi PIR2:<br />

Sơ đồ điều khiển ngắt:<br />

3.2 Các bước hiện thực yêu cầu 1<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Interrupt, tạo file interrupt.asm <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 25 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file interrupt.asm<br />

Bước 3: Khởi tạo PortB là output sử dụng các lệnh clrf, bcf<br />

INIT<br />

;assigning PORTB is a digital output<br />

MOVLW 0x0e<br />

MOVWF ADCON1<br />

; setup portb for outputs<br />

BCF TRISB,1<br />

BCF PORTB,1<br />

BCF TRISB,2<br />

BCF PORTB,2<br />

BCF TRISB,3<br />

BCF PORTB,3<br />

;initialize delay variable<br />

MOVLW .10<br />

MOVWF delay<br />

RETURN<br />

Bước 4: Khởi tạo timer 0, cho timer 0 ngắt có độ ưu tiên thấp, thiết lập<br />

timer0 cứ 100ms thì xảy ra ngắt một lần.<br />

INIT_TIMER0<br />

BSF RCON,IPEN ;enable priority interrupts.<br />

BCF INTCON2,TMR0IP ;timer0 with low priority<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 26 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

BSF INTCON,TMR0IF;set timer0 interrupt flag bit<br />

BSF INTCON,TMR0IE ; enable timer 0<br />

;set the global interrupt enable bits<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

Bước 5: Khởi tạo ngắt ngoài 0 tích cực cạnh xuống.<br />

Đối với ngắt ngoài 1 <strong>và</strong> ngắt ngoài 2 thì độ ưu tiên ngắt phụ thuộc <strong>và</strong>o 2 bit<br />

INT1IP <strong>và</strong> INT2IP trong thanh ghi INTCON3. Còn với ngắt ngoài 0 thì không có<br />

bít xác định độ ưu tiên, nó chỉ có một mức ưu tiên là high priority.<br />

INIT_EXTERNAL_INTERRUPT<br />

;falling edge on RB0<br />

BCF INTCON2,INTEDG0<br />

; clear external interrupt flag bit<br />

BCF INTCON,INT0IF<br />

; enable external 0 interrupt<br />

BSF INTCON,INT0IE<br />

;set the global interrupt enable bits<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

RETURN<br />

Bước 6: Viết chương trình cho ngắt ngoài 0, bật 3 đèn led đơn cùng<br />

sáng <strong>và</strong> khởi tạo lại giá trị cho biến delay để 1s sau thì ngắt timer sẽ tắt 3 đèn đó.<br />

EXTERNAL_INTERUPT_ROUTINE<br />

BCF INTCON,INT0IF<br />

BSF PORTB,1<br />

BSF PORTB,2<br />

BSF PORTB,3<br />

MOVLW .10<br />

MOVWF delay<br />

RETURN<br />

Bước 7: Viết chương trình cho ngắt timer0, sau 1s sau khi led được bật<br />

sáng thì nó sẽ làm cho led tắt.<br />

Thời gian để timer đếm lên 1 đơn vị đựơc <strong>tính</strong> bằng công thức :<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 27 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

T = 1/((Focs/4)/2) = 1/((4Mhz/4)/2) = 0.5us<br />

Nên khi ta để giá trị trong các thanh ghi của timer giá trị 50000 thì cứ sau<br />

100ms, timer sẽ ngắt một lần. Để <strong>tính</strong> được giá trị số Hex gán cho thanh ghi đếm<br />

của timer ta làm như sau:<br />

Đổi số 50000 sang số hex: C350.<br />

Lấy FFFF – C350 = 3CAF.<br />

Byte cao sẽ được lưu <strong>và</strong>o TMR0H, byte thấp lưu <strong>và</strong>o TMR0L.<br />

TIMER0_INTERRUPT_ROUTINE<br />

BCF INTCON,TMR0IF<br />

DECFSZ delay,1<br />

GOTO TIMER0_ROUTINE_1<br />

BCF PORTB,1<br />

BCF PORTB,2<br />

BCF PORTB,3<br />

MOVLW .10<br />

MOVWF delay<br />

TIMER0_ROUTINE_1<br />

BCF T0CON,TMR0ON<br />

MOVLW 0x3C<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

3.3 Chương trình mẫu yêu cầu 1<br />

;=====================================;<br />

; Name: led_don.asm<br />

; Project: Viết chương trình khởi tạo 2 ngắt:<br />

;- Ngắt ngoài 0 với độ ưu tiên cao.<br />

;- Ngắt timer 0 với độ ưu tiên thấp.<br />

;- Trong chương trình ngắt ngoài 0 bật 3 led đơn RB1, RB2, RB3sáng cùng<br />

;lúc<br />

;- Trong chương trình timer 0 sau 1s khi 3 led được bật ở trong ngắt ngoài thì<br />

;tắt 3 led đơn RB1, RB2, RB3 cùng lúc<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 7 - 31 - 2009<br />

;======================================;<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 28 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

list p = 18f4520<br />

#include P18f4520.inc<br />

delay res 1<br />

ORG 00h<br />

GOTO MAIN<br />

ORG 08H<br />

GOTO ISR_HIGH<br />

ORG 18H<br />

GOTO ISR_LOW<br />

MAIN<br />

CALL INIT<br />

CALL INIT_TIMER0<br />

CALL INIT_EXTERNAL_INTERRUPT<br />

GOTO $<br />

INIT<br />

;assigning PORTB is a digital output<br />

MOVLW 0x0e<br />

MOVWF ADCON1<br />

BCF TRISB,1<br />

BCF PORTB,1<br />

BCF TRISB,2<br />

BCF PORTB,2<br />

BCF TRISB,3<br />

BCF PORTB,3<br />

MOVLW .10<br />

MOVWF delay<br />

RETURN<br />

INIT_TIMER0<br />

BSF RCON,IPEN ;enable priority interrupts.<br />

BCF INTCON2,TMR0IP<br />

BSF INTCON,TMR0IF<br />

BSF INTCON,TMR0IE<br />

BSF INTCON,GIEH ;set the global interrupt enable bits<br />

BSF INTCON,GIEL<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

INIT_EXTERNAL_INTERRUPT<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 29 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

;Interrupt priority for INT1 and INT2 is determined by the<br />

;value contained in the interrupt priority bits, INT1IP<br />

;(INTCON3) and INT2IP (INTCON3). There is<br />

;no priority bit associated with INT0. It is always a high<br />

;priority interrupt source<br />

BCF INTCON2,INTEDG0<br />

BCF INTCON,INT0IF<br />

BSF INTCON,INT0IE<br />

BSF INTCON,GIEH ;set the global interrupt enable bits<br />

BSF INTCON,GIEL<br />

RETURN<br />

EXTERNAL_INTERUPT_ROUTINE<br />

BCF INTCON,INT0IF<br />

BSF PORTB,1<br />

BSF PORTB,2<br />

BSF PORTB,3<br />

MOVLW .10<br />

MOVWF delay<br />

RETURN<br />

TIMER0_INTERRUPT_ROUTINE<br />

; BSF INTCON,INT0IF<br />

BCF INTCON,TMR0IF<br />

DECFSZ delay,1<br />

GOTO TIMER0_ROUTINE_1<br />

BCF PORTB,1<br />

BCF PORTB,2<br />

BCF PORTB,3<br />

MOVLW .10<br />

MOVWF delay<br />

TIMER0_ROUTINE_1<br />

BCF T0CON,TMR0ON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xaf<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

ISR_HIGH<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 30 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

CALL EXTERNAL_INTERUPT_ROUTINE<br />

RETFIE<br />

ISR_LOW<br />

CALL TIMER0_INTERRUPT_ROUTINE<br />

RETFIE<br />

END<br />

Sau khi có chương trình mẫu ta thực hiện việc compile chương trình <strong>và</strong> nạp<br />

xuống mạch để chạy chương trình như hướng dẫn ở chương 1.<br />

3.4 LCD ký tự 2x16<br />

3.4.1 Hình dạng <strong>và</strong> ý nghĩa các chân:<br />

Tên chân Mức logic Mô tả<br />

GND - Đất (0V)<br />

VCC - Nguồn (+5V)<br />

VEE - Chỉnh contrast (0 – VCC)<br />

RS 0<br />

D0-D7 là giá trị lệnh<br />

1<br />

D0-D7 là giá trị dữ liệu<br />

R/W 0<br />

Ghi giá trị <strong>và</strong>o LCD<br />

1<br />

E 0<br />

1<br />

Từ 1 xuống 0<br />

Đọc giá trị ra từ LCD<br />

Cấm truy xuất LCD<br />

LCD hoạt động trao đổi dữ liệu<br />

Dữ liệu/Lệnh đưa <strong>và</strong>o LCD<br />

D0 0/1 Bit 0/LSB<br />

D1 0/1 Bit1<br />

D2 0/1 Bit2<br />

D3 0/1 Bit3<br />

D4 0/1 Bit4<br />

D5 0/1 Bit5<br />

D6 0/1 Bit6<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 31 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

D7 0/1 Bit7/MSB<br />

A - Chân Anode của đèn nền<br />

K - Chân Cathode của đèn nền<br />

3.4.2 Tổ chức vùng nhớ của LCD<br />

Display Data Ram (DDRAM): lưu trữ mã ký tự hiển thị ra màn hình. Mã này<br />

giống với mã ASCII. Có tất cả 80 ô nhớ DDRAM. Vùng hiển thị tương ứng với cửa sổ<br />

gồm 16 ô nhớ hàng đầu tiên <strong>và</strong> 16 ô nhớ hàng thứ hai. Chúng ta có thể tạo hiệu ứng dịch<br />

chữ bằng cách sử dụng lệnh dịch (mô tả sau), khi đó cửa sổ hiển thị sẽ dịch đem lại hiệu<br />

ứng dịch chữ.<br />

Character Generator Ram (CGRAM): lưu trữ tám mẫu ký tự do người dùng định<br />

nghĩa. Tám mẫu ký tự này tương ứng với các mã ký tự D7-D0 = 0000*D2D1D0 (* mang<br />

giá trị tùy định 0 hay 1).<br />

Character Generator Rom (CGROM): lưu trữ cứng các mẫu ký tự tương ứng với<br />

mã ASCII. Dưới đây là bảng ánh xạ giữa mã ký tự <strong>và</strong> mẫu ký tự.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 32 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Chúng ta muốn hiển thị chữ “CE” ở giữa hàng đầu tiên, giả sử cửa sổ hiển thị<br />

đang bắt đầu từ vị trí đầu tiên (hàng thứ nhất hiển thị dữ liệu của ô nhớ từ 0x00 đến 0x0f,<br />

hàng thứ hai hiển thị dữ liệu của ô nhớ từ 0x40 đến 0x4f, đây là vị trí home). Giá trị của ô<br />

nhớ 0x07 là 0x43 (ký tự C), của ô nhớ 0x08 là 0x45 (ký tự E).<br />

Chúng ta muốn hiển thị chữ “®” ở giữ hàng thứ hai, giả sử cử sổ hiển thị đang ở<br />

vị trí home. Trong bảng mẫu ký tự chúng ta thấy không có mẫu “®”. Lúc này chúng ta<br />

phải định nghĩa mẫu “®” 5x8 điểm, gồm có 8 byte, sau đó lưu <strong>và</strong>o vị trí của mẫu ký tự<br />

CGRAM thứ nhất. Lúc này giá trị của ô nhớ 0x47 là 0x00 hoặc 0x08 (vị trí của mẫu ký<br />

tự CGRAM thứ nhất “®”).<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 33 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

3.4.3 Các lệnh giao tiếp với LCD<br />

Lệnh RS RW D7 D6 D5 D4 D3 D2 D1 D0<br />

Clear display<br />

Return home<br />

Entry mode set<br />

Display on/off<br />

control<br />

Cursor/Display<br />

shift<br />

Function set<br />

Set CGRAM<br />

address<br />

Set DDRAM<br />

address<br />

Read BUSY flag<br />

(BF)<br />

Write to<br />

DDRAM or<br />

CGRAM<br />

Read from<br />

DDRAM or<br />

CGRAM<br />

Thời gian<br />

thực thi<br />

0 0 0 0 0 0 0 0 0 1 1.52ms<br />

0 0 0 0 0 0 0 0 1 * 1.52ms<br />

0 0 0 0 0 0 0 1 I/D SH 37µs<br />

0 0 0 0 0 0 1 D C B 37µs<br />

0 0 0 0 0 1<br />

S/<br />

C<br />

R/<br />

L<br />

* * 37µs<br />

0 0 0 0 1 DL N F * * 37µs<br />

0 0 0 1 CGRAM address 37µs<br />

0 0 1 DDRAM address 37µs<br />

0 1 BF DDRAM address 0µs<br />

1 0 D7 D6 D5 D4 D3 D2 D1 D0 43µs<br />

1 1 D7 D6 D5 D4 D3 D2 D1 D0 43µs<br />

Các bit trên bảng tóm tắt các lệnh có ý nghĩa như sau:<br />

I/D 1 Increment 0 Decrement<br />

SH 1 Entire shift on 0 Entire shift off<br />

S/C 1 Display shift 0 Cursor move<br />

R/L 1 Shift to the Right 0 Shift to the Left<br />

DL 1 8 bits 0 4 bits<br />

N 1 2 Lines 0 1 Lines<br />

F 1 5x10 dots Font 0 5x8 dots Font<br />

BF 1 Internally operating 0 Can accept instruction<br />

Trên kit thí nghiệm LCD ký tự 2x16 được kết nối <strong>và</strong>o Port D ở chế độ 4 bit. Ở chế<br />

độ 4 bit, để đọc hay ghi một byte phải tiến hành cài dữ liệu hai lần, lần đầu là 4 bit cao,<br />

lần thứ hai là 4 bit thấp.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 34 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

3.4.4 Khởi tạo LCD<br />

Sơ đồ kết nối LCD:<br />

RD7<br />

R20 2.2K<br />

VCC<br />

RD4<br />

RD5<br />

RD6<br />

RD0<br />

RD1<br />

RD2<br />

RD3<br />

Q2<br />

MMBT2222A<br />

LCD1<br />

1<br />

2<br />

Vss<br />

3<br />

Vdd<br />

4<br />

Vee<br />

5<br />

RS<br />

6<br />

R/W<br />

7<br />

E<br />

8<br />

D0<br />

9<br />

D1<br />

10<br />

D2<br />

11<br />

D3<br />

12<br />

D4<br />

13<br />

D5<br />

14<br />

D6<br />

15<br />

D7<br />

16<br />

A<br />

K<br />

Trước khi xuất ký tự ra màn hình LCD, LCD controller phải được khởi tạo khi<br />

mới được cấp nguồn. Trình tự khởi tạo như lược đồ sau. Trên lược đồ, lệnh “Display<br />

clear” có giá trị 0x01 được gửi hai lần, lần đầu là 4 bit cao có giá trị 0x0, lần thứ hai là<br />

bốn bit thấp có giá trị 0x01. Lệnh “Function set” gửi hai lần giá trị 0x2.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 35 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bật nguồn<br />

(chân PD7 out ra mức logic 1)<br />

Chờ tối thiểu 30ms<br />

(Đợi VDD > 4.5V)<br />

Gửi lệnh<br />

“Function set”<br />

RS RW D7 D6 D5 D4<br />

0 0 0 0 1 0<br />

0 0 0 0 1 0<br />

0 0 N F * *<br />

Chờ tối thiểu 39µs<br />

Gửi lệnh<br />

“Display on/off control”<br />

RS RW D7 D6 D5 D4<br />

0 0 0 0 0 0<br />

0 0 1 D C B<br />

Chờ tối thiểu 39µs<br />

Gửi lệnh<br />

“Display clear”<br />

RS RW D7 D6 D5 D4<br />

0 0 0 0 0 0<br />

0 0 0 0 0 1<br />

Gửi lệnh<br />

“Entry mode set”<br />

RS RW D7 D6 D5 D4<br />

0 0 0 0 0 0<br />

0 0 0 1 I/D SH<br />

Kết thúc khởi tạo<br />

3.5 Các bước hiện thực yêu cầu 2<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là LCD, tạo file lcd.asm <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 36 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file lcd.asm<br />

Bước 3: Dựa <strong>và</strong>o sơ đồ nguyên lý kết nối vi điều khiển với LCD kí tự ta<br />

define lại để dễ dàng sử dụng hơn.<br />

#define LCD_D4 PORTD, 0 ; LCD data bits<br />

#define LCD_D5 PORTD, 1<br />

#define LCD_D6 PORTD, 2<br />

#define LCD_D7 PORTD, 3<br />

#define LCD_D PORTD<br />

#define LCD_D4_DIR TRISD, 0 ; LCD data bits<br />

#define LCD_D5_DIR TRISD, 1<br />

#define LCD_D6_DIR TRISD, 2<br />

#define LCD_D7_DIR TRISD, 3<br />

#define LCD_E PORTD, 6 ; LCD E clock<br />

#define LCD_RW PORTD, 5 ; LCD read/write line<br />

#define LCD_RS PORTD, 4 ; LCD register select line<br />

#define LCD_E_DIR TRISD, 6<br />

#define LCD_RW_DIR TRISD, 5<br />

#define LCD_RS_DIR TRISD, 4<br />

#define LCD_INS 0<br />

#define LCD_DATA 1<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 37 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bước 4: Viết hàm xuất dữ liệu 4 bít ra cho LCD kí tự :<br />

LCDWriteNibble<br />

btfss STATUS, C ; Set the register select<br />

bcf LCD_RS<br />

btfsc STATUS, C<br />

bsf LCD_RS<br />

bcf LCD_RW ; Set write mode<br />

bcf LCD_D4_DIR ; Set data bits to outputs<br />

bcf LCD_D5_DIR<br />

bcf LCD_D6_DIR<br />

bcf LCD_D7_DIR<br />

NOP ; Small delay<br />

NOP<br />

bsf LCD_E ; Setup to clock data<br />

NOP ; Small delay<br />

NOP<br />

btfss temp_wr, 7 ; Set high nibble<br />

bcf LCD_D7<br />

btfsc temp_wr, 7<br />

bsf LCD_D7<br />

btfss temp_wr, 6<br />

bcf LCD_D6<br />

btfsc temp_wr, 6<br />

bsf LCD_D6<br />

btfss temp_wr, 5<br />

bcf LCD_D5<br />

btfsc temp_wr, 5<br />

bsf LCD_D5<br />

btfss temp_wr, 4<br />

bcf LCD_D4<br />

btfsc temp_wr, 4<br />

bsf LCD_D4<br />

NOP ; Small delay<br />

NOP<br />

bcf LCD_E ; Send the data<br />

return<br />

Bước 5: Tiếp tục ta viết hàm để truyền lệnh (command) cho lcd kí tự.<br />

Macro LCDWrite_command có một đối số là data, ta dùng đối số này để<br />

truyền lệnh cho lcd. Ở đây, LCD ta thiết lập chế độ 4 bít nên khi truyền lệnh nó<br />

cũng chỉ cần 4 bit để điều khiển. Trong macro này data1 chỉ sử dụng 4 bit cao mà<br />

thôi.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 38 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

LCDWrite_command macro data1<br />

bcf LCD_RS ;write command<br />

movlw data1<br />

movwf temp_wr<br />

call LCDWriteNibble<br />

movlw 0xF<br />

movwf delay<br />

rcall DelayXCycles<br />

endm<br />

Bước 6: Sau đó viết thêm hàm truyền dữ liệu hiển thị ra LCD kí tự.<br />

Macro LCDWrite_data có một đối số là data1, ta dùng macro với đối số<br />

tương ứng để truyền data hiển thị lên màn hình LCD. Như trên ta đã đề cập, trong<br />

ứng dụng này ta sử dụng LCD chế độ 4 bít, nên data ở đây được truyền theo thứ tự<br />

là 4 bit cao truyền trước sau đó 4 bít thấp được truyền sau.<br />

LCDWrite_data macro data1<br />

bsf LCD_RS ;write data<br />

movff data1,temp_wr<br />

rcall LCDBusy<br />

bsf STATUS, C<br />

rcall LCDWrite<br />

movlw 0x0F ;Wait ~100us @ 20 MHz<br />

movwf delay<br />

rcall DelayXCycles<br />

endm<br />

Bước 7: Hàm quan trọng nhất của LCD kí tự chính là hàm khởi tạo LCD.<br />

Trước khi sử dụng được lcd ta phải khởi tạo cho nó theo như giản đồ khởi tạo lcd<br />

ở trên phần hướng dẫn lý thuyết. Ngoài ra do thiết kế mạch, để LCD có thể hiện<br />

thị bình thường trước tiên ta phải bật nguồn của LCD lên, chân nguồn của LCD<br />

được điều khiển bởi PortD.7 tích cực mức cao, nên trước khi muốn sử dụng LCD<br />

ta phải bật PortD.7 lên 1.<br />

LCDInit1<br />

CALL Init_variable<br />

bsf LATD,7<br />

bcf TRISD,7<br />

bsf LATD,7<br />

bcf LCD_E_DIR ;configure control lines<br />

bcf LCD_RW_DIR<br />

bcf LCD_RS_DIR<br />

movlw b'00001110'<br />

movwf ADCON1<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 39 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

lil11<br />

movlw 0xff ; Wait ~15ms @ 20 MHz<br />

movwf COUNTER<br />

movlw 0xFF<br />

movwf delay<br />

rcall DelayXCycles<br />

decfsz COUNTER,F<br />

bra lil11<br />

LCDWrite_command 0x20<br />

LCDWrite_command 0x20<br />

LCDWrite_command 0x80<br />

LCDWrite_command 0x00<br />

LCDWrite_command 0xf0<br />

LCDWrite_command 0x00<br />

LCDWrite_command 0x10<br />

call LongDelay ;2ms<br />

call LongDelay ;2ms<br />

LCDWrite_command 0x00<br />

LCDWrite_command 0x20<br />

call Lcd_clear<br />

return<br />

Bước 8: Đến đây ta có thể viết chương trình để hiển thị kí tự lên lcd kí tự.<br />

Ý tưởng thực hiện ở đây là lúc đầu ta khai báo một vùng nhớ gồm 32 ô nhớ<br />

tương ứng với 32 vị trí trên lcd kí tự. Hàm lcd_display của chúng ta sẽ thực hiện<br />

một việc đơn giản là lấy dữ liệu chứa trong vùng nhớ này ra hiển thị lên lcd kí tự.<br />

Còn người dùng muốn hiển thị lên lcd thì chỉ cần update giá trị <strong>và</strong>o vùng nhớ này<br />

là xong.<br />

Lcd_display<br />

movff INDF0,temp_wr1<br />

movlw .0<br />

cpfseq temp_wr1<br />

goto Lcd_display1<br />

movlw 0x20<br />

movwf temp_wr1<br />

Lcd_display1<br />

LCDWrite_data temp_wr1<br />

INCF FSR0L<br />

CLRF WREG<br />

ADDWFC FSR0H,F<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 40 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

MOVLW .0<br />

cpfseq flag_line<br />

goto Lcd_display_line2<br />

;display line1<br />

INCF index_of_lcd<br />

MOVLW MAX_INDEX<br />

CPFSEQ index_of_lcd<br />

GOTO Exit_Lcd_display<br />

CLRF Index_of_lcd<br />

MOVLW .1<br />

MOVWF flag_line<br />

Set_cursor .0,.1<br />

goto Exit_Lcd_display<br />

;display line2<br />

Lcd_display_line2<br />

INCF index_of_lcd<br />

MOVLW MAX_INDEX<br />

CPFSEQ index_of_lcd<br />

GOTO Exit_Lcd_display<br />

CLRF Index_of_lcd<br />

MOVLW .0<br />

MOVWF flag_line<br />

Movlw HIGH Lcd_buffer<br />

Movwf FSR0H<br />

Movlw LOW Lcd_buffer<br />

Movwf FSR0L<br />

Set_cursor .0, .0<br />

Exit_Lcd_display<br />

RETURN<br />

3.6 Bài tập<br />

Viết chương trình chạy chữ qua LCD.<br />

Viết chương trình thay đổi chữ hiển thị trên LCD khi nhấn nút.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 41 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 4 : Khảo sát bộ định thời<br />

Nội dung:<br />

Khảo sát các chế độ hoạt động của các bộ định thời.<br />

Khảo sát các thanh ghi điều khiển bộ định thời.<br />

Sử dụng bộ định thời trong chương trình.<br />

Yêu cầu:<br />

Sử dụng bộ timer 1 cứ sau 1s đếm lên 1 đơn vị rồi xuất giá trị ra led đơn.<br />

Viết chương trình sử dụng bộ định thời làm đồng hồ điều khiển đèn giao thông.<br />

4.1 Các bước hiện thực yêu cầu 1<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là timer <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file timer.asm<br />

Bước 3: Khởi tạo PortB là output.<br />

Cần gán giá trị cho thanh ghi ADCON1 vì thanh ghi này có chức năng chọn<br />

các PORT có chức năng là input/output digital hay là input Analog. Do đó, trước<br />

khi sử dụng các port ta phải kiểm tra xem thanh ghi ADCON1 đã cấu hình đúng<br />

chưa.<br />

INIT<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 42 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

;assigning PORTB is a digital output<br />

MOVLW 0x0e<br />

MOVWF ADCON1<br />

; setup portb for outputs<br />

CLRF TRISB<br />

CLRF PORTB<br />

RETURN<br />

Bước 4: Khởi tạo các vector ngắt.<br />

Địa chỉ 0x00 bắt đầu chương trình chính.<br />

Địa chỉ 0x08 địa chỉ của vector ngắt có độ ưu tiên cao<br />

Địa chỉ 0x18 địa chỉ của vector ngắt có độ ưu tiên thấp.<br />

Chú ý: VĐK Pic chỉ có 2 độ ưu tiên khi ngắt xảy ra như nói ở trên.<br />

org 0x0<br />

goto MAIN<br />

ORG 0x000008 ; high priority interrupt vector<br />

GOTO ISR_HIGH<br />

ORG 0x000018 ; low priority interrupt vector<br />

GOTO ISR_LOW<br />

MAIN<br />

GOTO MAIN<br />

;interrupt sevice routine for high priority interrupt<br />

ISR_HIGH<br />

RETFIE<br />

;interrupt sevice routine for low priority interrupt<br />

ISR_LOW<br />

RETFIE<br />

Bước 5: Khởi tạo ngắt timer 0 cứ sau 100ms thì <strong>và</strong>o ngắt một lần.<br />

Thời gian để timer đếm lên 1 đơn vị đựơc <strong>tính</strong> bằng công thức<br />

T = 1/((Focs/4)/2) = 1/((4Mhz/4)/2) = 0.5us<br />

Nên khi ta để giá trị trong các thanh ghi của timer giá trị 50000 thì cứ sau<br />

100ms, timer sẽ ngắt một lần. Để <strong>tính</strong> được giá trị số Hex gán cho thanh ghi đếm<br />

của timer ta làm như sau :<br />

Đầu tiên đổi số 50000 sang số hex: C350.<br />

Sau đó lấy FFFF – C350 = 3CAF.<br />

Có được số này rồi ta lấy byte cao lưu <strong>và</strong>o TMR0H, byte thấp lưu <strong>và</strong>o<br />

TMR0L.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 43 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

;=====================;<br />

; Initializing timer 0: 16BIT<br />

;=====================;<br />

INIT_TIMER0<br />

;enable priority interrupts.<br />

BSF RCON,IPEN<br />

;set Timer0 as a HIGH priority interrupt source<br />

BSF INTCON2,TMR0IP<br />

;Clear the Timer0 interrupt flag.<br />

BCF INTCON,TMR0IF<br />

;enable Timer0 interrupts<br />

BSF INTCON,TMR0IE<br />

;set the global interrupt enable bits<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

;initialize timer0: 10ms<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xaf<br />

MOVWF TMR0L<br />

;turn on timer0<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

Bước 6: Viết chương trình con chạy trong timer, sau 1s tăng giá trị hiện thị<br />

ra ngoài led đơn.<br />

Vì cứ 100ms thì có ngắt một lần, do đó để sau 1s ta tăng lên một giá trị thì<br />

cần 10 lần ngắt như vậy, nên ban đầu ta phải khởi tạo cho biến delay = 10. Và đây<br />

là hàm chính thực hiện chức năng của bài tập 1.<br />

TIMER0_ROUTINE<br />

BCF INTCON,TMR0IF<br />

DECFSZ delay,1<br />

GOTO TIMER0_ROUTINE_1<br />

INCF PORTB<br />

MOVLW .10<br />

MOVWF delay<br />

TIMER0_ROUTINE_1<br />

BCF T0CON,TMR0ON<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 44 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xaf<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 45 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

4.2 Chương trình mẫu<br />

;=====================================;<br />

; Name: timer.asm<br />

; Project: Sử dụng bộ timer 1 cứ sau 1s đếm lên 1 đơn vị rồi xuất giá trị ra led<br />

; đơn.<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 8 - 6 - 2009<br />

;======================================;<br />

list p=18f4520<br />

#include p18f4520.inc<br />

delay res 1<br />

org 0x0<br />

goto MAIN<br />

ORG 0x000008 ; high priority interrupt vector<br />

GOTO ISR_HIGH<br />

ORG 0x000018 ; low priority interrupt vector<br />

GOTO ISR_LOW<br />

MAIN<br />

CALL INIT<br />

CALL INIT_TIMER0<br />

GOTO $<br />

INIT<br />

;assigning PORTB is a digital output<br />

movlw 0x0e<br />

movwf ADCON1<br />

; setup portb for outputs<br />

clrf TRISB<br />

clrf PORTB<br />

MOVLW .10<br />

MOVWF<br />

return<br />

delay<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 46 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

;===========================================;<br />

; Initializing timer 0: 16BIT<br />

;===========================================;<br />

;to calculate the accurately timing scheduling of timer 0.<br />

;we have to know something<br />

;1. External clock: 4Mhz (this ex)<br />

;2. Timer0 Prescaler: 1/2 (this ex)<br />

;cycle of timer0 = 1/((Fexternal/4)/2) = 0.5us<br />

INIT_TIMER0<br />

BSF RCON,IPEN ;enable priority interrupts.<br />

BSF INTCON2,TMR0IP<br />

BSF INTCON,TMR0IF<br />

BSF INTCON,TMR0IE<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

ISR_HIGH ; high priority isr<br />

BTFSC INTCON,TMR0IF<br />

GOTO ISR_TIMER0_HIGH<br />

ISR_TIMER0_HIGH<br />

CALL TIMER0_ROUTINE<br />

GOTO EXIT_ISR_HIGH<br />

EXIT_ISR_HIGH<br />

RETFIE<br />

;===============================================;<br />

; interrupt service routine for low priority interrupts<br />

;===============================================;<br />

ISR_LOW<br />

BTFSC INTCON,TMR0IF<br />

GOTO ISR_TIMER0_LOW<br />

ISR_TIMER0_LOW<br />

CALL TIMER0_ROUTINE<br />

GOTO EXIT_ISR_LOW<br />

EXIT_ISR_LOW<br />

RETFIE<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 47 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

;===============================================;<br />

;===============================================;<br />

;===============================================;<br />

;===============================================;<br />

TIMER0_ROUTINE<br />

BCF INTCON,TMR0IF<br />

DECFSZ delay,1<br />

GOTO TIMER0_ROUTINE_1<br />

INCF PORTB<br />

MOVLW .10<br />

MOVWF delay<br />

TIMER0_ROUTINE_1<br />

BCF T0CON,TMR0ON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xaf<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

END<br />

Yêu cầu 2 của bài thực hành này xem như bài tập<br />

4.3 Bài tập<br />

Dùng bộ định thời tạo xung vuông chu kì 10ms, duty cycle 30%.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 48 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 5 : <strong>Kỹ</strong> <strong>thuật</strong> quét ma trận phím<br />

Nội dung:<br />

Khảo sát cấu tạo, hoạt động của ma trận phím.<br />

Tìm hiểu kỹ <strong>thuật</strong> lấy dữ liệu từ ma trận phím, chống rung phím nhấn.<br />

Yêu cầu:<br />

Viết chương trình lấy dữ liệu từ phím nhấn sau đó hiện thị giá trị của phím nhấn<br />

ra led đơn.<br />

5.1 Kết nối mạch ma trận phím<br />

R1<br />

10K<br />

R2<br />

10K<br />

R3<br />

10K<br />

R4<br />

10K<br />

ROW1<br />

ROW2<br />

ROW3<br />

ROW4<br />

1 4<br />

SW1<br />

2 3<br />

1 4<br />

SW2<br />

2 3<br />

1 4<br />

SW3<br />

2 3<br />

1 4<br />

SW4<br />

VCC R5<br />

100R<br />

1 4<br />

SW5<br />

2 3<br />

1 4<br />

SW6<br />

2 3<br />

1 4<br />

SW7<br />

2 3<br />

1 4<br />

SW8<br />

1 4<br />

SW9<br />

2 3<br />

1 4<br />

SW10<br />

2 3<br />

1 4<br />

SW11<br />

2 3<br />

1 4<br />

SW12<br />

1 4<br />

SW13<br />

2 3<br />

1 4<br />

SW14<br />

2 3<br />

1 4<br />

SW15<br />

2 3<br />

1 4<br />

SW16<br />

2 3<br />

2 3<br />

2 3 2 3<br />

COLUMN1 COLUMN2 COLUMN3 COLUMN4<br />

COL1 COL2 COL3 COL4<br />

COL2<br />

COL4<br />

ROW2<br />

ROW4<br />

1<br />

3<br />

5<br />

7<br />

9<br />

11<br />

R6<br />

100R<br />

J4<br />

2<br />

RD1 RD0<br />

4<br />

RD3 RD2<br />

6<br />

RD5 RD4<br />

8<br />

RD7 RD6<br />

10<br />

RE1 RE0<br />

GNDVCC<br />

12<br />

CON12A<br />

COL1<br />

COL3<br />

ROW1<br />

ROW3<br />

Ma trận phím gồm 16 phím nhấn kết nối chung 4 hàng <strong>và</strong> 4 cột. Bốn cột COL1-<br />

COL4 nối <strong>và</strong>o bốn bit thấp của Port D D0-D3. Bốn hàng ROW1-ROW4 nối <strong>và</strong>o bốn bit<br />

cao của Port D D4-D7. Bốn hàng được nối với điện trở kéo lên để đảm bảo mức logic 1<br />

khi phím không được nhấn.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 49 Thực hành Vi xử lý<br />

VCC<br />

R7<br />

100R<br />

R8<br />

100R


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

5.2 Các bước hiện thực<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Key <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file key.asm<br />

Bước 3: Define các port tương ứng với hàng <strong>và</strong> cột của ma trận phím để dễ<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 50 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

sử dụng sau này. Dựa <strong>và</strong>o sơ đồ mạch ta định nghĩa như sau:<br />

#define COLUMN_1 PORTD, 0<br />

#define COLUMN_2 PORTD, 1<br />

#define COLUMN_3 PORTD, 2<br />

#define COLUMN_4 PORTD, 3<br />

#define ROW_1 PORTD, 4<br />

#define ROW_2 PORTD, 5<br />

#define ROW_3 PORTD, 6<br />

#define ROW_4 PORTD, 7<br />

Bước 4: Khởi tạo input <strong>và</strong> output cho các port tương ứng. Ở đây column là<br />

output, còn row là input. Portb dùng để hiển thị led đơn cũng được cấu hình là<br />

output.<br />

INIT_IO<br />

;assigning PORTB is a digital output<br />

MOVLW 0x0F<br />

MOVWF ADCON1<br />

; setup portb for outputs<br />

CLRF TRISB<br />

CLRF PORTB<br />

MOVLW 0x0F<br />

MOVWF TRISD<br />

MOVLW 0xFF<br />

MOVWF PORTD<br />

RETURN<br />

Bước 5: Khởi tạo timer, phần này chúng ta đã <strong>học</strong> từ chương 4, ta có thể có<br />

một hàm khởi tạo timer đơn giản như sau:<br />

INIT_TIMER0<br />

BSF RCON,IPEN ;enable priority interrupts.<br />

BSF INTCON2,TMR0IP<br />

BSF INTCON,TMR0IF<br />

BSF INTCON,TMR0IE<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

RETURN<br />

Bước 6: Viết hàm Get_key với 2 đối số. Đối số thứ nhất có tên là temp_wr,<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 51 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

chính là giá trị output tương ứng với các cột của ma trận phím, đối số thứ 2 có tến<br />

là col chính là giá trị bắt đầu của mỗi cột. Ví dụ cột 1 thì giá trị đó bằng 0, cột 2 thì<br />

giá trị đó bằng 1, cột 3 thì giá trị đó bằng 2 <strong>và</strong> cột 4 thì giá trị đó bằng 3.<br />

GET_KEY<br />

BTFSS temp_wr, 0<br />

BCF COLUMN_1<br />

BTFSS temp_wr, 0<br />

BSF COLUMN_1<br />

BTFSS temp_wr, 1<br />

BCF COLUMN_2<br />

BTFSS temp_wr, 1<br />

BSF COLUMN_2<br />

BTFSS temp_wr, 2<br />

BCF COLUMN_3<br />

BTFSS temp_wr, 2<br />

BSF COLUMN_3<br />

BTFSS temp_wr, 3<br />

BCF COLUMN_4<br />

BTFSS temp_wr, 3<br />

BSF COLUMN_4<br />

BTFSC PORTD,4 ;BIT TEST F, SKIP IF SET<br />

GOTO NEXT_BUTTON_1<br />

MOVLW .0<br />

MOVWF KeyReg1<br />

GOTO EXIT_GET_KEY<br />

NEXT_BUTTON_1<br />

BTFSC PORTD,5 ;BIT TEST F, SKIP IF SET<br />

GOTO NEXT_BUTTON_2<br />

MOVLW .4<br />

MOVWF KeyReg1<br />

GOTO EXIT_GET_KEY<br />

NEXT_BUTTON_2<br />

BTFSC PORTD,6 ;BIT TEST F, SKIP IF SET<br />

GOTO NEXT_BUTTON_3<br />

MOVLW .8<br />

MOVWF KeyReg1<br />

GOTO EXIT_GET_KEY<br />

NEXT_BUTTON_3<br />

BTFSC PORTD,7 ;BIT TEST F, SKIP IF SET<br />

GOTO NEXT_BUTTON_2<br />

MOVLW .12<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 52 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

MOVWF KeyReg1<br />

EXIT_GET_KEY<br />

MOVFF COL,W<br />

ADDWF KeyReg1,d<br />

RETURN<br />

Bước 7: Dựa <strong>và</strong>o hàm Get_key ở trên ta có thể hoàn thiện hàm<br />

Scan_button một cách dễ dàng. Ở đây ta nhắc lại cách mà sử lý phím để nhận dữ<br />

liệu ngược trở về là tại một thời điểm chỉ cho một cột được tích cực (ở đây là mức<br />

0) sau đó đọc ngược giá trị từ các hàng. Hàng 1 tương ứng với cột 1 là số 0, tương<br />

tự hàng 2 với cột 1 là số 4…<br />

Khi nhấn phím thì sẽ có hiện tượng rung phím, để giải quyết trường hợp<br />

này ta có một cách giải quyết ở đây là đọc dữ liệu 3 lần liên tiếp mỗi lần cách nhau<br />

10ms, sau đó so sánh 3 giá trị đọc được. Nếu 3 giá trị bằng nhau thì ta xem như có<br />

một nút nhấn được nhấn. Trong hàm Scan_button ta dùng 3 biến KeyReg1,<br />

KeyReg2 <strong>và</strong> KeyReg3 để lưu giá trị của 3 lần đọc dữ liệu liên tiếp, khi kiểm tra 3<br />

biến này có giá trị bằng nhau thì ta sẽ lưu <strong>và</strong>o biến KeyReg <strong>và</strong> xuất dữ liệu ra<br />

PORTB.<br />

Scan_button<br />

MOVFF KeyReg2,KeyReg3<br />

MOVFF KeyReg1,KeyReg2<br />

MOVLW 0x0E<br />

MOVWF temp_wr<br />

MOVLW .0<br />

MOVWF COL<br />

CALL GET_KEY<br />

MOVLW 0x0D<br />

MOVWF temp_wr<br />

MOVLW .1<br />

MOVWF COL<br />

CALL GET_KEY<br />

MOVLW 0x0B<br />

MOVWF temp_wr<br />

MOVLW .2<br />

MOVWF COL<br />

CALL GET_KEY<br />

MOVLW 0x07<br />

MOVWF temp_wr<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 53 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

MOVLW .3<br />

MOVWF COL<br />

CALL GET_KEY<br />

MOVFF KeyReg1,W<br />

CPFSEQ KeyReg2<br />

GOTO EXIT_SCAN_BUTTON<br />

CPFSEQ KeyReg3<br />

GOTO EXIT_SCAN_BUTTON<br />

MOVFF KeyReg,W<br />

CPFSEQ KeyReg1<br />

GOTO Scan_button1<br />

GOTO EXIT_SCAN_BUTTON<br />

Scan_button1<br />

MOVFF KeyReg1,KeyReg<br />

CALL Button_process<br />

EXIT_SCAN_BUTTON<br />

RETURN<br />

Bước 8: Như giải <strong>thuật</strong> trên nói là cứ mỗi 10ms thì ta đọc dữ liệu một lần,<br />

để cho điều này được thực hiện dễ dàng thì ta phải dùng đến interrupt timer. Ta<br />

khởi tạo một interrupt timer cứ sau 10ms thì interrupt một lần. Để làm được điều<br />

này các bạn có thể xem lại chương timer để có thể làm việc một cách dễ dàng.<br />

Ở đây chỉ giới thiệu cho các bạn là hàm Timer0_routine, hàm này được gọi<br />

trong interrupt timer <strong>và</strong> trong hàm này ta gọi hàm Scan_button ở trên.<br />

TIMER0_ROUTINE<br />

BCF INTCON,TMR0IF<br />

BCF T0CON,TMR0ON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xaf<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

CALL SCAN_BUTTON<br />

RETURN<br />

5.3 Bài tập<br />

Cải tiến hàm chống rung phím, khi nhấn đè 1 phím thì phải sau 1 thời gian<br />

TimeOutForKey thì mới tích cực phím nhấn đó.<br />

Viết ứng dụng đồng hồ casio đơn giản (hiển thị giờ, ngày, cho phép chỉnh sửa<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 54 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

ngày giờ) sử dụng ma trận phím <strong>và</strong> LCD.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 55 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 6 : <strong>Kỹ</strong> <strong>thuật</strong> quét LED<br />

Nội dung:<br />

Khảo sát cấu tạo, hoạt động của LED 7 đoạn, LED ma trận.<br />

Tìm hiểu kỹ <strong>thuật</strong> quét LED 7 đoạn <strong>và</strong> LED ma trận.<br />

Yêu cầu:<br />

Viết chương trình cho phép hiển thị giá trị ra led 7 đoạn <strong>và</strong> led ma trận.<br />

6.1 Cấu tạo LED 7 đoạn <strong>và</strong> LED ma trận<br />

LED 7 đoạn gồm có 7 đoạn được đánh dấu: a, b, c, d, e, f, g <strong>và</strong> một điểm dp.<br />

LED 7 đoạn có hai loại là Common Anode <strong>và</strong> Common Cathode, tương ứng các<br />

LED nối chung Anode hay nối chung Cathode.<br />

LED.<br />

LED ma trận 8x8 hai màu được bố trí thành 8 hàng <strong>và</strong> 8 cột. Mỗi điểm có hai<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 56 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Các LED trên cùng một hàng nối chung Anode, các LED cùng loại trên cùng một<br />

cột nối chung Cathode.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 57 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

6.2 Kết nối mạch<br />

A 7<br />

B 6<br />

C 4<br />

D 2<br />

E 1<br />

F 9<br />

G 10<br />

DOT5<br />

LED1<br />

3<br />

a<br />

b<br />

c<br />

d<br />

e<br />

f<br />

g<br />

dot<br />

Vcc<br />

led7<br />

ENABLE_LED1<br />

8<br />

Vcc<br />

8.<br />

Green.1<br />

24<br />

GR1<br />

GR5<br />

1<br />

Green.5<br />

A 7<br />

B 6<br />

C 4<br />

D 2<br />

E 1<br />

F 9<br />

G 10<br />

DOT5<br />

Red.1<br />

23<br />

RD1<br />

RD5<br />

2<br />

Red.5<br />

LED2<br />

Row.1<br />

22<br />

RW1<br />

RW5<br />

3<br />

Row.5<br />

3<br />

a<br />

b<br />

c<br />

d<br />

e<br />

f<br />

g<br />

dot<br />

Vcc<br />

led7<br />

ENABLE_LED2<br />

Green.2<br />

21<br />

GR2<br />

GR6<br />

4<br />

Green.6<br />

8<br />

Vcc<br />

8.<br />

Red.2<br />

20<br />

RD2<br />

RD6<br />

5<br />

Red.6<br />

Row.2<br />

19<br />

RW2<br />

RW6<br />

6<br />

Row.6<br />

A 7<br />

B 6<br />

C 4<br />

D 2<br />

E 1<br />

F 9<br />

G 10<br />

DOT5<br />

Green.3<br />

18<br />

GR3<br />

GR7<br />

7<br />

Green.7<br />

Red.3<br />

17<br />

RD3<br />

LED 8x8x2<br />

LED3<br />

RD7<br />

8<br />

Red.7<br />

3<br />

a<br />

b<br />

c<br />

d<br />

e<br />

f<br />

g<br />

dot<br />

Row.3<br />

16<br />

RW3<br />

RW7<br />

9<br />

Row.7<br />

Vcc<br />

led7<br />

ENABLE_LED3<br />

8<br />

Green.4<br />

15<br />

GR4<br />

GR8<br />

10<br />

Green.8<br />

Vcc<br />

8.<br />

Red.4<br />

14<br />

RD4<br />

ML1<br />

RD8<br />

11<br />

Red.8<br />

Row.4<br />

13<br />

RW4<br />

RW8<br />

12<br />

Row.8<br />

A 7<br />

B 6<br />

C 4<br />

D 2<br />

E 1<br />

F 9<br />

G 10<br />

DOT5<br />

LED4<br />

3<br />

a<br />

b<br />

c<br />

d<br />

e<br />

f<br />

g<br />

dot<br />

Vcc<br />

led7<br />

ENABLE_LED4<br />

Mạch LED mở rộng gồm có 4 LED 7 đoạn <strong>và</strong> 1 LED ma trận hai màu xanh đỏ.<br />

Mạch được nối <strong>và</strong>o một phần của Port PICtail. Dữ liệu được dịch nối tiếp <strong>và</strong> được cài bởi<br />

IC 74HC595, TPIC6595. Module SPI của PIC đảm nhận việc dịch dữ liệu nối tiếp thông<br />

qua chân dữ liệu SDO <strong>và</strong> chân clock dịch SCK. Sau khi dịch đủ 4 byte, tín hiệu LATCH<br />

chuyển từ mức 0 lên mức 1 sẽ đẩy dữ liệu của 4 byte tạm ra 4 byte ngõ ra QA-QH tương<br />

ứng. Tín hiệu CLR_DISP tích cực mức 0 không cho phép hiển thị.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 58 Thực hành Vi xử lý<br />

8<br />

Vcc<br />

8.


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

SDO<br />

LATCH<br />

12<br />

SCK<br />

13<br />

VCC<br />

8<br />

CLR_DISP 9<br />

U1 TPIC6595<br />

3<br />

SDI SDO<br />

12<br />

13<br />

8<br />

9<br />

RCLK<br />

SRCLK<br />

SRCLR<br />

G<br />

18<br />

U3 TPIC6595<br />

LATCH<br />

SCK<br />

VCC<br />

CLR_DISP<br />

DRAIN0<br />

DRAIN1<br />

DRAIN2<br />

DRAIN3<br />

DRAIN4<br />

DRAIN5<br />

DRAIN6<br />

DRAIN7<br />

4<br />

5<br />

6<br />

7<br />

14<br />

15<br />

16<br />

17<br />

LATCH<br />

SCK<br />

3<br />

SDI<br />

SDO 9<br />

U4 74HC595<br />

14<br />

SDI<br />

11<br />

VCC<br />

SRCLK<br />

10<br />

13<br />

CLR<br />

G<br />

RCLK<br />

12<br />

SDO 18<br />

RCLK DRAIN0<br />

SRCLK DRAIN1<br />

DRAIN2<br />

SRCLR DRAIN3<br />

G DRAIN4<br />

DRAIN5<br />

DRAIN6<br />

DRAIN7<br />

QA 15<br />

QB 1<br />

QC 2<br />

QD 3<br />

QE 4<br />

QF<br />

4<br />

5<br />

6<br />

7<br />

14<br />

15<br />

16<br />

17<br />

3<br />

SDI SDO<br />

LATCH<br />

12<br />

SCK<br />

13<br />

VCC<br />

8<br />

CLR_DISP 9<br />

RCLK<br />

SRCLK<br />

SRCLR<br />

G<br />

18<br />

U2 TPIC6595<br />

DRAIN0<br />

DRAIN1<br />

DRAIN2<br />

DRAIN3<br />

DRAIN4<br />

DRAIN5<br />

DRAIN6<br />

DRAIN7<br />

4<br />

5<br />

6<br />

7<br />

14<br />

15<br />

16<br />

17<br />

5<br />

QG 6<br />

QH 7<br />

1<br />

2<br />

3<br />

4<br />

5<br />

6<br />

7<br />

8<br />

10<br />

U3<br />

IN1<br />

IN2<br />

IN3<br />

IN4<br />

IN5<br />

IN6<br />

IN7<br />

IN8<br />

COM<br />

VCC<br />

9<br />

V+<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

100<br />

100<br />

100<br />

100<br />

100<br />

100<br />

100<br />

100<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

330<br />

OUT1<br />

OUT2<br />

OUT3<br />

OUT4<br />

OUT5<br />

OUT6<br />

OUT7<br />

OUT8<br />

UDN2981<br />

18<br />

17<br />

16<br />

15<br />

14<br />

13<br />

12<br />

11<br />

R1 Red.1<br />

R2 Red.2<br />

R3 Red.3<br />

R4 Red.4<br />

R5 Red.5<br />

R6 Red.6<br />

R7 Red.7<br />

R8 Red.8<br />

R9 Green.1<br />

R10 Green.2<br />

R11 Green.3<br />

R12 Green.4<br />

R13 Green.5<br />

R14 Green.6<br />

R15 Green.7<br />

R16 Green.8<br />

R17<br />

R18<br />

R19<br />

R20<br />

R21<br />

R22<br />

R23<br />

R24<br />

6.3 Các thanh ghi liên quan <strong>và</strong> cách điều khiển<br />

- Thanh ghi trạng thái SSPSTAT:<br />

A<br />

B<br />

C<br />

D<br />

E<br />

F<br />

G<br />

DOT<br />

SDO<br />

SCK<br />

LATCH<br />

CLR_DISP<br />

VCC<br />

Row.1 ENABLE_LED1<br />

Row.2 ENABLE_LED2<br />

Row.3 ENABLE_LED3<br />

Row.4 ENABLE_LED4<br />

Row.5<br />

Row.6<br />

Row.7<br />

Row.8<br />

2<br />

1<br />

+5V<br />

GND<br />

RC2<br />

3 RC1<br />

4 RC0<br />

5 RA2<br />

6 RA1<br />

7 RA0<br />

8 RC3<br />

9 RC4<br />

10 RC5<br />

11 RA3<br />

PICtail<br />

12<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 59 Thực hành Vi xử lý<br />

CON12


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

- Thanh ghi điều khiển SSPCON1:<br />

- Sơ đồ khối module Synchronous Serial Port:<br />

Với sơ đồ mạch trên, mỗi lần có một hàng LED ở LED ma trận hay một con LED<br />

7 đoạn hiển thị dữ liệu. Lợi dụng hiện tượng lưu ảnh của mắt, dữ liệu của mỗi hàng LED<br />

ma trận hay mỗi con LED 7 đoạn được xuất ra tuần tự hàng (con) này đến hàng (con)<br />

khác, chúng ta sẽ thấy được hình ảnh của cả màn hình ma trận LED hay của cả 4 con<br />

LED 7 đoạn.<br />

Khi tất cả các hàng LED ma trận <strong>và</strong> tấc cả các con LED 7 đoạn đã được hiển thị<br />

(quét) qua một lần, ta nói đã hiển thị một frame. Để mắt không cảm thấy hình ảnh bị rung<br />

thì số lần hiển thị frame trong một giây phải lớn hơn 24 lần (thường là 30 lần).<br />

Đầu tiên tín hiệu CLR_DISP tích cực (mức 0) không cho LED hiển thị, sau đó<br />

dịch bốn byte dữ liệu, tín hiệu LATCH chuyển từ mức 0 lên mức 1 đưa dữ liệu mong<br />

muốn sẵn sàn ở ngõ ra, cuối cùng đưa tín hiệu CLR_DISP lên mức 1 cho phép LED hiển<br />

thị dữ liệu mong muốn. Cứ như vậy lặp lại chu trình này.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 60 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bốn byte dữ liệu được dịch ra mỗi lần có ý nghĩa tương ứng là dữ liệu của một<br />

hàng LED đỏ, dữ liệu của một hàng LED xanh, dữ liệu của một con LED 7 đoạn, điều<br />

khiển hàng (con) LED nào hiển thị.<br />

Cách điều khiển được minh họa thông qua hình sau :<br />

Giá trị của byte “control” chỉ chứa nhiều nhất một bit 1. Như hình vẽ, cần 12 lần<br />

xuất dữ liệu (4 byte) cho 1 frame gồm cả LED ma trận <strong>và</strong> LED 7 đoạn, 8 lần xuất dữ liệu<br />

cho 1 frame gồm chỉ có LED ma trận (không quan tâm nội dung hiển thị LED 7 đoạn), 4<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 61 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

lần xuất dữ liệu cho 1 frame gồm chỉ có LED 7 đoạn(không quan tâm nội dung hiển thị<br />

LED ma trận).<br />

6.4 Các bước hiện thực.<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Led <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file Led_matran.asm<br />

Bước 3: Khai báo các buffer cần thiết để viết driver cho led. Vì ở đây ta<br />

viết driver nên mọi người khi sử dụng những module này sẽ không sử dụng những<br />

hàm mà chúng ta viết trong này chỉ có thể thao tác trên các buffer mà thôi.<br />

GREEN_SCREEN_BUFFER RES .8<br />

RED_SCREEN_BUFFER RES .8<br />

SEVEN_LED_BUFFER RES .8<br />

COLUMN_BUFFER RES .8<br />

INDEX_OF_BUFFER RES .1<br />

RED_DATA RES .1<br />

GREEN_DATA RES .1<br />

SEVEN_LED_DATA RES .1<br />

COLUMN_DATA RES .1<br />

Bước 4: Ngoài ra nhìn <strong>và</strong>o mạch ta có thể dễ dàng nhận thấy được rằng dữ<br />

liệu của chúng ta được truyền theo kiểu truyền đồng bộ nối tiếp, chính xác hơn ở<br />

đây người ta sử dụng chức năng SPI để truyền dữ liệu. Do đó ta phải cấu hình cho<br />

chip làm sao có thể hoạt động được ở chế độ SPI này.<br />

INIT_SPI<br />

CLRF SSPCON1 ;SET Fspi = f/4<br />

BSF SSPCON1,5 ;ENALBLE SPI MODE<br />

BCF TRISC,5<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 62 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

BCF TRISC,3<br />

RETURN<br />

Trên đây ta mới chỉ khởi tạo module SPI để nó có thể hoạt động nhưng<br />

nhìn lại sơ đồ mạch ta lại thấy có thêm <strong>và</strong>i kết nối nữa từ vi điều khiển ra<br />

IC74595. Để IC này hoạt động được thì ta cần thêm một chân tạo clock để có thể<br />

chuyển dữ liệu nối tiếp ra song song của IC này. Ta define thêm cho chân Latch<br />

của IC 74595.<br />

#define LATCH_DIR TRISA,1<br />

#define LATCH_DATA PORTA,1<br />

Đồng thời khởi tạo các PORT liên quan:<br />

INIT<br />

MOVLW 0x0F<br />

MOVWF ADCON1<br />

BCF LATCH_DIR<br />

BCF LATCH_DATA<br />

CLRF INDEX_OF_BUFFER<br />

RETURN<br />

Bước 5: Ngoài ra để thực hiện được bài này không thể nào thiếu timer<br />

được, vì để hiển thị ra led ma trận ta phải quét từng cột led trên ma trận led.<br />

Khi nhìn <strong>và</strong>o cấu tạo của ma trận led ta thấy để hiện thị được một hình gì<br />

đó trên ma trận led thì ta phải quét led, vì tại một thời điểm chỉ có thể hiển thị một<br />

cột led mà thôi. Nhờ <strong>và</strong>o hiện tượng lưu ảnh ở mắt mà khi quét với tần số cao thì<br />

mắt ta sẽ thấy như là cột đó sáng chứ không phải chớp nháy nữa.<br />

Vậy làm sao biết được ta quét led với tần số bao nhiêu là hợp lý. Như trong<br />

phim ảnh khi xem phim thực chất ta biết là nó đang chạy với tần số là 24 hình /s.<br />

Ở đây ta cũng giả sử như vậy, cả màn hình của led cũng chớp nháy với tần số là 24<br />

hình/s, mà mỗi hình ta phải quét 8 lần vì có 8 cột. Từ đó ta có thể suy ra tần số ta<br />

cần phải quét cho mỗi cột là 8x24 lần/s. Từ đây ta có thể dễ dàng <strong>tính</strong> được timer<br />

của chúng ta cần bao nhiêu để có thể quét led được một cách dễ dàng.<br />

INIT_TIMER0<br />

BSF RCON,IPEN ;enable priority interrupts.<br />

BSF INTCON2,TMR0IP<br />

BSF INTCON,TMR0IF<br />

BSF INTCON,TMR0IE<br />

BSF INTCON,GIEH<br />

BSF INTCON,GIEL<br />

CLRF T0CON<br />

MOVLW 0x3c<br />

MOVWF TMR0H<br />

MOVLW 0xAF<br />

MOVWF TMR0L<br />

BSF T0CON,TMR0ON<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 63 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

RETURN<br />

Bước 6: Ban đầu ta khởi tạo các buffer để hiển thị cũng như quét cột led.<br />

Để dễ dàng trong việc sử lý ta sẽ khởi tạo cho Column_Buffer các giá trị tương<br />

ứng làm sao, khi xuất ra nó chỉ tích cực một cột của led mà thôi. Ở đây giả sử tích<br />

cực tại mỗi cột là tích cực mức cao thì ta có thể khởi tạo cho Column_buffer các<br />

giá trị sau: 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80.<br />

Bước 7: Đến đây mọi sử chuẩn bị đã xong, ta có thể bắt đầu viết hàm để<br />

hiển thị dữ liệu ra led. Đầu tiên ta sẽ viết một macro SPI_transmit với đối số sẽ là<br />

giá trị byte sẽ được truyền nối tiếp ra ngoài.<br />

SPI_TRANSMIT MACRO TEMP_DATA<br />

;Has data been received (transmit complete)?<br />

BTFSS SSPSTAT, BF<br />

GOTO $-2 ;No<br />

MOVF TEMP_DATA, W ;W reg = contents of TXDATA<br />

MOVWF SSPBUF<br />

ENDM<br />

Bước 8: Tiếp theo là làm sao lấy dữ liệu từ các buffer để đưa <strong>và</strong>o các biến<br />

tương ứng xuất ra led. Ta viết thêm một Macro nữa gồm 2 đối số là buffer <strong>và</strong><br />

temp_data. Macro này sẽ làm nhiệm vụ là lấy dữ liệu tại vị trí (được lưu trong biến<br />

index_of_buffer) của buffer lưu <strong>và</strong>o temp_data.<br />

UPDATE_DATA MACRO BUFFER,TEMP_DATA<br />

MOVLW HIGH BUFFER<br />

MOVWF FSR0H<br />

MOVLW LOW BUFFER<br />

MOVWF FSR0L<br />

MOVFF INDEX_OF_BUFFER,W<br />

ADDWF FSR0L,F<br />

CLRF W<br />

ADDWFC FSR0H<br />

MOVFF INDF0,TEMP_DATA<br />

ENDM<br />

Bước 9: Như trên đã giới thiệu để xuất dữ liệu ra led, ngoài việc dùng<br />

module SPI để xuất dữ liệu ta cần phải có thêm một tín hiệu clock tác động lên<br />

IC74595 thì dữ liệu nối tiếp của ta mới chuyển qua song song <strong>và</strong> hiển thị ra led.<br />

Do đó ta phải viết thêm một hàm tạo clock trên chân đã define khi nãy là<br />

Latch_data.<br />

CLOCK_STORAGE<br />

BSF LATCH_DATA<br />

NOP<br />

NOP<br />

BCF LATCH_DATA<br />

NOP<br />

NOP<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 64 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

BSF LATCH_DATA<br />

RETURN<br />

Bước 10: Cuối cùng là hàm quan trọng nhất, hàm này được gọi trong timer<br />

để thực hiện việc quét led.<br />

DISPLAY<br />

CALL INCREASING_INDEX<br />

UPDATE_DATA RED_SCREEN_BUFFER,RED_DATA<br />

UPDATE_DATA GREEN_SCREEN_BUFFER,GREEN_DATA<br />

UPDATE_DATA SEVEN_LED_BUFFER,SEVEN_LED_DATA<br />

UPDATE_DATA COLUMN_BUFFER,COLUMN_DATA<br />

SPI_TRANSMIT RED_DATA<br />

SPI_TRANSMIT GREEN_DATA<br />

SPI_TRANSMIT SEVEN_LED_DATA<br />

SPI_TRANSMIT COLUMN_DATA<br />

CALL CLOCK_STORAGE<br />

RETURN<br />

6.5 Bài tập<br />

Xây dựng ứng dụng cho phép số “1234” chạy qua các led 7 đoạn.<br />

Xây dựng ứng dụng cho phép 1 dòng chữ chạy qua led ma trận.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 65 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 7 : Khảo sát bộ truyền nhận nối tiếp<br />

Nội dung:<br />

Khảo sát cổng COM máy PC, các thông số truyền nối tiếp.<br />

Khảo sát bộ truyền nối tiếp của PIC.<br />

Tìm hiểu cách sử dụng chương trình Hyper Terminal truyền nhận nối tiếp trên<br />

máy PC.<br />

Yêu cầu:<br />

Viết chương trình giao tiếp giữa máy <strong>tính</strong> <strong>và</strong> vi điều khiển PIC.<br />

7.1 Các bước hiện thực.<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là Uart <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file uart.asm<br />

Bước 3: Khởi tạo PortB là output, PORTC.6 là output, PORTC.7 là input.<br />

INIT_PORT<br />

CLRF LATB ; Clear PORTB output latches<br />

CLRF TRISB ; Config PORTB as all outputs<br />

BCF TRISC,6 ; Make RC6 an output<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 66 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

BSF TRISC,7<br />

RETURN<br />

Bước 4: Khởi tạo các vector ngắt<br />

org 00000h ; Reset Vector<br />

goto Start<br />

org 00008h ; Interrupt vector<br />

goto IntVector<br />

Start<br />

GOTO<br />

IntVector<br />

RETFIE<br />

$<br />

Bước 5: Khởi tạo cho ngắt UART, tốc độ 9600baud tại tần số 4Mhz.<br />

INIT_UART<br />

MOVLW 19h ; 9600 baud @4MHz<br />

MOVWF SPBRG<br />

BSF TXSTA,TXEN ; Enable transmit<br />

BSF TXSTA,BRGH ; Select high baud rate<br />

BSF RCSTA,SPEN ; Enable Serial Port<br />

BSF RCSTA,CREN ; Enable continuous reception<br />

BCF PIR1,RCIF ; Clear RCIF Interrupt Flag<br />

BSF PIE1,RCIE ; Set RCIE Interrupt Enable<br />

BSF INTCON,PEIE ; Enable peripheral interrupts<br />

BSF INTCON,GIE ; Enable global interrupts<br />

RETURN<br />

Bước 6: Viết chương trình trong ngắt thực hiện nhiệm vụ nhận một dữ liệu<br />

từ máy <strong>tính</strong> truyền xuống sau đó gởi lại kí tự đó cho máy tình nhận lại.<br />

IntVector<br />

btfss PIR1,RCIF ; Did USART cause interrupt?<br />

goto ISREnd ; No, some other interrupt<br />

movlw 06h ; Mask out unwanted bits<br />

andwf RCSTA,W ; Check for errors<br />

btfss STATUS,Z ; Was either error status bit set?<br />

goto RcvError ; Found error, flag it<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 67 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

return<br />

movf RCREG,W ; Get input data<br />

movwf LATB ; Display on LEDs<br />

movwf TXREG ; Echo character back<br />

goto ISREnd ; go to end of ISR, restore context,<br />

RcvError<br />

bcf RCSTA,CREN ; Clear receiver status<br />

bsf RCSTA,CREN<br />

movlw 0FFh ; Light all LEDs<br />

movwf PORTB<br />

goto ISREnd ; go to end of ISR, restore context,<br />

return<br />

ISREnd<br />

retfie<br />

7.2 Chương trình mẫu<br />

;=====================================;<br />

; Name: uart.asm<br />

; Project: Viết chương trình giao tiếp giữa máy <strong>tính</strong> <strong>và</strong> vi điều khiển PIC.<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 8 - 8 - 2009<br />

;======================================;<br />

list p=18F4520 ; set processor type<br />

include <br />

;************************************************************<br />

; Reset and Interrupt Vectors<br />

org 00000h ; Reset Vector<br />

goto Start<br />

org 00008h ; Interrupt vector<br />

goto IntVector<br />

;************************************************************<br />

; Program begins here<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 68 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Start<br />

Main<br />

org 00020h ; Beginning of program EPROM<br />

CALL INIT_PORT<br />

CALL INIT_UART<br />

goto Main ; loop to self doing nothing<br />

INIT_PORT<br />

clrf LATB ; Clear PORTB output latches<br />

clrf TRISB ; Config PORTB as all outputs<br />

bcf TRISC,6 ; Make RC6 an output<br />

bsf TRISC,7 ; Make RC7 an input<br />

RETURN<br />

INIT_UART<br />

movlw 19h ; 9600 baud @4MHz<br />

movwf SPBRG<br />

bsf TXSTA,TXEN ; Enable transmit<br />

bsf TXSTA,BRGH ; Select high baud rate<br />

bsf RCSTA,SPEN ; Enable Serial Port<br />

bsf RCSTA,CREN ; Enable continuous reception<br />

bcf PIR1,RCIF ; Clear RCIF Interrupt Flag<br />

bsf PIE1,RCIE ; Set RCIE Interrupt Enable<br />

bsf INTCON,PEIE ; Enable peripheral interrupts<br />

bsf INTCON,GIE ; Enable global interrupts<br />

RETURN<br />

;************************************************************<br />

; Interrupt Service Routine<br />

IntVector<br />

btfss PIR1,RCIF ; Did USART cause interrupt?<br />

goto ISREnd ; No, some other interrupt<br />

movlw 06h ; Mask out unwanted bits<br />

andwf RCSTA,W ; Check for errors<br />

btfss STATUS,Z ; Was either error status bit set?<br />

goto RcvError ; Found error, flag it<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 69 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

movf RCREG,W ; Get input data<br />

movwf LATB ; Display on LEDs<br />

movwf TXREG ; Echo character back<br />

goto ISREnd ; go to end of ISR, restore context, return<br />

RcvError<br />

bcf RCSTA,CREN ; Clear receiver status<br />

bsf RCSTA,CREN<br />

movlw 0FFh ; Light all LEDs<br />

movwf PORTB<br />

goto ISREnd ; go to end of ISR, restore context, return<br />

ISREnd<br />

retfie<br />

end<br />

7.3 Bài tập<br />

Viết chương trình trên PC, gửi 1 chuỗi string xuống board, dòng chữ này sẽ chạy<br />

qua led ma trận hoặc LCD.<br />

Khi nhấn 1 phím trên board nhấn, sẽ gửi 1 chuỗi string lên PC qua cổng COM,<br />

viết chương trình trên PC nhận chuỗi string này <strong>và</strong> in ra giao diện.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 70 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 8 : Khảo sát khối chuyển đổi A-D<br />

Nội dung:<br />

Khảo sát hoạt động khối chuyển đổi A-D.<br />

Khảo sát các thanh ghi điều khiển hoạt động khối chuyển đổi A-D.<br />

Yêu cầu:<br />

Viết chương trình đọc <strong>và</strong> hiển thị giá trị điện áp thay đổi bởi biến trở.<br />

8.1 Các bước hiện thực<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là a2d <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file a2d.asm<br />

Bước 3: Khởi tạo module ADC để ta có thể sử dụng một cách dễ dàng.<br />

InitializeAD<br />

Movlw B'00000100' ; Make RA0,RA1,RA4 analog inputs<br />

movwf ADCON1<br />

movlw B'11000001' ; Select RC osc, AN0 selected,<br />

movwf ADCON0 ; A/D enabled<br />

movlw 0x01<br />

movwf ADCON2<br />

call SetupDelay ; delay for 15 instruction cycles<br />

bsf ADCON0,GO ; Start first A/D conversion<br />

return<br />

Để khởi tạo được module ADC ta chỉ cần quan tâm chủ yếu tới các thanh<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 71 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

ghi ADCCON1, ADCCON0, ADCON2. Như chương trình khởi tạo trên ta thấy<br />

đầu tiên phải cấu hình cho các pin tương ứng phải là chân AN0, mặc định của các<br />

chân này có chức năng là Input/Output digital. Sau đó ta phải chọn kênh ADC<br />

tương ứng, ở đây ta sử dụng kênh AD0. Và một điểm quan trọng nữa chính là bit<br />

GO trong thanh ghi ADCON0, khi bít này được bật lên thì module AD mới bắt<br />

đầu chuyển đổi tín hiệu.<br />

Bước 4: Tiếp theo là hàm đọc giá trị ADC:<br />

Update_adc<br />

bsf ADCON0,GO ;start conversion<br />

btfsc ADCON0,GO<br />

bra $-2<br />

movf ADRESH,W<br />

return<br />

Sau khi chuyển đổi tín hiệu A-D, giá trị số sẽ được lưu <strong>và</strong>o thanh ghi<br />

ADRESH. Đến đây tùy <strong>và</strong>o ứng dụng cụ thể mà ta có thể biến đổi giá trị này tùy<br />

theo yêu cầu mà ta mong muốn.<br />

8.2 Bài tập<br />

Tích hợp module LCD, lấy giá trị điện thế từ biến trở hiển thị lên LCD.<br />

Sử dụng module ADC của Pic để đo nhiệt độ trong phòng, dùng LCD để hiển thị<br />

giá trị nhiệt độ.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 72 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

Bài 9 : Khảo sát các khối chức năng đặc biệt khác<br />

Nội dung:<br />

Khảo sát khối chức năng WDT.<br />

Khảo sát khối chức năng PWM .<br />

Khảo sát các chế độ hoạt động của vi điều khiển.<br />

Yêu cầu:<br />

Viết chương trình sử dụng chức năng WDT.<br />

Viết chương trình sử dụng chức năng PWM điều khiển độ sáng của LED.<br />

Viết chương trình sử dụng chức năng Power control.<br />

9.1 Các bước hiện thực PWM<br />

Bước 1: Tạo project mới giống như hướng dẫn ở chương 1 lấy tên project<br />

là pwm <strong>và</strong> chọn chip 18f4520. Ta được hình sau:<br />

LCD.<br />

Bước 2: Include file p18f4520.inc <strong>và</strong>o file pwm.asm.<br />

Bước 3: Tích hợp module LCD <strong>và</strong>o project pwm, tham khảo bài tập về<br />

Bước 4: Khởi tạo module PWM để ta có thể sử dụng một cách dễ dàng.<br />

Init_pwm<br />

;configure CCP1 module for buzzer<br />

bcf TRISC,2<br />

movlw 0x80<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 73 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

movwf PR2 ;initialize PWM period<br />

movlw 0x80 ;initialize PWM duty cycle<br />

movwf CCPR1L<br />

bcf CCP1CON,CCP1X<br />

bcf CCP1CON,CCP1Y<br />

;postscale 1:1, prescaler 4, Timer2 ON<br />

movlw 0x05<br />

movwf T2CON<br />

movlw 0x0F ;turn buzzer on<br />

movwf CCP1CON<br />

return<br />

Để khởi tạo chức năng pwm, đầu tiên ta phải cấu hình cho PORTC2 là<br />

output. Tiếp theo khởi tạo chu kì của PWM thông qua việc cấu hình thanh ghi<br />

PR2. Sau đó ta khởi tạo duty cycle của xung pwm bằng cách cấu hình thanh ghi<br />

CCPR1L.<br />

9.2 Chương trình mẫu<br />

;=====================================;<br />

; Name: pwm.asm<br />

; Project: Su dung Pwm de xuat am thanh ra loa.<br />

; Author: BKIT HARDWARE CLUB<br />

; Homepage: http://www.bkit4u.com/forum<br />

; Creation Date: 20 - 8 - 2009<br />

;======================================;<br />

; vectors<br />

list p=18f4520<br />

#include "p18f4520.inc"<br />

org 0x000000 ; reset vector<br />

bra START<br />

;************************************************************<br />

; program<br />

START<br />

call Init_pwm<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 74 Thực hành Vi xử lý


Trường ĐH. Bách <strong>Khoa</strong> TP.HCM <strong>Khoa</strong> KH & KTMT<br />

goto $<br />

Init_pwm<br />

bcf TRISC,2<br />

movlw 0x80<br />

movwf PR2 ;initialize PWM period<br />

movlw 0x80 ;initialize PWM duty cycle<br />

movwf CCPR1L<br />

bcf CCP1CON,CCP1X<br />

bcf CCP1CON,CCP1Y<br />

;postscale 1:1, prescaler 4, Timer2 ON<br />

movlw 0x05<br />

movwf T2CON<br />

movlw 0x0F ;turn buzzer on<br />

movwf CCP1CON<br />

return<br />

END<br />

9.3 Bài tập<br />

Tìm hiểu <strong>và</strong> hiện thực chương trình điều khiển RC Servo.<br />

Bộ môn <strong>Kỹ</strong> Thuật <strong>Máy</strong> Tính 75 Thực hành Vi xử lý

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!