Ai đã từng học vi điều khiển thì ko thể ko biết tới led matrix. Chúng ta thường thấy led matrix hiển thị theo kiểu quét cột và dữ liệu xuất ra hàng vì tính đơn giản trong lập trình. Nhưng điều này sẽ ảnh hưởng nếu
matrix của ta có quá nhiều cột, chữ hiển thị có thể bị nháy. Cách giải quyết ở đây là đưa dữ liệu ra cột và thực hiện quét hàng để giảm thời gian quét (vì bảng led matrix thường có số cột nhiều hơn số hàng rất nhiều)
Trước tiên các bác vẽ một hình nào đó trên máy tính, chẳng hạn viết câu: “Vita hư đi chơi không hỏi bà, mải chơi quá tối cũng không về nhà.”
khai báo một mảng trong bộ nhớ Flash như sau:
const unsigned char wDataArr=52;
const unsigned char DataArr[]={
0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00,0×00, 0×00,0×00,0×00,0×00,0×00,0×00,
………….dài quá em xin bỏ bớt…………
0×36,0×06,0×36,0x7F,0×30,0×36,0xE6,0×07,0x3C,0×66, 0x8C,0xC1,0xD8,0×18,0x8C,0x0D,
0×06,0×63,0×63,0×83,0xC7,0xD8,0xD8,0xD8,0×18,0x8C, 0x8D,0x0D,0xC6,0xC6,0×00,0×66,
0×36,0×36,0×18,0x8C,0x8D,0x0D,0xC6,0xC6,0xC6,0xC0, 0×18,0x1B,0x0C,0xC6,0xC6,0xC6,
0xE0,0×31,0×36,0×36,0×36,0×06,0×36,0×03,0×30,0×36, 0×36,0×06,0×18,0×66,0x8C,0xC1,
0xD8,0x1C,0xCC,0x0D,0×46,0×63,0×63,0×83,0xCD,0xD8, 0xD8,0xD8,0x1C,0x8C,0x8D,0x0D,
0xC6,0xC6,0x0C,0×66,0×36,0×36,0×18,0x8D,0x8D,0x0D, 0xE6,0xE6,0xC6,0xC0,0×18,0x1B,
0x8C,0xE6,0xC6,0xE6,0×60,0×33,0×36,0×36,0×36,0×07, 0x1C,0×43,0×30,0×36,0×36,0×66,
………….dài quá em xin bỏ bớt…………
0×18,0xC6,0xF9,0xC1,0×98,0x1B,0xB8,0x0D,0x3C,0×63, 0x3E,0×83,0xD9,0×98,0xCF,0×98,
0x1B,0x8C,0xF9,0x0C,0x7E,0xFC,0x0C,0×66,0xE6,0×37, 0xF0,0x8C,0xF9,0x0C,0xDC,0xDC,
0xFC,0×80,0xF3,0×19,0×78,0xDC,0xC6,0xDC,0×60,0×36, 0xE6,0×33,0xE6,0×06,0x1C,0x3E,
};
biến wDataArr=52 chỉ ra rằng mảng này có tất cả 52 x 8 cột.
mảng DataArr chứa câu: “Vita hư….về nhà”, gồm 52 x 8 cột và 16 dòng
Tiếp theo khai báo 2 mảng con trỏ. Thực ra chỉ cần 1 mảng thôi, nhưng nếu ta muốn chạy đi chạy lại nhiều lần thì phải backup cái mảng trên.
// DMem là bo nho man hinh: Display Memory;
// Con tro (pointer) DMem se tro vao DataArr; *DMem[i] se mang du lieu cua dong thu i
unsigned char flash *DMem[16];
unsigned char flash *DMemBackup[16];
Ban đầu ta sẽ cho bộ nhớ màn hình trỏ vào vùng dữ liệu Flash DataArr ở trên:
for (i=0;i // Con tro DMem[i] tro vao byte dau tien cua dong thu i trong DataArr
DMem[i]=DataArr+i*wDataArr;
DMemBackup[i]=DMem[i];
}
Các bác có thể thấy ngay DMem[0] sẽ trỏ vào byte đầu tiên (byte 0) của DataArr, DMem[1] trỏ vào byte thứ 52, DMem[2] trỏ vào byte thứ 104…
Như vậy DMem[i] sẽ trỏ vào byte đầu tiên của dòng thứ i tương ứng với byte thứ i*wDataArr của mảng DataArr
Em sử dụng Timer 1 để quyết định tốc độ quét led, ghi chú là ở đây dùng quét hàng, dữ liệu được dịch ra các thanh ghi 74595. Như vậy trong ngắt Timer1 em sẽ viết như sau: (tại thời điểm quét hàng thứ rowth)
if (!nextdataready){ //data chua co trong cac thanh ghi dich
byte1st=DMem[rowth];
//ncols (number of columns) là số lượng cột chia cho 8, tức là ncols x 8 là số cột của bảng led ma trận.
for (i=1;i byteth=byte1st+i;
temp=*byteth; // temp co gia tri của cot thu i, hang thu rowth
for (j=0;j>=1; // dich byte du lieu sang phai
Data=SREG.0; // lay du lieu trong co nho (Carry Flag)
SH_CP=0; SH_CP=1; // tao mot suon duong de dua du lieu vao thanh ghi dich
}
}
nextdataready=1; //du lieu da san sang trong thanh ghi dich
rowth++; // lan tiep theo se quet hang rowth+1
if (rowth==16) rowth=0 // neu quet den dong cuoi cung thi tro lai quet dong dau tien
Công việc còn lại là ở trong chương trình chính, còn rất đơn giản như sau:
while (1){
// Vòng lặp này chỉ có tác dụng cho chuỗi chạy đi chạy lại nhiều lần
for (i=0;i DMem[i]=DMemBackup[i];
}// Cho con tro DMem (hay bo nho man hinh DMem) dich chuyen moi lan 1 byte tu dau mang DataArr den cuoi mang DataArr
for (j=0;j delay_ms(200);
for (i=0;i DMem[i]++;
}
}
};
Như vậy không tính vòng lặp để chuỗi chạy đi chạy lại nhiều lần em chỉ cần đúng 2 vòng lặp.
Bây giờ còn phải sửa lại chương trình một chút, để sao cho nó chỉ dịch chuyển 1 bit thôi, chứ mỗi lần dịch chuyển cả 8 bits (1 byte) thì kỳ quá. Sửa lại trong chương trình chính như sau:
while (1){
for (i=0;i DMem[i]=DMemBackup[i];
}for (j=0;j //Thêm vào biến kk để cho chương trình ngắt trong Timer1 biết là xuất từ bit thứ kk của DMem[i] thôi chứ không phải lúc nào cũng xuất từ bit thứ 0
for (kk=0;kk delay_ms(movingspeed);
}
for (i=0;i>=kk;
for (j=kk;j>=1; // dich byte du lieu sang phai
Data=SREG.0; // lay du lieu trong co nho (Carry Flag)
SH_CP=0; SH_CP=1; // dua vao thanh ghi dich
}
// lấy đủ từ bit 0..7 của n bytes tiếp theo
for (i=1;i byteth=byte1st+i;
temp=*byteth;
for (j=0;j>=1; // dich byte du lieu sang phai
Data=SREG.0; // lay du lieu trong co nho (Carry Flag)
SH_CP=0; SH_CP=1; // dua vao thanh ghi dich
}
}
// lấy từ bit 0 đến bit thứ kk của byte cuối cùng
if (kk!=0){
byteth=byte1st+ncols;
temp=*byteth;
for (j=0;j>=1; // dich byte du lieu sang phai
Data=SREG.0; // lay du lieu trong co nho (Carry Flag)
SH_CP=0; SH_CP=1; // dua vao thanh ghi dich
}
}
nextdataready=1; //du lieu da san sang trong thanh ghi dich
}
}
// Timer 1 output compare A interrupt service routine
interrupt [TIM1_COMPA] void timer1_compa_isr(void){
OutEn=1;
ST_CP=0; ST_CP=1; // dua tu thanh ghi dich ra cac chan cua 74595
PORTB=ROW[rowth];
OutEn=0;
rowth++;
if (rowth==16) rowth=0;
nextdataready=0;
datapreparing();
}
OK?
>>>>> Download Now
ReplyDelete>>>>> Download Full
>>>>> Download LINK
>>>>> Download Now
>>>>> Download Full
>>>>> Download LINK