Lập trình C cho 8051 quét LED ma trận 16x64

e có đoạn code lập trình c cho 8051 quét led ma trận 16x64 , do code khá dài lên e chỉ copy 1 số điểm quan trọng mà e chưa hiểu được để hỏi thôi ạ

unsigned char buffer(unsigned char x,unsigned char y, chari )//ham xu ly du lieu hang
{
    unsigned char temp;
    temp=(x<<i) | (y>>(8-i));
    return temp;
}
char i,j,k,m;
void main()
{
    p3=0x00;
    while(1)
    {
        for(k=0; k<64-8; k++) //64 la kich thuoc cot cua mảng cột,8 la so led matrix
        {
            for(i=0; i<8; i++) //xử lý từng bit
            {
                for( m=0; m<16; m++)
                {

                    quet (buffer(cot[m*64+k+7],cot[m*64+k+8],i));//ma cho led 8
                    quet (buffer(cot[m*64+k+6],cot[m*64+k+7],i));//m*64 64la so cot cua mang
                    .
                    .
                    .
                    quet (buffer(cot[m*64+k],cot[m*64+k+1],i));	//ma cho led 1
                }
            }
        }
    }
}

cái làm e đau đầu là đây

buffer(cot[m*64+k+7],cot[m*64+k+8],i);//ma cho led 8

theo cách nghĩ của e là thế này các bác cho ý kiến nhé :slight_smile:

ban đầu vòng lặp for kiểm tra 3 vòng lặp for tức là k=0,i=0,m=0 đều thỏa mãn thì tại vị trí buffer (cot[m*64+k+7] , cot[m*64+k+8] , i) chuyển thành buffer (cot[7] , cot[8] , 0) , tức là hàm buffer sẽ truy xuất đến vị trí thứ 6 và 7 trong mảng cột và bít thứ 0

giải thích như vậy có đúng không ạ

3 Likes

Anh muốn giúp em bài này lắm, nhưng anh không làm LED và hiện giờ anh đang bận nhiều thứ quá không thể trả lời được. Em thử share bài này của em lên facebook xem có bạn nào biết không?

Cách để share 1 topic anh có hướng dẫn ở đây.

1 Like

Chào Tuấn,
Anh có thể giúp nếu em cho biết

  • Sơ đồ kết nối chân của LED tới mạch điều khiển
  • Định nghĩa hàm “quet()”, “buffer()” và dữ liệu của “cot[]”
    Chỉ một đoạn code ngắn rất khó đoán ý của tác giả. Tốt nhất là full code để mọi người dễ hình dung :smile:
5 Likes

hy vọng là e sẽ gặp cao thủ

ĐÂY LÀ PHƯƠNG PHÁP QUYETS HÀNG NHÉ A (16X64)

#include<reg52.h>
sbit SCK=P1^0;
sbit STR=P1^1;
sbit SDA= P1^2;
sbit Ctrl =P3^0;

/*-----------------------------------------------------------------------------------------------
Layer0
-----------------------------------------------------------------------------------------------*/
const unsigned char code cot[]=
{
/*-----------------------------------------------------------------------------------------------
Hexa C code for ledmatrix
Text content: "KHOA DIEN DIEN TU"
Code generated by the LedTECHPAL software
Width x Height(pixels):156x10
Size of data: 200 (byte)
Position of region(X:Y):0:0
-----------------------------------------------------------------------------------------------*/
   0xF9, 0xEF, 0xFF, 0x1F, 0x80, 0xC0, 0x1F, 0xE3, 0xFF, 0xFB, 0xC7, 0x87, 0xF8, 0xFF, 0xFE, 0xF1, 
   0xE1, 0xFF, 0xFE, 0xF0, 0x70, 0x87, 0x1C, 0x39, 0xC0, 0xE0, 0x0E, 0x71, 0xC7, 0x19, 0xE2, 0x03, 
   0x9C, 0x71, 0xC6, 0x78, 0x81, 0x39, 0xB8, 0x40, 0x73, 0x07, 0x1C, 0x70, 0xE0, 0xE0, 0x0E, 0x39, 
   0xC7, 0x01, 0xF2, 0x03, 0x8E, 0x71, 0xC0, 0x7C, 0x80, 0x38, 0x38, 0x40, 0x76, 0x07, 0x1C, 0xE0, 
   0xE1, 0xE0, 0x0E, 0x39, 0xC7, 0x61, 0x7A, 0x03, 0x8E, 0x71, 0xD8, 0x5E, 0x80, 0x38, 0x38, 0x40, 
   0x7E, 0x07, 0xFC, 0xE0, 0xE1, 0x70, 0x0E, 0x39, 0xC7, 0xE1, 0x3A, 0x03, 0x8E, 0x71, 0xF8, 0x4E, 
   0x80, 0x38, 0x38, 0x40, 0x7F, 0x07, 0x1C, 0xE0, 0xE2, 0x70, 0x0E, 0x39, 0xC7, 0x61, 0x1E, 0x03, 
   0x8E, 0x71, 0xD8, 0x47, 0x80, 0x38, 0x38, 0x40, 0x77, 0x07, 0x1C, 0xE0, 0xE3, 0xF8, 0x0E, 0x39, 
   0xC7, 0x01, 0x0E, 0x03, 0x8E, 0x71, 0xC0, 0x43, 0x80, 0x38, 0x38, 0x40, 0x73, 0x87, 0x1C, 0x70, 
   0xE2, 0x38, 0x0E, 0x39, 0xC7, 0x01, 0x0E, 0x03, 0x8E, 0x71, 0xC0, 0x43, 0x80, 0x38, 0x38, 0x40, 
   0x71, 0xC7, 0x1C, 0x31, 0xC4, 0x1C, 0x0E, 0x71, 0xC7, 0x09, 0x06, 0x03, 0x9C, 0x71, 0xC2, 0x41, 
   0x80, 0x38, 0x1C, 0xC0, 0xFF, 0xFF, 0xFF, 0x1F, 0x0F, 0x7E, 0x1F, 0xE3, 0xFF, 0xFB, 0xC2, 0x07, 
   0xF8, 0xFF, 0xFE, 0xF0, 0x80, 0x7E, 0x0F, 0x80, 
};



void delay(int t) // ham tao tre

{

  int a,b;

  for(a=0;a<t;a++)

  {

    for(b=0;b<120;b++);

  }

}

void quet(unsigned char d)

{

  unsigned char i,t;

   for(i=0;i<8;i++)

     {

      t==d&0x80;

      if(t==0x80)

      SDA=1;

      else SDA=0;

      d=d<<1'

      SCK=0;

      SCK=1;

     }

}

unsigned char buffer(unsigned char x,unsigned char y,char i)//xu ly du 

lieu hang

{

  unsigned char temp;

  temp=(x<<i) | (y>>(8-i));

  return temp;

}

void main() // chuong trinh chinh

{

  char i,j,k,m;

  P3=0x00;

  while(1)

  {

    for(k=0;k<64-8;k++)// 64 la kich thuoc mang cot, 8 la so led 

matrix 

{ 

  for(i=0;i<8;i++)// xu ly tung bit 

  { 

  for(j=0;j<10;j++) // vòn lap tạo trễ 

  { 

    for(m=0;m<16;m++)//quet tung hang 

{ 

           quet(buffer(cot[m*64+k+7],cot[m*64+k+8],i));//ma cho led 8

           quet(buffer(cot[m*64+k+6],cot[m*64+k+7],i));//ma cho led 7 
  
           quet(buffer(cot[m*64+k+5],cot[m*64+k+6],i));//"m*64" , 64 là số cột của mảng

             .

             .

             quet(buffer(cot[m*64+k],cot[m*64+k+1],i));//ma cho led 1

             STR=0; 

             STR=1;

             P2= m; 

             delay(2); 

             Ctrl=0;

             Ctrl=1; 
      } 
    } 
   }
  }
 }
}

kết nối chân như sau
3 chân vđk p1^0 , P1^1 ,P1^2 kết nối với 3 chân con 74hc595 ở đây dùng 8 con mắc nối tiếp với nhau
4 chân vđk p2^0 , P2^1 ,p2^2 p2^3 kết nối với 4 chân A B C D con 74hc154 (ic đệm dong để quét hàng)
chân p3^0 nối vào 2 chân E1 E2 của 154 nữa
tại e xem trên youtube nên chưa vẽ lại mạch này a ak , e nghĩ chắc với a từng đấy là đủ để a hình dung ra

2 Likes

Hi,

Muốn hiểu đoạn code này em phải hiểu cách dữ liệu được sắp xếp trong mảng “cot[]” trước.
Giả sử các phần tử trong cot[] được đánh số như thế này:

  • 0 1 … 7 8 … … … 63
  • 64 65 … 71 72 … … … 127
  • 128 129 … 135 136 … … … 191
  • 960 961 … 967 968 … … … 1023
    (Theo code thì số phần tử phải bằng 1024)
    Từ 0->63 : dữ liệu sẽ dùng để hiển thị trên hàng 0 (m=0)
    Từ 64->127 : dữ liệu sẽ dùng để hiển thị trên hàng 1 (m=1)
    … Tương tự với hàng cuối cùng (m=15), phần tử đầu tiên là 15*64=960
    Tất nhiên, mỗi thời điểm sẽ chỉ có 8 phần tử (ví dụ: 0->7, 64->71, 960->967) được dùng để hiển thị trên mỗi hàng (vì chỉ có 8 led).

Khi thực hiện xong 1 chu kì quét (m=0->15), k không đổi, i tăng (ví dụ từ 0->1). Khi đó hàm buffer():

sẽ dịch chuyển tất cả dữ liệu đang hiển thị trên LED sang trái (do i tác động, xem kĩ hàm buffer() để hiểu :slight_smile: )
Khi thực hiện được 7 lần dịch chuyển, k tăng (ví dụ 0->1), i=0: vị trí của phần tử trong cot[] được cập nhật, chữ trên LED sẽ tiếp tục chạy sang trái cho đến hết.

Nói tóm lại:

thì:

  • m=0: chọn data cho hàng thứ 0
  • i=0: dịch chuyển hiển thị trên LED sang trái 0 bit
  • k=0: chọn data cho các cột của LED 0 (data của LED 1 làm đệm khi dịch LED)
6 Likes

Đinh Quang Trí trước tiên cám ơn anh nhé . nhưng theo anh giải thích thì chúng ta nên dùng 1 mảng cột cot[m*64+k+7] thế này là đủ vậy tại sao tác giả lại sử dụng 2 mảng cột vậy anh (cot[m*64+k+7] ,cot[m*64+k+8] và tại sao tác giả lại cộng thêm 7 và 8 vào sau k làm j vậy a và tại sao đã dịch trái i lần lại còn OR dịch phải 8-i lần vậy anh temp=(x<<i) | (y>>(8-i));

anh trí thông cảm cho em tại vì với e trong lập trình e k làm khi chưa hiểu kỹ về nó

1 Like

à quên mất bảng mã ở đây sử dụng phần mềm tạo mã chữ của techpal anh ak có khi nào do đặc tính của mã chữ này mà tác giả thực hiện đưa 2 mảng cột vào buffer rồi sau đó dịch bít 2 mảng này và or lại với nhau (chắc chắn rằng y và x khai báo trong buffer là 2 mảng cột )

1 Like

Để a giải thích chỗ này rõ 1 chút:

cot[m*64+k+7] và cot[m*64+k+8] chỉ là 2 phần tử trong mảng cot[] thôi (ví dụ khi m=0, k=0 thì 2 phần tử 7 và 8 của mảng cot[] được truyền vào hàm buffer())

Vai trò của k là để xác định vị trí bắt đầu để lấy dữ liệu hiển thị trên LED. Khi đó e phải lấy lần lượt 8 byte dữ liệu (mỗi byte là dữ liệu tương ứng cho mỗi LED) từ vị trí bắt đầu đó (k+0 đến k+7) để hiển thị ra LED.
Do đó tác giả cộng 7 và 8 vào sau k (dữ liệu chính dùng để hiển thị cho LED cuối cùng (LED 8) là k+7, k+8 chỉ là dữ liệu đệm)

Giờ xét kĩ hơn hàm buffer()

x là data chính, y chỉ dùng để đệm khi dịch LED thôi nhé.
Giả sử byte x=cot[0*64+0+7]=0b11110000; y=cot[0*64*0+8]=0b10001111.
Chu kì đầu tiên i=0: temp = 11110000 | 00000000 = 11110000
Chu kì tiếp theo i=1: temp = 11100000 | 00000001 = 11100001
Chu kì tiếp theo i=2: temp = 11000000 | 00000010 = 11000010

Giá trị dịch trái là k+7, giá trị dịch phải là k+8. Một phần của byte k+8 sẽ được ghép vào cuối byte k+7 bởi hàm buffer() tùy vào giá trị của i, và giá trị trả về là giá trị sẽ được hiển thị lên LED ta thấy LED dịch chuyển sang trái.
A thấy giải thuật của hàm đơn giản nhưng hay. E nên viết thử ra giấy thì dễ hình dung hơn là chỉ suy nghĩ :slight_smile:
Thêm nữa, khi i=7 (chuẩn bị tăng lên 8), khi đó data của k+7 và k+8 không dịch trái hay phải được nữa. Lúc này tác giả mới tăng k lên 1 và i=0 để cập nhật vị trí dữ liệu bắt đầu và tiếp tục thực hiện việc dịch LED như trước đó.

5 Likes

cám ơn a Đinh Quang Trí , cám ơn cả người đã tạo ra nhóm này đã giúp e có cái nhìn sâu về bài này nhé . chỉ là 1 bài toán trên mạng nhưng nó chứa khá nhiều ý tưởng để mở rộng phạm vi ứng dụng nếu ta hiểu về nó

2 Likes

@phananhtuan123 Đinh Quang Trí là thạc sĩ bên ĐH BK TPHCM và hiện giờ là kỹ sư của Bosch Việt Nam đấy. Khoe thằng bạn tí :smiley:

4 Likes

a cho e 1 ví dụ cụ thể ở câu này đi

Ví dụ, dữ liệu cho hàng 0 của LED như sau:

k=0: dữ liệu cho LED 1->8 lần lượt là 0xF9, 0xEF, 0xFF, 0x1F, 0x80, 0xC0, 0x1F, 0xE3
k=1: dữ liệu cho LED 1->8 lần lượt là 0xEF, 0xFF, 0x1F, 0x80, 0xC0, 0x1F, 0xE3, 0xFF

Khi k tăng lên 1, những gì hiển thị trên LED 2->8 sẽ được hiển thị trên LED 1->7 (LED 8 sẽ được cấp dữ liệu hiển thị mới)

5 Likes
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?