LCD trên FPGA dùng verilog

Print

Phần I : Cơ sở lý thuyết

a, các tín hiệu quan trọng.
LCD_DATA data 8 bit, LCD_RW read/wirte, LCD_EN tín hiệu enable, LCD_ON tín hiệu nguồn vào, LCD_BLON đèn màn hình, LCD_RS chọn đọc dữ liệu hay đọc Command ( Command dùng để chứa 1 số các thiết lập lcd cơ bản )

chú ý các tín hiệu LCD_ON và LCD_BLON luôn là 1
chúng ta quan tâm đến 2 tín hiệu LCD_RW và LCD_RS nếu chỉ hiển thị lên LCD thì tín hiệu LCD_RW = 0, khi cài đặt vị trí hiển thị kí tự thì ta reset LCD_RS xuống mức 0, ghi dữ liệu thì ta set lên 1.
6304647.png

Trong phần hiển thị thì tín hiệu LCD_R/W các bạn luôn đặt là 0, còn LCD_RS khi muốn cấu hình LCD thì là 0, khi hiển thị dữ liệu thì được set lên 1
b, bảng mã kí tự trong ROM, và thanh ghi A

Bảng kí tự gồm chiều ngang là 4 bit cao chiều dọc là 4 bit thấp, bảng mã cung cấp các kí tự đơn giản đã được định nghĩa sẵn muốn hiển thị kí tự A thì dữ liệu vào sẽ là LHLL LLLH tức là 0100 0001 ok quá đơn giản.
Nói qua 1 chút nếu các bạn muốn có thêm những kí tự mới chúng ta cũng có thể định nghĩa 1 kí tự và lưu lại trong bộ tạo kí tự RAM ( đọc thêm ở tài liệu nhé )
c, Tập lệnh điều khiển LCD
LCD cung cấp cho chúng ta 1 số tập lệnh cơ bản để điều khiển LCD ví dụ : clear màn hình, tự động tăng con trỏ ( tự động tăng vị trí ), set chế độ giao tiếp là 4 bit hay 8 bit....
Muốn đọc 8 bit điều khiển LCD thì LCD_RS = 0 và LCD_R/W = 0, phần dưới mình sẽ đến những lệnh cơ bản nhất để tìm hiểu đầy đủ hãy đọc tài liệu
1, Clear Display
Mã lệnh: LCD_DATA= 0 0 0 0 0 0 0 1
lệnh này tắt hiển thị kí tự tất cả các ô sẽ có khoảng trắng, con trỏ về vị trí đầu tiên của LCD
2, Return home
Mã lệnh: LCD_DATA= 0 0 0 0 0 0 1 x
lệnh này trả thanh ghi AC về 0
3, Write DATA
lúc này tín hiệu LCD_RS = 1 và LCD_RW = 0, LCD_DATA = địa chỉ của kí tự cần ghi trong ROM
.............
Phần II: LCD Controller
Trong phần này chúng ta sẽ lập trình quá trình điều khiển đẩy dữ liệu từ input vào output LCD
Cài đặt chỉ hiển thị ( Write ) bằng lệnh
assign LCD_RW = 1'b0;
đoạn mã điều khiển quá trình Write Data
[​IMG]
mình sẽ giải thích đoạn code trên như sau. tín hiệu bắt đầu hiển thị mStart được điều khiển bởi tín hiệu input iStart và preStart
giả sử khi chư có dữ liệu được vào thì preStart và iStart đều bằng 0, khi bắt đầu có tín hiệu thì iStart được set lên 1 và preStart <=0 iStart ( có nghĩa là sau khi chu trình sau thì preStart mới được lên 1) lúc này preStart,iStart = 01 thì mStart sẽ được set lên 1 bắt đầu vào quá trình điều khiển.
thực chất vòng lặp case là 1 máy trạng thái ( đã giới thiệu ở phần FGPA cơ bản )

  1. Đầu tiên ST ( state ) là 0 và được gán là 1 không quan tâm đến tín hiệu đầu vào thực chất là đây chỉ là 1 trạng thái đợi để tín hiệu phải trễ đi 1 khoảng thời gian của 1 xung clock
  2. Tiếp theo ST là 1 tín hiệu LCD_EN được set lên 1 ST được gán là 2
  3. Dùng 1 biến đếm từ 0 - 16 thực chất là đợi khoảng 16 x 1/ tần số của xung clock đầu vào dữ liệu lúc này đang được đẩy vào để hiển thị, chắc các bạn thắc mắc tại sao k thấy tín hiệu LCD_DATA trong máy trạng thái này vì ở bên trên tín hiệu LCD_DATA (output) đã được gán với tín hiệu iDATA (input) và chỉ được hiển thị khi LCD_EN = 1 sau đó ST gán là 3 ( quá hay phải k :D )
  4. Trong khi ST = 3 tín hiệu LCD_EN= 0 , mStart = 0, oDone = 1 (tín hiệu báo hiệu quá trình hiển thị 1 kí tự kết thúc LCD lại đang nhàn rỗi đợi kí tự tiếp theo) Cont = 0, ST = 0, thực chất ở đây các tín hiệu được reset về trạng thái ban đầu.OK
Câu hỏi đặt ra là sao không dùng 1 tín hiệu iStat để điều khiển mStart mà lại cần 2 làm gì cho mệt ra, thực chất là như sau ví dụ bạn đang hiển thị kí tự A trong khi kí tự B lại được đẩy vào thì lúc này preStart làm nhiệm vụ báo cho quá trình hiển thị sau biết là tao đang bận đợi tí ( vì lúc này preStart= 1 và preStart,iStart = 2'b11 nên mStart = 0) không cho phép dữ liệu của kí tự B được vào.OK
Phần III: Hiển thị chuỗi kí tự.
Giả sử chúng ta cần hiển thị từ HELLO WORLD lên dòng 1 LCD, từ chúng ta muốn hiển thị bao gồm 11 kí tự, 1 hàng gồm 16 ô mình sẽ dùng 2 ô đầu tiên và 3 ô cuối cùng của dòng 1 là ký tự trống và 16 ô hàng 2 cũng là kí tự trống.
Muốn hiển thị lên LCD 11 kí tự trên ta phải có 1 bộ chia tần ( chính là module div_frequency trong module chính ) cái này mình nói rồi trong phần FPGA cơ bản.
Tiếp theo 11 kí tự sẽ được điều khiển để trở thành input của module lcd_controller, để làm được điều này ta dùng 1 biến LUT_DATA 9 bit ( gồm 1 bit cao là bit LCD_RS và 8 bit còn lại là 8 bit dữ liệu )
Biến LUT_INDEX chạy từ 0 đến 38:
  1. Từ 0 - 4 chính là cấu hình cho LCD hoạt động ở chế độ 8 bit và clear màn hình ban đầu ( LCD_INTIAL+0 -> LCD_INTIAL+4) tín hiệu LCD_RS = 0
  2. Từ 16 chỉ số tiếp theo là dữ liệu hiển thị lên dòng 1 LCD ( LCD_LINE1+0 -> LCD_LINE1+15) tín hiệu LCD_RS = 1
  3. Chỉ số 17 để cấu hình cho LCD xuống dòng (LCD_CH_LINE) tín hiệu LCD_RS = 0
  4. 16 chỉ số cuối cùng để hiển thị dữ liệu lên dòng 2 LCD (LCD_LINE2+0 -> LCD_LINE2+15) tín hiệu LCD_RS = 1

Cũng giống như LCD_controller cũng cần máy trạng thái để điều khiển quá trình từ input ra output, thì LCD_test ( chính là chương trình hiển thị HELLO WORLD) cũng cần máy trạng thái để điều khiển quá trình lựa chọn các giá trị LCD_DATA và LCD_RS.

 

Bạn có đam mê ngành thiết kế vi mạch và bạn muốn có mức lương 1000 usd cùng lúc bạn

đang muốn tìm một Trung tâm để học vậy hãy đến với ngành vi mạch tại SEMICON

     HotLine: 0972 800 931 Ms Duyên