Trong bài này chúng ta sẽ ứng dụng GPIO để lập trình 8051 led trái tim với các hiệu ứng khác nhau. Các bạn sẽ hiểu thêm về thuật toán sử dụng GPIO dạng output sau khi học xong bài này
Bài 5 trong Serie Học lập trình 8051 từ A tới Z
Led trái tim là gì?
Led trái tim là một sản phẩm mà thời mình học luôn là sản phẩm đầu tiên nhập môn lập trình 8051. Có một lời nguyền là cặp đôi nào yêu nhau mà tặng led trái tim thì y như rằng là chia tay :D.
Nói vui vậy thôi, led trái tim rất phù hợp để training việc sử dụng GPIO một cách linh hoạt. Vậy nên mình dùng nó để hướng dẫn các bạn trong bài này.
Một vài hình ảnh:


Mô phỏng trên proteus
B1: Lấy linh kiện:


B2: Tiến hành vẽ mạch
Do vi điều khiển này có 4 cổng vói 32 chân, ta sẽ tối đa cắm được 32 LED
Khá nhiều chân nên ta sẽ đặt tên từng chân tương ứng với LED nhé
Ta vào Terminals mode → Default đặt vào các chân từ P0 trở đi

Sau đó ta sẽ nối chân

Bây giờ ta sẽ tiến hành đặt tên nhé, nháy đúp vào từng chân và đặt tên lần lượt từ 1 → 32


Cứ tiếp tục cho đến khi bạn đánh xong chân của tất cả các cổng từ P0, P1, P2, P3

Bước tiếp theo chúng ta sẽ lấy LED để vẽ thành hình trái tim
- Quan trọng nhất là 2 bóng LED đầu tiên, các bạn đặt thẳng hàng với nhau, và có thể bỏ tên đi để đỡ bị rối mắt

- Tiếp theo là công đoạn công phu nhất – sắp xếp LED thành một hình trái tim (các bạn chú ý sắp xếp đúng chiều xoay theo kim đồng hồ của các bóng LED nhé)

- Ta kết nối các đầu âm của LED với vi điều khiển, do đó ta đánh số chân âm LED thứ nhất là 1 để kết nối với chân P0.0.
+ Để đánh số thì ta nối ra một đoạn dây nhỏ ở mỗi chân

+ Chọn Wire Label Mode để đánh nhãn cho các chân bóng LED

- Ta kết nối các đầu dương của LED với nguồn: Terminals Mode → POWER
+ Đặt nguồn thẳng hàng và nối với chân dương của bóng LED 1

+ Các chân dương của các bóng LED còn lại ta nối vào chân dương nguồn đó sao cho gọn gàng và đẹp mắt

- Như vậy, ta đã kết nối xong các cực dương của 32 bóng LED với nguồn. Trong thực tế, chúng ta có thể thêm điện trở vào nguồn để giảm dòng chảy qua LED. Hoặc LED sáng yếu / không sáng, ta có thể thêm các đệm dòng để LED sáng mạnh hơn.
- Tiếp theo, ta tiến hành lập trình để LED sáng theo các hiệu ứng mong muốn
Lập trình hiệu ứng cho led trái tim
Nguyên tắc: Vì chúng ta mắc theo hiểu hút dòng nên led nào sáng thì bật chân điều khiển của nó = 0 và tắt đi ta bật chân điều khiển của nó = 1
Thiết lập chương trình trên Keil C
Đây là chương trình đơn giản nhất
B1: Mở trình biên dịch KEIL C lên. Tạo một Project mới, đặt tên: ledTraiTim.
Sau đó chọn Atmel. Chọn AT89C51

Trong này có 1 loạt các hãng điện tử sản xuất 8051. Bạn lập trình cho con nào thì chọn con đấy
,kích chuột vào các dấu + để mở rộng các con IC của các hãng. Ở đây ta lập trình cho
AT89C51 của hãng Atmel

Khi chọn chip thì ngay lập tức cái bảng hiện ra 1 số tính năng của chíp các bạn có thể nhìn
thấy. 8051 based Fully Static 24Mhz … . Nhap OK được cửa sổ như sau:

Chọn No. Chọn Yes chỉ làm cho file lập trình của bạn thêm nặng .
B2: Tạo một file nguồn

- Rồi lưu nó lại với đuôi .C nhé


B3: Add file ledTraiTim.c vào Project đã tạo lúc đầu


- Sau đó, bấm Close nhé các bạn
B4: Tạo file dạng hex. Nhấn chuột phải vào Target 1

- Chọn Options for Target sẽ hiện ra một bảng

- Chọn OUTPUT, nhấn chọn Create HEX File

- Nhấn OK
B5: Tiến hành lập trình:
Code của chương trình bóng LED nhấp nháy:

B6: Nhấn Rebuid / Nhấn F7 để dịch ra file HEX
B7: Tiến hành mô phỏng trên Proteus
- Nháy đúp vào vđk trên Proteus

- Chọn để lấy file HEX vừa tạo ra


- Nhấn OK
- Kết quả mô phỏng trên Proteus:

- 32 bóng LED sáng – tắt liên tục
Hiệu ứng tăng dần
Tương tự như hiệu ứng đầu tiên, chúng ta tiến hành code theo nhu cầu:

- Kết quả mô phỏng trên Proteus:

- Các bóng led được bật lên đúng theo chiều thuận kim đồng hồ
Các bạn có thể thử với chiều ngược chiều kim đồng hồ

Hiệu ứng giảm dần
- Code trên KEIL C:

- Kết quả mô phỏng trên Proteus:

- Các bóng LED tắt dần theo chiều thuận kim đồng hồ
Tương tự chúng ta cũng có thể làm cho các bóng LED tắt dần theo chiều ngược chiều kim đồng hồ:

Hiệu ứng sáng sole nhỏ giọt 😊
Các bạn có thể sáng tạo theo ý thích của bản thân
- Gợi ý code:

- Kết quả mô phỏng trên Proteus

Full code mạch led trái tim
Chúng ta sẽ ghép toàn bộ các hiệu ứng trên, ta sẽ được một chương trình với nhiều hiệu ứng, mỗi hiệu ứng thực hiện 5 lần:
// Bai 5 - Lap trinh 8051 LED trai tim voi cac hieu ung
// AT89S52, thach anh 12MHz, mo phong Proteus
// 32 LED noi P0.0 - P3.7 theo chieu kim dong ho, kieu hut dong:
// anode noi VCC (qua dien tro), cathode noi chan vi dieu khien => muc 0 la sang, muc 1 la tat
#include <REGX52.H>
#define LED_ON 0x00
#define LED_OFF 0xFF
#define STEP_MS 100 // thoi gian moi buoc hieu ung
// Bang ma sang dan tu bit 0 len bit 7 (muc 0 la sang)
unsigned char code sang_thuan[8] = {0xFE, 0xFC, 0xF8, 0xF0, 0xE0, 0xC0, 0x80, 0x00};
// Bang ma sang dan tu bit 7 xuong bit 0
unsigned char code sang_nguoc[8] = {0x7F, 0x3F, 0x1F, 0x0F, 0x07, 0x03, 0x01, 0x00};
// Bang ma tat dan tu bit 0 len bit 7
unsigned char code tat_thuan[8] = {0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0xFF};
// Bang ma tat dan tu bit 7 xuong bit 0
unsigned char code tat_nguoc[8] = {0x80, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC, 0xFE, 0xFF};
// Tre khoang 1ms moi don vi voi thach anh 12MHz (Keil C51)
void delay_ms(unsigned int ms)
{
unsigned int i, j;
for (i = 0; i < ms; i++)
for (j = 0; j < 123; j++);
}
void Set_All(unsigned char value)
{
P0 = value;
P1 = value;
P2 = value;
P3 = value;
}
// Ghi gia tri ra 1 port theo so thu tu 0 - 3
void Set_Port(unsigned char port, unsigned char value)
{
switch (port)
{
case 0: P0 = value; break;
case 1: P1 = value; break;
case 2: P2 = value; break;
case 3: P3 = value; break;
}
}
// Hieu ung 1: 32 LED cung nhap nhay
void Nhap_Nhay(void)
{
Set_All(LED_ON);
delay_ms(300);
Set_All(LED_OFF);
delay_ms(300);
}
// Hieu ung 2: sang dan theo chieu kim dong ho, P0.0 -> P3.7
void Sang_Dan_Thuan(void)
{
unsigned char port, i;
Set_All(LED_OFF);
for (port = 0; port < 4; port++)
{
for (i = 0; i < 8; i++)
{
Set_Port(port, sang_thuan[i]);
delay_ms(STEP_MS);
}
}
}
// Hieu ung 3: sang dan nguoc chieu kim dong ho, P3.7 -> P0.0
void Sang_Dan_Nguoc(void)
{
unsigned char port, i;
Set_All(LED_OFF);
for (port = 4; port > 0; port--)
{
for (i = 0; i < 8; i++)
{
Set_Port(port - 1, sang_nguoc[i]);
delay_ms(STEP_MS);
}
}
}
// Hieu ung 4: tat dan theo chieu kim dong ho
void Tat_Dan_Thuan(void)
{
unsigned char port, i;
Set_All(LED_ON);
for (port = 0; port < 4; port++)
{
for (i = 0; i < 8; i++)
{
Set_Port(port, tat_thuan[i]);
delay_ms(STEP_MS);
}
}
}
// Hieu ung 5: tat dan nguoc chieu kim dong ho
void Tat_Dan_Nguoc(void)
{
unsigned char port, i;
Set_All(LED_ON);
for (port = 4; port > 0; port--)
{
for (i = 0; i < 8; i++)
{
Set_Port(port - 1, tat_nguoc[i]);
delay_ms(STEP_MS);
}
}
}
// Hieu ung 6: so le nho giot, 1 LED chay tu bit 0 toi cuoi roi dung lai, cac LED da roi xuong giu nguyen
// Lam dong thoi tren ca 4 port
void So_Le_Nho_Giot(void)
{
unsigned char i, j;
unsigned char da_sang = 0x00; // cac LED da roi xuong (bit 1 = sang)
for (i = 8; i > 0; i--)
{
for (j = 0; j < i; j++)
{
Set_All(~((0x01 << j) | da_sang)); // dao bit vi muc 0 moi la sang
delay_ms(STEP_MS);
}
da_sang |= 0x01 << (i - 1); // giot vua roi nam lai o vi tri cuoi
}
}
void main(void)
{
unsigned char n;
while (1)
{
for (n = 0; n < 5; n++) Nhap_Nhay();
for (n = 0; n < 5; n++) Sang_Dan_Thuan();
for (n = 0; n < 5; n++) Sang_Dan_Nguoc();
for (n = 0; n < 5; n++) Tat_Dan_Thuan();
for (n = 0; n < 5; n++) Tat_Dan_Nguoc();
for (n = 0; n < 5; n++) So_Le_Nho_Giot();
}
}
Ngoài ra: các bạn có thể tham khảo thêm các hiệu ứng khác:
https://drive.google.com/file/d/1rzT1Jhh1_jc6jK2C5wuatcFdsw8SQvkE/view?usp=sharing
Kết
Hi vọng sau bài này các bạn có thể làm được một mạch led trái tim để tặng gấu. Ngoài ra các bạn có thể tham khảo các code của những cao nhân khác để hoàn thiện bộ hiệu ứng nhìn pro hơn.
Tiếp tục tới bài sau trong serie nhé! Đừng quên gia nhập Hội Anh Em Nghiện Lập trình để giao lưu và học hỏi nhé!!!

