Led matrix 5x7 with XC8

7:17:00 AM
 I. Ma trận LED. 
       Ma trận LED tức Dot Matrix LED là tập hợp nhiều đèn LED được bố trí thành dạng “ma trận” hình chữ nhật hoặc vuông với số hàng là a và số cột là b. Ma trận LED được dùng rất nhiều trong các ứng dụng hiển thị như các biển quảng cáo, hiển thị thay thế LCD hoặc thậm chí dùng hiển thị video…Để giảm số lượng các đường điều khiển, trong các ma trận LED các LED được nối chung với nhau theo hàng và cột. Số lượng LED trên ma trận LED là axb trong khi số lượng ngõ ra bằng tổng số hàng và cột: a + b. Việc điều khiển 1 ma trận LED kích thước lớn đòi hỏi thiết kế một mạch driver và điều khiển rất phức tạp. Với mục đích giúp bạn đọc làm quen khái niệm ma trận LED, trong phạm vi bài này tôi chỉ trình bày thao tác với 1 ma trận LED có kích thước 7x5 (7 hàng, 5 cột). ma trận LED 7x5 thường được dùng để hiển thị các ký tự trong bảng mã ASCII thay cho Text LCD. Tuy nhiên, bạn có thể ghép các ma trận LED này lại để hiển thị các loại hình ảnh bất kỳ có độ phân giải thấp. Hình 1 mô tả một cấu trúc của một ma trận LCD 7x5 với 12 ngõ ra được đặt tên từ C0…C4 và D0…D6 (C đại diện cho Control line và D là Data line).


matrix 5x7 pic16f877a xc8

Hình 1. Ma trận LED 7x5.
       Bên trong các ô của ma trận LED là các LED phát sang. Trong mô hình trên, Cathod (cực âm) của các LED trên mỗi hàng được nối chung với nhau và ngõ ra chung là các ngõ D (Data). Các Anod của các LED trên mỗi cột được nối chung tạo thành các đường C (Control). Thông thường, các đường D và C được chọn sao số số lượng đường D nhiều hơn đường C hoặc sao cho số lương các đường D gần nhất với số 8, 16, 32…(lũy thừa của 2). Lý do của việc chọn này nhằm giảm kích thước bộ font chứa các ký tự hoặc hình ảnh hiển thị lên ma trận LED, bạn sẽ hiểu rõ hơn khi tìm hiểu các điều khiển ma trận LED 7x5 bên dưới.               
                                   
matrix 5x7 pic16f877a xc8

Hình 2 mô tả cách mà ma trận LED 7x5 được dùng để hiển thị các chữ. 
       Trước hết chúng ta sẽ khảo cách cho sang các LED mà không cần quan tâm đến bảng font. Quan sát cột thứ nhất (cột C0) trong hình 2a, trong cột này chỉ có 2 LED ở hàng D2 và D3 là sang, các LED còn lại tắt. Điều này được thực hiện bằng cách kích chân C0 (Anod) lên mức cao, kéo các chân D2, D3 xuống mức 0 trong khi các chân Data khác được giữ ở mức cao. Các cột khác được thực hiện tương tự. Tuy nhiên, câu hỏi ở đây là làm sao hiển thị các cột với các đèn LED sáng khác nhau trong khi các ngõ Cathod của chúng đều được nối chung (thành các chân D). Ví dụ một người kéo tất cả 5 chân C0…C4 lên mức cao vào xuất tín hiệu ra các chân D, khi đó tất cả các LED trên dùng một hàng sẽ sáng hoặc tắt như nhau. “Bí quyết” ở đây chính là kỹ thuật “quét”, chúng ta sẽ hiển thị tuần tự các cột với các giá trị tương ứng của chúng chứ không hiển thị đồng thời. Trong ví dụ hiển thị số ‘4’, trước hết hãy kích chân C0 lên cao trong khi các chân C1…C4 ở mức thấp, xuất tín hiệu ra các chân D để hiển thị lên cột C0. Tiếp theo kéo chân C1 lên cao và các chân Control khác ở mức thấp, xuất dữ liệu ra các chân D để hiển thị cột C1…Cứ như thế cho đến khi hiển thị hết các cột thì quay lại cột C0. Quá trình này gọi là “quét LED”. Do tốc độ “quét” rất cao nên chúng ta sẽ không có cảm giác “nhấp nháy”, các cột của ma trận như được hiển thị đồng thời. Chú ý là độ sáng của LED phụ thuộc vào số cột LED, nếu bạn “quét” quá nhiều cột LED, tỉ lệ thời gian “ON”  của mỗi cột sẽ rất nhỏ so với thời gian “OFF” vì phải chờ quét các cột khác. Vì thế nếu ma trận LED có nhiều cột hoặc khi ghép nhiều ma trận, các mạch driver cần được sử dụng để đảm bảo độ sáng của LED.
       Giả sử mỗi LED đại diện cho 1 bit và các LED sáng đại diện cho giá trị nhị phân 1 trong khi các LED tắt là số 0. Hình 2b thể hiện mô hình số nhị phân cho trường hợp hiển thị số 4 trên ma trận LED 7x5. Nếu xem mỗi cột của ma trận là 1 con số 7 bit thì 5 giá trị cần thiết để hiền thị số ‘4’ là: 0x0C, 0x14, 0x24, 0x7F, 0x04. Bộ 5 giá trị này tạo thành mã font cho ký tự ‘4’, chúng sẽ được định nghĩa trước và lưu trong bộ nhớ của chip điều khiển (AVR), mỗi lần một ký tự được yêu cầu hiển thị, bộ font tương ứng của ký tự đó sẽ được “load” ra và xuất lần lượt trên các đường Data, đây chính là lý do tại sao chúng ta gọi các đường D là các đường Data. Cách “quét” LED tôi vừa trình bày là cách “quét ngang”, bạn có thể thực hiện “quét dọc” nếu ứng dụng yêu cầu. Trong phương pháp quét dọc, các chân hàng chung sẽ được dùng để chọn hàng cần hiển thị, dữ liệu sẽ xuất ra theo từng hàng trên 5 cột và lần lượt thay đổi hàng (hàng 0 trước, đến 1…và cuối cùng là 6). So sánh 2 cách quét cho trường hợp ma trận LED 7x5, rõ ràng trong cách quét ngang chúng ta chỉ cần quet 5 cột cho mỗi lần LED nên tỉ lệ thời gian ON sẽ cao hơn (1/5 so với 1/8 của cách quét dọc). Mặt khác, nếu thực hiện quét dọc chúng ta cần 8 số số để tạo thành 1 bộ font cho một ký tự và vì thế tốn nhiều bộ nhớ hơn cho việc lưu trữ bảng font. Trong bài học này tôi thực hiện theo cách quét ngang và bảng font cũng được xây dựng cho cách quét này.
Đây là code chương trình.
#include <xc.h>
#include <stdio.h>
#include <string.h>
// CONFIG
#pragma config FOSC = HS        // Oscillator Selection bits (HS oscillator)
#pragma config WDTE = OFF       // Watchdog Timer (WDT disabled)
#pragma config PWRTE = ON       // Power-up Timer Enable bit (Power-up Timer is enabled)
#pragma config CP = OFF         // Code Protection bit (Code protection disabled)
#define _XTAL_FREQ 4000000
#define NUM_COLUMNAS 30
#define NUM_DATOS 115
unsigned char
    n_col = 0,
    n_veces = 0,
    desplazaTabla = 0;
unsigned const char tabla[NUM_DATOS] = {
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 
    127, 127, 8, 127, 127, 0, //H
    62, 127, 99, 127, 62, 0, //O
    127, 127, 64, 64, 96, 0, //L
    126, 127, 19, 127, 126, 0, //A       // mã DEC nha chứ không phải mã hex
    0, //separador
    127, 126, 12, 126, 127, 0, //M
    60, 64, 64, 64, 60, 0, //u
    120, 4, 4, 4, 120, 0, //n
    48, 72, 72, 72, 126, 0, //d
    56, 68, 68, 68, 56, 0, //o
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0
};
void main(void)
{
    TRISA = 0; 
    TRISB = 0; 
    PORTB = 0; 
    while (1)
    {
        for (desplazaTabla = 0; (desplazaTabla + n_col) != NUM_DATOS; desplazaTabla++)                                                                              
        {
            for (n_veces = 0; n_veces != 5; n_veces++)
            {
                for (n_col = 0; n_col != NUM_COLUMNAS; n_col++)
                                                               
                {
                    PORTA = n_col; 
                    PORTB = tabla[desplazaTabla + n_col];
                    __delay_ms(1); 
                }
            }
        }
    }
}
Video mô phỏng.


Share this

Related Posts

Previous
Next Post »