Download as pdf or txt
Download as pdf or txt
You are on page 1of 14

Chương 5:

ĐIỀU KHIỂN LED MA TRẬN 5x7

5.1. Giới thiệu 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. Trong phạm vi bài này chúng ta thao tác với 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 bên dưới 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).

Hình 1. Ma trận LED 7x5.

65
Bên trong các ô của ma trận LED là các LED phát sáng. 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 cho 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.

5.2. Sơ đồ mạch và nguyên lý hoạt động của LED ma trận 7x5


Ví dụ: Ma trận LED 5x7 được kết nối như hình sau, có ký hiệu là U6
U6

PC0 18 16 PA0
PC1 3 18 16 15 R13 PA1
PC2(TCK)4 3 15 17 R14 PA2
PC3(TMS)7 4 17 14 R15 PA3
PC4(TDO)
11 7 14 8 R16 PA4
11 8 5 R17 PA5
5 6 R18 PA6
1 6 R19
2 1
13 2 9
12 13 9
10 12
10

MATRIX 5x7 (2 COLORs)


Môđun Ma trận LED 5x7
Ma trận LED gồm các LED phát quang bố trí thành hàng và cột trong một võ. Các
tín hiệu điều khiển hàng PA0 - PA6 ( Port A ) nối vào Anode (cực dương) của tất cả các
LED trên cùng một hàng. Các tín hiệu điều khiển cột PC0 -PC4 (Port C) nối vào Cathode
(cực âm) của tất cả các LED trên cùng một cột (thông qua cổng đảo). Khi có 1 cặp tín
hiệu điều khiển hàng và cột ví dụ như khi PA0 = 1 và PC0 = 1, các Anode của hàng LED
thứ nhất RW1 (hàng trên cùng) được cấp điện thế cao. Đồng thời các Cathode của cột
LED thứ nhất CL1 (bìa trái) được cấp thế thấp. Tuy nhiên chỉ có LED 1 là sáng vì nó có
đồng thời thế cao trên Anode và thế thấp trên Cathode. Như vậy khi có 1 cặp tín hiệu
điều khiển hàng và cột thì chỉ có duy nhất 1 LED tại điểm hàng và cột gặp nhau là sáng.
Trên cơ sở cấu trúc như vậy ta có thể xây dựng được bảng ma trận LED với số lượng
LED lớn hơn ví dụ như trong các bảng quang báo.

66
Sơ đồ kết nối Ma trận LED 5x7
Trong trường hợp ta cần hiển thị đồng thời 1 số LED trong ma trận để có thể hiển
thị một ký hiệu nào đó ví dụ chữ „L„ trên ma trận LED. Khi đó ta thấy các LED ở cột bìa
trái (CL1) sáng và các LED ở hàng dưới cùng (RW7) sáng. Nếu trong hiển thị tĩnh ta
phải đặt tất cả các giá trị PA0 đến PA6 và PC0 đến PC4 ở mức cao, lúc này sẽ làm sáng
các LED ở hàng RW7 và cột CL1 nhưng khi đó thì các LED khác trong ma trận cũng
được cấp áp cao vào Anode và áp thấp vào Cathode do đó nó sẽ sáng tất cả các LED
trong ma trận. Vì vậy trong điều khiển ma trận LED ta không thể sử dụng phương pháp
hiển thị tĩnh mà phải dùng phương pháp quét (hiển thị động). Nghĩa là tiến hành cấp tín
hiệu điều khiển theo dạng xung theo kiểu quét cho các hàng và cột cần hiển thị. Tần số
quét nhỏ nhất cho một chu kỳ cần khoảng 20Hz (50ms) nhằm bảo đảm cho mắt thấy các
67
LED sáng đều không nháy. Như vậy để hiển thị được chữ L có thể điều khiển tuần tự như
trong bảng sau:
Nhịp 1 : PA0 - PA6 = 1, PC0 = 1 ; Sáng cột LED thứ nhất CL1
Nhịp 2 : PA1 – PA6 = 0, PA0= 1, PC1 = 1 ; Sáng LED hàng RW7 và cột CL2
Nhịp 3 : PA1 – PA6 = 0, PA0 =1, PC2 = 1 ; Sáng LED hàng RW7 và cột CL3
Nhịp 4 : PA1 – PA6= 0, PA0 = 1, PC3 = 1 ; Sáng LED hàng RW7 và cột CL4
Nhịp 5 : PA1 – PA6 = 0, PA0 = 1, PC4 = 1 ; Sáng LED hàng RW7 và cột CL5
Nhịp 6 : Quay lại giống nhịp 1.
(từ nhịp 1 đến nhịp 6 là 1 chu kỳ quét tối thiểu phải là 20Hz)
TÍN PC0 PC1 PC2 PC3 PC4
HIỆU
PA7 0 0 0 0 0
PA6 1 0 0 0 0
PA5 1 0 0 0 0
PA4 1 0 0 0 0
PA3 1 0 0 0 0
PA2 1 0 0 0 0
PA1 1 0 0 0 0
PA0 1 1 1 1 1
Giá trị 0x7F 0x01 0x01 0x01 0x01
giải mã

Tương tự khi hiển thị các ký hiệu hay các chữ khác.
Cách tính giá trị như sau:
Hàng \ Cột PC0 PC1 PC2 PC3 PC4
PA7 0 0 0 0 0 Bit cao

PA6 0 0 1 0 0
X
PA5 0 1 1 0 0
PA4 0 0 1 0 0 Bit thấp
PA3 0 0 1 0 0
Bit cao
PA2 0 0 1 0 0
PA1 0 0 1 0 0 Y
PA0 0 1 1 1 0
Bit thấp
Giá trị 0x00 0x21 0x7F 0x01 0x00
giải mã

Giá trị giải mã được hiển thị trên mỗi cột như sau: 0xXY

68
5.3. Code điều khiển hiển thị trên LED ma trận
VD1: Hiển thị số 1 trên led ma trận 5x7
#include <mega32.h>
#include <delay.h>

void main(void)
{
// Port C initialization
PORTC=0x00;
DDRC=0xFF;

// Port D initialization
PORTD=0x00;
DDRD=0xFF;

while (1)
{

//Lưu ý: Do ma trận LED có các hàng được nối với cực âm (Cathod) và các cột được nối với cực
dương (Anode), nên các led sẽ sáng khi tín hiệu điều khiển hàng có giá trị là 0, các led tắt khi tín
hiệu điều khiển hàng có giá trị là 1, đồng thời tín hiệu điều khiển cột phải có giá trị là 1.

//Quét cột 1
PORTC=0x01;
PORTD=0xFF;
delay_us(1000);
//Quét cột 2
PORTC=0x02;
PORTD=0xDE;
delay_us(1000);
//Quét cột 3
PORTC=0x04;
PORTD=0x80;
delay_us(1000);
//Quét cột 4
PORTC=0x08;
PORTD=0xFE;
delay_us(1000);
//Quét cột 5
PORTC=0x10;
PORTD=0xFF;
delay_us(1000);
};
}

69
VD2: Xây dựng thư viện dotfont.h để sử dụng cho việc hiển thị trên led ma trận.

PD6

.
.
.

PD0
..
.
PC0 PC4

1.#include "mega32.h"
2.#include "DotFont.h"
3.#include "delay.h"
4.
5.#define DATA_PORT PORTD //PORTD is connected to the data bus of DotMatrix
6.#define DATA_DDR DDRD
7.
8.#define CTRL_PORT PORTC //PORTC is connected to control lines of DotMatrix
9.#define CTRL_DDR DDRC
10.
11.
12.typedef unsigned char Byte;
13.
14.void DOTputChar57(char chr){
15. unsigned char line=1, i;
16. int tchr=chr;
17. for(i=0;i<5;i++) {
18. CTRL_PORT=~line;
19. DATA_PORT=font5x7[((tchr - 32) * 5)+i];
20. line<<=1;
21. delay_us(1000);
22. }
23.}
24.

25.void main(void){
70
26.
27. DATA_DDR=0xFF; // DATA_PORT is selected as an ouput PORT
28. CTRL_DDR=0xFF;
29. while(1){
30. DOTputChar57('1');
31. delay_ms(700);
32. DOTputChar57('2');
33. delay_ms(700);
34. }
35.}
(Để tạo file thư viện dotfont.h, chúng ta phải dùng chương trình CodeVisionAVR tạo
source *.h, nội dung của file gồm hàm flash char font5x7[] = {})
Điều cần quan tâm đầu tiên là kích thước bảng font, trong ví dụ này bảng font được xây
dựng cho 223 symbol có mã ASCII từ 32 đến 255 (do các mã ASCII trước 32 không có
symbol tương ứng nên có thể bỏ qua để tiết kiệm bộ nhớ), mỗi symbol cần 5 số 8 bits,
như thế chúng ta cần tổng cộng 1115 byte cho bảng font trong khi kích thước SRAM của
chip ATmega32 chỉ là 2KB (2048 byte). Nếu dùng SRAM chứa bảng font sẽ rất lãng phí
vì đây là một bảng tĩnh, giá trị trong bảng hoàn toàn không thay đổi mà chỉ được truy
xuất đọc. Vì thế chúng ta có thể tận dụng bộ nhớ chương trình (Flash) để lưu bảng font
này. Dòng thứ hai trong code chúng ta include header “DotFont.h” để sử dụng các thao
tác trên bộ nhớ chương trình. Tiếp theo chúng ta khai báo 1 mảng tĩnh có tên font7x5 với
kiểu dữ liệu là kiểu char nhưng chứa trong bộ nhớ chương trình (Flash). Giá trị chứa
trong mảng font7x5 chính là dữ liệu của bảng font nằm trong thư viện DotFont.h, thực
chất mảng font7x5 là mảng 1 chiều liên tục, việc tách ra trên nhiều dòng có mục đích
giúp người đọc dễ hình dung khi truy cập các giá trị của mảng để xuất ra sau này. Lưu ý
rằng cứ một tổ hợp 5 số sẽ tạo thành một symbol hiển thị cho ma trận LED. Dữ liệu trong
bảng font được sắp xếp theo trình tự ASCII và để tạo điều kiện thuận lợi khi truy xuất
bảng font theo mã ASCII của ký tự cần hiển thị. Tuy nhiên cần chú ý là bảng font được
bắt đầu cho symbol có mã ASCII là 32 chứ không bắt đầu từ mã ASCII 0, vì thế khi truy
cận bảng font từ mã ASCII chúng ta cần lấy mã ASCII trừ đi 32 để được vị trí chính xác
trong bảng.

71
flash char font5x7[] = {
0x00, 0x00, 0x00, 0x00, 0x00 ,// 32
0x00, 0x00, 0x7d, 0x00, 0x00 ,// 33
0x00, 0x70, 0x00, 0x70, 0x00 ,// 34
0x14, 0x7f, 0x14, 0x7f, 0x14 ,// 35
0x12, 0x2a, 0x7f, 0x2a, 0x24 ,// 36
0x62, 0x64, 0x08, 0x13, 0x23 ,// 37
0x36, 0x49, 0x55, 0x22, 0x05 ,// 38
0x00, 0x50, 0x60, 0x00, 0x00 ,// 39
0x00, 0x1c, 0x22, 0x41, 0x00 ,// 40
0x00, 0x41, 0x22, 0x1c, 0x00 ,// 41
0x14, 0x08, 0x3e, 0x08, 0x14 ,// 42
0x08, 0x08, 0x3e, 0x08, 0x08 ,// 43
0x00, 0x05, 0x06, 0x00, 0x00 ,// 44
0x08, 0x08, 0x08, 0x08, 0x08 ,// 45
0x00, 0x03, 0x03, 0x00, 0x00 ,// 46
0x02, 0x04, 0x08, 0x10, 0x20 ,// 47
0x3e, 0x45, 0x49, 0x51, 0x3e ,// 48: 0
0x00, 0x21, 0x7f, 0x01, 0x00 ,// 49: 1
0x21, 0x43, 0x45, 0x49, 0x31 ,// 50: 2
0x42, 0x41, 0x51, 0x69, 0x46 ,// 51: 3
0x0c, 0x14, 0x24, 0x7f, 0x04 ,// 52: 4
0x72, 0x51, 0x51, 0x51, 0x4e ,// 53: 5
0x1e, 0x29, 0x49, 0x49, 0x06 ,// 54: 6
0x40, 0x47, 0x48, 0x50, 0x60 ,// 55: 7
...
0x7f, 0x7f, 0x7f, 0x7f, 0x7f // 255
};

Các dòng từ 5 đến 9 định nghĩa các PORT kết nối với ma trận LED, PORTD là Data
bus trong khi PORTC là control lines. Chương trình con void DOTputChar75(chart chr)
trong dòng 17-21 là thủ tục đọc dữ liệu từ bảng font và hiển thị trên ma trận LED. Tham
số chr của chương trình này chính là mã ASCII của ký tự cần hiển thị trên ma trận LED.
Dòng 15 khai báo 2 biến phụ (line và i), trong đó biến line chứa tín hiệu điều khiển cho
các đường Control, biến i là biến chạy được sử dụng trong vòng lặp for. Dòng 16 khai
báo một biến tạm tchr dùng chứa địa chỉ dữ liệu cần lấy ra từ bảng font để xuất ra các
đường Data, vì mã ASCII là một số 8 bit trong khi số lượng dữ liệu trong bảng font lớn
gấp 5 lần số lượng ký tự, vì thế cần khai báo biến tchr có kiểu dữ liệu 16 bit. Nội dung
chính của đoạn chương trình này nằm trong vòng lặp for, biến i đại diện cho số thứ tự của
các chân Control được cho chạy từ 0 đến 4, trong dòng 18 “CTRL_PORT=~line;” xuất
tín hiệu điều khiển ra CTRL_PORT tức ra các chân C. Do biến line được khởi tạo bằng 1
nên ở lần lặp đầu tiên giá trị CTRL_PORT=0b00000001, tức chân PC0 ở mức cao trong
khi các chân còn lại ở mức thấp, cột đầu tiên được chọn. Phía trước line có dấu ~, do ma
trận LED có các hàng được nối với cực dương (Anode) và các cột được nối với cực âm

72
(Cathod), nên các led sẽ sáng khi tín hiệu điều khiển hàng có giá trị là 1, các led tắt khi
tín hiệu điều khiển hàng có giá trị là 0, đồng thời tín hiệu điều khiển cột phải có giá trị là
0. Sau khi 1 cột đã được chọn, dòng 19 “DATA_PORT=font7x5[((tchr - 32) * 5) + i]);”
đọc và xuất dữ liệu từ bảng font ra các chân Data. Trước hết là cách tính địa chỉ của dữ
liệu trong bảng font. Như trình bày trong phần giải thích cho bảng font, bảng này được
chúng ta bắt đầu từ ký tự có mã 32 nên chúng ta cần trừ đi 32 để tham chiếu đến vị trí
chính xác trong bảng font: tchr-32. Ví dụ muốn hiển thị ký tự có mã chr = 48 (mã của ký
tự „0‟), vị trí của tổ hợp dữ liệu tạo nên số „0‟ được chứa trong bảng font ở vị trí 16, giá
trị này được tính 48-32=16. Tiếp theo, do mỗi ký tự được tạo thành từ 5 số nên địa chỉ
thực chất của số đầu tiên trong tổ hợp sẽ là (tchr-32)*5. Để di chuyển trong phạm vi 5 dữ
liệu ứng với 5 cột của ma trận LED, biến i được cộng dồn vào địa chỉ này và chúng ta có:
((tchr - 32) * 5) + i. Như vậy sau khi thực hiện “font7x5[((tchr - 32) * 5) + i])” chúng ta
thu được dữ liệu 1 byte tương ứng với cột thứ i của ký tự chr từ bảng font, việc cuối cùng
là xuất giá trị này ra DATA_PORT. Trong trường hợp ma trận LED có các hàng nối với
cực dương Anode thì chúng ta không cần đảo giá trị đọc về. Dòng 20 thực hiện dịch
chuyển giá trị của biến line sang trái 1 vị trí, việc làm này có tác dụng chuẩn bị cho lần kế
tiếp chân C kế tiếp sẽ được kích. Hàm delay trong dòng 21 giúp các LED trong cột hiện
tại sáng trong 1 khoảng thời gian trước khi chuyển qua cột khác.
Chương trình chính trong ví dụ này rất đơn giản, chúng ta trước hết cần khởi động
hướng xuất nhập cho các PORT và sau đó gọi hàm DOTputChar75() trong vòng lặp vô
tận while(1). Ở ví dụ trên, ký tự „1‟ và „2‟ được xuất ra. Chú ý là hàm DOTputChar75()
chỉ “quét” qua các cột 1 lượt, vì thế muốn hiển thị một ký tự trong một khoảng thời gian
chúng ta cần gọi hàm DOTputChar75() lặp lại trong khoảng thời gian đó.

73
5.3.3 Các bước tạo thư viện dotfont.h trong CodevisionAVR
Trong cửa sổ chương trình quản lý project, chọn File -> New
Sau đó chọn Source -> Ok

Sau đó sẽ xuất hiện cửa sổ soạn thảo nội dung của thư viện. Sau khi soạn xong nội dung
thư viện chọn File -> Save As, đặt tên file là dotfont.h trong trường File name và chọn
loại file là *.h trong trường Save as type.

74
Như vậy, thư viện dotfont.h đã được tạo ra.

Để sử dụng thư viện này, trong file source (*.c) của project chúng ta khai báo vào ở đầu
chương trình như sau: #include "DotFont.h"

75
Bài tập
Thiết kế mạch như sau:

U1
9 22
RESET PC0/SCL
23
PC1/SDA
13 24
XTAL1 PC2/TCK
12 25
XTAL2 PC3/TMS
26
PC4/TDO
40 27
PA0/ADC0 PC5/TDI
39 28
PA1/ADC1 PC6/TOSC1
38 29
PA2/ADC2 PC7/TOSC2 RN1
37
PA3/ADC3
36 14 1 16
PA4/ADC4 PD0/RXD
35 15 2 15
PA5/ADC5 PD1/TXD
34 16 3 14
PA6/ADC6 PD2/INT0
33 17 4 13
PA7/ADC7 PD3/INT1
18 5 12
PD4/OC1B
1 19 6 11
PB0/XCK/T0 PD5/OC1A
2 20 7 10
PB1/T1 PD6/ICP
3 21 8 9
PB2/INT2/AIN0 PD7/OC2
4
PB3/OC0/AIN1
5 300X8
PB4/SS
6
PB5/MOSI
7 30
PB6/MISO AVCC
8 32
PB7/SCK AREF
ATMEGA32

1. Hãy tạo một Project với tên gọi MATRIX57, với yêu cầu hiển thị các số từ 0 -> F
trên Led ma trận.

76
2. Tính toán dữ liệu hiển thị
Chữ „A‟: 7Eh, 09h, 09h, 09h,7Eh
Chữ „B‟: 7Fh, 49h,49h,49h, 36h
Giữa chữ A và B có một cột trống để phân biệt.
->Chuỗi “AB”: 7Eh, 09h, 09h, 09h, 7Eh, 00h, 7Fh, 49h,49h,49h, 36h
Có thể thêm khoảng trắng trước và sau chuỗi để chuỗi hiện ra từ từ
->Chuỗi “ AB ”: 00h, 00h, 00h, 00h, 00h, 7Eh, 09h, 09h, 09h, 7Eh, 00h,
7Fh, 49h,49h,49h, 36h,00h, 00h, 00h, 00h
Như vậy, một ký tự cần hiển thị trên ma trận Led cần 6 byte và 5 byte 00h đầu chuỗi, 3
byte 00h cuối chuỗi -> một chuỗi dài 50 ký tự sẽ cần số byte lưu trữ cho mã Led là: 50*6
+ 5 + 3 = 308 byte.

Quá trình hiển thị và cho chữ chạy mô tả như hình vẽ:

77
Tóm tắt:
Lần 1: hiển thị từ pa[0] † pa[4]
Lần 2: hiển thị từ pa[1] † pa[5]
 lần j: hiển thị từ pa[j] ÷ pa[j+4]
Lần 16: hiển thị từ pa[15] † pa[19]

78

You might also like