[Matrix LED] Bài 3: Led Ma Trận 8x8 đếm Từ 0 đến 9

led ma tran dem tu 0 den 9

Bài này chúng ta sẽ lập trình cho LED đếm từ 0 đến 9

Trước tiên chúng ta sẽ lấy các font chữ cho các số từ 0 đến 9 nhé.

Giới thiệu phần mềm LCD font maker

Để lấy font dễ dàng thì sự giúp đỡ của phần mềm là cần thiết, các bạn hãy tải phần mềm này về tại đây

Giao diện phần mềm
Cài đặt như hình
Điền chữ muốn tạo font và bấm vào thẻ One Font data Output để sang tab lấy Font
Ấn F5 để tạo mã và COPY

Mình đã tạo sẵn mã từ 0 đến 9. Chúng ta sẽ đưa vào mảng 2 chiều để lưu mã này !

C unsigned char code maled[][8]= { 0x1C,0x22,0x32,0x2A,0x26,0x22,0x1C,0x00, //0 0x08,0x0C,0x08,0x08,0x08,0x08,0x1C,0x00, //1 0x1C,0x22,0x20,0x18,0x04,0x02,0x3E,0x00, //2 0x1C,0x22,0x20,0x1C,0x20,0x22,0x1C,0x00, //3 0x10,0x18,0x14,0x12,0x3E,0x10,0x10,0x00, //4 0x3E,0x02,0x02,0x1E,0x20,0x22,0x1C,0x00, //5 0x18,0x04,0x02,0x1E,0x22,0x22,0x1C,0x00, //6 0x3E,0x20,0x10,0x08,0x04,0x04,0x04,0x00, //7 0x1C,0x22,0x22,0x1C,0x22,0x22,0x1C,0x00, //8 0x1C,0x22,0x22,0x3C,0x20,0x10,0x0C,0x00, //9 };
12345678910111213 unsignedcharcode maled[][8]={0x1C,0x22,0x32,0x2A,0x26,0x22,0x1C,0x00,//00x08,0x0C,0x08,0x08,0x08,0x08,0x1C,0x00,//10x1C,0x22,0x20,0x18,0x04,0x02,0x3E,0x00,//20x1C,0x22,0x20,0x1C,0x20,0x22,0x1C,0x00,//30x10,0x18,0x14,0x12,0x3E,0x10,0x10,0x00,//40x3E,0x02,0x02,0x1E,0x20,0x22,0x1C,0x00,//50x18,0x04,0x02,0x1E,0x22,0x22,0x1C,0x00,//60x3E,0x20,0x10,0x08,0x04,0x04,0x04,0x00,//70x1C,0x22,0x22,0x1C,0x22,0x22,0x1C,0x00,//80x1C,0x22,0x22,0x3C,0x20,0x10,0x0C,0x00,//9};

Điều khiển LED ma trận bằng phương pháp ngắt TIMER

Trong hầu hết các lĩnh vực điều khiển có liên quan đến hiển thị, quét led. Người ta thường sử dụng ngắt để quét. Nó giống như 1 module tự động quét led và làm công việc hiển thị ra màn hình cho chúng ta. Trong hàm main ta có thể thoải mái làm những việc khác.

Tuy nhiên giữa hàm main và hàm ngắt phải có 1 mối liên hệ nhất định để hàm main muốn hiển thị gì thì ngắt phải nghe theo. Do vậy phương pháp này cần tới 1 Buffer ( bộ đệm hiển thị) – nó là 1 mảng dữ liệu chứa dữ liệu cần hiển thị. Khi hàm main muốn hiển thị gì thì chỉ cần ghi dữ liệu vào bộ đệm. Còn hàm ngắt sẽ tự động lấy dữ liệu trong bộ đệm ra để hiển thị 1 cách định kì và tự động.

Khởi tạo bộ đệm

Tùy vào số lượng led và cách điều khiển ta sẽ cần các bộ đệm có kích cỡ khác nhau. Ở ví dụ này, mình có con led ma trận 8×8, tức là 64 con led. Mỗi con led có 2 trạng thái ON và OF tương ứng 1 và 0. Như vậy mình sẽ cần 64 bit dữ liệu cho bộ đệm. 64 bit = 8 byte. Do vậy mình sẽ tạo 1 bộ đệm có 8 byte data :

C unsigned char Buffer_display[8];
1 unsignedcharBuffer_display[8];
Mối quan hệ giữa bộ đệm và LED thật

Thuật toán điều khiển của mình như sau: 1 bộ đệm được tạo ra để lưu trữ dữ liệu sáng hay tắt của led. Mỗi bit data tương ứng 1 led. 1 chương trình ngắt timer được gọi tự động sau 1 khoảng thời gian nào đó để lấy dữ liệu trong bộ đệm ra để xuất tín hiệu điều khiển ra LED. Đây là công việc tự động, do đó chúng ta chỉ cần xây dựng xong chương trình ngắt này thì có thế “bơ” nó luôn ! Công việc của ta là “vẽ” nhưng gì cần hiển thị vào bộ đệm hoy !

Xây dựng module ngắt

Module ngắt sẽ tự chạy vào bộ đệm, lấy dữ liệu và xuất ra 1 màn hình LED. Để làm được việc này, mình cần 1 cái timer, khi timer đếm đến 1 khoảng thời gian nào đó. Nó sẽ tự động nhảy vào hàm ngắt. Khoảng thời gian này quyết định tần số quét led của chúng ta. Như đã nói ở bài trước, tần số càng cao càng tốt. Nhưng cao quá thì chương trình chỉ lo nhảy vào ngắt mà bỏ bê hàm main, vì thể tùy theo tài nguyên, tốc độ MCU mà nên chọn tần số ngắt cho hợp lí nhé !

Mỗi lần ngắt tương ứng 1 lần quét hàng hoặc quét cột. Module matrix 8×8 của chúng ta quét 8 lần sẽ xong 1 bảng. Do vậy cần 8 lần ngắt cho khung hình. Mình muốn quét ở ~120 khung hình 1 giây. Nên tần số ngắt sẽ xấp xỉ 1 giây / (120*8) = 0.001s = 1ms

Như vậy mình sẽ nạp giá trị vào timer sao cho nó đếm đc 1ms thì tràn để nhảy vào hàm ngắt

Mình sẽ dùng timer1 của vi điều khiển 89s52, thạch anh 12Mhz qua bộ chia 12 còn 1Mhz => 1 xung sẽ đếm trong 1us => cần 1000 xung để đếm được 1ms. Do cần tới 1000 xung nên mình sẽ cài timer ở chế độ 16bit và nạp giá trị cho thanh ghi TH1 và TL1 là 64535 = 0xFC17

C TMOD=0x10; // khoi tao ngat T1, 16bit ET1=1; // cho phep ngat T1 TF1=0; // xoa co ngat T1 TR1=1; // khoi dong T1 EA = 1; // cho phep ngat toan cuc
12345 TMOD=0x10;// khoi tao ngat T1, 16bitET1=1;// cho phep ngat T1 TF1=0;// xoa co ngat T1 TR1=1;// khoi dong T1 EA=1;// cho phep ngat toan cuc

OK bây giờ xây dựng hàm ngắt

C void T1_ISR() interrupt 3 // Dung timer 1 de quet led matrix { static unsigned char z ; // Bien dem P3=0xFF; //tat het LED P2=Buffer_display[z]; //lay du lieu trong bo dem hien thi ra man hinh P3=maquet[z]; //cho phep LED sang z++;if(z==8)z=0; TH1=0xFC; // Nap gia tri cho TH1 TL1=0x17; // Nap gia tri cho TL1 }
12345678910 voidT1_ISR()interrupt3// Dung timer 1 de quet led matrix{staticunsignedcharz;// Bien demP3=0xFF;//tat het LEDP2=Buffer_display[z];//lay du lieu trong bo dem hien thi ra man hinhP3=maquet[z];//cho phep LED sangz++;if(z==8)z=0;TH1=0xFC;// Nap gia tri cho TH1TL1=0x17;// Nap gia tri cho TL1 }

Hãy nói qua 1 chút về hàm ngắt này nào ! Đầu tiến biến z là 1 biến con chạy từ 0 đến 7. Do chúng ta quét 8 lần cho 1 khung hình nên chỉ cần nó chạy từ 0 đến 7 thôi. Cách khai báo static giống như khai báo biến toàn cục nhưng chỉ hàm ngắt mới được dùng !Tiếp đó, tắt hết led đi ( trước khi xuất dữ liệu luôn luôn phải tắt led đi nhé – nếu không sẽ xuất hiện hiện tượng bóng ma, thử đi là biêt :v)Sau đó lấy dữ liệu trong bộ đệm để hiển thị ra ngoài qua cổng P2Tiếp đó cho phép LED sáng bằng cách xuất dữ liệu ra công P3Sau đó tăng biến con chạy z lên để lần ngắt tiếp nó sẽ quét vào dòng tiếp

  • z=0 quét hàng 1
  • z=1 quét hàng 2
  • z=2 quét hàng 3
  • z=3 quét hàng 4
  • z=4 quét hàng 5
  • z=5 quét hàng 6
  • z=6 quét hàng 7
  • z=7 quét hàng 8
  • z=8 đã quét xong 1 khung hình, quay trở lại từ đầu

Do chúng ta quét theo hàng và mỗi lần ngắt quét 1 hàng, tổng số hàng cần quét là 8. Nên phương pháp quét này còn gọi là quét 1/8

Cuối hàm mình nạp lại giá trị vào thanh TH1 TL1 để đảm bảo mỗi lần ngắt cách nhau 1ms

OK ! Thế là chương trình ngắt (module hiển thị) đã xây dựng xong, chúng ta có thể bơ nó luôn không cần quan tâm gì nữa. Từ giờ là phần việc của hàm main, việc lập trình bây giờ gần như là lập trình C thuần túy (làm việc với dữ liệu), dó đó các bạn có thể tạo thành 1 thư viện riêng để sử dụng sau này mà không cần quan tâm tới việc chúng ta sẽ dùng vi điều khiển nào !

Bây giờ muốn hiện thị cái gì, chỉ cần bắn dữ liệu vào bộ đệm, trước đó chúng ta đã có bộ font từ 0 đến 9. Giờ hãy xây dựng hàm lấy font ra để bắn vào bộ đệm nhé

C void print_number(char number) { int i; for(i=0;i<8;i++) { Buffer_display[i]=maled[number][i]; } }
12345678 voidprint_number(charnumber){inti;for(i=0;i<8;i++){Buffer_display[i]=maled[number][i];}}

Hàm trên chỉ đơn giản là nhảy vào mảng dữ liệu font từ 0 đến 9 để bắn 8 byte data vào bộ đệm

Giờ muốn hiển thị số mấy thì chỉ cần gọi hàm kèm theo số cần hiện trong hàm mainVí dụ, mình muốn matrix hiện số 2print_number(2);

Còn muốn đếm từ 0 đến 9 thì sao

C for(i=0;i<10;i++) { print_number(i); delay(500); }
12345 for(i=0;i<10;i++){print_number(i);delay(500);}

Full code cho project đếm từ 0 đến 9 led matrix 8×8

C #include <REGX52.H> unsigned char code maquet[8]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; unsigned char code maled[][8]= { 0x1C,0x22,0x32,0x2A,0x26,0x22,0x1C,0x00, //0 0x08,0x0C,0x08,0x08,0x08,0x08,0x1C,0x00, //1 0x1C,0x22,0x20,0x18,0x04,0x02,0x3E,0x00, //2 0x1C,0x22,0x20,0x1C,0x20,0x22,0x1C,0x00, //3 0x10,0x18,0x14,0x12,0x3E,0x10,0x10,0x00, //4 0x3E,0x02,0x02,0x1E,0x20,0x22,0x1C,0x00, //5 0x18,0x04,0x02,0x1E,0x22,0x22,0x1C,0x00, //6 0x3E,0x20,0x10,0x08,0x04,0x04,0x04,0x00, //7 0x1C,0x22,0x22,0x1C,0x22,0x22,0x1C,0x00, //8 0x1C,0x22,0x22,0x3C,0x20,0x10,0x0C,0x00, //9 }; unsigned char Buffer_display[8]; void delay(unsigned int t) //hàm delay { unsigned int x,y; for(x=0;x<t;x++) { for(y=0;y<123;y++); } } void T1_ISR() interrupt 3 // Dung timer 1 de quet led matrix { static unsigned char z ; // Bien dem P3=0xFF; //tat het LED P2=Buffer_display[z]; //lay du lieu trong bo dem hien thi ra man hinh P3=maquet[z]; //cho phep LED sang z++;if(z==8)z=0; TH1=0xFC; // Nap gia tri cho TH1 TL1=0x17; // Nap gia tri cho TL1 } void print_number(char number) { int i; for(i=0;i<8;i++) { Buffer_display[i]=maled[number][i]; } } void main() { int i; TMOD=0x10; // khoi tao ngat T1, 16bit ET1=1; // cho phep ngat T1 TF1=0; // xoa co ngat T1 TR1=1; // khoi dong T1 EA = 1; // cho phep ngat toan cuc while(1) { for(i=0;i<10;i++) { print_number(i); delay(500); } } }
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263 #include <REGX52.H> unsignedcharcode maquet[8]={0xFE,0xFD,0xFB,0xF7,0xEF,0xDF,0xBF,0x7F}; unsignedcharcode maled[][8]={0x1C,0x22,0x32,0x2A,0x26,0x22,0x1C,0x00,//00x08,0x0C,0x08,0x08,0x08,0x08,0x1C,0x00,//10x1C,0x22,0x20,0x18,0x04,0x02,0x3E,0x00,//20x1C,0x22,0x20,0x1C,0x20,0x22,0x1C,0x00,//30x10,0x18,0x14,0x12,0x3E,0x10,0x10,0x00,//40x3E,0x02,0x02,0x1E,0x20,0x22,0x1C,0x00,//50x18,0x04,0x02,0x1E,0x22,0x22,0x1C,0x00,//60x3E,0x20,0x10,0x08,0x04,0x04,0x04,0x00,//70x1C,0x22,0x22,0x1C,0x22,0x22,0x1C,0x00,//80x1C,0x22,0x22,0x3C,0x20,0x10,0x0C,0x00,//9}; unsignedcharBuffer_display[8]; voiddelay(unsignedintt)//hàm delay{unsignedintx,y;for(x=0;x<t;x++){for(y=0;y<123;y++);}}voidT1_ISR()interrupt3// Dung timer 1 de quet led matrix{staticunsignedcharz;// Bien demP3=0xFF;//tat het LEDP2=Buffer_display[z];//lay du lieu trong bo dem hien thi ra man hinhP3=maquet[z];//cho phep LED sangz++;if(z==8)z=0;TH1=0xFC;// Nap gia tri cho TH1TL1=0x17;// Nap gia tri cho TL1 }voidprint_number(charnumber){inti;for(i=0;i<8;i++){Buffer_display[i]=maled[number][i];}}voidmain(){inti;TMOD=0x10;// khoi tao ngat T1, 16bitET1=1;// cho phep ngat T1 TF1=0;// xoa co ngat T1 TR1=1;// khoi dong T1 EA=1;// cho phep ngat toan cucwhile(1){for(i=0;i<10;i++){print_number(i);delay(500);}}}

Tổng kết

Có thể bạn sẽ thấy có cái project đếm từ 0 đến 9 thôi mà code dài hơn so với code mẫu khác trên mạng rất nhiều. Nhưng sau này làm tới các project phức tạp sử dụng led ma trận như đồng hồ led có các hiệu ứng đẹp. Các bạn bắt buộc phải dùng tới kĩ thuật quét LED này. Do vậy mình giới thiệu sớm và từ nay đến hết tutorial về LED ma trận mình đều code sử dụng kĩ thuật này

Đây cũng chính là kĩ thuật dùng trong hầu hết các thiết bị hiển thị, card đồ họa

Tham khảo Frame Buffer tại Wikipedia

Các bạn có thể tải file mô phỏng và code cho project này Tại đây

Related posts:

[Matrix LED]Bài 13: Thiết kế bộ font tiếng việt[Matrix LED] Bài 7: Tìm hiểu Module Led Ma Trận P10 - lập trình led ma trận[Matrix LED] Bài 11: Tìm hiểu module LED ma trận P10 Full Color - lập trình led matrix full color[Matrix LED] Bài 4: Hiển thị chữ trên led ma trận 8x32

Từ khóa » đệm Dòng Cho Led