19

Click here to load reader

8051 giao tiep lcd

Embed Size (px)

DESCRIPTION

giao tiếp LCD với 8051

Citation preview

Page 1: 8051 giao tiep lcd

1

ĐIỀU KHIỂN LCD BẰNG 8051 VỚI BUS 8 BIT

Created by Nguyen Duc Minh. 15-04-2009

CƠ BẢN VỀ LCD VÀ 44780

- Giao tiếp với LCD có hai cách 4 bít (cần 7 đường dây) và 8 bít (cần 11 đường

dây). LCD có 3 đường điều khiển: RS, EN và RW.

- Muốn giao tiếp với LCD trước hết cần sử dụng chân EN (enable=cho phép). Chân

này dùng để thông báo với LCD rằng ta đang gửi dữ liệu. Để gửi dữ liệu tới LCD

chương trình của bạn phải bảo đảm chân EN ở mức thấp (low=0),sau đó thiết lập

các chân dữ liệu và 2 chân điều khiển còn lại. Khi các chân này sẵn sàng, thiết lập

mức cao cho chân EN trong một quãng thời gian nhất định tuỳ thuộc vào LCD mà

bạn dùng (xem datasheet của từng LCD cụ thể) sau đó lại đưa chân EN về mức

thấp.

- Đường dây RS (register select=lựa chọn thanh ghi). Khi RS ở mức thấp, dữ liệu

được xem như là một lệnh hoặc một lệnh đặc biệt (ví dụ như xoá màn hình, đặt vị

trí con trỏ, vvv). Khi RS ở mức 1 (cao=high) dữ liệu đang được gửi là dữ liệu dạng

văn bản (text), dữ liệu này có thể được hiển thị lên màn hình LCD. Ví dụ để hiển

thị chữ “M” lên màn hình LCD bạn phải thiết lập cho chân RS ở mức cao “1”.

- Chân RW là đường điều khiển ghi/đọc (read/write). Khi RW ở mức thấp (0),

thông tin trên bus dữ liệu được ghi vào LCD. Khi RW ở mức cao („1‟) chương

trình sẽ đọc LCD. Chỉ duy nhất một lệnh Get LCD status=đọc trạng thái LCD là

lệnh đọc, còn lại tất cả đều là lệnh ghi. Do vậy chân RW gần như luôn luôn ở mức

thấp (0).

- Bus dữ liệu bao gồm 4 hoặc 8 đường dây (tuỳ thuộc vào chế độ hoạt động mà

người dùng lựa chọn). Trong trường hợp bus dữ liệu là 8 bít, các đường dây được

sử dụng là DB0....DB7.

- Ví dụ cấu hình phần cứng: Như chúng ta đã nói ở trên LCD cần 8 hoặc 11 đường

dây để giao tiếp. Chúng ta xét trường hợp sử dụng 8 bít dữ liệu (bus 8 bít DB0-

DB7) do vậy cần 11 đường dây giao tiếp. Dưới đây là sơ đồ đơn giản nhất nối

LCD với 8051.

Page 2: 8051 giao tiep lcd

2

Như thấy trên hình vẽ chúng ta đang thiết lập mối quan hệ 1-1 giữa các chân của

VĐK 8051 với LCD44780. Khi chúng ta viết chương trình assembly để truy cập

LCD chúng ta coi tương đương các chân của cổng 1và 3 của vi điều khiển 8051

bằng với các chân dữ liệu và điều khiển tương ứng của của LCD bằng cách khai

báo:

DB0 EQU P1.0

DB1 EQU P1.1

DB2 EQU P1.2

DB3 EQU P1.3

DB4 EQU P1.4

DB5 EQU P1.5

DB6 EQU P1.6

DB7 EQU P1.7

EN EQU P3.7

RS EQU P3.6

RW EQU P3.5

DATA EQU P1

Với các thiết lập như trên chúng ta có thể chúng ta có thể tham chiếu tới các

đường dây I/O của một cổng của vi điều khiển 8052 với tên của các chân LCD

tương ứng. Ví dụ để thiết lập chân RW lên mức cao chúng ta có lệnh:

SETB RW ; (sét bít cổng P3.5 lên 1)

Cũng như vậy, chúng ta có thể xoá đường dây EN bằng lệnh

CLR EN ;clear EN=P3.7

- Các thao tác với đường dây điều khiển EN (enable)

Page 3: 8051 giao tiep lcd

3

Như đã đề cập ở trên, đường dây EN được dùng để nói với LCD rằng bạn đã sẵn

sàng để thực thi một lệnh mà bạn đã chuẩn bị trên bus dữ liệu và trên các đường

dây điều khiển khác. Chú ý rằng đường dây điều khiển EN phải được lên mức cao

trước khi một lệnh được gửi tới LCD hoặc xuống mức thấp sau khi một lệnh được

gửi tới LCD ngoại trừ trường hợp mà ở đó lệnh là đọc hoặc ghi, văn bản (text)

hoặc lệnh (instruction). Tóm lại, bạn phải luôn luôn xắp xếp EN sao cho khi trao

đổi tin với LCD thì EN là cách mà LCD biết được bạn đang nói chuyện với nó.

Nếu bạn không lập/xoá chân EN một cách phù hợp thì LCD không bao giờ hiểu

được rằng bạn đang nói chuyện với nó.

Do vậy trước khi tương tác với LCD theo bất kỳ cách nào, bạn sẽ luôn phải đưa

chân EN về mức thấp bằng lệnh sau:

CLR EN

Sau đó khi đã hoàn thành việc thiết lập lệnh của chúng ta với các chân điều khiển

khác và bus dữ liệu, chúng ta luôn phải đưa chân EN về mức cao:

SETB EN

Đường dây EN phải giữ ở mức cao trong một khoảng thời gian nhất định tuỳ theo

datasheet của từng loại LCD. Thông thường nó vào khoảng 250 nano giây, nhưng

tốt nhất là nên kiểm tra lại trong datasheet cho chắc ăn. Trong trường hợp 8051

chạy với đồng hồ thạch anh 12MHz một lệnh cần 1,08uS để thực thi do vậy chân

EN có thể thoả mãn điều kiện 280 nano giây ở mức cao chỉ trong 1lệnh. Tuy nhiên

với các vi điều khiển nhanh hơn (ví dụ như DS89C420 thực hiện 1 lệnh trong 90

nano giây với tần số thạch anh 11,0592MHz thì chúng ta cần một số lệnh NOP để

tạo ra độ trễ trong khi EN vẫn giữ ở mức cao). Số lệnh NOP (No-

operation=Không làm gì cả) phải chèn vào tuỳ thuộc vào loại vi điều khiển bạn

dùng và tần số thạch anh mà bạn chọn.

Lệnh này được thực thi bởi LCD tại thời điểm đường dây EN chuyển xuống mức

thấp với lệnh CLR EN cuối cùng.

Chú ý: LCD biên dịch và thực thi lệnh của chúng ta ngay tại thời điểm chân EN được

đưa xuống mức thấp. Nếu bạn không bao giờ đưa chân EN xuống mức thấp thì lệnh của bạn

không bao giờ được thực thi.Hơn nữa khi bạn đưa chân EN xuống mức thấp và LCD thực thi lệnh

của bạn, nó yêu cầu một khoảng thời gian xác định nào đó để thực hiện lệnh. Thời gian cần thiết

để thực thi một lệnh tuỳ thuộc vào lệnh và tốc độ của thạch anh được gắn với lối vào bộ tạo dao

động của LCD 44780.

KIỂM TRA TRẠNG THÁI BẬN CỦA LCD

Như đã biết, LCD phải cần một quãng thời gian để thực hiện lệnh, phương pháp

chờ đợi thì không được “mềm dẻo” lắm, nếu tần số thạch anh được thay đổi thì

Page 4: 8051 giao tiep lcd

4

phần mềm viết trên 8051 cũng phải thay đổi theo, cũng giống như khi thay đổi

một LCD khác tương thích với LCD HD44780.

Nhiều phương pháp lập trình sử dụng lệnh “Get LCD Status” để xác định xem

rằng có phải LCD vẫn đang bận thực thi lệnh cuối cùng nhận được hay không.

Lệnh “Get LCD status” sẽ trả lại cho chúng ta hai bít thông tin (tidbit) hữu

ích.Thông tin hữu ích cho chúng ta bây giờ là bit DB7. Nhìn chung khi chúng ta

đưa ra lệnh “Get LCD Status” thì LCD sẽ ngay lập tức lập bít DB7 hoặc xoá bít

DB7 để thể hiện rằng LCD không bận nữa. Chương trình của chúng ta có thể

“hỏi” LCD một cách liên tục cho tới khi DB7 chuyển xuống mức thấp thể hiện

rằng LCD không còn bận nữa. Khi đó chúng ta có thể tự do tiếp tục và gửi lệnh

tiếp theo. Như vậy chúng ta có thể sử dụng đoạn mã sau đây mỗi khi chúng ta gửi

một lệnh tới LCD. Tốt nhất là viết nó thành một đoản trình như sau:

WAIT_LCD:

CLR EN ;Start LCD command CLR RS ;It's a command

SETB RW ;It's a read command MOV DATA,#0FFh ;Set all pins to FF initially SETB EN ;Clock out command to LCD

MOV A,DATA ;Read the return value JB ACC.7,WAIT_LCD ;If bit 7 high, LCD still busy

CLR EN ;Finish the command CLR RW ;Turn off RW for future commands RET

Bài thực tập của chúng ta sẽ gửi một lệnh đến LCD và gọi chương trình WAIT_LCD cho

tới khi lệnh đó được thực hiện hoàn tất bởi LCD. Điều này cũng sẽ bảo đảm rằng chương

trình của chúng ta phù hợp cho mọi LCD mặc cho nó nhanh hay chậm mức nào.

Chú ý: đoản trình trên thực hiện công việc là “chờ” LCD, nhưng khi sử dụng trong các ứng dụng

thực tế chúng ta cần cải thiện một chút: khi ghi vào LCD, nếu LCD trở nên “Không bao giờ hết bận” thì

chương trình của chúng ta sẽ dẫn đến bị “treo” để chờ DB7 chuyển xuống mức thấp. Nếu điều này không

bao giờ xảy ra (DB7 chuyển xuống mức thấp) thì chương trình sẽ bị đóng băng (rơi vào 1 vòng lặp bất

tận). Tất nhiên là điều này không bao giờ xảy ra và sẽ không xảy ra khi phần cứng làm việc tốt. Nhưng

trong các ứng dụng thực tế sẽ là sáng suốt khi chúng ta đặt một kiểu hạn chế thời gian vào độ trễ. Ví

dụ:một giá trị max bằng 256 để chờ tín hiệu bận chuyển xuống mức thấp. Điều này sẽ bảo đảm rằng ngay

cả khi LCD lỗi chương trình cũng sẽ không bị đóng băng.

KHỞI TẠO LCD

Page 5: 8051 giao tiep lcd

5

Trước khi có thể thực sự sử dụng LCD, chúng ta phải khởi tạo và config nó. Việc này

được thực hiện bằng cách gửi một số lệnh khởi tạo tới LCD.

Lệnh đầu tiên chúng ta gửi tới LCD phải nói cho LCD biết chúng ta trao đổi với LCD

theo chế độ 4 bít hay 8 bít (bus 4 bít hay 8 bít). Chúng ta cũng phải lựa chọn font ký tự

5x8 cho LCD. Hai lựa cọn này được thực hiện bằng việc gửi giá trị 38h tới LCD như là

một lệnh. Ở phần trước chúng ta thấy rằng đường dây RS phải ở mức thấp nếu chúng ta

đang gửi một lệnh tới LCD. Do vậy để gửi lệnh 38h tới LCD chúng ta phải thực hiện lệnh

sau đây của 8051:

CLR RS

MOV DATA,#38h

SETB EN

CLR EN

LCALL WAIT_LCD

Chú ý: Lệnh 38h của LCD thực sự là tổng của một số bít lựa chọn. Bản thân lệnh này là lệnh 20h

(function set). Mặc dầu vậy chúng ta cộng giá trị 10h vào để thể hiện rằng bus dữ liệu là 8 bít, cộng 8h

vào để thể hiện rằng việc hiển thị là hai hàng.

Bây giờ chúng ta đã gửi xong byte đầu tiên của chuỗi công việc khởi tạo. Byte thứ hai

của chuỗi công việc khởi tạo là lệnh 0Eh. Vì vậy chúng ta phải lặp lại đoạn mã trên,

nhưng với lệnh mới. Mã lệnh có dạng:

CLR RS

MOV DATA,#0Eh

SETB EN

CLR EN

LCALL WAIT_LCD

Chú ý:Lệnh 0Eh thực sự là lệnh 08h cộng với 04h để bật LCD lên và cộng thêm 02h để config

LCD sao cho con trỏ được hiển thị.

Byte cuối cùng chúng ta cần phải gửi để config các tham số hoạt động của LCD là 06h.

Lệnh có dạng:

CLR RS

MOV DATA,#06h

SETB EN

CLR EN

LCALL WAIT_LCD

Chú ý:Lệnh 06h thực sự là lệnh 04h cộng với 02h để config LCD sao cho mỗi lần chúng ta gửi tới

nó một ký tự thì vị trí con trỏ phải tự động dịch sang phải một vị trí.

Cuối cùng thì toàn bộ mã lệnh khởi tạo có dạng như sau:

Page 6: 8051 giao tiep lcd

6

INIT_LCD: CLR RS

MOV DATA,#38h

SETB EN

CLR EN

LCALL WAIT_LCD

CLR RS

MOV DATA,#0Eh

SETB EN

CLR EN

LCALL WAIT_LCD

CLR RS

MOV DATA,#06h

SETB EN

CLR EN

LCALL WAIT_LCD

RET

Khi thực thi xong chuỗi lệnh này thì LCD đã được khởi tạo dầy đủ và sẵn sàng cho chúng

ta gửi dữ liệu cần hiển thị lên nó.

XOÁ MÀN HÌNH HIỂN THỊ

Sau khi LCD được khởi tạo lần đầu tiên, màn hình sẽ tự động bị xoá bởi bộ điều khiển

44780. Mặc dầu vậy sẽ tốt hơn nếu chúng ta tự làm điều này sao cho bạn có thể hoàn toàn

chắc chắn rằng việc hiển thị là theo ý bạn. Do đó tốt nhất là chúng ta xoá màn hình hiển

thị mỗi khi khởi tạo LCD xong.

Một lệnh LCD tồn tại để thực hiện việc này. Không ngạc nhiên gì nếu đây là lệnh 01h.

Khi việc xoá màn hình là một chức năng thường được dùng thì tốt nhất là ta viết nó dưới

dạng một đoản trình con.

Mã lệnh như sau:

CLEAR_LCD:

CLR RS

MOV DATA,#01h

SETB EN

CLR EN

LCALL WAIT_LCD

RET

Từ đây chúng ta có thể xoá màn hình bất kỳ lúc nào bằng việc thực hiện lệnh

LCALL CLEAR_LCD

Chú ý: Sau khi xoá màn hình thì con trỏ sẽ nằm ở góc cao nhất bên tay trái (hàng thứ nhất, cột

thứ nhất).

Page 7: 8051 giao tiep lcd

7

GHI VĂN BẢN (TEXT) RA LCD

Đây là phần việc mong đợi nhất và hay dùng nhất, chúng ta hãy viết nó thành đoản trình

con như sau:

WRITE_TEXT:

SETB RS

MOV DATA,A

SETB EN

CLR EN

LCALL WAIT_LCD

RET

Đoản trình WRITE_TEXT mà chúng ta viết bên trên sẽ gửi ký tự trong thanh ghi tích luỹ

ra LCD và LCD đến lượt mình sẽ hiển thị nó lên. Do vậy để hiển thị text trên LCD, tất cả

những gì chúng ta cần làm là nạp vào thanh ghi tích luỹ byte cần hiển thị và gọi đoản

trình con. Thật dễ phải không nào :-))

MỘT CHƯƠNG TRÌNH “HELLO WORLD”

Bây giờ chúng ta đã có các đoản trình cần thiết để viết một chương trình. Hãy viết một

chương trình hiển thị chữ hello world lên màn hình LCD. Chương trình như sau:

LCALL INIT_LCD

LCALL CLEAR_LCD

MOV A,#'H'

LCALL WRITE_TEXT

MOV A,#'E'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#' '

LCALL WRITE_TEXT

MOV A,#'W'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#'R'

LCALL WRITE_TEXT

Page 8: 8051 giao tiep lcd

8

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'D'

LCALL WRITE_TEXT

Chương trình hello world trên thực hiện việc khởi tạo LCD, xoá màn hình LCD và hiển

thị chữ “Hello world” ở góc cao bên trái màn hình.

VỊ TRÍ CON TRỎ

Trên đây là chương trình hiển thị chữ “hello world” đơn giản lên góc cao bên trái màn

hình. Mặc dầu vậy nếu chúng ta muốn chữ “world” hiển thị ở vị trí dòng 2 cột thứ 10 thì

sao ? Việc này rất đơn giản và thực tế nó cũng đơn giản thôi :-)) Ngoại trừ một vài hiểu

biết về việc thiết kế LCD. 44789 có chứa sẵn một số cố định bộ nhớ dùng cho việc hiển

thị. Tất cả các text gửi tới LCD đều được chứa trong bộ nhớ và 44780 lần lượt đọc bộ

nhớ này để hiển thị dữ liệu lên màn LCD của nó. Bộ nhớ này có thể được biểu diễn dưới

dạng bản đồ bộ nhớ như sau:

Trong bản đồ bộ nhớ ở trên vùng có màu xanh là vùng hiển thị nhìn thấy được. Như bạn

có thể thấy nó bao gồm 2 hàng, mỗi hàng có 16 ký tự. Các con số trong mỗi một ô chính

là địa chỉ bộ nhớ tương ứng với vị trí trên màn hình.

Ký tự đầu tiên ở góc cao bên trái có địa chỉ bộ nhớ là 00, vị trí tiếp theo là 01...vvv cứ

như vậy cho tới ký tự cuối cùng góc cao bên tay phải có địa chỉ là 0F. Mặc dầu vậy ký tự

ở dòng thứ hai có địa chỉ 40h. Nó có nghĩa rằng nếu chúng ta ghi một ký tự tới vị trí cuối

cùng của dòng đầu tiên và sau đó ghi một ký tự thứ hai, thì ký tự thứ hai này sẽ không

xuất hiện trên dòng thứ hai. Đó là vì ký tự thứ hai sẽ được ghi vào địa chỉ 10h trong khi

đó dòng thứ hai lại bắt đầu ở địa chỉ 40h.

Vì thế chúng ta cần phải gửi một lệnh tới LCD để nói với nó về vị trí của con trỏ trên

dòng thứ hai. Lệnh thiết lập vị trí con trỏ (set cursor position) có giá trị 80h. Với lệnh này

chúng ta phải cộng địa chỉ của vị trí nơi mà chúng ta muốn con trỏ xuất hiện. Trong ví dụ

của chúng ta, ta muốn hiển thị chữ “world” ở dòng 2 vị trí số 10.

Tham chiếu tới bản đồ bộ nhớ, chúng ta thấy rằng vị trí ký tự thứ 10 ở dòng 2 có địa chỉ

4Ah. Do đó trước khi viết từ “world” tới LCD chúng ta phải gửi lệnh thiết lập vị trí con

trỏ “set cursor position”- giá trị lệnh sẽ bằng 80h cộng với địa chỉ 4Ah. 80h+4Ah=CAh.

Do đó chúng ta gửi lệnh CAh tới LCD thì LCD sẽ định vị vị trí con trỏ tại dòng 2 ô số 10.

Mã lệnh như sau:

Page 9: 8051 giao tiep lcd

9

CLR RS

MOV DATA,#0CAh

SETB EN

CLR EN

LCALL WAIT_LCD

Mã trên đây giúp chúng ta hiển thị đúng mong muốn của mình: hiển thị chữ “world” ở

dòng 2 ô số 10. Vậy mã lệnh đầy đủ cho việc hiển thị chữ hello world theo mong muốn

phải có thêm đoạn mã trên chèn vào. Kết quả ta có mã lệnh đầy đủ như sau:

LCALL INIT_LCD

LCALL CLEAR_LCD

MOV A,#'H'

LCALL WRITE_TEXT

MOV A,#'E'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

CLR RS

MOV DATA,#0CAh

SETB EN

CLR EN

LCALL WAIT_LCD

MOV A,#'W'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#'R'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'D'

LCALL WRITE_TEXT

Page 10: 8051 giao tiep lcd

10

KẾT LUẬN

Mã lệnh trên trình bày những vẫn đề cơ bản về việc lập trình hiển thị cho LCD. Rõ ràng

rằng nó không phải là tất cả. 44780 có một số option cho các lệnh mà ta không đề cập ở

đây, cũng như còn rất nhiều lệnh khác truy cập đến các chức năng mà ta chưa nhắc tới ví

dụ như hiển thị các thanh bar..vvv. Mặc dầu vậy hi vọng với những gì trình bày các bạn

sẽ có hướng đi đúng trong việc lập trình cho LCD.

ĐIỀU KHIỂN LCD BẰNG 8051 VỚI BUS 4 BIT

Ở phần trước chúng ta đã nói đến việc điều khiển LCD theo phương pháp bus 8 bít, lần

này chúng ta tiếp tục xem xét phương pháp làm việc với LCD qua bus 4 bít.

Khi làm việc với LCD dựa trên 44780 bằng bus8 bít chúng ta cần 11 đường dây nối,

nhưng với chế độ bus 4 bít chúng ta chỉ cần 7 đường dây nối, trong trường hợp chân R/W

nối đất thì thực tế chỉ có thể dùng 6 đường dây nối mà thôi. Loại cấu hình này chúng ta

rất hay thấy trong các ứng dụng. Thay vì đọc cờ bận (busy flag)-đôi khi tạo khó khăn hơn

cho chúng ta như trong trường hợp bus 8 bít- chúng ta phải sử dụng các vòng lặp trễ. Các

vòng lặp trễ này sẽ phải tính toán lại khi chúng ta sử dụng các tần số thạch anh khác nhau

cho vi điều khiển 8051. Ở đây chúng ta sẽ tìm hiểu một cách mà có vẻ như phức tạp hơn

một chút, đó là sử dụng cờ bận (busy flag) và do đó không phụ thuộc vào tần số thạch

anh được sử dụng. Điều bất lợi duy nhất khi sử dụng phương pháp giao tiếp 4 bít đó là

các lệnh phải được gửi theo từng 2 nibble và do đó sẽ tốn thời gian hơn một chút. Nhưng

trong thực tế vấn đề này không quan trọng và ta không cần quan tâm đến nó nhiều lắm.

CẤU HÌNH PHẦN CỨNG

Sự khác nhau duy nhất giữa phương pháp giao tiếp 4 bít và 8 bít đó là các bít DB0…DB3

trên phía màn hình hiển thị LCD. Các đường dây này không được nối với bộ vi điều

khiển. Hãy thả nổi các đường dây này, không được nối chúng với đất giống như trường

hợp dây R/W. Chúng ta hãy khai báo

DB4 EQU P1.4

DB5 EQU P1.5

DB6 EQU P1.6

DB7 EQU P1.7

EN EQU P3.7

RS EQU P3.6

Page 11: 8051 giao tiep lcd

11

RW EQU P3.5

DATA EQU P1

Để biết về cách điều khiển các chân điều khiển của LCD, hãy đọc phần đầu của tài liệu

này. Trong chế độ làm việc 4 bít chúng ta phải đọc và ghi các byte dữ l iệu và các byte

lệnh trong hai nibble riêng rẽ. Để tạo ra sự thay đổi không đáng kể so với ví dụ ban đầu,

chúng ta tạo ra hai đoản trình con: đoản trình con thứ nhất để đọc hai nibble từ LCD và

đoản trình co thứ hai ghi 2 nibble tới LCD. Thêm vào đó, việc chuyển trạng thái đường

dây EN cũng được thực hiện trong các đoản trình này do chúng ta sẽ phải lật trạng thái của đường dây này sau mỗi khi truyền đi một nibble.

Mã lệnh như sau:

READ_2_NIBBLES:

ORL DATA,#0F0 ;Be sure to release datalines (set

outputlatches

;to '1') so we can read the LCD

SETB EN

MOV A,DATA ;Read first part of the return

value (high nibble)

CLR EN

ANL A,#0F0h ;Only high nibble is usable

PUSH ACC

SETB EN

MOV A,DATA ;Read second part of the return value (low

nibble)

CLR EN

ANL A,#0F0h ;Only high nibble is usable

SWAP A ;Last received is actually low nibble, so

put it in place

MOV R7,A

POP ACC

ORL A,R7 ;And combine it with low nibble

RET

WRITE_2_NIBBLES:

PUSH ACC ;Save A for low nibble

ORL DATA,#0F0h ;Bits 4..7 <- 1

ORL A,#0Fh ;Don't affect bits 0-3

ANL DATA,A ;High nibble to display

SETB EN

CLR EN

POP ACC ;Prepare to send

SWAP A ;...second nibble

ORL DATA,#0F0h ; Bits 4...7 <- 1

ORL A,#0Fh ; Don't affect bits 0...3

Page 12: 8051 giao tiep lcd

12

ANL DATA,A ;Low nibble to display

SETB EN

CLR EN

RET

Như chúng ta thấy trong đoản trình WRITE_2_NIBBLES có một số lệnh logic (ORL,

ANL) các chân I/O từ P1.0 tới P1.3 không bị ảnh hưởng. Các đường dây tương ứng này

tự do vào, ra và không bị ảnh hưởng bởi đoản trình này.

KIỂM TRA TRẠNG THÁI BẬN CỦA LCD

WAIT_LCD:

CLR RS ;It's a command

SETB RW ;It's a read command

LCALL READ_2_NIBBLES ;Take two nibbles from LCD in A

JB ACC.7,WAIT_LCD ;If bit 7 high, LCD still busy

CLR RW ;Turn off RW for future commands

RET

KHỞI TẠO LCD

Trước khi bạn có thể thực sự sử dụng LCD bạn phải khởi tạo và cấu hình cho nó. Việc

này được thực hiện bằng cách gửi một số các lệnh khởi tạo tới LCD.

Lệnh đầu tiên chúng ta gửi phải nói cho LCD biết rằng chúng ta đang thực hiện trao đổi

thông tin với nó. Chúng ta cũng lựa chọn kiểu phông ký tự là 5x8. Hai option này đwọc

lựa chọn bằng cách gửi giá trị 28h tới LCD như là một lệnh. Sau khi cấp nguồn cho LCD

nó luôn ở trong chế độ làm việc 8 bít. Do chỉ có 4 bít được kết nối (trường hợp mà ta

đang xét), lệnh đầu tiên phải được gửi hai lần: lần đầu tiên để chuyển sang chế độ 4 bít (4

bít thấp của lệnh không nhìn thấy), lần thứ hai để gửi nó như là hai nibble sao cho phần

thấp được nhận.

Mã lệnh như sau:

CLR RS

CLR RW

CLR EN

SETB EN

MOV DATA,#28h

CLR EN

LCALL WAIT_LCD

MOV A,#28h

LCALL WRITE_2_NIBBLES ;Write A as two separate nibbles to LCD

LCALL WAIT_LCD

Page 13: 8051 giao tiep lcd

13

Chú ý: Lệnh 28h của LCD thực ra là tổng của các bít option. Bản thân lệnh có giá trị 20h

(Function set). Mặc dầu vậy chúng ta phải cộng thêm gia strị 0h vào để báo hiệu rằng bus dữ liệu là 4 bít

và sau đó cộng thêm 8h để báo hiệu rằng việc hiển thị là hai hàng.

Chúng ta đã gửi byte đầu tiên của chuỗi lệnh khởi tạo. Byte thứ hai của chuỗi lệnh khởi

tạo là 0Eh. Chúng ta vẫn phải lặp lại mã lệnh khởi tạo như ở trên nhưng có khác một

chút. Mã lệnh có dạng:

MOV A,#0Eh

LCALL WRITE_2_NIBBLES ;Write A as two separate nibbles to LCD

LCALL WAIT_LCD

Chú ý: Lệnh 06h thực ra là lệnh 04h cộng với 02h để config LCD sao cho mỗi lần chúng ta gửi dữ liệu tới

nó thì con trỏ của LCD phải dịch đi 1 vị trí.

Cuối cùng thì mã lệnh khởi tạo có dạng như sau:

INIT_LCD:

CLR RS

CLR RW

CLR EN

SETB EN

MOV DATA,#28h

CLR EN

LCALL WAIT_LCD

MOV A,#28h

LCALL WRITE_2_NIBBLES

LCALL WAIT_LCD

MOV A,#0Eh

LCALL WRITE_2_NIBBLES

LCALL WAIT_LCD

MOV A,#06h

LCALL WRITE_2_NIBBLES

LCALL WAIT_LCD

RET

Khi chạy đoạn mã trên chúng ta đã khởi tạo LCD và thiết lập các chế đô phù hợp để có

thể gửi dữ liệu ra LCD.

XÓA MÀN HÌNH HIỂN THỊ

CLEAR_LCD:

CLR RS

MOV A,#01h

LCALL WRITE_2_NIBBLES ;Write A as two separate nibbles to LCD

LCALL WAIT_LCD

RET

Page 14: 8051 giao tiep lcd

14

GHI VĂN BẢN TEXT RA LCD

WRITE_TEXT:

SETB RS

LCALL WRITE_2_NIBBLES

LCALL WAIT_LCD

RET

CHƯƠNG TRÌNH “HELLO WORLD” LCALL INIT_LCD

LCALL CLEAR_LCD

MOV A,#'H'

LCALL WRITE_TEXT

MOV A,#'E'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#' '

LCALL WRITE_TEXT

MOV A,#'W'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#'R'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'D'

LCALL WRITE_TEXT

Chương trình “”hello world” ở trên khi được thực thi sẽ khởi tạo LCD, xoá LCD và hiển

thị chữ Hello world trên góc cao bên trái của màn hình hiển thị. Như bạn có thể thấy

không có sự khác biệt giữa chương trình làm việc với LCD qua giao tiếp 8 bít và chương

trình làm việc với LCD qua giao tiếp 4 bít.

VỊ TRÍ CON TRỎ

Chúng ta lại viết chường trình để hiển thi chữ “world” trên dòng thứ hai, ô số 10. Mã chương trình như sau:

Page 15: 8051 giao tiep lcd

15

LCALL INIT_LCD

LCALL CLEAR_LCD

MOV A,#'H'

LCALL WRITE_TEXT

MOV A,#'E'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

CLR RS

MOV A,#0C9h

LCALL WRITE_2_NIBBLES

LCALL WAIT_LCD

MOV A,#'W'

LCALL WRITE_TEXT

MOV A,#'O'

LCALL WRITE_TEXT

MOV A,#'R'

LCALL WRITE_TEXT

MOV A,#'L'

LCALL WRITE_TEXT

MOV A,#'D'

LCALL WRITE_TEXT

KẾT LUẬN

Trên đây là các kiến thức cơ bản để chúng ta làm việc với LCD khi dùng họ vi điều khiển

8051. Sau đây là một số kiến thức phụ trợ về các loại LCD khác nhau:

The HD44780 or compatible controller is basically designed to build LCDisplays with one or two lines with a maximum of 40 characterpositions each. A single HD44780 is able to display two lines of 8 characters each. If we want more, the HD44780 has to be expanded with one or

more expansion chips, like the HD 44100 (2 x 8 characters expansion) or the HD 66100 (2 x 16 characters expansion). Seen from the HD44780, the first line starts with 00h; the second line

with 40h.

LAYOUT OF DISPLAY MODULES WITHOUT EXPANSION CHIP(S):

1. 8 characters x 1 line

First Line: 00 01 02 03 04 05 06 07

2. The module has to be initialised as a ONE line display.

Page 16: 8051 giao tiep lcd

16

3. 8 characters x 2 lines

First Line:

Second Line: 00 01 02 03 04 05 06 07

40 41 42 43 44 45 46 47

4. To use the second line, don't forget to initialise the display as a TWO lines display. 5. 16 characters x 1 line

First Line: 00 01 02 03 04 05 06 07 40 41 42 43 44 45 46 47

6. In fact, in this case the two lines are placed one after another. So when we want to use the display from the ninth position, it has to be initialised as if it were a TWO lines display!

Mind the ninth position is addressed as 40h, not 08h.

LAYOUT OF DISPLAY MODULES WITH EXPANSION CHIP(S)

1. 16 characters x 1 line

First Line: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

2. On the outside this module looks the same like #3 above, but all characterpositions are

addressed continuously. The module has to be initialised as a ONE-line display. 3. 20 characters x 1 line

First Line: 00 01 02 03 04 05 06 07 08 09 40 41 42 43 44 45 46 47 48 49

4. In fact, from HD44780 point of view, in this case two lines are placed one after another. So when we want to use the display from the eleventh position, it has to be initialised as

if it were a TWO lines display! Mind the eleventh position is addressed as 40h, not 0Ah. 5. 40 characters x 1 line

First Line: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11...27

6. The module has to be initialised as a TWO lines display, if we also want to use the second line.

7. 24 characters x 2 lines

First Line:

Second

Line:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13

14 15 16 17

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53

54 55 56 57

8. The module has to be initialised as a TWO lines display, if we also want to use the second line.

9. 40 characters x 2 lines

Page 17: 8051 giao tiep lcd

17

First Line:

Second Line: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11... 27

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51... 67

10. The module has to be initialised as a TWO lines display, if we also want to use the second line. This is also the maximum configuration which is possible with one HD44780 + extension chips (80 characters).

11. 16 characters x 4 lines

First Line:

Second Line:

Third Line:

Fourth Line:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F

10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F

50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F

12. To use the second and the fourth line, the module has to be initialised as a TWO lines display (strange, no?). In fact, the third line is continuous to the first line, and the fourth

line is continuous two the second line (from addressing point of view). 13. 20 characters x 4 lines

First Line:

Second Line:

Third Line:

Fourth Line:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53

14 15 16 17 18 19 1A 1B 1C 1D 1E 1F 20 21 22 23 24 25 26 27

54 55 56 57 58 59 5A 5B 5C 5D 5E 5F 60 61 62 63 64 65 66 67

14. To use the second and the fourth line, the module has to be initialised as a TWO lines display. In fact, the third line is continuous to the first line, and the fourth line is continuous two the second line (from addressing point of view).

15. 24 characters x 4 lines

First Line:

Second

Line:

Third Line:

Fourth

Line:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12 13

14 15 16 17

20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F 30 31 32 33

34 35 36 37

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52 53

54 55 56 57

60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F 70 71 72 73

74 75 76 77

16. To use the THIRD and the FOURTH line, the module has to be initialised as a TWO lines display. Look out! There is a small 'view'-gap between the address ing of the first and the second line (and the third and fourth line respectively).

17. 40 characters x 4 lines

First Line:

Second

Line:

Third Line:

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12...

27

40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52...

67

00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F 10 11 12...

27

Page 18: 8051 giao tiep lcd

18

Fourth Line: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F 50 51 52... 67

18. These modules uses two HD44780's (each with expansion chips) and can be seen as two 40 x 2 modules in one. All wiring is common, except for the EN (enable) lines, which are

separate to drive each HD44780 apart.

Tip:If you are not sure what configuration your display has, you can do use the following trick: Imagine you have a 16 characters x 1 line display. You want to know if it has configuration #3 in

the first section or #1 in this section. Just connect the contrast input of your module to GND (= maximum contrast) and apply only power (+5V) to the module. The module will be initialised by an internal routine, which puts it in single line modus. Only the positions that belong to the first

line will be black.

Conclusion: If all positions are black, we have a module as described under #1 of this section. If only the first 8 characters are black, you have a module as described under # of the previous

section.

Not all possible module configurations are described here, but with the help of this information you must be able to work with different modules. Some (functional, not necessary pin-) compatible chips; to help you to determine your module:

Controller: HD44780 (Hitachi) KS0066 (Samsung)

SED1278 (Epson)

Expansion 8 x 2: HD44100 (Hitachi)

KS0061 (Samsung) M5259 (OKI)

Expansion 12 x 2: SED1181 (Epson)

Expansion 16 x 2: HD66100 (Hitachi)

Note: Some modules have black blobs which are chips direct mounted on the pc-board, covered with some resin substantion, so the chips are not recognisable.

Page 19: 8051 giao tiep lcd

19