107
Giáo trình thí nghiệm vi điều khin ng dng 1 MC LC CHƢƠNG I : PHẦN CNG PIC16F.......................................................................................... 4 I.KIN TRÚC .......................................................................................................................... 4 1.Kiến trúc Von neumann .................................................................................................... 4 2.Kiến trúc harvard ............................................................................................................. 4 II.INSTRUCTION PIPELINING ........................................................................................... 5 III.KÍCH THƢỚC TLNH ................................................................................................. 9 IV.THIT KPHN CNG CHO PIC .............................................................................. 10 1.Mch nguyên lý.................................................................................................................. 10 2.Chun ICSP(In-Circurt Serial Programming) .................................................................... 11 3.Các tính năng đặc bit, các bit cu hình ca PIC16F887................................................... 11 CHƢƠNG II : XUẤT NHP I/O PORT .................................................................................. 21 I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 21 II.DNG CTHÍ NGHIM ............................................................................................... 21 III.CƠ SỞ LÝ THUYT ....................................................................................................... 21 1.Thanh ghi qui định tín hiu x...................................................................................... 21 2.Chức năng của thanh ghi TRIS ......................................................................................... 22 3. Chức năng của thanh ghi PORT ...................................................................................... 22 4.Những thanh ghi đặc bit chcó riêng PORTB .............................................................. 23 IV.BÀI TP THC HÀNH .................................................................................................. 26 V.BÀI TP TGII ........................................................................................................... 32 CHƢƠNG III : ADC MODULE................................................................................................ 33 I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 33 II.DNG CTHÍ NGHIM ................................................................................................. 33 III.CƠ SỞ LÝ THUYT ...................................................................................................... 33 1.Tín hiệu tương tự và tín hiu s........................................................................................ 33 2.ADC của vi điều khin PIC16F887 ................................................................................... 34 3.Làm vic vi LCD 16x2 ................................................................................................... 38 IV.BÀI TP THC HÀNH .................................................................................................. 40 V.BÀI TP TGII ............................................................................................................. 44

Giao Trinh Thi Nghiem VDK

Embed Size (px)

Citation preview

Page 1: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

1

MỤC LỤC

CHƢƠNG I : PHẦN CỨNG PIC16F .......................................................................................... 4

I.KIẾN TRÚC .......................................................................................................................... 4

1.Kiến trúc Von neumann .................................................................................................... 4

2.Kiến trúc harvard ............................................................................................................. 4

II.INSTRUCTION PIPELINING ........................................................................................... 5

III.KÍCH THƢỚC TỪ LỆNH ................................................................................................. 9

IV.THIẾT KẾ PHẦN CỨNG CHO PIC .............................................................................. 10

1.Mạch nguyên lý.................................................................................................................. 10

2.Chuẩn ICSP(In-Circurt Serial Programming) .................................................................... 11

3.Các tính năng đặc biệt, các bit cấu hình của PIC16F887................................................... 11

CHƢƠNG II : XUẤT NHẬP I/O PORT .................................................................................. 21

I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 21

II.DỤNG CỤ THÍ NGHIỆM ............................................................................................... 21

III.CƠ SỞ LÝ THUYẾT ....................................................................................................... 21

1.Thanh ghi qui định tín hiệu xử lý ...................................................................................... 21

2.Chức năng của thanh ghi TRIS ......................................................................................... 22

3. Chức năng của thanh ghi PORT ...................................................................................... 22

4.Những thanh ghi đặc biệt chỉ có riêng ở PORTB .............................................................. 23

IV.BÀI TẬP THỰC HÀNH .................................................................................................. 26

V.BÀI TẬP TỰ GIẢI ........................................................................................................... 32

CHƢƠNG III : ADC MODULE................................................................................................ 33

I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 33

II.DỤNG CỤ THÍ NGHIỆM ................................................................................................. 33

III.CƠ SỞ LÝ THUYẾT ...................................................................................................... 33

1.Tín hiệu tương tự và tín hiệu số ........................................................................................ 33

2.ADC của vi điều khiển PIC16F887 ................................................................................... 34

3.Làm việc với LCD 16x2 ................................................................................................... 38

IV.BÀI TẬP THỰC HÀNH .................................................................................................. 40

V.BÀI TẬP TỰ GIẢI ............................................................................................................. 44

Page 2: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

2

CHƢƠNG IV :TIMER ............................................................................................................... 46

I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 46

II.DỤNG CỤ THÍ NGHIỆM ................................................................................................. 46

III.CƠ SỞ LÝ THUYẾT ....................................................................................................... 46

1.Nguyên tắc hoạt động của timer : ...................................................................................... 47

2.Timer 0 .............................................................................................................................. 47

3.Timer 1 .............................................................................................................................. 50

4.Timer 2 .............................................................................................................................. 53

IV.BÀI TẬP THỰC HÀNH .................................................................................................. 55

V.BÀI TẬP TỰ GIẢI ............................................................................................................. 60

CHƢƠNG V: KHỐI CCP .......................................................................................................... 61

(CAPTURE-COMPARE-PWM) ............................................................................................... 61

I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 61

II.DỤNG CỤ THÍ NGHIỆM ................................................................................................. 61

III.CƠ SỞ LÝ THUYẾT ....................................................................................................... 61

1.Thanh ghi khởi tạo khối CCP1 . .................................................................................. 62

2.Thanh ghi khởi tạo khối CCP2 .......................................................................................... 63

3.Capture .............................................................................................................................. 64

4.Compare ............................................................................................................................ 64

5.PWM(Pulse-Width Modulated) ........................................................................................ 65

6.Các bước khởi tạo chức năng PWM ................................................................................. 66

IV.BÀI TẬP THỰC HÀNH ................................................................................................... 67

V.BÀI TẬP TỰ GIẢI ............................................................................................................. 70

CHƢƠNG VI :GIAO TIẾP NỐI TIẾP BẤT ĐỒNG BỘ ........................................................ 72

I.MỤC ĐÍCH THÍ NGHIỆM ................................................................................................ 72

II.DỤNG CỤ THÍ NGHIỆM ................................................................................................. 72

III.CƠ SỞ LÝ THUYẾT ....................................................................................................... 72

1.Khái niệm về giao tiếp nối tiếp bất đồng bộ ..................................................................... 72

2.Các thanh ghi điều khiển truyền UART ............................................................................ 74

3.Các thanh ghi điều khiển nhận UART .............................................................................. 76

5.Công thức tính tốc độ baund rate ...................................................................................... 78

Page 3: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

3

IV:BÀI TẬP THỰC HÀNH .................................................................................................. 78

V.BÀI TẬP TỰ GIẢI ............................................................................................................. 81

TÀI LIỆU THAM KHẢO ......................................................................................................... 83

PHỤ LỤC ..................................................................................................................................... 84

I.CỬA SỔ CHƢƠNG TRÌNH .............................................................................................. 84

II.CÁC BƢỚC KHỞI TẠO MỘT PROJECT MỚI ............................................................ 84

II.HI TECH C CƠ BẢN ......................................................................................................... 88

1.Khai báo biến .................................................................................................................... 88

2.Kiểu con trỏ ....................................................................................................................... 89

3.Kiểu enum .......................................................................................................................... 89

4.Phép toán học ..................................................................................................................... 90

5.Phép toán gán ..................................................................................................................... 90

6.Phép toán tăng , giảm ......................................................................................................... 90

7.Phép toán quan hệ .............................................................................................................. 90

8.Tóan tử logic ..................................................................................................................... 91

9.Toán tử theo bit ................................................................................................................. 91

10.Chèn một đoạn code Assembly ....................................................................................... 91

11.Các toán tử ưu tiên .......................................................................................................... 92

12.Câu điều kiện .................................................................................................................. 92

13.Toán tử lựa chọn ............................................................................................................. 94

14.Vòng lặp ........................................................................................................................... 95

15.Mảng 1 chiều ................................................................................................................... 96

16.Mảng hai chiều ................................................................................................................ 97

17.Cấu trúc của một chương trình c cơ bản ......................................................................... 97

IV.SƠ ĐỒ NGUYÊN LÝ KIT THÍ NGHIỆM ..................................................................... 98

V.FILE LCD ......................................................................................................................... 101

1.lcd.c ...................................................................................................................................... 101

2.lcd.h ...................................................................................................................................... 106

Page 4: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

4

CHƯƠNG I : PHẦN CỨNG PIC16F

I.KIẾN TRÚC :

Microchip Pic được thiết kế dựa trên kiến trúc Harvard, một kiến trúc RISC (Reduced

Instruction Set Conputer – Máy tính với tập lệnh đơn giản hóa). Đây là một kiến trúc mới với

nhiều cải tiến nâng cao hiệu năng xử lý và giảm thiểu giá thành sản xuất. Vậy thì những đặc tính

nào của kiến trúc Havard mang lại hiệu quả cho PIC, chúng ta thử so sánh hai kiểu RISC khá

phổ biến là Von Neumann và Harvard.

1.Kiến trúc Von neumann:

Còn gọi là kiến trúc Princeton, cách tổ chức bộ nhớ của kiểu kiến trúc này là cả bộ nhớ

chương trình và bộ nhớ dữ liệu được xem như một vùng nhớ, dùng chung một Bus dữ liệu. Thời

kỳ đầu của kỷ nguyên máy tính, bộ nhớ không có độ tin cậy như hiện nay và hay tạo ra những lỗi

hệ thống. Chính vì vậy mà kiểu kiến trúc này được ưa chuộng, bởi vì nó được dễ dàng thiết kế,

nâng cao độ tin cậy của hệ thống và dễ dàng thay thế những vùng nhớ bị lỗi kỹ thuật. Nhờ những

lợi thế đó mà trong một thời gian kiểu kiến trúc này đã được thương mại và sản xuất. Tuy nhiên

nó cũng có một số nhược điểm: hạn chế băng thông, thực hiện nhiều lần lấy dữ liệu chỉ cho một

lệnh, không thể thực hiện song song thao tác này. Chính vì sự phổ biến đầu tiên của kiến trúc

Von Neumann mà hầu hết các loại Vi Điều Khiến đều được xây dựng quanh cấu trúc này, mặc

dù giá thành bộ nhớ hiện nay đã rẻ hơn rất nhiều và độ tin cậy cũng tăng lên rất nhiều.

Hình 1: Kiến trúc bộ nhớ kiểu Von Neuman

2.Kiến trúc harvard :

Havard có không gian nhớ dành cho bộ nhớ dữ liệu và bộ nhớ chương trình riêng biệt. Lợi

thế và hiệu năng chính của kiểu dữ liệu này là nó có 2 Bus dữ liệu riêng biệt hoạt động đồng thời

phục vụ cho bộ nhớ dữ liệu và bộ nhớ chương trình: Trong khi CPU lấy dữ liệu từ bộ nhớ

chương trình, thì nó vẫn có thể đọc ghi dữ liệu ở vùng nhớ dữ liệu.

Von Neumann

Architecture

8-bit

Bus

CPU

Program

& Data

Memory

Page 5: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

5

Một lợi thế khác của kiến trúc Harvard là độ rộng Bus bộ nhớ chương trình và Bus dữ liệu

có thể khác nhau. Không phải tất tất cà các loại Vi Điều Khiển có kiến trúc Harvard điều có lợi

thế này, nhưng PIC thì có. Do bus có độ rộng khác nhau nên độ rộng Bus bộ nhớ chương trình có

thể rộng hơn bộ nhớ dữ liệu. Với PIC-8bit thì Bus dự liệu luôn là 8-bit, tuy nhiên Bus bộ nhớ

chương trình có thể rộng hơn, bao nhiêu tùy thuộc và mục đích của loại PIC đó. Với PIC 8-bit

thì có 3 loại được phân chia thành loại có độ rộng Bus bộ nhớ chương trình là 12-bit, 14-bit, và

16-bit. Bus bộ nhớ chương trình rộng hơn sẽ đưa dữ liệu từ bộ nhớ chương trình nhiều hơn cũng

trong một chu kỳ máy.

Hình 2: Kiến trúc bộ nhớ kiểu Von Neuman

II.INSTRUCTION PIPELINING:

Việc lấy lệnh/dữ liệu từ bộ nhớ chương trình cũng được thiết kế nâng cao hiệu suất.

Instruction pipelining là cách thức lấy và thực thi lệnh từ bộ nhớ chương trình một cách đồng

thời. Có thể xem hình:

Hình 3: Quy trình thực thi các lệnh

PIC có bus truy xuất bộ nhớ chương trình và bus truy xuất bộ nhớ dữ liệu riêng biệt có thể

hoạt động đồng thời. Nhưng trong quá trình ta lấy một lệnh, làm thế nào biết được dữ liệu cần

CPU

Harvard

Architecture

Data

Memory

Program

Memory

8-bit

Bus

14-bit

Bus

Page 6: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

6

thiết cho lệnh đó ở đâu để thực thi đồng thời hai thao tác này trong một chu kỳ lệnh, bởi vì thông

tin địa chỉ của dữ liệu cần thiết trong vùng nhớ dữ liệu nằm trong lệnh kia.Vấn đề được giải

quyết bằng Instruction Pipelining.

Trong chu kỳ lệnh đầu tiên khi CPU hoạt động, lệnh được lấy vào Pipeline. Bus bộ nhớ

chương trình được truy xuất, Bus dự liệu không hoạt động.

Hình 4: Thực hiện lệnh trong chu kỳ đầu tiên

Trong chu kỳ lệnh thứ 2, lệnh lấy trước đó được thực thi, có nghĩa là Bus dữ liệu hoạt động

trao đổi dữ liệu với CPU khi CPU thực thi lệnh. Đồng thời trong lúc này, cả 2 Bus đều hoạt động

đồng thời.

Hình 5: Thực hiện lệnh trong chu kỳ thứ hai

Trong chu kỳ lệnh thứ 3, lệnh thứ 2 lấy trước đó được thực thi, đồng thời lệnh tiếp theo

được lấy. Tới lúc này thì mọi thứ đã khá rõ ràng, ngoại trừ chu kỳ lệnh đầu tiên ra, mỗi chu kỳ

lệnh sẽ thực thi xong một lệnh, bao gồm 2 bước lấy lệnh và thực thi. Bởi vì lúc thực thi 1 lệnh thì

lệnh đó đã có sẵn, và thông tin về địa chỉ bộ nhớ dữ liệu cũng đã được lấy vào từ lúc lệnh trước

thực thi.

Page 7: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

7

Hình 6:Thực hiện lệnh trong chu kỳ thứ ba

Chu kỳ thứ 4,5:Với quy trình như vậy thì lệnh nằm sau luôn luôn thực thi khi lệnh trước nó

thực thi xong. Tuy nhiên khi bộ đếm chương trình bị thay đổi bằng một lệnh, thì có thể lệnh sau

đó không được thực hiện. Ở đây, lệnh Call được thực thi khiến chương trình nhảy đến vùng nhớ

khác và lệnh đằng sau lệnh Call tất nhiên chỉ được thực thi sau khi chương trình trở về từ hàm

SUB1. Nhưng, khi lệnh Call được thực thi thì lệnh kế tiếp nó vẫn được lấy vào Pipeline.

Hình 7: Thực hiện lệnh trong chu kỳ thứ 4

Như vậy cần thiết phải loại bỏ lệnh sau Call ra khỏi Pipeline, đồng thời lấy một lệnh khác

vào Pipeline. Có thể thấy, với bất kỳ một lệnh nào làm thay đổi bộ đếm chương trình thì phải mất

2 chu kỳ máy.

Page 8: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

8

Page 9: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

9

III.KÍCH THƢỚC TỪ LỆNH

Bởi vì có kiến trúc Harvard nên vi điều khiển PIC có độ rộng của Bus bộ nhớ chương trình

không nhất thiết bằng với độ rộng của Bus bộ nhớ dữ liệu (vi điều khiển 8 bit thì bus có độ rộng

8 bit). Đối với một số vi điều khiển dùng kiến trúc Von neumann thì sẽ có cùng độ rộng bus. Do

đó rất nhiều lệnh đòi hỏi 2 byte mới có thể cung cấp đầy đủ thông tin để thực thi. Đơn giản, một

lệnh LDAA(Load Data to Accumulator A) chuyển một hằng số 8 bit vào thanh ghi A đòi hỏi ít

nhất 2 byte dữ liệu hằng 8 bit, và byte còn lại cho lệnh. Điều này có nghĩa là, khi thực hiện lệnh

này, bộ nhớ bị truy xuất 2 lần. Ngoài việc kém hiệu quả về tốc độ truy xuất ra, các tổ chức từ

lệnh 1, 2 hay 3 của kiểu kiến trúc này làm cho việc thiết kế một vi điều khiển với bộ nhớ vừa

phải hợp yêu cầu khó khăn hơn.

Hình 8: Quy trình thực thi lệnh LDAA

Đối với PIC16F mà chúng ta đang dùng, kiến trúc bộ nhớ được thiết kế là 14 bit có độ rộng

bus bộ nhớ chương trình, phù hợp với các ứng dụng vừa phải. Từ lệnh dài như vậy sẽ chứa được

nhiều thông tin hơn, đủ để thực thi một công việc chỉ với một từ lệnh, có nghĩa là chỉ cần truy

xuất bộ nhớ 1 lần cho 1 lệnh. Với thiết kế này thì kích thước bộ nhớ sẽ tối ưu hơn so với các kích

thước bộ nhớ kiểu khác.

Hình 9: Thực thi một công việc chỉ với một từ lệnh

Page 10: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

10

IV.THIẾT KẾ PHẦN CỨNG CHO PIC

1.Mạch nguyên lý:

Các chân nguồn Vdd phải được cấp nguồn đầy đủ, không được bỏ trống: Chip càng nhiều

tính năng thì lượng Transistor càng lớn, khi số lượng Transistor trong chip tăng lên, thì độ dài

đường cấp nguồn trong diesilicon cũng tăng lên, làm điện trở tăng gây ra mất cân đối điện áp

cung cấp trên các vùng của chip. Hơn nữa khi đường nối dài thì cảm kháng ký sinh cũng tăng

theo làm áp cung cấp cho các vùng trên cũng bị sụt tức thời khi chip hoạt động ở tần số cao.

Những hiệu ứng này làm chip hoạt động kém ổn định. Do đó chip đưa ra nhiều đầu cấp nguồn

để làm giảm các hiệu ứng trên.

Phải có các tụ decouling 0.1uF đặt gần các chân cấp nguồn (khi vẽ PCB phải đặt càng gần

càng tốt): Mặt dù dòng tiêu thụ trung bình có thể nhỏ nhưng khi hoạt động ở tần số cao, dòng

điện tức thời mà chip cần (để nạp các cổng của các MOSFET) là rất lớn. Do di/dt lớn nên ảnh

hưởng của điện cảm trên đường mạch cũng rất lớn.

Ngoài ra các ổn áp tuyến tính điều không thể cung cấp được dòng điện này cho chip. Vì

vậy bạn phải cần các tụ điện để tích điện tạm thời trong chu kỳ chip không hoạt động và xả dòng

để cung cấp cho chip trong chu kỳ hoạt động. Các tụ điện này phải: ESR thấp để có khả năng xả

dòng lớn. Tụ gốm (tụ bi) 0.1uF là phù hợp. Đôi khi có thể mắc song song thêm 1 tụ 0.01uF thật

gần 2 chân nguồn của chip để giảm điện cảm, điện trở của đường mạch. Khi lắp các tụ

decouling, trên các đường cấp nguồn sẽ có nhiễu tần số cao do nạp và xả các tụ này cộng thêm

nhiễu từ các nguồn khác và cần phải triệt tiêu. Nhưng đây là vấn để rất phức tạp: Sử dụng LDO

tốt , dòng tĩnh thấp, nếu phải xài 7805, với một loại chỉ cần có 1 con 0.1uF sát ngay chân output

để tránh bị dao động.

Tăng kích thướng đường nguồn để giảm điện cảm.

Đặt rải rác các tụ 10uF(low ESR) trên các đường cấp nguồn.

Nếu phải dùng các tải cảm như relay, motor, và dùng chung nguồn, nên đi 2 đường mạch

Vss – Vdd riêng.

Dủng diode schottky(1N5817, 1N5822…) thay vì các loại nắn dòng (1N4001, 1N4007…)

để dập dòng cảm ứng trong các tải cảm. Có một số linh kiện gọi là tranzorbs, sidactor để dập các

dòng cảm ứng.

Đặt thạch anh sát gần với PIC: Khi thiết kế PCB, nên đặt thạch anh gần với PIC, nhất là

khoảng cách từ chân OSCI đến chân thạch anh phải càng ngắn càng tốt, dao động đi vào chân

này, càng xa càng nhiễu gây mất ổn định cho PIC.

Page 11: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

11

2.Chuẩn ICSP(In-Circurt Serial Programming)

Đây là chuẩn nạp trực tiếp cho vi điều khiển PIC kể cả khi PIC được hàn trên Board, gồm

có 6 chân như theo thứ tự :

Hình 10: Vị trí các chân trong chuẩn ICSP

Chỉ cần 5 chân từ 1 đến 5 là có thể nạp được PIC, tuy nhiên có thêm chân số 6 để đề phòng

trường hợp nếu như cắm ngược, lúc đó chân MCLR/Vpp sẽ đưa vào chân NC, khi thiết bị nạp

chân Chip, nó sẽ nâng điện áp chân MCLR/Vpp lên từ 8-13V, nếu chân MCLR/Vpp nối vào một

I/O bất kỳ, có thể gây hỏng.

Bus nạp cho chuẩn ICSP này ta có thể chọn loại Bus có quy định chiều cắm thì càng tốt.

3.Các tính năng đặc biệt, các bit cấu hình của PIC16F887:

PIC16F887 có một loại các tính năng nhằm tối đa hóa độ tin cậy của hệ thống, giảm thiểu

chi phí qua việc loại bỏ các linh kiện bên ngoài, các tính năng bảo vệ mã, tiết kiệm năng lượng.

Những tính năng đó là:

Reset

Power-on Reset (POR)

Power-up timer (PWRT)

Oscillator Start-up Timer (OST)

Brown-out Reset (BOR)

Interrupts

Watchdog timer (WDT)

Oscillator selection

Sleep

Code protection

ID Locations

In-Circurt Serial Programming

Low-voltage In-Circurt Serial Progrmamming

Page 12: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

12

Một vài tính năng trên sẽ luôn luôn sẵn có, nhưng một vài tính năng khác thì cần phải cấu

hình trong lúc nạp chương trình cho PIC. Cấu hình là việc bật/tắt các bit trong thanh ghi cấu

hình CONFIG1 và CONFIG2 của PIC, thanh ghi này nằm trong bộ nhớ chương trình nên có độ

rộng bằng độ rộng của từ lệnh (14-bits) và được ghi bằng bộ nạp (hay self-write). Các tính năng

đó cũng là tính năng cần thiết để PIC có thể chạy được , do đó trước khi lập trình cần xác định

PIC cần những tính năng gì để tiến hành cấu hình cho nó trước khi chạy. Có 2 cách để thực hiện

công việc cấu hình này, sử dụng từ khóa chỉ dẫn của Hi-tech C để đưa các bit này vào trong

code (file*.hex) và dùng MPLAB để cấu hình. Phần tiếp theo sẽ trình bày về các tính năng của

PIC và cách thức cấu hình bằng Hi-Tech C, phần dùng MPLAB sẽ trình bày sau cùng.

Trước khi thực hiện cấu hình các bit cấu hình cho PIC, cần tham khảo datasheetsPIC

16F887, mục 14.0 special features of the CPU và file pic16f887.h trong thư mục include của

trình biên dịch Hi-Tech C (ví dụ ở phiên bản 9.65 Pro, thư mục mặc định này nằm ở c:\program

Files\Hi-Tech\Software\PICC\PRO\9.65\include\pic16f887.h).

Khi muốn đặt trước các bit cấu hình vào trong chương trình viết bằng Hi-Tech C, từ khóa

để trình dịch biết được để đặt những tùy chọn vào mã là __CONFIG (nhớ là có hai dấu gạch

dưới).

__CONFIG (OPTION & OPTION2 & OPTION3 &…);

__CONFIG (OPTION & OPTION2 & OPTION3 &…);

….

Trong đó các OPTION1,OPTION2 … là những định nghĩa nằm trong file pic16f887.h của

Hi-tech C, được cách nhau bằng dấu „&‟. Từ __CONFIG đầu tiên cấu hình cho thanh ghi

CONFIG1,__CONFIG thứ 2 cấu hình cho thanh ghi CONFIG2

Một chương trình mẫu khi sử dụng các bit cấu hình đặt trong chương trình:

/////////////////////Cấu hình thanh ghi CONFIG1

XT: Dao động thạch anh bên ngoài, 4Mhz

WDTDIS: Tắt chức năng watch-dog

PWRTEN: Mở tính năng Power-up Timer

MCLREN: Mở tính năng master clear từ chân MCLR

UNPROTECH : không bảo vệ mã

DUNPROTECH: Không bảo vệ dữ liệu trong EEPROM

BORDIS: Không sử dụng Brown-out reset

IESODIS: Không sử dụng tính năng Internal External Switchoer

FCMDIS: Không sử dụng tính năng Fail-Safe Clock Monitor

LVPDIS:Không sử dụng tính năng LVP.

/////////////////////Cấu hình thanh ghi CONFIG2

BORV40: Nếu Brown-out Reset được cho phép, thì điện áp Vbor = 4V

Cho phép PIC được ghi lên Flash ( không xuất hiện WP0,WP1, WP2 nghĩa là cho

phép tất cả ).

Page 13: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

13

Thanh ghi cấu hình CONFIG1:

DEBUG: tích cực mức thấp, khi bit này bị xóa(0), chip sẽ hoạt động ở chế độ gỡ rối, chạy

từng bước, truyền thông tin bộ nhớ về thiết bị gỡ rối. Chân RB6/CLK và RB7/DAT hoạt động

với chức năng gỡ rối. Ngược lại, khi bit này bật lên bằng (1), chip không thực hiện tính năng

Debug, thay vào đó RB6/CLK và RB7/DAT hoạt động như một I/O thông thường. Chú ý là bit

này có thể xóa hay bật bởi MPLAB khi chọn chế độ nạp hay gỡ rối trên MPLAB, do vậy trong

quá trình làm việc không nhất thiết quan tâm đến bit này.

Trong Hi-tech C định nghĩa Debug:

// In-Circuit Debugger Mode

#define DEBUGEN 0x1FFF // Enable ICD2 debugging

#define DEBUGDIS 0x3FFF // Disable ICD2 debugging

LVP (Low Voltage Programming): tính năng lập trình điện áp thấp, nghĩa là nạp chip với

điện áp làm việc của nó(5V), khi tính năng này được cho phép (bit được bật(1)) , có thể nạp chip

thông qua ICSP với điện áp nguồn của nó.Khi thực hiện tính năng này, chân RB3/PGM phải

được nối lên Vdd, điều này có nghĩa là không thể sữ dụng RB3 như một I/O, nó phục vụ cho tính

năng LVP và chân MCPR/Vpp phải cấp điện áp VDD. Chú ý : tính năng lập trình điện áp cao

luôn có, với tính năng này , PIC luôn được có thể nạp thông qua cổng ICSP khi điện áp chân

MCLR/Vpp nâng lên khoảng 13V (tùy loại PIC, có loại chỉ có 8V).Thông thường tính năng này

ít sử dụng và được tắt để tận dụng chân RB3 như I/O.

Trong Hi-Tech C định nghĩa như sau:

// Low Voltage Programming

#define LVPDIS 0x2FFF // Disabled

#define LVPEN 0x3FFF // Enabled

FCMEN (Fali safe Clock Monitor Enable ): Tính năng này cho phép PIC tiếp tục hoạt

động nếu nguồn dao động bên ngoài bị hỏng. FSCM có thể dùng với các nguồn dao động ngoài

như: LP , XT, HS, EC, RC và RCIO (tham khảo phần dao động). Nguyên tắc hoạt động, xem

mạch mô tả.

Hình 11: Sơ đồ khối FSCM trong PIC16F887

Page 14: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

14

FSCM phát hiện sự sai khác dao động bằng cách so sánh dao động bên ngoài với dao động

mẫu từ nguồn dao động nội tần số thấp (LFINTOSC) được chia 64. Như hình trên, bên trong

FSCM là một SR Latch, cứ mỗi xung clock bên ngoài đưa vào sẽ bậc ngõ ra Q=1 và cứ khoảng

2ms, dao động mẫu sẽ xóa ngõ ra Q=0; Dao động bên ngoài hỏng sẽ được phát hiện ngay nếu

trong hơn một nữa chu kỳ của dao động mẫu, Q luôn bằng 0.

Hình 12: Quy trình hoạt động khối FSCM

Khi dao động bên ngoài bị hỏng, FSCM sẽ chuyển dao động dùng cho PIC từ nguồn dao

động bên ngoài sang nguồn dao động nội, đồng thời bật cờ OSFIF trong thanh ghi PIR2, sẽ gây

ngắt nếu OSFIF trong thanh ghi PIE2 được cho phép. Dao động nội được dùng cho tới khi nào

nguồn dao động bên ngoài được phục hồi và phần mềm trong PIC chuyển sang dao động ngoài.

Dao động nội được FSCM chọn phục thuộc vào 3 bit IRCF<2:0> trong thanh ghi OSCCON,

nghĩa là FSCM cho phép cấu hình dao động nội trước khi FSCM nhận biết sự hỏng hóc của dao

động bên ngoài.

Khi phần mềm PIC thay đổi nguồn dao động (dao động nội và dao động ngoại), tức là bật,

tắt bit SCS, thì coi như FSCM khởi động lại từ đầu, lúc này bit OSFIF mới được phép xóa.Ngoài

ra, sau khi PIC khởi động từ RESET hay SLEEP, FSCM cũng khởi động.

Định nghĩa trong Hi-Tech C:

// Monitor Clock Fail-safe

#define FCMEN 0x3FFF // Enabled

#define FCMDIS 0x37FF // Disabled

IESO (Internal External Switch Over ): Bit này dùng để cấu hình cho chế độ khởi động 2

tốc độ (Two-speech Start up). Đây là tính năng giúp giảm thiểu năng lượng tiêu hao trên PIC do

quá trình khởi động gây ra bằng cách giảm thiểu độ trễ dao động bên ngoài và quá trình thực thi

mã.Với những ứng dụng thường sử sụng như SLEEP để tiết kiện năng lượng, TSS thực sự hiệu

quả khi mà PIC đi vào SLEEP và thức dậy tử SLEEP một cách nhanh chóng.TSS sẽ sử dụng dao

động nội trong quá trỉnh khởi động, ngay sau khi dao động bên ngoài ổn định, PIC sẽ tự chuyển

sử dụng dao động bên ngoài.

Page 15: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

15

Các bước thực hiện khi sữ dụng TSS:

Cấu hỉnh IESO=1, trong thanh ghi CONFIG1, cấu hình này thực hiện trong quá trình nạp.

SCS=0 (trong thanh ghi OSCCON), chọn nguồn dao động sử dụng lả dao động nội.

FOSC<2:0> phải chọn dao động chính là dao động bên ngoài (LP,XT hat HS).

Định nghĩa IESO trong Hi-Tech C:

// Internal External Switch Over Mode

#define IESOEN 0x3FFF // Enabled

#define IESODIS 0x3BFF // Disabled

BOREN<1:0> (Brown – Out Reset Enable): Đây là tính năng Reset của PIC khi điệp áp nhỏ hơn

một mức nào đó đã được định nghĩa (VBOR). Brown –Out Reset hoạt động như sau:

Hình 13: Sơ đồ tín hiệu điện áp Brown out

Khi điện áp trên chân cấp nguồn (Vdd) nhỏ hơn điện áp VBOR, PIC sẽ bị Reset, quá trình

này giữ khoảng 64ms kể từ lần cuối cùng bị Brown – Out. Cấu hình Brown – out trong thanh ghi

CONFIG1 chia ra làm 4 chế độ:

BOREN<1:0> = 11:Brown – out Reset được cho phép, hoạt động cả khi PIC Sleep, điện

áp VBOR phụ thuộc vào BOR4V ở thanh ghi CONFIG2.

BOREN<1:0> = 10:Brown – out Reset Chỉ hoạt động khi PIC hoạt động, và tắt khi PIC

sleep .

BOREN<1:0> = 01:Brown – out Reset phụ thuộc vào bit SBOREN trong thanh ghi

PCON, bit này có thể bật/tắt bằng phần mềm trong PIC .

BOREN<1:0> = 0:Brown – out Reset không hoạt động.

Page 16: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

16

Định nghĩa Brown – Out Reset trong Hi – tech C:

// Brown Out Detect

#define BORDIS 0x3CFF // BOD and SBOREN disabled

#define SWBOREN 0x3DFF // SBOREN controls BOR function

(Software control)

#define BORXSLP 0x3EFF // BOD enabled in run, disabled in

sleep, SBOREN disabled

#define BOREN 0x3FFF // BOD Enabled, SBOREN Disabled

CPD (Code Protect Data): Bit này tích cực mức thấp, khi cấu hình bằng 0, cho phép bảo vệ

dữ liệu trong EEPROM, sẽ không thể đọc lại dữ liệu EEPROM từ PIC bằng bất cứ chương trình

với sự hỗ trợ của thiết bị nạp nào.

Định nghĩa tring Hi – tech C:

// Data EE Read Protect

#define DUNPROTECT 0x3FFF // Do not read protect EEPROM data

#define CPD 0x3F7F // Read protect EEPROM data

CP(Code Protect): Bảo vệ toàn bộ bộ nhớ chương trình, tích cực mức thấp, khi được xóa

bằng 0, không thể đọc lại nội dung từ bộ nhớ chương trình của PIC.Chú ý: trong quá trình gỡ rối

(Debug), CP không cho phép, MPLAB sẽ cảnh báo và yêu cầu nếu cố tình cho phép CP (CP=0)

trong quá trình gỡ rối.

// Code Protect

#define UNPROTECT 0x3FFF // Code is not protected

#define CP 0x3FBF // Code is protected

#define PROTECT CP //alternate

MCLRE(Master Clear Enable): Đây là tính năng cho phép PIC có thể bị reset bằng chân

MCLR. Khi bit MCLRE(tích cực mức thấp) được cho phép (bị xóa bằng 0), thì chân Master

Clear có thể reset PIC khi được cấp mức 0, và khi PIC hoạt động, phải cấp mức logic1. Mạch

điện trên chân MCLR nên dùng như hình :

Hình 14: Kết nối phần cứng khi sử dụng chế độ Master clear

Page 17: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

17

Khi bit MCLRE không được cho phép (bằng 1), thì chân MCLR không có tính năng reset

PIC, lúc này chân MCLR/RA3 chỉ hoạt động như một ngõ vào.

Định nghĩa trong Hi-Tech C:

// Master Clear Enable

#define MCLREN 0x3FFF // MCLR function is enabled

#define MCLRDIS 0x3FDF // MCLR functions as IO

PWRTEN(Power – up Timer Enable): Tính năng này cho phép giữ PIC reset trong khoảng

64ms từ khi cấp nguồn, hay bị reset bởi Brown – out. Bit này tích cực mức thấp.

// Power Up Timer

#define PWRTDIS 0x3FFF // Off

#define PWRTEN 0x3FEF // On

WDTE (Watchdog Timer Enable): Tích cực mức cao khi được cho phép, Timer Watchdog

sẽ chạy, và sẽ gây reset chip mỗi khi tràn. Nếu không được cho phép thì WDT sẽ bị tắt, đồng

thời được điều khiển bằng phần mềm trong PIC thông qua thanh ghi WDTCON

Hình 15: Khối Watch dog timer trong Vi điều khiển

Sơ lược về tính năng Watchdog: Watchdog timer là một timer có nguồn dao động RC

31Khz độc lập với dao động của PIC, có thể coi đây là mộ timer có thể cấu hình được giá trị nó

đếm, (đếm 32xung tràn (5 bit) hay đếm 65536 xung tràn(16 bit) … ), khi WDT Timer tràn sẽ

Reset PIC. Nếu sử dụng WDT, trong một khoảng thời gian nhất định, nhỏ hơn thời gian tràn của

WDT Timer thì phải xóa bộ đếm của WDT về 0, đều này hữu ích khi PIC bị treo và không thể

xóa bộ đếm của WDT Timer.

Page 18: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

18

Chú ý: Khi dùng Watchdog Timer, thì cần cấu hình thời gian cần thiết để WDT tràn, việc

cấu hình bằng phần mềm trong PIC, tác động lên các bit WDTPS<3:0> trong thanh ghi

WDTCON.

Định nghĩa trong Hi – Tech C:

// Watchdog Timer

#define WDTEN 0x3FFF // On

#define WDTDIS 0x3FF7 // Disabled / SWDTEN control

FOSC<2:0> (Oscliiator Selection): Chọn chế độ dao động chính của PIC, 3 bit FOSC<2:0>

có thể lựa chọn được 8 chế độ. Khi lựa chọn chế độ dao động, cần phải tìm hiểu các chế độ dao

động của: PIC hoạt động như thế nào.

Hình 16: Sơ đồ khối dao động bên trong vi điều khiển

FOSC<2:0>=000:chế độ dao động dùng thạch anh LP(Low power), 2 chân OSC1 và

OSC2 được nối với thạch anh tần số thấp (32Khz).

FOSC<2:0>=001:chế độ dao động dùng thạch anh với độ lợi trung bình XT, sử dụng hai

chân OSC1 và OSC2 nối với thạch anh có tần số nhỏ hơn 10Mhz.

FOSC<2:0>=010:chế độ dao động dùng thạch anh với độ lợi cao HS, sử dụng 2 chân

OSC1 và OSC2 nối với thạch anh có tần số lớn hơn 10 Mhz.

Page 19: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

19

Hình 17: Sơ đồ sử dụng thạch anh ngoài, tần số cao

FOSC<2:0>=011:chế độ dao động từ nguồn xung clock bên ngoài EC(External

Clock).Chân RA6/OSC2/CLKOUT hoạt động như một I/O thông thường, clock đưa vào chân

RA7/OSC1.CLKIN.

Hình 18: Chế độ sử dụng clock ngoài với một chân clock

FOSC<2:0>=100: Chế độ dao động nội INTOSCIO, lúc này dao động được lấy từ nguồn

dao động bên trong PIC, tần số dao động phụ thuộc vào các bit IRCF<2:0> trong thanh ghi

OSCCON, mặc định các bit IRCF<2:0> cấu hình dao động nội là 4Mhz khi Reset.Chân

RA6/OSC2/CLKOUT và RA7/OSCI/CLKIN hoạt động như I/O thông thường.

FOSC<2:0>=101:Chế độ dao động nội INTOSC, tương tự như INTOSCIO, nhưng chân

RA6/OSC2/CLKOUT xuất xung clock ta ngoài với tần số bằng tần số đã chọn chia 4.

FOSC<2:0>=110:Chế độ dao động dùng tụ điện trở bên ngoài RCIO, dao động sẽ được

đưa vào chân RA7/OAC1/CLKI, và chân RA6/OSC2/CLKOUT hoạt động như một I/O thông

thường.

Hình 18: Dao động dùng tụ và điện trở

Page 20: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

20

FOSC<2:0>=111:Chế độ RC, giống như RCIO, tuy nhiên RA6/OSC2/CLKOUT xuất

xung clock bằng xung đưa vào chia 4.

Đối với phần dao động, chú ý đến bit SCS trong thanh ghi OSCCON, bit này có thể thay

đổi bằng phần mềm trong PIC, mặc định SCS = 0. Khi SCS bằng 0, PIC sẽ chạy bằng dao động

định nghĩa bởi FOSC<2:0> trong thanh ghi CONFIG1 như đã bàn ở trên, khi SCS bằng 1, dao

động được sử dụng là dao động nội, và tần số được quyết định bởi IRCF<2:0> trong thanh ghi

OSCCON. Ngoài ra việc cân chỉnh cho dao động nội chính xác thì sử dụng thanh ghi

OSCTUNE.

Định nghĩa trong Hi – TechC:

// Oscillator

#define EXTCLK 0x3FFF // External RC Clockout

#define EXTIO 0x3FFE // External RC No Clock

#define INTCLK 0x3FFD // Internal RC Clockout

#define INTIO 0x3FFC // Internal RC No Clock

#define EC 0x3FFB // EC

#define HS 0x3FFA // HS

#define XT 0x3FF9 // XT

#define LP 0x3FF8 // LP

Page 21: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

21

CHƯƠNG II: XUẤT NHẬP I/O PORT

I.MỤC ĐÍCH THÍ NGHIỆM :

Kiến thức sinh viên cần đạt được sau khi thực tập:

Liệt kê các thanh ghi liên quan đến việc xử lý tín hiệu số ở các chân vi điều khiển .

Khởi tạo các chân của vi điều khiển là ngõ ra , vào số .

Giải thích được công dụng của hàm _delay(n) , cách dùng hàm delay để chống dội cho

nút nhấn.

Lập trình điều khiển led theo yêu cầu .

Giải thích ưu khuyết điểm của ngắt .

II.DỤNG CỤ THÍ NGHIỆM :

Kít thí nghiệm + cáp USB.

Máy tính .

Nguồn 12V/1A.

III.CƠ SỞ LÝ THUYẾT :

1.Thanh ghi qui định tín hiệu xử lý ở chân vi điều khiển là tín hiệu số hay tín hiệu tƣơng

tự:

Hình 19: Các chân có thể xử lý tín hiệu số Hình 20: Các chân có thể xử lý tín hiệu tương tự

Những chân có kí hiệu ANX là những chân vừa có thể xử lý tín hiệu số vừa có thể xử lý tín

hiệu tương tự . Do đó khi làm việc với những chân này ta cần chú ý đến hai thanh ghi :

Page 22: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

22

Hai thanh ghi này có tổng cộng 14bit từ ANS0 đến ANS13 , sẽ quy định tín hiệu làm việc

của các chân từ AN0 đến AN13 là tín hiệu số hay tín hiệu analog .

ANSX=0 : Cho phép chân ANX xử lý tín hiệu số .

ANSX=1 : Cho phép chân ANX xử lý tín hiệu tương tự .

Trong đó : X= 0 – 13

2.Chức năng của thanh ghi TRIS :

Trong các chân xử lý tín hiệu số , hoạt động của chân có thể là ngõ ra (làm cho led chớp tắt,

kích transistor , điều khiển hoạt động IC....) , hay có thể là ngõ vào (đọc trạng thái nút nhấn , đọc

encoder , đọc tín hiệu từ cảm biến số....). Như vậy , để khởi tạo cho các chân là ngõ ra hay ngõ

vào tín hiệu số , chúng ta cần chú ý đến thanh ghi TRISX (X=A,B,C,D,E):

TRISXY=0:Quy định bit thứ Y của PORTX là ngõ ra (0 = Output)

TRISXY=1:Quy định bit thứ Y của PORTX là ngõ vào (1=Input)

(Trong đó :X=A,B,C,D,E ; Y=0-7)

Chú ý : PORTE chỉ có 4 bit thấp : TRISE0, TRISE1, TRISE2 ,TRISE3.

3. Chức năng của thanh ghi PORT :

Trong trường hợp xử lý tín hiệu số và là ngõ ra , thì có thể là ngõ ra mức cao (điện áp ở chân

đó là VH) , hay ngõ ra là mức thấp (điện áp là VL) sẽ do bit RXY của thanh ghi PORTX quy

định .

RXY=0 : Quy định chân thứ Y của PORTX là mức thấp(VL).

Page 23: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

23

RXY=1: Quy định chân thứ Y của PORTX là mức cao(VH).

(Trong đó : X=A,B,C,D,E ; Y=0-7)

Tóm lại ta có bảng tóm tắt sau :

ANSX TRISXY RXY Kết quả

0 0 0 Ngõ ra mức thấp(0V)

0 0 1 Ngõ ra mức cao(+5V)

0 1 0 Tổng trở cao (R=∞)

0 1 1 Ngõ vào , tác động mức thấp

1 1 x Xử lý tín hiệu tương tự .

Hình 21: Ứng dụng xử lý tín hiệu số

4.Những thanh ghi đặc biệt chỉ có riêng ở PORTB:

4.1.Thanh ghi hỗ trợ điện trở treo bên trong:

Để tránh trạng thái thả nổi (tín hiệu điện áp ở chân đó không rõ ràng) khi khởi tạo PORTB là

ngõ vào số , PIC16f887 tích hợp thêm vào cho PORTB các điện trở kéo lên (pull-up), để sử dụng

các điện trở này ta chú ý đến thanh ghi :

WPUBy=0: Không cho phép điện trở kéo lên ở chân thứ y của PORTB.

WPUBy=1: Cho phép điện trở kéo lên ở chân thứ y của PORTB.

Khi sử dụng điện trở kéo lên ngoài việc sử dụng thanh ghi WPUB còn phải khởi tạo bit:

RBPU

Page 24: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

24

Điện trở kéo lên nên khởi tạo khi PORTB là ngõ vào số , các PORT khác không có hỗ

trợ điện trở treo trong , do đó nếu có nhu cầu sử dụng ta có thể mắc thêm điện trở bên

ngoài.

4.2.Ngắt ngoài ở chân RB0:

Để xử lý được các tín hiệu tác động tức thời (cạnh lên hay cạnh xuống), chân RB0 có hỗ trợ

xử lý ngắt (interrupt ) kí hiệu ở chân là INT, khởi tạo ngắt ngoài ở chân RB0 ta cần chú ý đến

các bit sau :

INTE(Interrupt enable ) : bit cho phép ngắt ở PORTB

INTF(Interrupt flag): cờ ngắt , bit này tự động bằng 1 khi có sự kiện ngắt (cạnh lên hay

cạnh xuống) xảy ra ở chân RB0, ta phải xóa bít này trong khi lập trình .

GIE(Global interrupt ) : bit cho phép ngắt toàn cục.

INTEDG (interrupt edge select bit ) : Bit chọn cạnh tác động để sinh ra sự kiện ngắt ở

RB0.

INTEDG=1: Xảy ra ngắt khi có tín hiệu cạnh lên ở RB0

INTEDG=0: Xảy ra ngắt khi có tín hiệu cạnh xuống ở RB0

Hình 22: Sơ đồ ngắt INT ở chân RB0

Các bƣớc khởi tạo ngắt INT:

Bước 1 : Khởi tạo chân RB0 là ngõ vào số , điện trở treo.

Bước 2 : Khởi tạo ngắt INT

INTE=1; //Cho phép ngắt hoạt động

INTF=0; //Xóa cờ ngắt thì ngắt lần tiếp theo mới có thể xảy ra.

INTEDG=....; //Chọn cạnh tác động ngắt.

GIE=1; //Cho phép ngắt toàn cục .

4.3.Ngắt on-change ở PORTB:

Ngoài ngắt INT chỉ có duy nhất ở chân RB0 , thì cả PORTB (từ RB0 đến RB7) còn hỗ trợ

ngắt on-change , ngắt on-change xảy ra khi tín hiệu logic ở chân của PORTB thay đổi trạng thái

logic.

Page 25: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

25

Sơ đồ ngắt on-change:

Hình 23: Sơ đồ ngắt on-change ở PORTB

Các thanh ghi và các bit điều khiển ngắt on-change :

IOCBX=0 : Không cho phép ngắt on-change ở chân thứ X của PORTB.

IOCBX=1 : Cho phép ngắt on-change ở chân thứ X của PORTB.

Các bit khởi tạo khác :

RBIF : Cờ ngắt on-change ở PORTB, cần phải xóa bít này trong lập trình.

RBIE : Bit cho phép ngắt on-change của PORTB.

GIE : Bit cho phép ngắt toàn cục.

Các bƣớc khởi tạo ngắt on-change :

Bước 1 : Khởi tạo PORTB là ngõ vào số , có điện trở treo.

Bước 2 : Khởi tạo ngắt on-change ở PORTB

IOCB=0xFF; //khởi tạo toàn bộ PORTB ngắt on-change(có thể khởi tạo

một hay cả PORTB).

RBIE=1; //Cho phép ngắt xảy ra .

RBIF=0; //Xóa cờ ngắt

GIE=1; //Cho phép ngắt toàn cục

Chú ý : Đối với ngắt on-change , việc xóa cờ ngắt (RBIF=0) không đủ để cho lần ngắt

tiếp theo được thực hiện , mà còn phải thêm điều kiện đọc hoặc viết vào thanh ghi PORTB.

Page 26: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

26

Ví dụ :

unsigned char bien ;

bien = PORTB ; //đọc thanh ghi PORTB.

hoặc PORTB = 5 ; //viết vào thanh ghi PORTB

4.4.Bảng so sánh giữa ngắt INT và ngắt on-change :

Ngắt ở chân INT(RB0) Ngắt on-change

Chí có duy nhất ở chân RB0 Xảy ra trên cả PORTB

Để xảy ra ngắt thì tín hiệu logic là cạnh lên

hoặc cạnh xuống.

Chỉ cần tín hiệu logic thay đổi là xảy ra ngắt,

không phân biệt cạnh lên hay cạnh xuống.

Các bit khởi tạo :

INTE , INTF , INTEDG , GIE

Các bit khởi tạo :

IOCBx , RBIE , RBIF , GIE

Để cho lần ngắt tiếp theo được thực hiện thì

cần phải xóa cờ ngắt INTF.

Để cho lần ngắt tiếp theo được thực hiện thì

cần phải xóa cờ ngắt INTF và đọc ( hoặc ghi)

vào thanh ghi PORTB.

IV.BÀI TẬP THỰC HÀNH :

Bài 1: Viết chương trình điều khiển led theo yêu cầu sau :

Nhấn (không giữ) nút nhấn nối với chân RB0 : led RE1 và led RE2 chớp tắt xen kẽ trong

thời gian T=0.2(s).

Nhấn (không giữ) nút nhấn nối với chân RB1 : led RE1 và led RE2 cùng chớp tắt trong

thời gian T=0.5(s).

Nhấn (không giữ) nút nhấn nối với chân RB2 : led RE1 sáng và led RE2 tắt trong thời

gian T=0.1(s) , led RE1 tat và LED2 sáng T=0.7(s).

Sử dụng định thời bằng hàm _delay(n) ; thạch anh Fosc = 4 Mhz.

Sơ đồ phần cứng :

Page 27: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

27

*Bƣớc 1: Tạo một project mới với tên 01_01_MSSV .

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành các dấu …….

#include<htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

void delay(unsigned char counter); //Khai báo chương trình con hàm delay

void RB_0( );void RB_1( );void RB_2( );

char so_lan_nhan;

void main( ) //Chương trình chính

{

//Disable analog ở các chân RE1,RE2,RB0,RB1,RB2

ANS6=ANS7=ANS12=ANS10=ANS8= …….;

//Khởi tạo các chân RE1,RE2 là ngõ ra , ban đầu led tắt

TRISE1=TRISE2= …….; RE1=RE2= ……. ;

//Khởi tạo chân RB0,RB1,RB2 là ngõ vào, tác động mức thấp

TRISB0=TRISB1=TRISB2= …….; RB0=RB1=RB2= …….;

//Khởi tạo điện trở kéo lên ở các chân RB0,RB1,RB2

WPUB0=WPUB1=WPUB2= …….; RBPU= ……. ;

//(-------------1------------)

while(1)

{

//Xác định trạng thái các nút nhấn

if(!RB0)so_lan_nhan=0; //(------------2-----------)

else if(!RB1)so_lan_nhan=1; //(------------3-----------)

else if(!RB2)so_lan_nhan=2; //(------------4-----------)

//Hiển thị led

if (so_lan_nhan==0) RB_0( );//Chạy chương trình con RB_0

else if(so_lan_nhan==1) RB_1( ); //Chạy chương trình con RB_1

else if(so_lan_nhan==2) RB_2( ); //Chạy chương trình con RB_2

}

}

//(-------------5-----------)

void delay(unsigned char counter) //Chương trình con làm tăng thời gian delay

{

unsigned char value=0;

while(counter>value)

{

value++;

_delay(100000); //trễ 1ms với Fosc = 4MHz

}

}

void RB_0( )

{

RE1^=1;RE2= …….RE1; // led RE1 và led RE2 chớp tắt xen kẽ

Page 28: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

28

delay(2); //delay 0.2s

}

void RB_1( )

{

RE1^=1;RE2 …….RE1; // led RE1 và led RE2 cùng chớp tắt

delay(5); //delay 0.5s

}

void RB_2( )

{

RE1= …….;RE2= …….; // led RE1 sáng và led RE2 tắt

delay(1); //delay 0.1s

RE1= …….;RE2= …….; // led RE1 tat và LED2 sáng

delay(7); //delay 0.7s

}

*Bƣớc 3: Biên dịch chương trình, nạp xuống kít thí nghiệm , tiến hành nhấn các nút nhấn và

quan sát 2 led.

*Bƣớc 4: Thay đổi chương trình như sau:

Thêm vào dòng : (-------------1------------) đoạn code sau:

IOCB0=IOCB1=IOCB2=1; //Cho phép ngắt onchange ở chân B0,B1,B2

RBIE=1; //Cho phép ngắt onchange toàn PORTB

RBIF=0; //Reset cờ ngắt

PEIE=1; //Cho phép ngắt ngoại vi

GIE=1; //Cho phép ngắt toàn cục

Xóa các dòng 2,3,4.

Thêm vào dòng: (-------------5-----------) đoạn code sau:

void interrupt isr( ) //Chương trình con xử lý tất cả ngắt

{

if(RBIE&&RBIF) //Chương trình con cho ngắt on-change

{

if(!RB0) so_lan_nhan=0; //nhấn RB0

else if(!RB1) so_lan_nhan=1; //nhấn RB1

else if(!RB2) so_lan_nhan=2; //nhấn RB2

RBIF=0; //Reset cờ ngắt

}

}

*Bƣớc 5: Biên dịch chương trình, nạp xuống kít thí nghiệm , tiến hành nhấn các nút nhấn và

quan sát 2 led.

*Bƣớc 6: Nhận xét sự khác nhau về tốc độ đáp ứng khi nhấn nút nhấn trước và sau khi sửa code,

giải thích, rút ra kết luận:

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Page 29: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

29

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Bài 2 : Viết chương trình điều khiển led theo yêu cầu sau :

Nhấn (không giữ) nút nhấn nối với chân RB0 lần (2n+1) : 8 led dịch từ trái qua phải.

Nhấn (không giữ) nút nhấn nối với chân RB0 lần (2n) : 8 led dịch từ phải qua trái.

n = 0,1,3,4,5…k

Sử dụng định thời bằng hàm _delay(n) ; thạch anh Fosc = 4 Mhz.

Sơ đồ phần cứng :

*Bƣớc 1: Tạo một project mới với tên 01_02_MSSV.

*Bƣớc 2 : Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

char count=0;

void display(char number);

void main( )

{

Page 30: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

30

char i=0;

//Disable analog các chân RE1,RE2,RB0,RB3,RB4,RB5

ANS6=ANS7=ANS9=ANS11=ANS12=ANS13=…….;

//Khởi tạo RE1 , RE2 là ngõ ra , trạng thái ban đầu led tắt

TRISE1=TRISE2=…….; RE1=RE2=…….;

//Khởi tạo RB0 là ngõ vào , tác động mức thấp

TRISB0=…….; RB0=…….;

//Cho phép điện trở kéo lên ở chân RB0;

IOCB0=…….; RBPU=…….;

//Khởi tạo ngắt ngoài ở chân RB0 .

INTEDG=..........; //cạnh lên

INTE =…….;

INTF =…….;

GIE =…….;

while(1)

{

while(count==1) //Chương trình dịch từ trái qua phải.

{

i++;

if(i>=9)

i=1;

display(i);

_delay(100000);

}

while(count==2) //Chương trình dịch từ phải qua trái.

{

i--;

if(i<=0)

i=9;

display(i);

_delay(100000);

}

}

}

void interrupt isr( )

{

if(INTE&&INTF)

{

count++;

if(count…….3)count=1;

INTF=…….;

}

}

void display(char number) //Chương trình con hiển thị led khi nhận vào một số tương ứng

Page 31: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

31

{

RE1=RE2=…….; //Tắt led RE1, RE2

TRISB |= 0b00111000;

RB3=RB4=RB5=…….; //Khởi tạo chân RB3 , RB4 , RB5 là tổng trở cao

switch(number)

{

case 1:

RE2=…….; //RE2 sáng

break;

case 2:

RE1=…….; //RE1 sáng

break;

case 3: //led D6 sáng

TRISB3=0;RB3=…….;TRISB4=…….;RB4=0;

break;

case 4: //led D7 sáng

TRISB3=…….;RB3=0;TRISB4=…….;RB4=1;

break;

case 5: //led D8 sáng

TRISB4=…….;RB4=1;TRISB5=…….;RB5=0;

break;

case 6: //led D9 sáng

TRISB4=…….;RB4=0;TRISB5=…….;RB5=1;

break;

case 7: //led D10 sáng

TRISB5=0;RB5=…….;TRISB3=0;RB3=…….;

break;

case 8: //led D11 sáng

TRISB5=0;RB5=…….;TRISB3=0;RB3=…….;

break;

}

}

*Bƣớc 3: Biên dịch chương trình , nạp xuống kít thí nghiệm , tiến hành nhấn nút nhấn và quan

sát các led.

*Bƣớc 4:Trả lời câu hỏi :

Đề ra các phương pháp xử lý khi ngõ vào tác động mức cao :

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Page 32: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

32

V.BÀI TẬP TỰ GIẢI :

Bài 3.Viết chƣơng trình đọc giá trị phím và hiển thị giá trị lên led 7 đoạn theo sơ đồ phần

cứng sau : (Tạo một project mới với tên 01_03_MSSV)

(Phím từ 0-9 , led hiển thị số tương ứng , phím „*‟ thể hiện chữ „S‟, phím „#‟ thể hiện chữ

„H‟, lúc không nhấn thể hiện chữ „U‟ ).

Bài 4.Viết chƣơng trình theo yêu cầu sau , 16 led kết nối với PORTD, PORTC (tác động

mức cao) , 8 nút nhấn kết nối với PORTB : (Tạo một project mới với tên 01_04_MSSV)

Nhấn nút RB0 :16 led dịch từ phải qua trái.

Nhấn nút RB1:16 led dịch từ trái qua phải.

Nhấn nút RB2:16 led chớp tắt xen kẽ.

Nhấn nút RB3:16 led sáng dần từ trái qua phải .

Nhấn nút RB4 :16 led sáng dần từ phải qua trái.

Nhấn nút RB5:16 led sáng dần từ trong ra ngoài.

Nhấn nút RB6:16 led sáng dần từ ngoài vào trong .

Nhấn nút RB7:16 led cùng chớp tắt.

Bài 5.Viết chƣơng trình đếm số lần nhấn nút (RB0) và hiển thị từ 000 đến 255 lên 3 led bảy

đoạn theo sơ đồ phần cứng sau : (Tạo một project mới với tên 01_05_MSSV)

Page 33: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

33

CHƯƠNG III: ADC MODULE

I.MỤC ĐÍCH THÍ NGHIỆM :

Kiến thức sinh viên cần đạt được sau khi thực tập :

Giải thích được khái niệm và chức năng của điện áp tham chiếu.

Thiết lập được điện áp tham chiếu trong và ngoài cho khối ADC của vi điều khiển.

Liệt kê được các bước thiết lập đo ADC cho một hoặc nhiều kênh.

Thiết lập được công thức tính ADC 8-bit , và ADC 10-bit ở chế độ định dạng canh trái và

canh phải .

Tín toán được giá trị tín hiệu tương tự thu được thông qua giá trị của thanh ghi ADRESL,

ADRESH.

Thiết lập và khởi tạo được một project có liên quan LCD , thay đổi file LCD.h phù hợp

với cấu hình phần cứng bên ngoài .

II.DỤNG CỤ THÍ NGHIỆM:

Kít thí nghiệm + cáp USB.

Vít (vặn biến trở).

Máy tính .

Nguồn 12V/1A.

III.CƠ SỞ LÝ THUYẾT :

1.Tín hiệu tƣơng tự và tín hiệu số :

Tín hiệu tƣơng tự Tín hiệu số

Hình 24: Đồ thị tín hiệu tương tự và tín hiệu số

Trong thực tế , tín hiệu cần xử lý xung quanh ta là tín hiệu tương tự , ví dụ : vận tốc , nhiệt

độ , độ ẩm , cường độ ánh sáng , áp suất v.v...Tuy nhiên vi xử lý chỉ có thể làm việc với tín hiệu

số (chỉ có hai trạng thái 0 và 1) do đó để xử lý được các tín hiệu tương tự , thì vi điều khiển cần

phải có bộ chuyển đổi tín hiệu tương tự sang số ADC (Analog to Digital Converter).

Page 34: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

34

Hình 25: Bộ ADC được tích hợp bên trong vi điều khiển

Hình 26: Đồ thị của bộ chuyển đổi ADC 8-bit:

Độ phân giải (Resolution) : Từ sơ đồ trên ta thấy bộ chuyển đổi ADC có độ phân giải 8-

bit thì sẽ có 256 giá trị dùng để chứa các giá trị điện áp từ VREF- đến VREF+ , như vậy nếu bộ

chuyển đổi ADC có độ phân giải n bit thì sẽ có 2n giá trị . Độ phân giải có liên quan mật thiết

đến chất lượng chuyển đổi ADC , độ phân giải càng cao thì kết quả chuyển đổi càng chính xác .

Điện áp tham chiếu (Reference voltage) : điện áp tham chiếu là điện áp dùng để so sánh

với tín hiệu điện áp analog cần đo , VREF+ nên chọn bằng với mức điện áp lớn nhất cần đo ,

không nên chọn nhỏ hơn hay lớn hơn .

2.ADC của vi điều khiển PIC16F887:

2.1Các chân vi điều khiển có khả năng xử lý tín hiệu analog :

VREF+ VREF-

255

0

Tín hiệu tương tự

Tín hiệu số

Page 35: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

35

Hình 27: Các chân có thể làm việc với tín hiệu analog

Hình 28: Sơ đồ khối bộ ADC trong vi điều khiển PIC16F887.

2.2Các thanh ghi điều khiển hoạt động chuyển đổi của bộ ADC :

ADON : Bit cho phép bộ ADC hoạt động

ADON=1 : Cho phép bộ ADC hoạt động

ADON=0 : Không cho phép hoạt động

GO/𝐃𝐎𝐍𝐄 : Bit chỉ trạng thái chuyển đổi , bit này tự động bằng 0 khi bộ ADC chuyển đổi xong,

muốn cho lần chuyển đổi tiếp theo được thực hiện , cần phải đặt bit này lên bằng 1 trong lập

trình .

Page 36: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

36

CHS<3:0>: Dùng để chọn kênh cần chuyển đổi .

ADCS<1:0> : Bit lựa chọn tần số chuyển đổi .

VCFG1 : Dùng để chọn điện áp tham chiếu VREF- .

VCFG1=1: khi đó VREF-= điện áp ở chân số 4 (VREF-)

VCFG1=0: khi đó VREF- = Vss

VCFG0 : Dùng để chọn điện áp tham chiếu VREF+.

VCFG0=1: khi đó VREF+= điện áp ở chân số 5 (VREF+)

VCFG0=0: khi đó VREF+= VDD

ADFM : bit dùng để lựa chọn kiểu định dạng kết quả chuyển đổi :

Sau khi chuyển đổi hoàn tất , kết quả sẽ được lưu theo một trong hai kiểu

Page 37: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

37

Hai thanh ghi ADRESH và ADRESL là hai thanh ghi dùng để chứa kết quả khi bộ ADC

chuyển đổi hoàn tất , bộ ADC của vi điều khiển PIC16F887 có độ phân giải 10-bit do đó cần hai

byte để chứa kết quả, tuy nhiên kết quả có thể lưu theo hai kiểu : canh trái (ADFM=0) và canh

phải (ADFM=1).

Đối với định dạng kết quả bên trái : ADFM=0 thì ta có thể đọc kết quả như sau :

Độ phân giải 10-bit : Kết quả = ADRESH*4+ADRESL >> 6 (1)

Độ phân giải 8-bit : Kết quả = ADRESH (2)

Đối với định dạng kết quả bên phải : ADFM=1 thì ta có thể đọc kết quả như sau :

Độ phân giải 10-bit : Kết quả = ADRESH*256+ADRESL (3)

Độ phân giải 8-bit : Kết quả = ADRESH*64+ADRESL>>2 (4)

Rõ ràng ta thấy biểu thức (1) và (4) gây khó khăn trong việc lập trình và thời gian cần tín

toán lâu hơn , do đó ta rút ra kết luận:

Khi cần đọc ADC 8-bit thì cần định dạng kết quả bên trái(ADFM=0)

Khi cần đọc ADC 10-bit thì cần định dạng kết quả bên phải(ADFM=1)

2.3 Ngắt ADC :

Khối ADC cũng có thể tạo ra sự kiện ngắt (ngắt trong) , sự kiện ngắt xảy ra khi bộ ADC

chuyển đổi hoàn tất .

Hình 29: Sơ đồ khởi tạo ngắt ADC

ADIE : Bit cho phép bộ chuyển đổi ADC.

ADIF : Cờ ngắt ADC , bit này tự động bằng 1 khi bộ ADC chuyển đổi hoàn tất , để cho

lần chuyển đổi tiếp theo được thực hiện , chúng ta cần phải xóa bít này bằng phầm mềm lập

trình.

PEIE : Bit cho phép ngắt ngoại vi .

GIE : Bit cho phép ngắt toàn cục.

2.4 Các bƣớc khởi tạo bộ chuyển đổi ADC:

Bước 1:Chọn tín hiệu xử lý

Khởi tạo chân là ngõ vào: TRISxy=1; //x:A,B,E , y:0-7

Khởi tạo chân xử lý tín hiệu tương tự : ANSx=1; //Trong đó : x=0-13

Bước 2:Khởi tạo khối ADC

Chọn tần số chuyển đổi ADCS1=.........;ADCS0=........;

Page 38: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

38

Chọn điện áp tham chiếu VCFG1=......; VCFG0=.........;

Chọn kênh cần đo .

CHS3=....;CHS2=.....;CHS1=.....;CHS0=.....;

Chọn định dạng kết quả ADFM=......;

Cho phép module ADC ADON=1;

Bước 3: Khởi tạo ngắt ADC(có thể bỏ qua bước này nếu không sử dụng ngắt):

Xóa cờ ngắt: ADIF=0;

Cho phép ngắt ADC: ADIE=1;

Cho phép ngắt ngoại vi: PEIE=1;

Cho phép ngắt toàn cục : GIE=1;

Bước 4:Chờ thời gian khởi tạo.

Bước 5:Bắt đầu cho phép chuyển đổi . GODONE=1;

Bước 6:Chờ cho bộ ADC chuyển đổi hoàn tất bằng các dấu hiệu sau :

Bit GODONE tự động xuống 0 , ta có thể sử dụng code sau để thực hiện việc chờ:

while(GODONE) ;

Ngắt ADC xảy ra.(Nếu bước 3 được thực hiện)

Bước 7 : Đọc kết quả

ADC 8-bit : kết quả = ADRESH //canh trái

ADC 10-bit : kết quả = ADRESH*64+ADRESL //canh phải

Bước 8:Xóa cờ ngắt cho lần chuyển đổi tiếp theo (Nếu bước 3 được thực hiện)

ADIF=0;

3.Làm việc với LCD 16x2 :

Để vi điều khiển PIC16F887 giao tiếp được với LCD đòi hỏi trong code chương trình cần

phải có những dòng lệnh phù hợp lcd , thường những yêu cầu lệnh này được quy định bởi chip

xử lý bên trong lcd , do đó để chương trình ngắn gọn và đơn giản , ta thường xây dựng file lcd.c

và lcd.h là những file chứa sẵn những chương trình con có những câu lệnh giao tiếp với lcd , ta

chỉ cần khai báo hai file lcd.c và lcd.h thì có thể dễ dàng giao tiếp với lcd bằng những câu lệnh

bên trong file đó. Các bước khởi tạo và làm việc với LCD :

− Bước 1 : Kiểm tra phần cứng , phải phù hợp với những khai báo trong file LCD.h

− Bước 2 : Copy 2 file LCD.c và LCD.h vào thư mục của project đang lập trình .

− Bước 3 : Add hai file trên vào Header file và Source file .

− Bước 4 : Tối thiểu cần phải khai báo 2 dòng lệnh sau (tô đen) trong chương trình khi có

liên quan tới file LCD:

Page 39: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

39

#include<htc.h>

__CONFIG(…….);

#include “lcd.h” //khai báo thư viện hàm lcd.h

void main( )

{

lcd_init( ); //lệnh khởi tạo lcd

while(1)

{

}

}

*Ngoài ra còn có thể sử dụng hàm printf nhưng cần khai báo như sau :

#include<htc.h>

#include<stdio.h> //khai báo thư viện cho hàm printf

__CONFIG(…….);

#include “lcd.h” //khai báo thư viện hàm lcd.h

void main( )

{

lcd_init( ); //lệnh khởi tạo lcd

printf(“In gia tri :%3d ”, bien2); //Hiển thị chuỗi In gia tri : 6

printf(“In gia tri :%03d ”, bien2); //Hiển thị chuỗi In gia tri :006

printf(“In gia tri :%5.3d ”, bien2); //Hiển thị chuỗi In gia tri : 006

printf(“In gia tri :%f ”, bien1); //Hiển thị chuỗi In gia tri :19.6666

printf(“In gia tri :%3.2f ”, bien1); //Hiển thị chuỗi In gia tri : 19.67

printf(“In gia tri :%d ”, bien3); //Hiển thị chuỗi In gia tri :-5536

printf(“In gia tri :%ld ”, bien3); //Hiển thị chuỗi In gia tri :60000

//Các lệnh được sử dụng cho lcd có thể tham khảo trong file LCD.c ví dụ :

lcd_gotoxy(x,y); //Lệnh này dùng để di chuyển con trỏ đi đến các vị trí trên màn hình lcd,

trong đó x là giá trị của hàng ngang (x=[0,1]) , y là giá trị của hàng dọc(y=[0,15]).

lcd_putc(„kí tự cần in‟); //Lệnh này dùng để in kí tự lên màn hình lcd tại vị trí con trỏ .

lcd_puts(“chuỗi cần in”); //Lệnh này dùng để in chuỗi lên màn hình lcd tại vị trí con trỏ ,

chú ý chuỗi cần in nằm giữa hai dấu “ ” và kí tự cần in nằm giữa hai dấu „ ‟ .

lcd_putc(„\f‟) ; //xóa màn hình lcd , sau đó con trỏ trở về vị trí (0,0).

Page 40: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

40

while(1);

}

void putch(char ki_tu)

{

lcd_putc(ki_tu);

}

Chú ý : Khi viết chương trình có liên quan lcd mà phần cứng thực tế không có lcd hay

lcd kết nối không đúng với thư viên lcd.h thì con trỏ chương trình sẽ dừng ngay lệnh lcd_init();

IV.BÀI TẬP THỰC HÀNH :

Bài 1: Viết chương trình đọc ADC 8 bit ở chân AN3 và thực hiện theo yêu cầu sau :

Hiển thị giá trị thanh ghi ANSEL ở hàng (0,0) của LCD.

Hiển thị giá trị điện áp chân AN3 ở hàng (0,1) của LCD.

Định thời bằng hàm delay , điện áp tham chiếu trong , Fosc = 4Mhz , giao tiếp LCD

bằng thư viện LCD.h

Sơ đồ phần cứng :

*Bƣớc 1 : Tạo một project mới với tên 02_01_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

#include<stdio.h> //thư viện cho hàm printf( );

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

char bien2=6;

float bien1=19.66667 ;

unsigned int bien3=60000;

printf(“In ra man hinh ”); //Hiển thị chuỗi In ra man hinh

printf(“In ra \n man hinh ”); //Hiển thị chuỗi In ra

man hinh

printf(“In gia tri :%d ”, bien2); //Hiển thị chuỗi In gia tri :6

printf(“In gia tri :%3d ”, bien2); //Hiển thị chuỗi In gia tri : 6

printf(“In gia tri :%03d ”, bien2); //Hiển thị chuỗi In gia tri :006

printf(“In gia tri :%5.3d ”, bien2); //Hiển thị chuỗi In gia tri : 006

printf(“In gia tri :%f ”, bien1); //Hiển thị chuỗi In gia tri :19.6666

printf(“In gia tri :%3.2f ”, bien1); //Hiển thị chuỗi In gia tri : 19.67

printf(“In gia tri :%d ”, bien3); //Hiển thị chuỗi In gia tri :-5536

printf(“In gia tri :%ld ”, bien3); //Hiển thị chuỗi In gia tri :60000

Page 41: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

41

#include"lcd.h";

void main( )

{

lcd_init( ); //Khởi tạo LCD

ANS3=…….; //Enable analog ở chân RA3

TRISA3=…….;RA3=…….; //Khởi tạo RA3 là ngõ vào

VCFG0=VCFG1=…….; //Chọn điện áp tham chiếu trong

CHS3=CHS2=…….;CHS1=CHS0=…….; //Chọn kênh đo là AN3

ADFM=…….; //Định dạng dữ liệu canh trái , bởi vì chỉ sử dụng ADC 8 bit

ADCS0=ADCS1=…….; //Tần số chuyển đổi

ADON=…….; //Enable module ADC hoạt động

while(1)

{

GODONE=…….; //Cho phép ADC bắt đầu chuyển đổi

while(GODONE) ……. //Chờ bộ ADC chuyển đổi xong

lcd_gotoxy(0,0);

printf("\fADRESH :%d",ADRESH);

lcd_gotoxy(0,1);

printf("Dien ap :%3.2f",ADRESH*5.0/255.0);

_delay(100000);

}

}

void putch(char c) //Hỗ trợ cho hàm printf in ra LCD

{

lcd_putc(c);

}

*Bƣớc 3: Biên dịch chương trình , nạp xuống kít thí nghiệm , jum header 3 ở vị trí POT , dùng

vít vặn biến trở và quan sát kết quả trên LCD.

*Bƣớc 4:Thiết lập công thức quan hệ giữa điện áp và giá trị thanh ghi ADRESH .

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Bài 2: Viết chƣơng trình đọc ADC 10 bit ở hai kênh AN3 , AN12 và thực hiện theo yêu cầu

sau :

Hiển thị giá trị điện áp tại chân AN3 ở hàng (0,0) của LCD.

Hiển thị giá trị điện áp tại chân AN12 ở hàng (0,1) của LCD.

Định thời bằng hàm delay , điện áp tham chiếu trong , Fosc = 4Mhz, giao tiếp LCD

bằng thư viện LCD.h

Page 42: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

42

Sơ đồ phần cứng :

*Bƣớc 1 : Tạo một project mới với tên 02_02_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

#include<stdio.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

#include "lcd.h"

void main( )

{

unsigned char old_ADRESH;

lcd_init( );

ANS3= …….;ANS12= …….; //Enable analog ở chân RA3 và chân RB0

TRISA3= …….;RA3= …….;TRISB0=1;RB0=1; //Khởi tạo RA3,RB0 là ngõ vào

VCFG0=VCFG1= …….; //Chọn điện áp tham chiếu trong

ADFM= …….; //Định dạng kết quả bên phải (ADC 10 bit)

ADCS0=ADCS1=0; //Tần số chuyển đổi

ADON= …….; //Enable module ADC

while(1)

{

CHS3=CHS2= …….;CHS1=CHS0= …….; //Chọn kênh AN3

GODONE= …….;

while(GODONE);

lcd_gotoxy(0,0);

printf("\fAN3 la:%d",ADRESH*256+ADRESL);

_delay(100000);

CHS3=CHS2= …….;CHS1=CHS0= …….; //chon kenh AN12

GODONE= …….;

Page 43: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

43

while(GODONE);

lcd_gotoxy(0,1);

printf("AN12 la:%d",ADRESH*256+ADRESL);

_delay(100000);

}

}

void putch(char c)

{

lcd_putc(c);

}

*Bƣớc 3 : Jum header 3 ở vị trí BUTTON

Nhấn giữ nút nhấn SW2 và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả đo kênh

AN3.

Nhấn giữ nút nhấn SW3và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả đo kênh

AN3.

Nhấn giữ cả hai nút SW2,SW3 và quan sát kết quả trên LCD ở vị trí (0,0) tức là kết quả

đo kênh AN3.

Dựa vào mạch điện nguyên lý, chứng minh cả 3 kết quả quan sát được .

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

*Bƣớc 4 : Quan sát kết quả ở hàng (0,1) của lcd , tức là kết quả đo được ở kênh AN12 khi có

nhấn nút RB0 và khi không có nhấn nút và nhận xét :

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Page 44: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

44

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

V.BÀI TẬP TỰ GIẢI :

Bài 3 : Viết chƣơng trình sử dụng khối ADC của vi điều khiển PIC16F887 đo nhiệt độ của

5 phòng và hiển thị lên LCD, sử dụng LM35 theo yêu cầu sau :

(Tạo một project mới với tên 02_03_ MSSV)

Khi nhấn (không giữ )RB0 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 1.

Khi nhấn (không giữ )RB1thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 2.

Khi nhấn (không giữ )RB2 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 3.

Khi nhấn (không giữ )RB3 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 4.

Khi nhấn (không giữ )RB4 thì LCD hiển thị giá trị giá trị nhiệt độ của phòng 5.

Tần số hoạt động Fosc = 4MHz , phần cứng LCD được kết nối với PORTD của Vi Điều khiển

theo sơ đồ chân của thư viện lcd.h , điện áp tham chiếu bên trong , sử dụng ADC 8 bit .

Bài 4:Viết chƣơng trình đọc giá trị điện áp ở chân AN0 và hiển thị lên LCD 16x2 theo yêu

cầu sau : (Tạo một project mới với tên 02_04_ MSSV)

Hiển thị giá trị hai thanh ghi ADRESH và ADRESL ở vị trí (0,0) của LCD.

Hiển thị giá trị điện áp đo được ở vị trí (0,1) của LCD .

Page 45: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

45

Tần số hoạt động Fosc = 4MHz , phần cứng LCD được kết nối với PORTD của Vi Điều

khiển theo sơ đồ chân của thư viện lcd.h , điện áp tham chiếu bên ngoài , sử dụng ADC 10 bit .

Bài 5 : Viết chƣơng trình dùng vi điều khiển PIC16F887 thực hiện chức năng nhƣ một

máy tính theo sơ đồ phần cứng sau : (Tạo một project mới với tên 02_05_ MSSV)

Page 46: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

46

CHƯƠNG IV: TIMER

I.MỤC ĐÍCH THÍ NGHIỆM :

Kiến thức sinh viên cần đạt được sau khi thực tập :

− Giải thích được nguyên tắc hoạt động của timer0 , timer1 , timer 2.

− Thiết lập công thức tính định thời của từng timer .

− Liệt kê các bit điều khiển từng hoạt động của timer .

− Phân biệt sự khác nhau và giống nhau giữa hai chế độ timer và counter trong timer 0 ,

timer1.

− Giải thích chức năng của bộ chia trong timer .

− Khởi tạo ngắt cho timer0 , timer 1 , timer 2 .

II.DỤNG CỤ THÍ NGHIỆM:

Kít thí nghiệm + cáp USB.

Máy tính .

Nguồn 12V/1A.

Oscilloscope

III.CƠ SỞ LÝ THUYẾT :

Timer là khối hoạt động độc lập với CPU , do đó nếu trong lập trình chúng ta sử dụng timer

thì sẽ làm giảm đi thời gian xử lý , giúp vi điều khiển hoạt động nhanh hơn . Ứng dụng chủ yếu

của timer là định thời trong khoảng thời gian ngắn , đếm số lượng xung clock bên ngoài cho các

ứng dụng như : đếm sản phẩm , đọc số xung encoder v.v... PIC16f887 có tích hợp 3 timer : timer

0(8-bit), timer 1(16-bit), timer 2(8-bit).

Hình 30: Sơ đồ khối các timer trong PIC16F887

Page 47: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

47

: Tràn timer

1.Nguyên tắc hoạt động của timer :

Nguyên tắc hoạt động chung của timer là tăng giá trị của thanh ghi đếm lên khi nhận được

một xung clock (đã qua bộ chia ) . Khi thanh ghi đếm đến giá trị lớn nhất , nếu có xung clock

tiếp tục tác động thì timer sẽ xảy ra sự kiện tràn timer (overflow) , sự kiện này có thể xảy ra

ngắt.

Ví dụ : Thanh ghi TMR0 là thanh ghi 8-bit chứa giá trị đếm của timer 0 :

0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 1

0 0 0 0 0 0 1 0

0 0 0 0 0 0 1 1

1 1 1 1 1 1 1 1

Hình 31: Quá trình hoạt động của một timer

2.Timer 0 :

Timer 0 có những đặc tính sau :

− Thanh ghi 8-bit timer/counter (TMR0).

− Bộ chia prescaler 8-bit (dùng chung với Watchdog timer )

− Hoạt động với xung clock bên trong hoặc bên ngoài .

− Hoạt động với việc lựa chọn cạnh của xung clock bên ngoài .

− Ngắt tràn timer .

Hình 32: sơ đồ khối timer 0 và watchdog timer trong PIC16F887

TMR0=0

+∆𝑡 TMR0=1

+∆𝑡

TMR0=2

+∆𝑡 TMR0=3

+∆𝑡

TMR0=255

+∆𝑡

Page 48: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

48

2.1 Các thanh ghi khởi tạo timer 0 :

T0CS : bit lựa chọn chế độ hoạt động của timer 0

− T0CS=1: Timer 0 hoạt động với chế độ đếm counter .(clock được cấp từ chân T0CKI)

− T0CS=0:Timer 1 hoạt động với chế độ định thời timer.(clock được cấp từ thạch anh hoạt

động của vi điều khiển ).

T0SE : Bit chọn cạnh tác động khi timer hoạt động với chế độ đếm counter.

− T0SE=1: Thanh ghi TMR0 tăng khi có sự kiện cạnh xuống ở chân T0CKI.

− T0SE=0: Thanh ghi TMR0 tăng khi có sự kiện cạnh lên ở chân T0CKI.

PSA : Dùng để lựa chọn bộ chia Prescaler thuộc về của timer 0 hay của Watchdog.

− PSA=1:Bộ chia prescaler thuộc về Watchdog .

− PSA=0: Bộ chia prescaler thuộc về Timer 0.

PS<2:0> : Chọn tỉ lệ cho bộ chia prescaler

2.2 Công thức định thời timer 0:

Hình 33: Thời gian hoạt động của timer0 (8-bit)

TMR0‟ 255

Over flow

∆𝑡

0

Page 49: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

49

Từ sơ đồ trên ta thấy thời gian định thời của timer 0 :

T=(255-TMR0‟)*∆𝑡 = (255−𝑇𝑀𝑅0′)∗𝑃𝑟𝑒𝑠𝑐𝑎𝑙 𝑒𝑟∗4

𝐹𝑜𝑠𝑐

Do đó để thay đổi thời gian định thời T ta có thể thay đổi một trong các thông số sau :

− TMR0‟ : Giá trị ban đầu của thanh ghi TMR0 cho timer 0 bắt đầu đếm. Khi trong

lập trình không gán giá trị đầu cho thanh ghi TMR0 thì timer bắt đầu đếm là 0.

(TMR0‟=0).

− Prescaler : Tỉ lệ bộ chia của timer 0.

− Fosc : Tần số hoạt động của vi điều khiển.(Ít khi thay đổi thông số này)

Chú ý : Trong quá trình tính toán tìm ra thời gian định thời T hợp lý , thường có sai số

xảy ra , do đó chúng ta chọn Prescaler và TMR0‟ sao cho sai số ít nhất .

2.3 Ngắt trong timer0 :

Timer 0 cũng có thể xảy ra ngắt , ngắt timer 0 xảy ra khi timer 0 tràn (tức là thanh ghi

TMR0=255 rồi sau đó trở về giá trị ban đầu).

Sơ đồ ngắt timer 0 :

Hình 34: Sơ đồ ngắt timer 0

T0IE : Bit cho phép xảy ra ngắt timer 0 , để ngắt timer 0 xảy ra thì bit này phải bằng 1.

T0IF : Cờ ngắt timer 0 , khi ngắt xảy ra bít này tự động bằng 1 , chúng ta cần phải xóa (=0) bít

này trong lập trình .

GIE : GIE bit cho phép ngắt toàn cục , để ngắt timer 0 xảy ra thì bit này phải bằng 1.

2.4 : Các bƣớc khởi tạo timer 0:

2.4.1 : Khởi tạo timer 0 hoạt động với chế độ định thời timer:

T0CS=0; //Clock cấp cho timer 0 là Fosc (tần số hoạt động của vi điều khiển)

PSA=0 ; //Bộ chia prescaler được sử dụng cho timer 0 .

PS<2:0>=....; //Chọn tỉ lệ bộ chia . Nếu PSA=1 thì có thể bỏ qua dòng này .

//Khởi tạo ngắt nếu có sử dụng

INTE=1;

INTF=0;

GIE=1;

Page 50: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

50

2.4.2:Khởi tạo timer 0 hoạt động với chế độ đếm counter :

//Khởi tạo chân T0CKI là ngõ vào .

TRISA4=1;

RA4=1;

T0CS=1; // Clock cấp cho timer 0 từ chân T0CKI

PSA=0 ; //Bộ chia prescaler được sử dụng cho timer 0 .

PS<2:0>=....; //Chọn tỉ lệ bộ chia .Nếu PSA=1thì có thể bỏ qua dòng này .

//Khởi tạo ngắt nếu có sử dụng

INTE=1;

INTF=0;

GIE=1;

3.Timer 1 :

Timer 1 có hai thanh ghi chứa giá trị đếm , do đó có thể đếm lên đến 65535(2^16

-1) mới xảy

sự kiện tràn timer , timer 1 thích hợp nhất cho việc đếm xung encoder tốc độ cao , cũng giống

như timer 0 , timer 1 cũng hoạt động với hai chế độ : chế độ định thời và chế độ đếm counter.

Hình 35: Sơ đồ khối timer 1

Page 51: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

51

3.1 Công thức định thời timer 1 :

T= [65535−(TMR 1H∗256+TMR 1L)]∗Prescaler ∗4

Fosc

Trong đó :

− T thời gian định thời timer 1

− TMR1L , TMR1H : thanh ghi chứa giá trị đếm của timer 1

− FOSC : tần số hoạt động của vi điều khiển

− Prescaler : tỉ lệ bộ chia .

3.2Thanh ghi điều khiển timer1 :

TMR1ON : Bit cho phép timer1 hoạt động

− 1: Cho phép timer 1 (điều kiện cần cho timer 1 hoạt động , chưa đủ)

− 0: Timer 1 ngừng hoạt động .

TMR1CS :Bit lựa chọn clock cho timer 1

− 1:Clock từ bên ngoài (từ chân T1CKI)

− 0:Clock bên trong (FOSC/4)

𝐓𝟏𝐒𝐘𝐍𝐂 : Bit điều khiển lựa chọn đồng bộ clock vào từ bên ngoài của timer 1

Nếu TMR1CS =1:

− 1:Clock vào từ bên ngoài không được đồng bộ

− 0:Clock vào từ bên ngoài được đồng bộ

Nếu TMR1CS = 0:

− Không cần quan tâm bit này , timer 1 sử dụng clock bên trong .

T1OSCEN : Bit điều khiển cho phép dao động LP

− 1: Dao động LP được cho phép cho clock timer 1 .

− 0: Tắt dao động LP .

T1CKPS<1:0> : Bit lựa chọn tỉ lệ bộ chia Prescale

11 = 1:8

10 = 1:4

01 = 1:2

00 = 1:1

TMR1GE : Bit cho phép cổng timer 1

Nếu TMR1ON=0 : bit này không cần quan tâm

Nếu TMR1ON=1 :

− 1 : Sự đếm lên của timer1 sẽ được điểu khiển bởi cổng Timer 1

− 0 : Timer 1 có thể đếm lên mà không cần quan tâm đến trạng thái của cổng timer 1 .

T1GINV : Bit đảo cổng timer1

Page 52: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

52

1 : Cổng timer1 tác động mức cao (Timer1 hoạt động khi cổng ở mức cao ).

0 : Cổng timer 1 tác động mức thấp (Timer 1 hoạt động khi cổng ở mức thấp).

3.3 Timer1 on :

Không giống với timer 0 , chúng ta cần khởi tạo một số bit thì timer 1 mới có thể hoạt động

được . Từ sơ đồ trên ta có thể thấy việc bật/tắt timer 1có hai dạng :

Cho phép timer 1 hoạt động mà không cần tác động từ bên ngoài :

TMR1ON=1;

TMR1GE=0;

Cho phép timer 1 hoạt động khi có tín hiệu logic ở chân T1G :

//Cho phép điện trở treo .

//Khởi tạo chân T1G là ngõ vào .

ANS13=0;

TRISB5=1;

RB5=1;

TMR1ON=1;

TMR1GE=1;

T1GINV=.....; //Tùy theo mức logic ở chân T1G là mức cao hay thấp.

T1GSS=1;

3.4 Ngắt trong timer 1 :

Timer 1 cũng có thể tạo ra sự kiện ngắt khi xảy ra tràn timer , các bit khởi tạo ngắt của

timer 1 :

TMR1IF : Cờ ngắt , bit này tự động bằng 1 khi có sự kiện tràn timer .

TMR1IE :Bit cho phép ngắt tràn timer .

PEIE :Bit cho phép ngắt ngoại vi .

GIE :Bit cho phép ngắt toàn cục .

Hình 36: Sơ đồ ngắt timer 1

3.5 Khởi tạo timer 1 hoạt động với chế độ đếm counter :

//Khởi tạo chân T1CKI là ngõ vào số ……

T1OSCEN=1;

TMR1CS=1;

T1CKPS1=…..;

T1CKPS0=…..;

T1SYNC=0;

//Cho phép timer 1 on

//Khởi tạo ngắt nếu có

Page 53: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

53

Ngoài ra , timer 1 còn có thể hoạt động với chế độ timer sử dụng thạch anh ngoài , độc

lập với tần số họat động của vi điều khiển , thạch anh ngoài ta có thể kết nối với hai chân :

OSC1 và OSC2 và khởi tạo tương tự như trên .

3.6 Khởi tạo timer 1 hoạt động với chế độ định thời timer :

TMR1CS=0;

T1CKPS1=…..;

T1CKPS0=…..;

T1SYNC=1;

//Cho phép timer 1 on

//Khởi tạo ngắt nếu có

4.Timer 2 :

Khác với timer 0 và timer 1 , timer 2 chỉ có thể hoạt động ở chế độ định thời timer , tuy nhiên

timer 2 có hai bộ chia và một giá trị đặt do đó thời gian định thời có thể linh hoạt hơn , và ít sai

số trong tín toán .

Hình 37: Sơ đồ khối timer 2

Nguyên tắc hoạt động timer 2 :

Khi có xung clock tần số Fosc/4 qua bộ chia Prescaler đi vào thanh ghi TMR2 , làm thanh

ghi TMR2 tăng lên , khi thanh ghi TMR2 bằng giá trị thanh ghi đặt PR2 thì sẽ có một xung clock

đi qua bộ chia Postscaler , đồng thời thanh ghi TMR2 trở về vị trí ban đầu , nếu tỉ lệ bộ chia

Postscaler được chọn 1:1 thì sẽ xảy ra sự kiện ngắt timer 2 .

4.1 Công thức tính định thời timer 2 :

T= PR 2−TMR 2′ ∗Postscaler ∗Prescaler ∗4

Fosc

Trong đó

T :Thời gian định thời timer 2

PR2 :giá trị thanh ghi đặt

TMR2‟ : giá trị bắt đầu đếm của thanh ghi TMR0

Prescaler : Tỉ lệ bộ chia prescaler

Postscaler : Tỉ lệ bộ chia Postscaler

Fosc :Tần số hoạt động của vi điều khiển .

Page 54: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

54

4.2. Thanh ghi điều khiển timer 2 :

T2CKPS<1:0>: Bit lựa chọn tỉ lệ bộ chia Prescaler

00 : 1:1

01 : 1:4

1x : 1:16

TMR2ON : Bit cho phép timer 2 hoạt động

0:Không cho phép timer2 hoạt động

1:Cho phép timer 2 hoạt động

TOUTPS<3:0>: Bit lựa chọn tỉ lệ bộ chia Postscaler

4.2.Khởi tạo timer 2 hoạt động với chế độ định thời timer :

//Tín toán lựa chọn tỉ lệ bộ chia Prescaler , Postscaler

//Chọn tỉ lệ bộ chia Prescaler

T2CKPS1=……..; T2CKPS0=……;

//Chọn tỉ lệ bộ chia Postscaler

TOUTPS3=…….; TOUTPS2=…….;

TOUTPS1=…….; TOUTPS0=…….;

//Đặt giá trị lớn nhất cho giá trị thanh ghi đếm TMR2

PR2=……;

//Cho phép timer 2 họat động

TMR2ON=1;

//Khởi tạo ngắt timer 2 nếu có sử dụng :

TMR2IE=1;

TMR2IF=0;

PEIE=1;

GIE=1;

Page 55: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

55

IV.BÀI TẬP THỰC HÀNH :

Bài 1: Viết chƣơng trình đọc số lần nhấn nút tại chân T0CKI(RA4) và hiển thị kết quả lên

LCD:

Sơ đồ phần cứng :

*Bƣớc 1: Tạo một project mới với tên 03_01_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

#include<stdio.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

#include "lcd.h";

void main( )

{

lcd_init( );

TRISA4=…….; RA4=…….; //Khởi tạo chân T0CKI là ngõ vào

T0CS =…….; //Chọn clock cấp cho Timer0 là từ chân T0CKI

T0SE =…….; //Chọn cạnh tác động là cạnh xuống

PSA =…….; //Xung clock không qua bộ chia (-------------1------------)

//(-------------2------------) while(1)

{

lcd_gotoxy(0,0);

printf("\fSo lan nhan nut la:\r\n %d",TMR0);

_delay(100000);

}

}

void putch(char c)

{

lcd_putc(c);

}

*Bƣớc 3:Nhấn nút nhấn kết nối với chân T0CKI và quan sát kết quả trên LCD.

*Bƣớc 4:Xóa dòng (-------------1------------)

Page 56: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

56

*Bước 5:Thêm vào dòng (-------------2------------) đoạn code sau :

PSA=0; //Chọn bộ chia thuộc về timer

PS2=0; //Chọn tỉ lệ chia

PS1=1;

PS0=1;

*Bƣớc 6: Quan sát kết quả khi nhấn nút nhấn.

*Bƣớc 7: So sánh hai kết quả trước và sau khi sửa code , giải thích ? Nêu chức năng của bộ chia

trong timer 0:

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Bài 2: Viết chƣơng trình chớp tắt led RE1 , định thời bằng timer 0,tần số Fosc/4:

*Bƣớc 1: Tạo một project mới với tên 03_02_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

void main( )

{

ANS6=…….;TRISE1=…….; //Khởi tạo chân RE1 là digital output

T0CS=…….; //Chọn xung clock cấp cho timer 0 là từ Fosc/4

PSA=…….; //Xung clock sẽ đi qua bộ chia

PS2=…….; PS1=…….; PS0=…….; //Tỉ lệ bộ chia là 128

//Khởi tạo ngắt cho timer 0

T0IE=…….; //Cho phép ngắt timer 0

T0IF=…….; //Reset cờ ngắt

GIE=…….; //Cho phép ngắt toàn cục

while(1); //Lặp vô tận

}

void interrupt isr()

{

if(T0IE&T0IF) //Chương trình con ngắt cho timer0

{

RE1^=1; //Chớp tắt led

TMR0=0; //Khởi tạo giá trị đếm ban đầu cho timer0(-------1--------)

T0IF=0; //Reset cờ ngắt.

}

Page 57: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

57

}

*Bƣớc 3 : Biên dịch chương trình , nạp xuống kít thí nghiệm , quan sát trạng thái của led .

*Bƣớc 4:Tăng giá trị TMR0 ở dòng (-------1--------) từ thấp đến cao(0-255) , biên dịch chương

trình và nạp xuống kit thí nghiệm , đến lúc mắt không còn nhìn thấy led RE1 chớp tắt , tính

tần số ứng với giá trị thanh ghi TMR0 vừa tìm được .

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

*Bƣớc 5 : Sử dụng oscillocope đo tần số vừa tìm được và so sánh với kết quả tính toán , nhận

xét.

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Bài 3:Viết chƣơng trình hiển thị đồng hồ lên LCD , sử dụng timer 1 định thời , thạch anh

ngoài 32.768KHz.

*Bƣớc 1 : Tạo một project mới với tên 03_03_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include<htc.h>

#include<stdio.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);void insothuc(unsigned char old_ADRESH);

#include "lcd.h"

unsigned char hh,mm,ss; //Khai báo biến chứa giờ , phút , giây

void main()

{

lcd_init();

//Khởi tạo các chân ngõ vào thạch anh 32.768KHz

TRISC0=TRISC1=1;RC0=RC1=0;

T1OSCEN= …….; //Cho phép timer 1 hoạt động clock ngoài

TMR1CS= …….; //Clock cấp cho timer 1 là clock ngoài

T1CKPS1=T1CKPS0=…….; //Tỉ lệ bộ chia 1:8(-------1--------)

T1SYNC= …….; //Qua khối đồng bộ

//Cho phép timer hoạt động không cần tác động bên ngoài

TMR1ON= …….;

TMR1GE= …….;

Page 58: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

58

TMR1IE= …….; //Khởi tạo ngắt timer1

TMR1IF= …….; //Reset cờ ngắt timer 1

PEIE= …….; //Cho phép ngắt ngoại vi

GIE= …….; //Cho phép ngắt toàn cục

while(1); //Lặp vô tận

}

void putch(char c) //Chương trình con cho hàm printf( )

{

lcd_putc(c);

}

void interrupt isr( )

{

if(TMR1IE&&TMR1IF) //Ngắt tràn timer 1

{

ss++;

if(ss==60)

{

ss=0;

mm++;

if(mm==60)

{

mm=0;

hh++;

}

}

lcd_gotoxy(0,0);

printf("\fBay Gio La :\r\n %02d:%02d:%02d",hh,mm,ss);

TMR1H=239; //Khởi tạo giá trị đếm ban đầu cho timer1 (-------2--------)

TMR1L=255; // (-------3--------)

TMR1IF=0;

}

}

*Bƣớc 3 : Nạp chương trình xuống kit thí nghiệm , jumper J1(XTAL).Quan sát lcd , và so sánh

kết quả với đồng hồ thực, nhận xét :

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Dựa vào công thức định thời của timer 1, chứng minh những thông số ở các dòng (1),(2),(3):

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Page 59: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

59

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

Bài 4: Viết chƣơng trình sử dụng timer 2 điều khiển led RE1 chớp tắt với chu kì T=0.1s ,

sử dụng thạch anh ngoài 20MHz.

*Bƣớc 1 : Tạo một project mới với tên 03_04_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính :

#include<htc.h>

#include<stdio.h>

__CONFIG(HS&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BORDI

S&IESODIS&LVPDIS&FCMDIS);

void main()

{

ANS6=…….;TRISE1=…….;RE1=…….; //Khởi tạo chân RE1 là ngõ ra số

T2CKPS1=…….;T2CKPS0=…….; //chọn tỉ lệ bộ chia prescaler 1:1

//Chọn tỉ lệ bộ chia postscaler 1:2 (-------1--------)

TOUTPS3=0;TOUTPS2=0;TOUTPS1=…….;TOUTPS0=…….;

PR2=…….; //Giá trị thanh ghi PR2 (-------2--------)

TMR2=…….; //Giá trị bắt đầu đếm của timer 2 (-------3--------)

//Cho phép timer 2 hoạt động

TMR2ON=…….;

//Khởi tạo ngắt timer 2

TMR2IE=…….; //Cho phép ngắt tràn timer 2

TMR2IF=…….; //Reset cờ ngắt

PEIE=…….; //Cho phép ngắt ngoại vi

GIE=…….; //Cho phép ngắt toàn cục

while(1)

{

}

}

void interrupt isr()

{

if(TMR2IE&&TMR2IF)

{

RE1^=1;

TMR2IF=…….; //Xóa cờ ngắt Timer2

TMR2=……. ; //Khởi tạo giá trị bắt đầu đếm timer2(-------4------)

}

}

Page 60: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

60

*Bƣớc 3 : Tính toán các thông số ở dòng (1),(2),(3),(4)

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------- *Bƣớc 4 : Hoàn thành vào dấu .............và biên dịch chương trình , nạp xuống kít thí nghiệm ,

quan sát led .

V.BÀI TẬP TỰ GIẢI :

Bài 5 : Viết chương trình hiển thị tốc độ động cơ lên lcd theo sơ đồ phần cứng sau :

(Tạo một project mới với tên 03_05_ MSSV)

Page 61: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

61

CHƯƠNG V: KHỐI CCP

(CAPTURE-COMPARE-PWM)

I.MỤC ĐÍCH THÍ NGHIỆM :

Kiến thức sinh viên cần đạt được sau khi thực tập:

− Giải thích nguyên tắc hoạt động và khởi tạo chế độ Capture.

− Giải thích nguyên tắc hoạt động và khởi tạo chế độ Compare .

− Giải thích nguyên tắc hoạt động và khởi tạo chế độ PWM.

− Phân biệt sự khác nhau và giống nhau giữa hai khối CCP1 và CCP2.

− Thiết lập được tần số PWM và điều chỉnh độ rộng xung PWM theo yêu cầu.

II.DỤNG CỤ THÍ NGHIỆM:

Kít thí nghiệm + cáp USB.

Động cơ DC12V.

Oscillocope.

Máy tính .

Nguồn 12V/1A.

III.CƠ SỞ LÝ THUYẾT :

Các chân được sử dụng cho khối CCP:

Hình 38: Các chân được sử dụng trong khối CCP

Để sử dụng khối CCP chúng ta cần phải biết khởi tạo và sử dụng thành thạo timer 0,1,2 bởi

vì một mình khối CCP không thể hoạt động được một ứng dụng mà phải sử dụng kết hợp với

một trong 3 timer , cụ thể là :

Page 62: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

62

1.Thanh ghi khởi tạo khối CCP1:

Khối CCP1 còn tích hợp thêm 4 chân mang kí hiệu : P1A, P1B, P1C, P1D hỗ trợ cho việc

điều khiển cầu H.

Hình 39: Các chân CCP1 hỗ trợ điều khiển cầu H

P1M<1:0> : Bit khởi tạo ngõ ra PWM

Nếu khối CCP1 được khởi tạo ở chế độ capture hoặc compare thì chân có kí hiệu P1A là

chân hoạt động ở chế độ capture hoặc compare , còn các chân có kí hiệu P1B, P1C, P1D là các

chân không liên quan đến khối CCP1 , chúng ta có thể gán cho chúng chức năng I/O thông

thường .

Nếu khối CCP1 được khởi tạo ở chế độ PWM thì 2 bit P1M<1:0> có 4 trạng thái điều khiển

cầu H như sau :

00:Ngõ ra đơn , P1A tạo xung , P1B , P1C, P1D hoạt động với chức năng I/O.

01:Chế độ Full – Bridge thuận , P1D tạo xung , P1A tác động , P1B , P1C không tác động

10:Chế độ hafl – Bridge , P1A ,P1B tạo xung , P1C, P1D hoạt động với chức năng I/O.

11: Chế độ Full – Bridge nghịch , P1B tạo xung , P1C tác động , P1A , P1D không tác

động .

DC1B<1:0> : Hai bit mang trọng số nhỏ nhất trong chế độ hoạt động PWM10bit .Ở chế độ

Capture và Compare thì không cần quan tâm đến hai bit này.

CCP1M<3:0> : Bit lựa chọn chế độ họat động khối CCP1

0000: Capture/Compare/PWM off(reset khối CCP1)

0001: Không sử dụng

0010: Chế độ Compare , đảo ngõ ra khi có sự kiện Compare (bit CCP1IF = 1).

0011: Không sử dụng

0100: Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 1 xung cạnh xuống .

0101: Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 1 xung cạnh lên .

0110: Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 4 xung cạnh lên .

0111: Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 16 xung cạnh lên .

Page 63: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

63

1000: Chế độ Compare , ngõ ra bằng 1 khi có sự kiện Compare (bit CCP1IF = 1).

1001: Chế độ Compare , ngõ ra bằng 0 khi có sự kiện Compare (bit CCP1IF = 1).

1010: Chế độ Compare , tạo ra sự kiện ngắt nội (bit CCP1IF = 1 , chân CCP1 không sử

dụng ).

1011: Chế độ Compare, tạo ra sự kiện trigger (CCP1IF =1; CCP1 resets TMR1 or

TMR2)

1100: Chế độ PWM , P1A , P1C tác động – mức cao , P1B , P1D tác động – mức cao

1101: Chế độ PWM , P1A , P1C tác động – mức cao , P1B , P1D tác động – mức thấp

1110: Chế độ PWM , P1A , P1C tác động – mức thấp , P1B , P1D tác động – mức cao

1111: Chế độ PWM , P1A , P1C tác động – mức thấp , P1B , P1D tác động – mức thấp

2.Thanh ghi khởi tạo khối CCP2:

Khác với khối CCP1 , khối CCP2 không có chức năng hỗ trợ điều khiển cầu H , trong chế

độ PWM , khối CCP2 chỉ có chức năng tạo ra xung PWM 10 bít ở chân CCP2.

DC2B<1:0> : Hai bit mang trọng số nhỏ nhất trong chế độ hoạt động PWM-10bit , ở chế độ

Capture và Compare thì không cần quan tâm đến hai bit này.

CCP2M<3:0> : Bit lực chọn chế độ họa động khối CCP1

0000: Capture/Compare/PWM off(reset khối CCP1)

0001:Không sử dụng

0010: Không sử dụng

0011:Không sử dụng

0100:Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 1 xung cạnh xuống .

0101:Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 1 xung cạnh lên .

0110:Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 4 xung cạnh lên .

0111:Chế độ Capture , sự kiện Capture xảy ra khi ở chân CCP1 có 16 xung cạnh lên .

1000: Chế độ Compare , ngõ ra bằng 1 khi có sự kiện Compare (bit CCP1IF = 1).

1001: Chế độ Compare , ngõ ra bằng 0 khi có sự kiện Compare (bit CCP1IF = 1).

1010: Chế độ Compare , tạo ra sự kiện ngắt nội (bit CCP1IF = 1 , chân CCP1 không sử

dụng ).

1011: Chế độ Compare, tạo ra sự kiện trigger (CCP1IF =1; CCP1 resets TMR1 or

TMR2).

11XX:Chế độ PWM.

Page 64: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

64

3.Capture :

Hình 40: Sơ đồ khối chế độ capture

3.1 Nguyên tắc hoạt động của chế độ capture :

Khi có sự kiện (cạnh lên , cạnh xuống , 4 cạnh lên hoặc 16 cạnh lên ) ở chân CCPx (có thể là

CCP1 hay CCP2 tùy vào ta sử dụng khối CCP1 hay CCP2) thì giá trị thanh ghi đếm của timer 1

là TMR1H và TMR1L sẽ được cập nhật qua hai thanh ghi CCPRxH và CCPRxL của khối CCPx.

đồng thời có thể xảy ra ngắt nội bằng việc cho phép cờ ngắt CCPRxIF = 1 .(x=0,1)

3.2 Các bƣớc khởi tạo chế độ capture :

Khởi tạo chân CCPx là ngõ vào : TRISCx=1;RCx=1;

Khởi tạo timer 1 hoạt động .

Khởi tạo khối CCPx hoạt động với chế độ capture :

CCPxCON = ......; //Chọn chế độ capture .

CCPRxH=CCPRxL=0; //reset hai thanh ghi của khối CCPx.

Khởi tạo ngắt (nếu có sử dụng):

CCPxIE=1; //Cho phép ngắt CCP

CCPxIF=0; //Reset cờ ngắt

PEIE=1; //Cho phép ngắt ngoại vi

GIE=1; //Cho phép ngắt toàn cục .

4.Compare :

Hình 41: Sơ đồ khối chế độ compare

Page 65: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

65

4.1Nguyên tắt hoạt động của chế độ compare :

Khi hai thanh ghi đếm TMR1H và TMR1L của timer 1 đếm đến giá trị của hai thanh ghi

CCPRxH và CCPRxL thì sẽ xảy ra một trong các sự kiện sau :

Đảo trạng thái ngõ ra của chân CCPx.

Tạo tín hiệu chân CCPx lên bằng 1 .

Xóa tín hiệu chân CCPx xuống bằng 0 .

Tạo ra ngắt .(CCPxIF =1 , chân CCPx không sử dụng )

Tạo ra sự kiện trigger .(CCP1IF=1,CCP1 reset timer 1 hoặc timer 2,CCP2IF=1,CCP2

reset timer 1 và ADC bắt đầu chuyển đổi nếu khối ADC được cho phép chuyển đổi , chân

CCP2 không sử dụng ).

4.2Các bƣớc khởi tạo chế độ compare:

Khởi tạo chân CCPx là ngõ ra : TRISCx=0;

Khởi tạo timer 1 hoạt động .

Khởi tạo khối CCPx hoạt động với chế độ compare :

CCPxCON = ......; //Chọn chế độ compare .

CCPRxH=....;CCPRxL=.....; //Chọn giá trị đặt .

Khởi tạo ngắt (nếu có sử dụng) :

CCPxIE=1; //Cho phép ngắt CCP

CCPxIF=0; //Reset cờ ngắt

PEIE=1; //Cho phép ngắt ngoại vi

GIE=1; //Cho phép ngắt toàn cục .

5.PWM(Pulse-Width Modulated) :

Nói đến PWM thì ta phải nói đến hai đặc tính cơ bản là : tần số (do timer 2 tạo ra ) và độ

rộng xung (do thanh ghi CCPRxL:CCPxCON<5:4> tạo ra ).

Sơ đồ tạo xung PWM là sự kết hợp của khối CCPx với timer 2 :

Hình 42: Sơ đồ điều chế PWM

5.1Nguyên tắt hoạt động của chế độ PWM :

Thanh ghi đếm của timer 2 là TMR2 đếm đến giá trị thanh ghi CCPRxL:CCPxCON<5:4>

của khối CCPx thì trạng thái logic chân CCPx bị đảo , khi giá trị của thanh ghi TMR2 đến giá trị

PR2 thì hoàn tất một chu kỳ tạo xung PWM .

Chú ý : Từ sơ đồ trên ta thấy để tạo xung PWM thì giá trị

CCPRxL::CCPxCON<5:4> phải nhỏ hơn hoặc bằng giá trị thanh ghi PR2 , và muốn thay

Page 66: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

66

đổi độ rộng xung ta chỉ cần thay đổi giá trị thanh ghi CCPRxL::CCPxCON<5:4> trong lập

trình .

Công thức tính chu kỳ PWM :

Công thức tính độ rộng xung PWM :

6.Các bƣớc khởi tạo chức năng PWM:

Bước 1 : Cho phép chân PWM là ngõ vào:

TRISCx=1; //x= 1 , 2

Bước 2 : Khởi tạo tần số PWM bằng việc định giá trị thanh ghi PR2 của timer 2:

PR2=....; //Tính toán được từ công thức chu kỳ PWM

Bước 3: Đặt khối CCP hoạt động ở chế độ PWM

CCPxCON=0bxxxx11xx; //x=0;1

Bước 4 : Đặt độ rộng xung của khối PWM bằng việc đặt giá trị cho thanh ghi CCPRxL

và 2 bit DCxB<1:0> của thanh ghi CCPxCON

CCPRxL=.....; //Có thể điều chỉnh giá trị này trong khi vi điểu khiển hoạt động

để thay đổi độ rộng xung khi cần thiết .

DCxB1=.....; //Nếu sử dụng PWM 8 bit thì có thể bỏ qua dòng này

DCxB0=.....; //Nếu sử dụng PWM 8 bit thì có thể bỏ qua dòng này

Bước 5 : Khởi tạo và cho phép timer 2 hoạt động :

TMR2IF=0; //Xóa cờ ngắt TMR2IF của thanh ghi PIR1

//Chọn tỉ lệ bộ chia của timer 2 :

T2CKPS1=.....; //Chọn tỉ lệ bộ chia Prescaler

T2CKPS0=.....;

TOUTPS3=....; //Chon tỉ lệ bộ chia Postscaler

TOUTPS2=....;

TOUTPS1=....;

TOUTPS0=....;

//Cho phép timer 2 hoạt động

TMR2ON=1;

Bước 6 : Cho phép ngõ ta PWM sau khi chu kỳ PWM mới được bắt đầu :

while(TMR2IF); // Chờ cho đến khi timer 2 tràn (bit TMR2IF của thanh ghi

PIR1 được bậc lên 1)

TRISCx = 0 ; //x = 1 , 2 .

Page 67: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

67

IV.BÀI TẬP THỰC HÀNH :

Bài 1:Viết chương trình tạo xung PWM có tần số 20KHz ở hai chân : CCP1(RC2) và

CCP2(RC1) với độ rộng xung CCP1 là 50% xung , CCP2 là 80% xung .

Sơ đồ phần cứng :

*Bƣớc 1 :Tạo một project mới với tên 04_01_ MSSV

*Bƣớc 2: Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include <htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

void main( )

{

//Khởi tạo tần số 20Khz PWM (timer 2)

PR2=…….; //Chọn tần số 20KHz

T2CKPS1=T2CKPS0=…….; //Bộ chia Prescales 1:1

TOUTPS3=TOUTPS2=TOUTPS1=TOUTPS0=…….;//Bộ chia Postcales1:1

//Khởi tạo khối CCP1

TRISC2=…….; //Disable ngõ ra của chân CCP1

CCP1CON=0b00001100; //(-------1--------)

CCPR1L=…….; //Tạo PWM 50% xung ỡ chân CCP1(-------2--------)

TMR1IF=…….; //Xóa cờ ngắt của khối CCP1

// Khởi tạo khối CCP2

TRISC1=…….; // Disable ngõ ra của chân CCP1

CCP2CON=0b00001100; // Khởi tạo module CCP2 hoạt động chế độ PWM

CCPR2L=…….; //Tạo xung PWM 80% ở chân CCP2(-------3--------)

TMR2IF=…….; // Xóa cờ ngắt của khối CCP2

//Cho phép timer 2 hoạt động bắt đầu tạo xung PWM

TMR2ON =…….; //Cho phép timer 2 hoạt động

TRISC2 =…….; //Cho phép chân CCP1 là ngõ ra

TRISC1 =…….; //Cho phép chân CCP2 là ngõ ra .

while(1);

}

*Bƣớc 3 : Nạp chương trình vào kit thí nghiệm , dùng oscillocope đo tín hiệu hai xung ở chân

CCP1 và CCP2 .

*Bƣớc 4 : Thay đổi dòng (-------1--------) thành đoạn code sau :

CCP1CON=0b00001111;

Page 68: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

68

Biên dịch chương trình nạp vào kít , dùng oscillocope đo ngõ ra PWM chân CCP1 , quan

sát xung được tạo ra , nhận xét sự khác nhau giữa xung trước và sau khi thay đổi code , và giải

thích sự khác nhau đó .

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

*Bƣớc 5 : Tính toán giá trị thanh ghi CCPR1L cho CCP1 tạo ra PWM 90% .

Tính toán giá trị thanh ghi CCPR2L cho CCP2 tạo ra PWM 10% .

Thay vào (-------2--------) và (-------3--------) , biên dịch chương trình , nạp xuống kít

thí nghiệm , sử dụng oscillocope đo ngõ ra xung và hoàn thành vào bảng sau :

PWM 90% PWM 10%

CCPR1L

CCPR2L

Bài 2 : Viết chƣơng trình điều khiển tốc độ động cơ sử dụng IC chuyên dụng L298 theo

yêu cầu sau : (Tạo một project mới với tên 04_02_ MSSV)

− Nhấn RB0 tốc độ động cơ tăng dần (mỗi lần nhấn tăng 10% độ rộng xung).

− Nhấn RB1 tốc độ động cơ giảm dần(mỗi lần nhấn giảm 10% độ rộng xung).

− Nhấn RB2 động cơ đảo chiều quay .

Với PWM tần số 10Khz , độ phân giải 8 bit , thạch anh nội 4MHz.

Phần cứng :

Page 69: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

69

*Bƣớc 1 :Tạo một project mới với tên 04_02_ MSSV

*Bƣớc 2 :Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include <htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&BO

RDIS&IESODIS&LVPDIS&FCMDIS);

void main( )

{

ANSEL=ANSELH=…….; //Tắt chức năng xử lý analog ở tất cả các chân

TRISB=…….; //Khởi tạo PORTB là ngõ vào

PORTB=…….;

WPUB=…….; //Cho phép điện trở treo tất cả PORTB

RBPU=…….;

IOCB =…….; //Cho phép ngắt on-change cả PORTB

RBIE =…….; //Enable ngắt on-change ở PORTB

RBIF =…….; //Xóa cờ ngắt on-change

GIE =…….; //Cho phép ngắt toàn cục

TRISE0=…….; //Khởi tạo chân RE0 là ngõ ra , mức cao

RE0 =…….;

T2CON = 0x04; //Timer 2 , prescaler 1:1 , postcaler 1:1 , TMR2ON=1

PR2 =…….; //tần số 10KHz

CCP1CON=0x0C; //Khởi tạo chế độ PWM cho module CCP1

CCP2CON=0x0C; //Khởi tạo chế độ PWM cho module CCCP2

CCPR1L=0;

CCPR2L=0;

TRISC2=1;

TRISC1=1;

while(1)

{

}

}

void interrupt isr()

{

if(RBIE&&RBIF)

{

if(!RB0)

{

CCPR1L+=10;

CCPR2L+=10;

TMR2ON=1;

}

if(!RB1)

{

CCPR1L-=10;

Page 70: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

70

CCPR2L-=10;

TMR2ON=1;

}

if(!RB2)

{

TRISC2^=1;

TRISC1=~TRISC2;

TMR2ON=1;

}

RBIF=0;

}

}

*Bƣớc 3 : Jum header CCP2 (J2) , biên dịch chương trình nạp xuống kít thí nghiệm , kết nối

động cơ và cấp nguồn cho L298 , tiến hành nhấn nút và quan sát kết quả .

V.BÀI TẬP TỰ GIẢI :

*Bài 3 : Viết chương trình sử dụng chức năng capture đo tần số ở chân CCP1(RC2) và hiển thị

giá trị đó lên LCD theo sơ đồ phần cứng sau (Tạo một project mới với tên 04_03_ MSSV):

*Bài 4 : Viết chƣơng trình tạo xung PWM 8 bit ở chân CCP2(RC1) với tần số 15 KHz theo

yêu cầu sau (Tạo một project mới với tên 04_04_ MSSV)::

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 1 : Độ rộng xung 15% .

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 2 : Độ rộng xung 30% .

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 3 : Độ rộng xung 45% .

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 4 : Độ rộng xung 60% .

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 5 : Độ rộng xung 75% .

Page 71: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

71

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 6 : Độ rộng xung 90% .

Nhấn nút nhấn (không giữ ) ở chân RB0 lần 7 : Trở lại trạng thái nhấn lần 1 .

*Bài 5 :Viết chƣơng trình theo yêu cầu sau (Tạo một project mới với tên 04_05_ MSSV):

Nhấn RB0 động cơ quay cùng chiều kim đồng hồ , PWM 10Khz , độ rộng xung 90%.

Nhấn RB1 động cơ quay ngược chiều kim đồng hồ , PWM 15Khz , độ rộng xung 70%.

Page 72: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

72

CHƯƠNG VI: GIAO TIẾP NỐI TIẾP BẤT ĐỒNG BỘ

I.MỤC ĐÍCH THÍ NGHIỆM :

Kiến thức sinh viên cần đạt được sau khi thực tập:

Giải thích nguyên lý truyền nhận tín hiệu UART.

Trình bày được khái niệm : baud , start bit , stop bit , frame truyền , parity .

Liệt kê được các thanh ghi liên quan truyền nhận UART.

Thiết lập các bit cho vi điều khiển truyền nhận dữ liệu qua chuẩn UART.

II.DỤNG CỤ THÍ NGHIỆM:

Kít thí nghiệm + cáp USB.

Động cơ DC12V.

Oscillocope.

Máy tính .

Nguồn 12V/1A.

III.CƠ SỞ LÝ THUYẾT :

Các chân liên quan đến chức năng giao tiếp nối tiếp :

Hình 43: Các chân truyền nhận UART

1.Khái niệm về giao tiếp nối tiếp bất đồng bộ :

Các thuật ngữ trong truyền nhận nối tiếp bất đồng bộ :

Thuật ngữ USART trong tiếng anh gọi là :Universal Synchronous và Asynchronous serial

Receiver and Transmitter , nghĩa là bộ truyền nối tiếp đồng bộ và bất đồng bộ . USART hay

UART cần phải kết hợp với một thiết bị chuyển đổi điện áp để tạo nên một chuẩn giao tiếp nào

đó .Ví dụ chuẩn Rs232(COM Port ) trên máy tính là sự kết hợp của chip UART và chip chuyển

đổi mức điện áp .Tín hiệu từ chip UART thường theo mức điện áp : mức high là +5V , mức slow

là 0V. Trong khi đó tín hiệu theo chuẩn RS232 trên máy tính thường là -12v cho mức high , và

+12v cho mức slow .

Hình 44: Cấu trúc một frame truyền

Page 73: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

73

Truyền thông nối tiếp :

Giả sử muốn truyền một dữ liệu 8-bit giữa hai vi điều khiển với nhau , chúng ta có thể nghĩ

đến cách đơn giản nhất là kết nối một PORT (8 bit) của mỗi vi điều khiển với nhau , mỗi đường

trên PORT sẽ đảm nhiệm việc truyền/nhận một bit dữ liệu . Đây gọi là cách giao tiếp song song ,

cách này đơn giản và truyền nhận dữ liệu cũng không qua bất cứ một giải thuật truyền nhận nào ,

và tốc độ truyền nhận cũng rất nhanh .Tuy nhiên , nhược điểm của cách truyền này là số đường

truyền nhiều , dữ liệu truyền càng lớn thì số đường truyền càng nhiều , do đó hệ thống truyền

nhận song song thường rất cồng kềnh và kém hiệu quả . Ngược lại trong truyền thông nối tiếp ,

dữ liệu được truyền theo từng bit trên một đừơng truyền , chính vì vậy dữ liệu cho dù có lớn thì

chúng ta cũng chỉ cần có một đường truyền duy nhất .

Hình 45: Sơ đồ truyền nhận 8 bit theo giao thức song song và nối tiếp .

Các thông số cơ bản trong truyền nhận nối tiếp :

Baud rate (tốc độ baud ): để truyền nhận nối tiếp xảy ra thành công thì các thiết bị phải

thống nhất với nhau về khoảng thời gian giành cho một bit truyền , hay nói cách khác là tốc độ

truyền phải được cài đặt giống nhau , tốc độ này gọi là tốc độ baud .Tốc độ baud là số bit truyền

trong 1 giây . Ví dụ nếu tốc độ baud là 9600 thì thời gian giành cho một bit truyền là 1/9600(s).

Frame (khung truyền ) : Khung truyền quy định về số bit trong mỗi lần truyền , các bit

báo như start , stop , các bit kiểm tra như parity , ngoài ra số lượng các bit trong một dữ liệu cũng

được quy định bởi khung truyền . Hình trên mô tả ví dụ về một khung truyền theo UART , khung

truyền này được bắt đầu bằng một start bit , tiếp theo là 8 bit , sau đó là 1bit parity dùng để

kiểm tra dữ liệu và cuối cùng là 2 bits stop .

Start bit : start bit là bit đầu tiên được truyền trong một frame , bit này có nhiệm vụ báo

cho thiết bị nhận biết rằng có một gói dữ liệu sắp được truyền tới .Start bit là bit bắt buộc phải có

trong một khung truyền .

Data : là số dữ liệu mà chúng ta cần phải truyền nhận , data có thể là gói 8 bit hay 9 bit

tùy theo yêu cầu truyền nhận mà ta quy định .Trong truyền thông nối tiếp UART , bit có trọng số

nhỏ nhất LSB(Least significant bit ) sẽ được truyền trước , sau đó bit có trọng số lớn nhất sẽ

được truyền sau cùng MSB(Most signnificant bit ).

Parity bit : parity dùng để kiểm tra dữ liệu truyền có đúng không , có hai loại parity là

parity chẳn (event parity )và parity lẻ (odd parity ) .

Stop bit : stop bit là một hoặc các bit báo cho thiết bị rằng các bit đã được gởi xong. Sau

khi nhận được stop bit , thiết bị nhận sẽ tiến hành kiển ra khung truyền để đảm bảo tính chính

xác của dữ liệu .Stop bit là bit bắt buộc xuất hiện trong khung truyền .

Page 74: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

74

2.Các thanh ghi điều khiển truyền UART:

Hình 46: Sơ đồ khối bộ truyền UART

Nguyên tắc hoạt động :

Dữ liệu cần truyền được đặt vào thanh ghi TXREG , baud rate được tạo ra , khi bit TXEN

được gán bằng một , dữ liệu từ thanh ghi TXREG đi vào thanh ghi TSR đồng thời baud rate tác

động đến thanh ghi TSR , đẩy dữ liệu cần truyền ra bộ điệm , sau đó xuất ra chân TX và đi ra

ngoài .

Bit TXIF dùng để báo trạng thái trong thanh ghi TXREG , nếu có dữ liệu trong thanh ghi

TXREG thì bít này sẽ có tín hiệu là 1 , ngược lại sau khi dữ liệu đã được truyền xuống thanh ghi

TSR thì bít TXIF được xóa về không .Tương tự như bit TXIF , bit TRMT dùng để báo trạng thái

của thanh ghi TSR .Quá trình truyền cũng có thể tạo ra ngắt truyền , mỗi khi dữ liệu truyền đã

kết thúc bằng việc đặt bit TXIF=1.

Ngoải ra bộ truyền còn có thể truyền với chế độ 9 bit bằng việc cho bit TX9 =1 , và dữ liệu

của bit thứ 9 do bit TX9D quy định .

Thanh ghi quy định chế độ truyền :

Các bit liên quan đến chế độ truyền nhận bất đồng bộ.

TX9 :bit cho phép truyền nhận chế độ 9-bit

− 1:Cho phép hoạt động với chế độ 9 bit

− 0:Hoạt động với chế độ 8bit

TXEN:bit cho phép truyền UART

− 1:Cho phép truyền .

− 0:Không cho phép truyền .

Page 75: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

75

SYNC :bit lựa chọn chế độ truyền .

− 1:Truyền nhận chế độ đồng bộ.

− 0:Truyền nhận chế độ bất đồng bộ.

BRGH: bit lựa chọn chế độ baud rate

− 1: tốc độ cao (bất đổng bộ )

− 0:tốc độ thấp (bất đồng bộ)

TRMT : bit hiển thị trạng thái thanh ghi truyền

− 1:Thanh ghi TSR trống .

− 0:Thanh ghi TSR có dữ liệu .

TX9D : Dữ liệu bit thứ 9 trong chế độ truyền 9 bit

Hình 47: Ngắt truyền UART

Các bit khởi tạo ngắt truyền UART :

TXIF : cờ ngắt , sau khi thanh ghi TXREG truyền dữ liệu xuống thanh ghi TSR thì bit này tự

động bằng 1 .

TXIE : bit cho phép ngắt truyền , để tạo ra ngắt truyền ta cần phải cho phép bit này bằng 1 .

PEIE : bit cho pháp ngắt ngoại vi .

GIE : bit cho phép ngắt toàn cục .

Các bƣớc khởi tạo chế độ truyền UART :

*Bước 1 : Khởi tạo thanh ghi SPBRGH , SPBRG và các bit BRGH và BRG16 để tạo ra baud

rate cần thiết .

*Bước 2 : Cho phép giao tiếp bất đồng bộ :

SYNC=0;

SPEN=1;

*Bước 3 : Cho phép chế độ 9 bit (nếu sử dụng truyền nhận 9 bit ) :

TX9=1;

*Bước 4 : Cho phép truyền :

TXEN=1;

*Bước 5 : Nếu sử dụng ngắt thì cần phải khởi tạo :

TXIE=1;

PEIE=1;

GIE=1;

*Bước 6: Gởi dữ liệu cần truyền của bit thứ 9 (nếu sử dụng truyền nhận 9 bit ):

Page 76: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

76

TX9D=…..;

*Bước 7 : Gởi dữ liệu cần truyền vào thanh ghi 8 bit:

TXREG=…..;

3.Các thanh ghi điều khiển nhận UART:

Hình 48: Sơ đồ khối bộ truyền UART

Nguyên tắc hoạt động :

Khi có dữ liệu được truyền tới chân RX , nếu bit SPEN được cho phép , thì dữ liệu sẽ được

đồng bộ với khối tạo xung , vì baund rate giữa hai khối truyền nhận bằng nhau, nên xung baud

mang dữ liệu từng bit vào thanh ghi RSR , khi một frame truyền hoàn tất (dấu hiệu từ bit stop) ,

thì dữ liệu được truyền xuống thanh ghi RCREG , bit thứ 9 được truyền xuống RX9D(nếu sử

dụng chế độ 9 bit) , nếu trên đường truyền có lỗi thì các bit OERR, FERR sẽ được hiển thị để

báo .

Quá trình nhận củng có thể tạo ra ngắt sau khi kết thúc một frame truyền nhận, bằng việc làm

cho bit RCIF =1 .

Thanh ghi quy định chế độ nhận :

Các bit liên quan đến chế độ truyền nhận bất đồng bộ.

SPEN : Bit cho phép khởi tạo cổng nối tiếp :

− 1:Cho phép cổng nối tiếp

− 0: Không cho phép cổng nối tiếp

RX9: Bit cho phép nhận 9 bit

− 1: Chế độ nhận 9 bit

− 0: Chế độ nhận 8 bit

Page 77: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

77

CREN : bit cho phép nhận liên tục

− 1: Cho phép .

− 0: Không cho phép .

ADDEN : bit cho phép phát hiện địa chỉ (sử dụng ở chế độ truyền nhận bất đồng bộ 9 bit )

− 1:Cho phép phát hiện địa chỉ , cho phép ngắt và tải bộ đệm nhận khi RSR<8> được set.

− 0:Không cho phép phát hiện địa chỉ , tất cả byte được nhận và bit thứ 9 dùng làm bit

parity

FERR : bit báo lỗi frame

− 1: Có lỗi

− 0:Không có lỗi .

OERR : lỗi OVERRUN

− 1:Có lỗi (có thể xóa bằng việc xóa bít CREN)

− 0:Không lỗi .

RX9D : Bit chứa dữ liệu nhận của bit thứ 9

Hình 49: Ngắt nhận UART

Các bit khởi tạo ngắt nhận UART :

RCIF : cờ ngắt , sau khi thanh ghi RCREG nhận được dữ liệu thì bit này tự động bằng 1.

RCIE : bit cho phép ngắt nhận , để tạo ra ngắt nhận ta cần phải cho phép bit này bằng 1 .

PEIE : bit cho pháp ngắt ngoại vi .

GIE : bit cho phép ngắt toàn cục .

Các bƣớc khởi tạo chế độ nhận UART :

*Bước 1 : Khởi tạo thanh ghi SPBRGH , SPBRG và các bit BRGH và BRG16 để tạo ra baund

rate cần thiết .

*Bước 2 : Cho phép giao tiếp bất đồng bộ :

SYNC=0;

SPEN=1;

*Bước 3 : Nếu sử dụng ngắt nhận :

RCIE=1;

PEIE=1;

GIE=1;

*Bước 4 : Cho phép chế độ 9 bit bằng (nếu sử dụng truyền nhận 9 bit ) :

RX9=1;

Page 78: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

78

*Bước 5 : Cho phép nhận dữ liệu :

CREN=1;

*Bước 6 : Cờ ngắt RCIF = 1 khi dữ liệu chuyển đổi từ RSR tới bộ điệm nhận . Ngắt sẽ được tạo

ra nếu RCIE=1.

*Bước 7 : Đọc thanh ghi RCSTA để phát hiện các lỗi trong quá trình truyền nhận.

*Bước 8 : Nhận 8 bit dữ liệu từ bộ điệm nhận bằng cách đọc thanh ghi RCREG.

*Bước 9 : Nếu có lỗi overrun xảy ra , xóa cờ OERR bằng cách xóa bit CREN.

5.Công thức tính tốc độ baud rate :

Trong đó :

FOSC là tần số hoạt động của vi điều khiển .

n=SPBRGH:SPBRG

Ví dụ : Tính tốc độ baud 9600 ,với điều kiện các bit khởi tạo như sau :

SYNC=0 ; BRG16=1; BRGH=1; Fosc= 4Mhz

Khi đó theo bảng ta có :

9600= 𝐹𝑂𝑆𝐶

4(𝑛+1)

n=103

Do đó : SPBRG=103 , SPBRGH=0;

IV:BÀI TẬP THỰC HÀNH :

Bài 1 :Viết chƣơng trình truyền nhận UART của vi điều khiển với máy tính , điều khiển

hoạt động của led theo yêu cầu sau :

Vi điều khiển nhận một số từ máy tính và điều khiển hai led RE1 va RE2 với 4 trạng thái

Nhận số 1: Hai led tắt , gởi lên máy tính chuỗi "Number 1".

Nhận số 2: Hai led sáng, gởi lên máy tính chuỗi "Number 2".

Nhận số 3:Led RE1 sáng,RE2 tắt ,gởi lại máy tính chuỗi "Number 3".

Nhận số 4:Led RE1 tắt ,RE2 sáng ,gởi lại máy chuỗi "Number 4".

Số khác :Hai led cùng chớp tắt với chu kỳ _delay(100000);gởi lại máy tính chuỗi "Other

numbers".

Page 79: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

79

Vi điều khiển sử dụng thạch anh nội 4MHz , tốc độ baund : 9600 , truyền nhận 8 bit .

Cấu hình phần cứng :

*Bƣớc 1 : Tạo một project mới với tên 05_01_ MSSV

*Bƣớc 2 : Nhập chương trình sau vào máy tính và hoàn thành vào dấu …….

#include <htc.h>

#include <stdio.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTECT&FC

MDIS&IESODIS&LVPDIS&BORDIS);

void send_string(char *s);

void send_char(char c);

char data ;

void main()

{

ANS6=ANS7=…….;TRISE1=TRISE2=…….; //Khởi tạo RE1,RE2 là ngõ ra số

//Cấu hình truyền UART

TXEN=…….; //Cho phép truyền

SYNC=…….;

//Cấu hình nhận UART

SPEN =…….; //Cấu hình chân RX,TX ở chế độ truyền nhận UART

CREN=…….;

//Khởi tạo tốc độ baund 9600=Fosc/(4*(n+1)) với n=SPBRGH:SPBRG

BRG16=1; //(--------1----------)

BRGH=1; //(--------2----------)

SPBRG=103;SPBRGH=0; //(--------3----------)

//Khởi tạo ngắt nhận

RCIE =…….;

PEIE =…….;

GIE =…….;

while(1)

{

Page 80: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

80

switch(data)

{

case 1:

RE1=RE2=…….;send_string("Number 1\r"); //Hai led tắt

break;

case 2:

RE1=RE2=…….;send_string("Number 2\r"); //Hai led sáng

break;

case 3:

RE1=0;RE2=…….;

send_string("Number 3\r"); //RE1 tắt , RE2 sáng

break;

case 4:

RE1=…….;RE2=…….;

send_string("Numer 4\r"); //RE2 tắt , RE1 sáng

break;

default:

RE1^=…….;RE2=RE1; //Hai led cùng chớp tắt.

send_string("Other numbers\r");

break;

}

_delay(100000);

}

}

void interrupt isr()

{

if(RCIF)

{

data=RCREG;

}

}

void send_char(char c)

{

while(!TXIF);

TXREG=c;

}

void send_string(char *s)

{

while(*s)

send_char(*s++);

}

*Bƣớc 3 : Nạp chương trình vào kít thí nghiệm , kết nối máy tính với kít thí nghiệm bằng cổng

COM(Nếu sử dụng Laptop không có cổng COM thì cần có cáp USB→COM ).

Page 81: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

81

*Bƣớc 4 : Sử dụng chương trình Terminal (chương trình dùng test cổng COM) truyền nhận kí tự

xuống kit thí nghiệm , đồng thời quan sát 2 led trên kit thí nghiệm .

*Bƣớc 5 : Chứng minh thông số của dòng (1) , (2), (3).

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

---------------------------------------------------------------------------------------------------------------------

--------------------------------------------------------------------------------------------------------------------

Bài 2 : Làm lại bài 1 với tốc độ baud 14400 (Tạo một project mới với tên 05_02_ MSSV).

V.BÀI TẬP TỰ GIẢI :

Bài 3 : Viết chƣơng trình truyền nhận UART của vi điều khiển với máy tính , hiển thị kết

quả lên lcd theo sơ đồ phần cứng sau (Tạo một project mới với tên 05_02_ MSSV):

Yêu cầu : Truyền một chuỗi số (tối đa 5 chữ số xxxxx) từ máy tính xuống vi điều khiển , vi điều

khiển hiển thị số vừa nhận được từ máy tính lên lcd , đồng thời gởi lại máy tính số vừa nhận

cộng thêm 10.Thạch anh 4Mhz , baud 9600 , truyền nhận 8-bit , phần cứng kết nối lcd theo thư

viện lcd.h .

Page 82: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

82

Bài 4 : Viết chƣơng trình truyền nhận giữa vi điều khiển và máy tinh với các yêu cầu sau :

Máy tính truyền xuống vi điều khiển kí tự „S‟ , động cơ start.

Máy tính truyền xuống vi điều khiển kí tự „P‟ , động cơ stop.

Máy tính truyền xuống vi điều khiển kí tự „B-xxx‟ , động cơ quay thuận ,với xxx là độ

rộng xung PWM 8 bit .

Máy tính truyền xuống vi điều khiển kí tự „F-xxx‟ , động cơ quay nghịch , với xxx là độ

rộng xung PWM 8 bit .

Bài 5 : Viết chương trình truyền nhận giữa máy tính và vi điều khiển với yêu cầu sau : máy tính

hiển thị vận tốc động cơ trên Terminal , baud 9600, Fosc = 4Mhz .

Page 83: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

83

TÀI LIỆU THAM KHẢO :

[1] PIC16F882/883/884/886/887 Data Sheet

[2]Dogan lbrahim , Advanced PIC Microcontroller Projects in C

[3] 101 ASP Getting Started with PICmicro® Mid-Range, Microchip

[4] Tài liệu giảng dạy R&P

Page 84: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

84

PHỤ LỤC

I.CỬA SỔ CHƢƠNG TRÌNH :

II.CÁC BƢỚC KHỞI TẠO MỘT PROJECT MỚI: 1.Tạo một folder (A) chứa tất cả các file chương trình

2.Khởi động MPLAB : Chọn Project , Project Wizard

Thanh Menu

Thanh Công Cụ

Của sổ viết

chương trình

1 2

Page 85: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

85

3.Chọn Next :

4.Chọn dòng PIC muốn lập trình , Next :

5.Lựa chọn công cụ lập trình (ở đây chọn H-TECH) , Next:

Chú ý : Chỉ duy nhất có dòng H-TECH sau khi cài đặt thành công Hi-tech C.

3

4

5

6

7

Page 86: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

86

6.Browse tới folder (A) , đặt tên cho bài làm (main), Next :

7.Nhấn Next , chọn Finish:

9 9

10

Page 87: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

87

8.Chọn NewFile ở thanh công cụ , viết đoạn chương trình #include<htc.h> trong MPLAB

IDE Editor , chọn Save :

9.Đặt tên main.c (Chú ý : phải có “.c” và Save in ở thư mục A) ,chọn save :

11

12 13

15

14

16

Page 88: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

88

10.Right click vào Source file ở cửa sổ main.mcw chọn Add files , Browse tới main.c

chọn open :

11.Hoàn tất tạo một project , tiếp tục viết chương trình .

II.HI TECH C CƠ BẢN:

1.Khai báo biến :

<Kiểu biến > <Tên biến > ;

Kiểu biến :

Kiểu biến Kích thƣớc (bit) Tầm giá trị

bit 1 0,1(false, true)

char 8 0 = >255

signed char 8 -128=>127

int 16 -32768 => 32767

unsigned int 16 0=>65535

short int 8 0=>255

signed short int 8 -128=>127

17 18

Page 89: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

89

long int 32 0=>4294967295

signed long int 32 -2147483648=>2147483647

float 32 ±1.755 .10-38

=>±6.8056.1038

double 32 ±1.755 .10-38

=>±6.8056.1038

Tên biến :

Tên biến bao gồm các kí tự từ A tới Z ,các số từ 0 tới 9 và dấu “_” , tên biến không bắt

đầu với một số và không trùng với từ khóa .

Ví dụ : char bien_1, bien_2;

signed char bien3=5;

int bien4=bien5=3;

2.Kiểu con trỏ :

Khai báo con trỏ :

<Kiểu con trỏ > *<Tên con trỏ> ;

Kiểu con trỏ : Giống kiểu biến.

Tên con trỏ : Giống tên biến .

Ví dụ :

unsigned int *con_tro;

con_tro = &bien1; //Con trỏ trỏ tới biến mang tên 1

*con_tro = 6 ; //Gán số 6 cho biến 1 , tương đương bien1=6;

bien2 = *con_tro ; //gán giá trị mà bien1 đang chứa cho bien2 ;

//Tương đương với : bien2=bien1;

3.Kiểu enum:

Ví dụ

enum motor{up,down,left,right};

Khí đó : giá trị các biến sẽ là

motor(up) = 0

motor(down)= 1

motor(left) = 2

motor(right)=3

Page 90: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

90

4.Phép toán học :

Phép toán Kí hiệu

Cộng +

Trừ -

Nhân *

Chia /

Chia lấy dư %

5.Phép toán gán :

Toán tử Ví dụ

Biểu thức Bằng

+= a+=8 a=a+8

-= a-=8 a=a-8

*= a*=8 a=a*8

/= a/=8 a=a/8

%= a%=8 a=a%8

6.Phép toán tăng , giảm :

Toán tử Ví dụ Bằng

++ ++a Tăng biến a lên 1 đơn vị.

a++

-- --a Giảm biến a xuống 1

đơn vị. a--

7.Phép toán quan hệ :

Phép toán Ví dụ Ý nghĩa

> b>a Lớn hơn

>= b>=a Lớn hơn hoặc bằng

< b<a Bé hơn

<= b<=a Bé hơn hoặc bằng

== b==a Bằng

!= b!=a Không bằng

Page 91: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

91

8.Tóan tử logic :

Toán tử AND

&&

Tham số 1 Tham số 2 Kết quả

0 0 0

0 1 0

1 0 0

1 1 1

||

OR

0 0 0

0 1 1

1 0 1

1 1 1

!

NOT

0 1

1 0

9.Toán tử theo bit :

Toán tử Ý nghĩa Ví dụ Kết quả

~ Đảo bit a=~b b=5 a=-5

<< Dịch trái a=b<<2 b=0b01011001 a=0b01100100

>> Dịch phải a=b>>2 b=0b11101011 b=0b00010110

& AND bit c=a&b a=0b01101110

b=0b01101011 c=0b01101010

| OR bit c=a|b a=0b01101110

b=0b01101011 c=0b01101111

^ XOR bit c=a^b a=0b01101110

b=0b01101011 c=0b00000101

10.Chèn một đoạn code Assembly :

Trong C ta cũng có thể chèn một đoạn code Assembly bất kỳ vào bằng câu lệnh sau :

Ví dụ :

unsigned int b=0;

asm

{

MOVE maximun,W

..............................

}

b =10;

Page 92: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

92

11.Các toán tử ƣu tiên :

12.Câu điều kiện :

Câu điều kiện có hai dạng sau : if hoặc if-else

Dạng if :

if(<điều kiện>)câu lệnh ;

Nếu <điều kiện> đúng thì câu lệnh được thực hiện .

Nếu <điều kiện> sai thì câu lệnh không được thực hiện .

Ví dụ :

char a,b;

a=1, b=5;

if(a==1)

a=5;

b=6;

Kết quả : a=5 , b=6

Dạng if-else :

if(<điều kiện>)câu lệnh 1 ; else câu lệnh 2;

Page 93: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

93

Nếu <điều kiện> đúng thì câu lệnh 1 được thực hiện , câu lệnh 2 không được thực hiện.

Nếu <điều kiện> sai thì câu lệnh 1 không được thực hiện , câu lệnh 2 được thực hiện .

Quy ước số 0 = false , và số khác không = true .

Ví dụ :

char a,b;

a=1;b=5;

if(a==1)

a=5

else

b=6;

Kết quả : a=5 , b=5 .

Nếu trong câu lệnh 1 có từ 2 câu lệnh trở lên ta phải đặt chúng trong dấu ngoặc {}

Ví dụ :

char a,b

c=1 ; b=5;

if(a==1)

{

a=5;

b=6;

}

else

b=3;

Kết quả : a=5 , b=6.

Chú ý :

char a,b;

a=1;b=5;

if(a==1)

a=5;

b=6;

else

if(<điều kiện>)

{câu lệnh 1; câu lệnh 2 ; câu lệnh 3 ;}

else

{câu lệnh 4 ; câu lệnh 5;}

Page 94: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

94

switch(<lựa chọn>)

{

case hằng 1:

câu lệnh 1:

..................

break;

case hằng 2 :

câu lệnh 5 ;

..................

break ;

default :

câu lệnh n ;

..................

}

b=3;

Kết quả : biên dịch báo lỗi .

Toán tử “if-else” có thể thay thế bằng toán tử “?”

(điều kiện)?câu lệnh 1: câu lệnh 2;

Nếu điều kiện = true thì câu lệnh 1 được thực hiện.

Nếu điều kiện = false thì câu lệnh 2 được thực hiện .

13.Toán tử lựa chọn :

Khác với câu lệnh if-else chỉ cho lựa chọn một trong hai thuộc tính , thì switch – case cho

lựa chọn một vào thuộc tính .

Nếu biểu thức <lựa chọn> = hằng

1 thì câu lệnh 1 được thực hiện .

Nếu biểu thức <lựa chọn> = hằng 2 thì câu lệnh 2 được thực hiện .

Nếu biểu thức <lựa chọn> != hằng 1 , hằng 2 thì câu lệnh n được thực hiện.

Page 95: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

95

14.Vòng lặp:

14.1 while:

Nếu biểu thức điều kiện đúng thì : lệnh 1 , lệnh 2 ............lệnh n được thực hiện , sau đó

quay lại kiểm tra biểu thức điều kiện.

Nếu biểu thức điều kiện sai thì lệnh 1, 2 .......lệnh n không được thực hiện , và thoát ra

ngoài thực hiện dòng lệnh tiếp theo lệnh while .

Ví dụ :

char a=3;

while(a<=19)

{

a+=5;

}

Kết quả : a=18

14.2 do_while:

Vòng lặp do_while() thực hiện lệnh 1 , lệnh 2,.....,lệnh n , sau đó xét <điều kiện>

Nếu điều kiện đúng thì tiếp tục lặp lại thực hiện lệnh 1 , lệnh 2 ....lệnh n.

Nếu điều kiện sai thì thoát ra ngoài và thực hiện lệnh tiếp theo lệnh while .

Khác với vòng lặp while , vòng lặp do_while thực hiện lệnh bên trong ít nhất 1 lần , nếu

điều kiện sai .

while(<biểu thức điều kiện>)

{

lệnh 1;

lệnh 2;

............

lệnh n ;

}

do

lệnh 1;

lệnh 2;

...........

lệnh n;

while(<điều kiện>);

Page 96: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

96

14.3 :Vòng lặp for :

1. <Khởi tạo biểu thức>

2. Xét <biểu thức điều kiện> :

Nếu <biểu thức điều kiện> đúng thì thực hiện lệnh 1 , lệnh 2 ,....,lệnh n , <thay đổi

biểu thức >,tiếp tục xét<biểu thức điều kiện>

Nếu<biểu thức điều kiện> sai thì thoát ra khỏi vòng for.

Ví dụ :

unsigned int b=0;

for(int a=10;a<=15;a++)

{

b+=5;

}

Kết quả a=15 , b = 30 ;

15.Mảng 1 chiều :

Khai báo :

<Kiểu mảng > <Tên mảng >[<số phần tử mảng >] ;

Kiểu mảng = kiểu biến

Tên mảng = tên biến 2

Số phần tử mảng = số nguyên.

Ví dụ :

char mang[4]={2,4,7,5};

Khi đó :

mang[0]=2, mang[1]=4, mang[2]=7,mang[3]=5

for(<khởi tạo biểu thức >;<biểu thức điều kiện>;<thay đổi biểu thức>)

{

lệnh 1 ;

lệnh 2;

............

lệnh n ;

}

Page 97: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

97

16.Mảng hai chiều :

Ví dụ :

int table[3][4];

Khi đó :

table[0][0] table[0][1] table[0][2] table[0][3]

table[1][0] table[1][1] table[1][2] table[1][3]

table[2][0] table[2][1] table[2][2] table[2][3]

17.Cấu trúc của một chƣơng trình c cơ bản :

#include<htc.h>

__CONFIG(INTIO&WDTDIS&PWRTEN&MCLREN&UNPROTECT&DUNPROTEC

T&BORDIS&IESODIS&FCMDIS&LVPDIS)//

//Khai báo biến toàn cục

//Khái báo tên chương trình con

void main()

{

//khai báo biến cục bộ cho chương trình void main

//khởi tạo chức năng cho vi điều khiển

while(1); //Lặp vô tận .

}

//Nằm trong chương trình con đã khai báo ở trên .

<Kiểu mảng > <Tên mảng>[<số hàng>][<số cột>];

Page 98: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

98

IV.SƠ ĐỒ NGUYÊN LÝ KIT THÍ NGHIỆM:

Page 99: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

99

Page 100: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

100

Page 101: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

101

V.FILE LCD : 1.lcd.c:

#include <stdlib.h>

#include <ctype.h>

#include "lcd.h"

unsigned char i ;

void lcd_init()

{

unsigned char i;

LCD_EN_TRIS = 0;

LCD_RS_TRIS = 0;

LCD_RW_TRIS = 0;

LCD_DATA4_TRIS = 0;

LCD_DATA5_TRIS = 0;

LCD_DATA6_TRIS = 0;

LCD_DATA7_TRIS = 0;

LCD_EN = 0;

LCD_RS = 0;

LCD_RW = 0;

for(i=0;i<10;i++){Nop();} // delay for power on

// reset LCD

lcd_put_byte(0,0x30);

for(i=0;i<5;i++){Nop();}

lcd_put_byte(0,0x30);

for(i=0;i<5;i++){Nop();}

lcd_put_byte(0,0x32);

for(i=0;i<10;i++){Nop();}

for(i=0;i<10;i++){Nop();}

for(i=0;i<10;i++){Nop();}

// __delay_ms(100); // delay for LCD reset

// __delay_ms(100); // delay for LCD reset

// __delay_ms(100); // delay for LCD reset

while(lcd_busy());

lcd_put_byte(0,FOUR_BIT & LINES_5X7); // Set LCD

type

Page 102: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

102

while(lcd_busy());

lcd_put_byte(0,DOFF&CURSOR_OFF&BLINK_OFF); // display off

while(lcd_busy());

lcd_put_byte(0,DON&CURSOR_OFF&BLINK_OFF); // display on

while(lcd_busy());

lcd_put_byte(0,0x01); // clear display

and move cursor to home

while(lcd_busy());

lcd_put_byte(0,SHIFT_CUR_LEFT); // cursor shift

mode

while(lcd_busy());

lcd_put_byte(0,0x01); // clear display

and move cursor to home

while(lcd_busy());

}

unsigned char lcd_busy()

{

unsigned char busy;

LCD_DATA4_TRIS = 1;

LCD_DATA5_TRIS = 1;

LCD_DATA6_TRIS = 1;

LCD_DATA7_TRIS = 1;

LCD_RW = 1;

LCD_RS = 0;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

busy = LCD_DATA7;

LCD_EN = 0;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

Page 103: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

103

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 0;

return busy;

}

unsigned char lcd_get_byte(unsigned char rs)

{

BYTE_VAL b;

LCD_DATA4_TRIS = 1;

LCD_DATA5_TRIS = 1;

LCD_DATA6_TRIS = 1;

LCD_DATA7_TRIS = 1;

LCD_RW = 1;

LCD_RS = 0;

if(rs) LCD_RS = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

b.bits.b7 = LCD_DATA7;

b.bits.b6 = LCD_DATA6;

b.bits.b5 = LCD_DATA5;

b.bits.b4 = LCD_DATA4;

LCD_EN = 0;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

b.bits.b3 = LCD_DATA7;

b.bits.b2 = LCD_DATA6;

b.bits.b1 = LCD_DATA5;

b.bits.b0 = LCD_DATA4;

Page 104: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

104

LCD_EN = 0;

return b.Val;

}

void lcd_put_byte(unsigned char rs, unsigned char b)

{

BYTE_VAL temp;

LCD_DATA4_TRIS = 0;

LCD_DATA5_TRIS = 0;

LCD_DATA6_TRIS = 0;

LCD_DATA7_TRIS = 0;

LCD_RS = 0;

if(rs) LCD_RS = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_RW = 0;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 0;

temp.Val = b;

// send the high nibble

LCD_DATA4 = temp.bits.b4;

LCD_DATA5 = temp.bits.b5;

LCD_DATA6 = temp.bits.b6;

LCD_DATA7 = temp.bits.b7;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 0;

// send the low nibble

LCD_DATA4 = temp.bits.b0;

LCD_DATA5 = temp.bits.b1;

LCD_DATA6 = temp.bits.b2;

Page 105: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

105

LCD_DATA7 = temp.bits.b3;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 1;

// __delay_us(20);

for(i=0;i<2;i++){Nop();}

LCD_EN = 0;

}

void lcd_putc(char c){

switch(c){

case '\f':

lcd_put_byte(0, 1);

while(lcd_busy());

break;

case '\n':

lcd_gotoxy(0, 1);

break;

default:

if(isprint(c)){

lcd_put_byte(1, c);

while(lcd_busy());

}

break;

}

}

void lcd_gotoxy(unsigned char col, unsigned char row)

{

unsigned char address;

if(row!=0)

address=0x40;

else

address=0;

address += col;

lcd_put_byte(0,0x80|address);

while(lcd_busy());

}

void lcd_puts(const char* s)

Page 106: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

106

{

while(*s)

{l

cd_putc(*s++);

}

}

2.lcd.h:

#ifndef _LCD_H_

#define _LCD_H_

#include <p24fxxxx.h>

//#ifndef _XTAL_FREQ

//#define _XTAL_FREQ 20000000

#endif

/* Display ON/OFF Control defines */

#define DON 0b00001111 /* Display on */

#define DOFF 0b00001011 /* Display off */

#define CURSOR_ON 0b00001111 /* Cursor on */

#define CURSOR_OFF 0b00001101 /* Cursor off */

#define BLINK_ON 0b00001111 /* Cursor Blink */

#define BLINK_OFF 0b00001110 /* Cursor No Blink */

/* Cursor or Display Shift defines */

#define SHIFT_CUR_LEFT 0b00000100 /* Cursor shifts to the left */

#define SHIFT_CUR_RIGHT 0b00000101 /* Cursor shifts to the right */

#define SHIFT_DISP_LEFT 0b00000110 /* Display shifts to the left */

#define SHIFT_DISP_RIGHT 0b00000111 /* Display shifts to the right */

/* Function Set defines */

#define FOUR_BIT 0b00101100 /* 4-bit Interface */

#define EIGHT_BIT 0b00111100 /* 8-bit Interface */

#define LINE_5X7 0b00110000 /* 5x7 characters, single line */

#define LINE_5X10 0b00110100 /* 5x10 characters */

#define LINES_5X7 0b00111000 /* 5x7 characters, multiple line */

/* Pins mapping */

#ifndef LCD_RS

#defineLCD_RS PORTDbits.RD1

#defineLCD_EN PORTDbits.RD3

#defineLCD_RW PORTDbits.RD2

#defineLCD_DATA4 PORTDbits.RD4

#defineLCD_DATA5 PORTDbits.RD5

#defineLCD_DATA6 PORTDbits.RD6

#defineLCD_DATA7 PORTDbits.RD7

Page 107: Giao Trinh Thi Nghiem VDK

Giáo trình thí nghiệm vi điều khiển ứng dụng

107

#defineLCD_RS_TRIS TRISDbits.TRISD1

#defineLCD_EN_TRIS TRISDbits.TRISD3

#defineLCD_RW_TRIS TRISDbits.TRISD2

#defineLCD_DATA4_TRIS TRISDbits.TRISD4

#defineLCD_DATA5_TRIS TRISDbits.TRISD5

#defineLCD_DATA6_TRIS TRISDbits.TRISD6

#defineLCD_DATA7_TRIS TRISDbits.TRISD7

#endif

//typedef unsigned char unsigned char; // 8-bit unsigned

typedef union _BYTE_VAL

{

unsigned char Val;

struct

{

unsigned char b0:1;

unsigned char b1:1;

unsigned char b2:1;

unsigned char b3:1;

unsigned char b4:1;

unsigned char b5:1;

unsigned char b6:1;

unsigned char b7:1;

} bits;

} BYTE_VAL;

void lcd_init();

unsigned char lcd_busy();

unsigned char lcd_get_byte(unsigned char rs);

void lcd_put_byte(unsigned char a,unsigned char b);

void lcd_gotoxy(unsigned char col, unsigned char row);

void lcd_putc(char c);

void lcd_puts(const char* s);

//#endif