Lập trình pic 16f877A quét 2 led 7 đoạn – 7 segment
Trong bài viết này chúng ta cùng tìm hiểu về led 7 đoạn (led 7 segment) – Cấu tạo led 7 đoạn, led 7 đoạn cực âm chung, 7 đoạn cực dương chung, cách kết nối với vi điều khiển. Thực hành lập trình vi điều khiển pic 16f877A quét led 7 đoạn – hiển thị số từ 0-99.
Ở bài trước Điện tử điều khiển đã có bài viết “tìm hiểu led 7 đoạn và quét 1 led 7 đoạn với pic 16f877A“. Với nhiều nhu cầu khác chúng ta cần hiển thị 2 digit trở lên thì làm như thế nào? Sau đây chúng ta cùng nhau tìm hiểu cách quét 2 led 7 đoạn, trên cơ sở này bạn hoàn toàn có thể áp dụng cho hiển thị từ 3, 4 led 7 đoạn trở lên. Trong project này chúng ta dùng ngắt Interrupt để điều khiển các digit led, chúng ta cần chú ý những đoạn code sau:
Đoạn code thứ nhất:
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0xc0;
case 1 : return 0xf9;
case 2 : return 0xa4;
case 3 : return 0xb0;
case 4 : return 0x99;
case 5 : return 0x92;
case 6 : return 0x82;
case 7 : return 0xf8;
case 8 : return 0x80;
case 9 : return 0x90;
}
}
Đoạn code này nói một cách đại khái là chuyển từ số thập phân sang số hex để led 7 đoạn có thể hiển thị, các mã số hex này ta hoàn toàn có thể dùng tool Seven Segment Editor được hỗ trợ từ mikroC để tạo ra như sau:
Qua hình trên, bạn thấy việc tạo ra mã hex từ tool seven segment editor rất đơn giản phải không, bạn chỉ cần click để tạo số cần hiển thị, chương trình sẽ sinh ra mã hex hoặc mã decimal (bạn cần chọn loại mã trong phần Decoding format) cho cả hai loại của led 7 đoạn là common cathode và Common anode.
Đoạn code thứ hai:
void interrupt() {
if (digit_no==0) {
PORTA = 0; // Turn off both displays
PORTD = digit1; // Set mask for displaying ones on PORTD
PORTA = 1; // Turn on display for ones (LSD)
digit_no = 1;
} else {
PORTA = 0; // Turn off both displays
PORTD = digit10; // Set mask for displaying tens on PORTD
PORTA = 2; // Turn on display for tens (MSD)
digit_no = 0;
}
TMR0 = 0; // Reset counter TMRO
INTCON = 0x20; // Bit T0IF=0, T0IE=1
}
Đây là đoạn code thực hiện ngắt tràn TMR0, điều khiển việc quét (bật, tắt) và truyền data cho hai led 7 đoạn.
Đoạn code thứ ba:
for (i = 0; i<=99; i++) { // Count from 0 to 99
digit = i % 10u;
digit1 = mask(digit); // Prepare mask for displaying ones
digit = (char)(i / 10u) % 10u;
digit10 = mask(digit); // Prepare mask for displaying tens
Delay_ms(200);
}
Đoạn code này thực hiện việc tách các chữ số hàng đơn vị, hàng chục và sử dụng vòng lặp for để hiển thị tuần tự từ số 0 đến số 99, khoảng delay giữa các lần hiển thị là 200ms.
Sau đây là chương trình quét 2 led 7 đoạn trên vi điều khiển pic 16f877A hoàn chỉnh:
/*
Ten Project: Quet 2 led 7 doan cuc duong chung
Cmu: pic 16f877A, thach anh 8Mhz
Ket noi: Ta su dung porta de dieu khien 2 led 7 doan, portd (RA0…RA7) ket noi den 7 segment (a, b, c….dp)
Author: http://dientudieukhien.net
Tham khảo: mkroE
*/
/*Tao ma hex cho led 7 doan*/
unsigned short mask(unsigned short num) {
switch (num) {
case 0 : return 0xc0;
case 1 : return 0xf9;
case 2 : return 0xa4;
case 3 : return 0xb0;
case 4 : return 0x99;
case 5 : return 0x92;
case 6 : return 0x82;
case 7 : return 0xf8;
case 8 : return 0x80;
case 9 : return 0x90;
}
}
unsigned short mask(unsigned short num);
unsigned short digit_no, digit10, digit1, digit, i;
void interrupt() {
if (digit_no==0) {
PORTA = 0; // Turn off both displays
PORTD = digit1; // Set mask for displaying ones on PORTD
PORTA = 1; // Turn on display for ones (LSD)
digit_no = 1;
} else {
PORTA = 0; // Turn off both displays
PORTD = digit10; // Set mask for displaying tens on PORTD
PORTA = 2; // Turn on display for tens (MSD)
digit_no = 0;
}
TMR0 = 0; // Reset counter TMRO
INTCON = 0x20; // Bit T0IF=0, T0IE=1
}
void main() {
OPTION_REG = 0x80; // Set timer TMR0
TMR0 = 0;
INTCON = 0xA0; // Disable interrupt PEIE,INTE,RBIE,T0IE
PORTA = 0; // Turn off both displays
TRISA = 0; // All port A pins are configured as outputs
PORTD = 0; // Turn off all display segments
TRISD = 0; // All port D pins are configured as outputs
do {
for (i = 0; i<=99; i++) { // Count from 0 to 99
digit = i % 10u;
digit1 = mask(digit); // Prepare mask for displaying ones
digit = (char)(i / 10u) % 10u;
digit10 = mask(digit); // Prepare mask for displaying tens
Delay_ms(200);
}
} while (1); // Endless loop
}
Code trên sử dụng trình biên dịch mikroC Pro for Pic ver 6.6.1, bạn có thể tải code C, Hex, file mô phỏng bằng proteus theo link dưới.