Hotline : 0166.666.1219
63 Lê Đức Thọ - Từ Liêm - Hà Nội
Sản phẩm Mới Nhất

Tìm hiểu Module Led Ma Trận P10 Và ứng dụng làm đồng hồ số sử dụng vi điều khiển ATmega 8

 
Phần 1 : Tìm hiểu module P10 và cách giao tiếp với vi điều khiển
                                      
Ảnh mặt trước của module led matrix P10     
                                  
Ảnh mặt sau của module led matrix P10 
       Module led ma trận P10 kích cỡ 16x32. Mỗi led là 1 pixel cách nhau 1 centi mét. Cấu tạo của module này bao gồm. 
               - 16 IC ghi dịch 8 bit 74hc595 
               - 1 IC ghi đệm dòng 74hc245 
               - 1 IC vào 3 ra 8 74hc138 
               - 4 con FET kích 16 hàng ( 1 còn kéo 4 hàng) 
               - 2 jump kết nối 2x8. 1 cái là đầu vào dữ liệu, 1 cái là đầu ra ( để mắc nối tiếp với tấm khác) 
      Jump 2x8 nhưng các bạn chỉ cần chú ý tới 6 chân này thôi : 
               - OE : Đây là chân điều khiển IC 138. Nếu nó OE=0 thì IC 138 không hoạt động. Tất cả các hàng đều không sáng ( cả biển LED sẽ tắt). Như vậy chân này có 2 nhiệm vụ là quét led, và băm xung PWM điều khiển độ sáng của bảng LED.

               - 2 chân A và B : 2 chân này sẽ điều khiển ngõ ra của ic 138, thực ra nó còn chân C nhưng chân này được nối thằng xuống mass rồi (ta không sử dụng chân này). Khi A=B=0 thì hàng 1,5,9,13 sẽ được tích cực. Khi A=1,B=0 thì hàng 2,6,10,14 được tích cực. Khi A=0, B=1 thì hàng 3,7,11,15 được tích cực. Khi A=B=1 thì hàng 4,8,12,16 được tích cực. Đọc đến đây nếu đã biết qua về quét LED chắc bạn sẽ hiểu ngay module này chỉ quét 4 phát là quét xong cả bảng. ( 1 phát quét có 4 hàng sáng, 16 hàng nên có 4 lần quét) 

               - CLK : Chân tạo xung đẩy dữ liệu vào HC595 

               - SCLK : Chân tạo xung xuất dữ liệu trong HC595 ra ngoài 
               - DATA (R) : Chân dữ liệu 

                                                                       
       Cái jump 2x8 đối diện nó cũng có sơ đồ y chang và các chân OE, A, B, CLK, SCLK của 2 jump thực chất nối thông với nhau. Duy chỉ có chân DATA là khác nhau. DATA của jump 2x8 (vào) thì nó nối với chân 14 của 74hc595 thứ 1. Còn DATA của cái jump 2x8 (ra) nó nối với chân 9 của con 74hc595 thứ 16 
       Các hàng của Module được kích bằng 4 con FET. Cấu tạo của module này khá đơn giản thế thôi. Bây giờ mình sẽ trình bày về chiều đi của dữ liệu. Các bạn nhìn vào mặt LED của module. Dữ liệu sẽ đi từ phải sang, từ trên xuống.
  
       
Ảnh trên thể hiện chiều đi của dữ liệu. Mỗi ô vuông là 1 ic 74HC595 và được đánh số từ 1 đến 16. Mỗi 1 ic như trên sẽ điều khiển 4 hàng led và 8 cột led. Ví dụ ic số 1 sẽ điều khiển được 4 hàng đầu 8 cột led ngoài cùng bên tay phải. Con số 2 sẽ điều khiển 4 hàng led tiếp theo của 8 cột ngoài cùng bên phải. Cứ thế các bạn tự tính tiếp nhe.
  
       Phương pháp quét LED, hiện thị lên module như sau: 
               Phát 1 : Tắt OE . Gửi 16 byte vào HC595 
               1 : Bật sáng hàng 1 5 9 13 bằng cách đưa A=B=0, OE=1 
               Phát 2: Tắt OE . Gửi 16 byte tiếp theo vào HC595 
               2: Bật sáng hàng 2 6 10 14 bằng cách đưa A=1;B=0, OE=1 
               Phát 3: Tắt OE . Gửi 16 byte tiếp theo vào HC595 
               3: Bật sáng hàng 3 7 11 15 bằng cách đưa A=0;B=1, OE=1 
               Phát 4: Tắt OE . Gửi 16 byte tiếp theo vào HC595 
               4: Bật sáng hàng 4 8 12 16 bằng cách đưa A=1;B=1, OE=1 
       Vậy là bạn đã có thể hiện 1 cái gi đó lên màn hình LED matrix P10 rồi đó. Đương nhiên sẽ phải mất khá khá thời gian để tạo mã, lấy mã LED. Có thể lấy thue công hoặc bằng phần mềm ( ví dụ LCD font maker) tùy các bạn. Riêng mình chọn cách dùng photoshop thiết kế font rồi lấy mã thủ công =))
  
       
Tuy nhiên đễ có thể tạo được các hiệu ứng chạy chữ ngang dọc,lên xuống sẽ phải code phức tạp hơn 1 chút. Mình sẽ trình bày rõ thuật toán điều khiển LED matrix P10 đủ các hiệu ứng trong các bài viết tiếp. 
       
OK bây giờ mình cùng thử làm hiện 1 chữ gì đó lên một tấm Matrix P10 nhé. Mình sẽ sử dụng phần mềm CodeVision AVR và chíp ATmega 8 
       
Trước tiên là định nghĩa 1 số chân giao tiếp như sau :
    1:  #define OE PORTD.0
   2:  #define _A PORTD.1
   3:  #define _B PORTD.2
   4:  #define clk PORTD.3
   5:  #define xuat PORTD.4
   6:  #define DS PORTD.5

       
Tạo 1 mảng có tên là ma[16][4]. Trong đó 16 số chính là số hàng. Và 4 biến cho 32 cột ( vì mỗi biến chứa 8 bit nên cần 4 biến là đủ rồi 
       
Tiếp đến mình sẽ xây dựng hàm phục vụ điều khiển IC 138 quét hàng
   1:  void hang(unsigned char sohang)
   2:  {
   3:   switch(sohang)
   4:   {
   5:    case 1:{_A=0;_B=0;OE=1;break;} 
   6:    case 2:{_A=1;_B=0;OE=1;break;}
   7:    case 3:{_A=0;_B=1;OE=1;break;}
   8:    case 4:{_A=1;_B=1;OE=1;break;} 
   9:   }
  10:  }

       
Khi mình gọi hang(1); thì nó sẽ là sáng 4 hàng 1 5 9 13. Tương tự với các hàng khác. 
      Tiếp theo là hàm gửi dữ liệu vào IC ghi dịch HC595
   1:  void chuyen(unsigned char b)
   2:  {
   3:      unsigned char i;
   4:      for(i=0;i<8;i++)
   5:      {
   6:          DS = b & (0x80>>i);        // Lay tung Bit cua byte b gui ra DS, lay bit MSB truoc
   7:   
   8:          // Tao xung dich du lieu
   9:              clk = 0;
  10:              clk = 1;
  11:      }
  12:  }

       
Hàm hiện thị, hàm này có nhiệm vụ lấy từng byte trong mảng ma[16][4] để xuất ra màn hình sau đó bật sáng các hàng tương ứng.
   1:  void hienthi()
   2:  {
   3:   
   4:     unsigned char a,b,x;  
   5:      for(x=1;x<5;x++)
   6:      {    
   7:         for(a=0;a<4;a++)
   8:         {
   9:            for(b=16;b>0;b=b-4)
  10:            {
  11:             chuyen(~ma[b-x][a]);  
  12:            }
  13:         }         
  14:     xuat=0;
  15:     xuat=1;  
  16:     hang(5-x);                                                      
  17:     delay(sang); 
  18:     OE=0;     
  19:     delay(1000-sang);
  20:     }  
  21:  }

       
Các bạn hãy để ý biến "sang". Đây là biến có giá trị từ 0 đến 1000 chính là để băm chân OE điều khiển độ sáng của bảng matrix. Khi biến này này bằng 0 thì matrix gần như không sáng. Còn nếu các bạn để = 1000 thì sáng MAX và giải giá trị theo mình thấy nhìn sáng đẹp nhất là trong khoảng từ 20 đến 300.

OK bây giờ chỉ việc tống hàm hiển thị vào vòng lặp while(1) trong hàm Main là được. Nhưng còn 1 việc phải làm là tạo mã led để cho vào mang ma[16][4] cái đã nếu không bảng LED sẽ không sáng gì cả do các biến trong mảng này đều là 0x00 (tắt hết). Để tạo được mã thì các bạn có thể dùng phần mềm tại mã LED LCD Font Maker. Các bạn tải tại đây nhé ! 
       
Cài đặt phần mềm xong các bạn mở lên rồi nhấn vào phần "Character input" ở góc dưới màn hình để thiết kế mã chữ cho LED. Vì chúng ta dùng 1 tấm P10 có độ phân giải là 16x32 nên cái bạn nhớ cài các thông số With và Height cho đúng 16x32 nhé. Mình sẽ thiết kế 1 chữ DIY như hình dưới.
  
       
Sau đó nhấn vào ô ở góc dưới bên trái màn hình mà mình đã đánh dấu trên ảnh trên đó. Ấn F5 để biên dịch. Và phần mềm sẽ cho ra 1 đoạn code chính là mã led mà ta cần.  
       
Các bạn copy vá dán vào mảng ma[16][4]. Biên dịch code và nạp vào mạch test thử xem nhé :P Thạch anh thì mình sẽ dùng ngoại 16M vì Projec này yêu cầu tốc độ xử lí cao. Và đây là kết quả của mình 

  
       
Tiếp theo là tạo các hiệu ứng chạy chữ, đầu tiền là hiệu ứng chạy chữ từ trên xuống, hoặc từ dưới lên. Mình sẽ hướng dẫn các bạn viết hiệu ứng chạy chữ từ trên xuống. Sau đó các bạn có thể tự viết được hiệu ứng chạy chữ từ dưới lên nếu hiểu bài này. Hãy xem qua 2 hình ảnh sau đã. 

   
       
Như vậy mảng ma[16][4] chứa các mã led ( bít 1 và 0 ) để điều khiều khiển trang thái của từng led. Vậy muốn led sáng dịch xuống ta chỉ việc dịch các mã led trong mảng này xuống phía dưới. Cụ thể như sau: 


             
- Mã có vị trí [14][0] sẽ bị dịch xuống trở thành [15][0]

             
- Mã có vị trị [13][0] sẽ bị dịch xuống trở thành [14][0]

             
- Mã có vị trí [12][0] sẽ bị dịch xuống trở thành [13][0]

             
- Mã có vị trị [11][0] sẽ bị dịch xuống trở thành [12][0]

             
- -----------------------------------------------

             
- Mã có vị trị [0][0] sẽ bị dịch xuống trở thành [1][0]

       
Túm cái váy lại : Mã có vị trị [x][0] sẽ trở thành [x+1][0], hay nói cách khác đi, trong lập trình, ta nói : mã có vị trí [x][0] = ma[x-1][0] ( phép trừ nha)

       
Xong phát dịch thứ 1. Chữ của chúng ta đã bị dịch xuống 1 dòng. Các bạn muốn dịch thêm 1 dòng nữa thì lại tiếp tục các thao tác như trên. 10 dòng thì làm 10 lần. OK. Vòng lặp for phục vụ dịch mã xuống 1 dòng như sau: 

    1:  void dichxuong()
   2:  {
   3:   unsigned char a,b;
   4:         for(a=16;a>1;a--)
   5:           {
   6:             ma[a-1][0]=ma[a-2][0];   
   7:             ma[a-1][1]=ma[a-2][1];     
   8:             ma[a-1][2]=ma[a-2][2];  
   9:             ma[a-1][3]=ma[a-2][3];     
  10:           } 
  11:          for(b=0;b<100;b++)
  12:          {
  13:           hienthi();
  14:          }
  15:  }

       
Bây giờ, gọi hàm hiển thị là chữ nó sẽ bị dịch xuống 1 dòng, tạo thêm 1 vòng for bên ngoài nữa để dịch xuống x dòng. Cái vòng lặp for (b=0;b<100;b++) để chỉnh tốc độ dịch xuống nha. 


                                                                               
       
Giờ đến phần hóc búa nhất đây, làm sao để dịch chữ sang phải được ? Khi dịch chữ từ trên xuống theo hàng, chúng ta xử lí mảng ma[16][4] trên cả 1 byte, còn bây giờ phải xử lí mảng này theo từng bit, đương nhiên khi thao tác với bit là bắt buộc phải sử dụng đến các toán tử OR END dịch trái, dịch phải. Công việc của chúng ta thay vì dịch mảng ma[16][4] này xuống dưới thì giờ sẽ dịch sang trái. Có nhiều cách nhưng mình xin đề xuất 1 phương pháp như sau, các bạn nào nghĩ ra phương pháp khác hay hơn thì chia sẻ cho anh em nhé. 

  
             
- B1: Dịch ma[a][0] sang trái 1 lần ( trong đó a có giá trị từ 0 đến 15). Sau khi dịch xong thì 16 biến ma[a][0] sẽ bị đẩy sang trái và trình biên dịch sẽ nhét bit 0 vào bên phải ( tức là bit có trong số thấp nhất đó), chúng ta không cần bit này. Mà phải thay thế nó bằng bit có trọng số cao nhất (7) của cái byte đứng bên phải byte mà ta vừa dịch. Công thức dịch là : 
                                                 ma[a][0]=ma[a][0]<<1 


  
             
- B2: Lấy ra bit có trọng số cao nhất của byte bên phải . Với toán tử End (&) chúng ta sẽ lấy được byte có trọng số cao nhất bằng thủ đoạn End nó với 0x80. Công thức là : 
                                                 x=ma[a][1] & 0x80 (x là biến lưu) 
  
             
- B3: Sau khi đã lấy ra được bit cần lấy rồi thì ta đắp nó vào bit 0 (bit có trọng số thấp nhất) mà ở B1 thằng trình biên dịch bố láo dám đẩy bừa vào =)) Mình sẽ dùng toán tử OR. Bằng cách OR cái byte nhận đc ở B1 với cái byte nhận được ở bước 2. Tuy nhiên chờ chút đã, ở B1 bít bị thay có trong số thấp nhất. Còn B2 bit được thay năm ở vị trí cao nhất, nên mình phải xoay phải byte ở B2 7 lần để nó về vị trí thấp nhất. Công thức cho B3 là : 
                                                 ma[a][0]=ma[a][0] | (x>>7) 

       
Túm cái áo lại, 1 công thức duy nhất cho cả ba bước như sau : 
                                                 ma[a][0]= (ma[a][0] <<1 ) | ((ma[a][1] & 0x80 ) >>7); 

  
       
Code dịch chữ sang 1 cột như sau. Muốn dịch sang bao nhiêu cột thì cho vào vòng lặp for, mỗi lần lặp là 1 cột 

    1:  void chaychu()
   2:  {
   3:    unsigned char i,y;  
   4:    //--xu li 1 luc 3 cot dau tien = vong lap for
   5:    for(y=1;y<4;y++)
   6:    {        
   7:        for(i=1;i<17;i++)
   8:        {                   
   9:            ma[i-1][y-1]= ma[i-1][y-1] << 1;
  10:            ma[i-1][y-1]= ma[i-1][y-1] | ((ma[i-1][y] & 0x80 ) >>7);  
  11:        }   
  12:    }   
  13:    
  14:        //--xu li cot 3 rieng--//
  15:     for(i=1;i<17;i++)
  16:        {                   
  17:            ma[i-1][7]= ma[i-1][7] << 1;    
  18:            ma[i-1][7]= ma[i-1][7] | ((font[i-1][dem1] & (0x80>>dem) ) >> (7-dem));   
  19:        } 
  20:       dem++;if(dem==8){dem=0;dem1++;if(dem1>42){dem1=0;xoamanhinh();}}   
  21:      for(i=0;i<2;i++){hienthi();} // tốc độ quét 
  22:  }


(Code PIC)

(Code AVR)
Khi nhấn nút "Tải Về Máy", bạn sẽ vào trang quảng cáo, vui lòng chờ 5 giây. Nút  hiện ra ở góc phải phía trên, nhấn vào để đến trang download

Nguồn DaoNguyen(Gocdiy.com) CTV ChipKool
                            
eChipKool.Shop Trân trọng từng giây phút được phục vụ quý khách hàng

No comments:

Post a Comment