[Matrix LED] Bài 4: Hiển thị chữ trên led ma trận 8×32

matrix 8x32

Trong bài này mình sẽ hướng dẫn các bạn làm việc với nhiều led ma trận hơn để hiển thị chữ cái mình muốn lên màn hình led ma trận.Cụ thể, chúng ta sẽ làm việc với 4 tấm matrix led 8×8, tức là led ma trận 8×32

Giới thiệu IC mở rộng ngõ ra 74hc595

Do dùng tới 4 tấm nên 32 chân của 89s52 không thể đủ để điều khiển. Mình sẽ cần tới sự hỗ trợ của ic mở rộng ngõ ra 74hc595, hay còn gọi là thanh ghi dịch 8 bit

Còn ic này cũng thuộc vào dòng kinh điển rồi, trên mạng cũng rất nhiều bài viết nói về ic này nên mình không nói lại nữa. Các bạn chưa biết có thể tham khảo tại đây:

Với ic mở rộng ngõ ra 74hc595. Chỉ với 3 chân của vi điều khiển, chúng ta có thể mở rộng ra vô cực chân theo ý thích. Nhưng nhược điểm của nó là làm chậm tốc độ của vi điều khiển đi do dữ liệu được chuyển tự dạng song song sang nối tiếp. Hãy tượng tượng như kiểu dữ liệu của bạn phải xếp hàng để đẩy đi lần lượt từng bit một thay vì tất cả đi cùng nhau đến đích vậy.

Do vậy, hãy tính toán số lượng chân mở rộng cho hợp lí với tốc độ của MCU, nếu không bạn sẽ phải giảm tần số quét xuống dẫn tới hình ảnh hiển thị không được đẹp. Nếu cố tình tăng tần số quét lên thì MCU dành hết tài nguyên cho việc quét led, sẽ không thể làm được việc khác.

Project này. Mình sẽ sử dụng 1 Port của 89s52 để quét led và 4 con 74hc595 mắc nối tiếp để mở rộng ngõ ra. Như vậy, tổng số chân cần dùng chỉ là 11 chân.

Sơ đồ nguyên lí

3 chân mở rộng ngõ ra sẽ được nối vào IC74hc595 và 32 đầu ra nối vào 32 cột LED
8 chân âm quét hàng sẽ được nối vào PORT P2 để quét hàng. Do vậy phương pháp quét vẫn là 1/8
Thạch anh mình sử dụng sẽ là 24Mhz để đảm bảo tốc độ nhanh nhất có thể

Xây dựng bộ font ASCII

Mình sẽ lại dùng phần mềm LCD font maker để tạo font
Các bạn để ý sẽ thấy các chân có trọng số cao ( Q7 -> Q0 ) nối với các led từ trái sang phải. Do vậy led bên trái sẽ có trọng số cao hơn bên phải. Hãy setup ở phần mềm LCD font maker sao cho pixel bên trái là bit cao hơn

Chọn dòng 1 nhé

Giờ hãy tạo bộ font theo đúng thứ tự của mã ASCII, bắt đầu từ kí tự Space. Đây là bộ font mình đã lấy sẵn

Xây dựng module ngắt hiện thị dữ liệu từ bộ đệm

Do có 8×32 con LED nên sẽ cần 8×32 bit dữ liệu cho bộ đệm. Mà cứ 8 bit là 1 byte nên ta cần 32byte cho bộ đệm. Có 2 cách để thiết lập bộ đệm như sau:

  1. unsigned char Buffer_display[32];
  2. unsigned char Buffer_display[8][4];

Với cách 1: bộ đệm sẽ là mảng 1 chiều, còn cách 2 thì là mảng 2 chiều. Mình sẽ khởi tạo mảng với 2 chiều để việc thao tác với mảng dễ dàng thuận tiện hơn

Mối quan hệ giữa bộ đệm và LED thật

Bây giờ xây dựng hàm ngắt để đẩy data ra. Có thể nói hàm ngắt y chang như ở bài 3, chỉ khác 1 chút ở chỗ đẩy dữ liệu ra IO thôi. Mà IO ở đây là 4 con ic74hc595 nối tiếp nên trước tiên dựng 1 hàm đẩy dữ liệu ra HC595 nhé

Hàm ngắt Timer1 bắn dự liệu trong bộ đệm ra

Vậy là xong, công việc hiển thị đã có ngắt lo. Bây giờ chúng ta chỉ việc xây dựng các hàm để bắn dữ liệu vào bộ đệm.

Hãy thử gọi hàm này trong main để in ra chữ ‘A’ nhé !

matrix 3x32

Matrix_guikitu(‘A’);

Giải thích

Hàm này yêu cầu nạp vào biến txt chính là kí tự mà ta muốn in ra.
Vòng lặp for tới 7 vì mỗi kí tự được tạo với font gồm 7 byte data.
Chúng ta phải trừ txt đi 32 vì mảng font của ta bắt đầu từ 0 nhưng mã ascii lại bắt đầu từ 32. Do vậy phải trừ đi để 2 font này trùng khớp nhau.
Giờ hãy để ý số 0 trong bộ đệm Buffer_display, nó đại diện cho tấm matrix thứ 1 ngoài cùng bên trái. Nếu ta điền vô đó là 1 thì nó sẽ in ra tấm matrix thứ 2. Tương tự …

Do vậy, mình sẽ chỉnh thêm 1 chút đó là thêm 1 biến vị trí được nạp vào hàm để chọn tấm matrix ta sẽ in ra

matrix 8x32

Gọi lệnh Matrix_guikitu(2,’A’);
Giờ thi chữ ‘A’ đã được in ở tấm thứ 3

Tiếp tục, mình sẽ xây dựng 1 hàm gửi chuỗi kí tự

Hàm này thực chất chỉ là gọi lại hàm Matrix_guikitu nhiều lần. Vòng lặp while sẽ lặp cho tới khi gặp NULL để thoát. Mỗi lần in sẽ tăng biến vitri lên 1 tấm. Do chỉ có 4 tấm matrix lên mình chỉ in đc có 4 kí tự. Vậy nên mình để thêm 1 dòng lệnh kiểm tra nếu đã in đủ 4 kí tự thì thoát

Giờ test thử hàm này nhé

matrix 8x32

Matrix_guichuoi(“ABCD”);

FULL code

Đến đây cũng có thể nói là xong rồi. Nhưng hãy để ý các chữ của chúng ta cách nhau khá xa. Hãy tùy biến hàm gửi kí tự lại 1 chút để nhìn chữ đẹp hơn và có thêm không gian để hiện đc nhiều kí tự hơn nhé ! Chúng ta cũng thể hiện thị chữ thoải mái ở bất kì vị trí nào trên màn hình

Các bạn nên hiểu kĩ code bên trên trước khi đọc tiếp

Điều khiển matrix bằng tọa độ pixel

Đầu tiên mình khai báo hai biến toàn cục
MatrixX, MatrixY

Viết 1 hàm để set vị trí con trỏ màn hình

Hàm Set pixel, hàm này có nhiệm vụ làm sáng hoặc tắt 1 con LED ở tọa độ nào đó trên màn hình

Tham số đầu tiền là tọa độ x, tiếp theo là tọa độ y, cuối cùng là trạng thái bật hay tắt
color = 0 là tắt
color = 1 là bật
Mình có thêm 1 lệnh kiểm tra if(x>31 || y>7 || x<0 || y < 0)return; có nghĩa là nếu tọa độ cần set vọt lố ra ngoài chiều dài tối đa và chiều rộng tối của tấm LED thì sẽ thoát luôn !
Nhắc tới tọa độ lại phải nhắc tới hệ tọa độ và gốc tọa độ. Mình đã chọn gốc tọa độ ở trên cùng phía bên trái của màn hình LED

Gốc tọa độ bắt đầu từ 0. Do đó con led trên cùng bên trái sẽ có tọa độ (0,0)

Matrix_setpx(0,0,1);

Khi chạy hàm này thì con led ở tọa độ 0,0 đã sáng

Giờ thì viết lại hàm Matrix_guikitu nhé !

Thử test hàm này nào

Matrix_chonvitri(0,0);
Matrix_guikitu(‘A’);

Các bạn có thể thấy vùng không gian mà chữ ‘A’ chiếm chỗ bắt đầu từ tọa độ (0,0) do mình set vị trí con trỏ hiên tại là (0,0). Các bạn hãy thử test vị trí chỗ khác xem nhé !

Nhưng tại sao chữ A chưa hiện. Vì code trên mình chỉ gọi hàm Matrix_setpx(x,y,1); làm cho led sáng hết. Giờ phải quyết định xem led nào sáng , led nào tắt bằng cách đọc từ bộ font ra

Matrix_chonvitri(0,0);
Matrix_guikitu(‘A’);

Nếu thấy đoạn code trên khó hiểu, hãy thử thay giá trị của các biến, xóa biến này biến kia đi và quan sát sự thay đổi. Các bạn sẽ tự hiểu ngay thôi !

Matrix_chonvitri(-3,0);
Matrix_guikitu(‘A’);

Các bạn có thể chọn ví trí âm thoải mái nhé ! Lúc đó chữ sẽ bị cắt bớt đi 1 phần và lọt ra ngoài không gian hiển thị

OK, giờ viết lại hàm gửi chuỗi kí tự nào

Hàm này thực chất cũng chỉ là gọi lại hàm Matrix_guikitu nhiều lần

matrix 8x32

Matrix_chonvitri(0,1);
Matrix_guichuoi(“IoT47”);

FULL CODE

Tổng kết

Các bạn có thể tải về toàn bộ file cho bài này Tại đây
Nếu chưa hiểu code, cách tốt nhất là tải project của mình về, thử thay đổi các giá trị data, biến, cắt bớt vòng lặp, tưởng tượng cách thực thi của các vòng lặp để nhận thấy sự khác biệt là sẽ hiểu được cách hoạt động của code thôi

Các bạn nên đọc các bài viết của mình từ bài 1 sẽ dễ hiểu hơn là đọc tắt, nhảy bài. Vì các bài đều có sự liên quan và có lộ trình !

Trong bài tiếp theo mình sẽ hướng dẫn về các hiệu ứng chạy chữ, lật chữ …

 

Từ tác giả:

Nếu có bất kì thắc mắc nào trong bài viết, vui lòng để lại comment dưới mỗi bài ! Mình sẽ không trả lời thắc mắc của các bạn ở facebook hay email !

Nếu trong phần code bạn nhìn thấy nhưng thứ kiểu như &amp; thì đó là lỗi hiển thị, cụ thể 3 kí tự < > & bị biến đổi thành như thế
&amp; là &
&lt;  là <
&gt; là >

Giới thiệu Đào Nguyện 80 bài viết
DIY,chế cháo, viết blog chia sẽ kiến thức về lập trình,điện tử - IoT. Rất mong được giao lưu, kết bạn với các bạn cùng đam mê. Địa chỉ Facebook: https://www.facebook.com/nguyendao207

16 bình luận

    • Ví dụ font có byte data là 0xA5 = 10100101 nằm ở tọa độ n m
      txt phải -32 vì mã ascii bắt đầu từ 32 ( trong khi font bắt đầu từ 0 )
      y-MatrixY và (x-MatrixX : Do x,y là tọa độ trên màn led, trong khi tọa độ của font bắt đầu từ 0 nên mình – đi để căn chỉnh lại đúng tọa độ font về vị trí n m => chính là byte 0xA5 ví dụ bên trên
      Sau khi lấy được mã font chính xác là 0xA5 mình sẽ cần lấy chính xác bit của nó bằng cách cho & với 0x80 dịch trái 1 lượng

  1. hc595_out(Buffer_display[z][0]);
    hc595_out(Buffer_display[z][1]);
    hc595_out(Buffer_display[z][2]);
    hc595_out(Buffer_display[z][3]);
    chỉ với 1 hàm hc595_out làm sao để ic biết mà xuất ra lần lượt 4 con hc595 ạ, e không thấy phần nào là chỉ định con hc595 nào nhận dat để xuất.

  2. Mình thấy mạch test cùng OK, nhưng vẫn đề lên mạch thực điện áp cấp sao hả bạn. Giả sử mình muốn mở thêm 1;2 tấm nữa thì áp cấp ra sao.

  3. void Matrix_setpx(int x,int y,char color)
    {
    if(x>31 || y>7 || x<0 || y > (x%8)); //sáng led
    else Buffer_display[y][x/8] &= ~(0x80 >> (x%8)); //tắt led
    }
    Mình không hiểu ý nghĩa của [y][x/8] . Ban có thể giải thích cho mình 1 chút về nó được không?

Đã đóng bình luận.