Gạt switch 2 lên ON để kích hoạt Port 3 là các nút nhấn. Gạt switch 4 lên ON để kích hoạt Led 7 đoạn.
Port 2 dùng để chọn led 7 đoạn nào sẽ được sáng và Port 0 là dữ liệu cho led 7 đoạn đó. P0 : Data P2 : Select P0.0 : a P2.0 : Led 1 P0.1 : b P2.0 : Led 2 P0.2 : c P2.0 : Led 3 P0.3 : d P2.0 : Led 4 P0.4 : e P2.0 : Led 5 P0.5 : f P2.0 : Led 6 P0.6 : g P2.0 : Led 7 P0.7 : dot P2.0 : Led 8
Với kết nối phần cứng như vậy, để hiện thị số 5 thì dữ liệu xuất ra sẽ là 0x6D (0110 1101). Tương tự, giá trị cho các số từ 0 đến 9 sẽ là :
unsigned char led7_data[10] = {0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F};
3.2 Viết chương trình
3.2.1 Hàm init_main()
Do đăc điểm của phần cứng, trong hàm main, bạn phải dùng thêm hàm init_main, để gán các Port 0,1,2 với giá trị 0x00.
void init_main() { P0 = 0x00; P2 = 0x00; P1 = 0x00; }
Các chương trình sau này sẽ đều có hàm này.
3.2.2 Hàm main()
Hàm này sẽ gọi init_main(), sau đó xét các giá trị của Port 3 và hiển thị ra led 7 đoạn giá trị tương ứng.
void main() { //P0 : Data P2 : Select //P0.0 : a P2.0 : Led 1 //P0.1 : b P2.0 : Led 2 //P0.2 : c P2.0 : Led 3
//P0.4 : e P2.0 : Led 5
//P0.5 : f P2.0 : Led 6
//P0.6 : g P2.0 : Led 7
//P0.7 : dot P2.0 : Led 8
unsigned char led7_data[10] =
{0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F}; init_main(); while(1) { if((P3 & 0x01) == 0) // P3 = 1111 1110 { P0 = led7_data[0]; P2 = 0x01; }
else if((P3 & 0x02) == 0)// P3 = 1111 1101 {
P0 = led7_data[1]; P2 = 0x02;
}
else if((P3 & 0x04) == 0)// P3 = 1111 1011 {
P0 = led7_data[2]; P2 = 0x04;
}
else if((P3 & 0x08) == 0) // P3 = 1111 0111 {
P0 = led7_data[3]; P2 = 0x08;
}
else if((P3 & 0x10) == 0) // P3 = 1110 1111 {
P0 = led7_data[4]; P2 = 0x10;
P2 = 0x40; }
else if((P3 & 0x80) == 0) // P3 = 0111 1111 { P0 = led7_data[7]; P2 = 0x80; } else { P0 = 0x00; P2 = 0x00; } } }
Các bước dịch và nạp chương trình bạn xem lại ở bài trước. Code mẫu của bài thí nghiệm này bạn có thể tham khảo ở thư mục Bài 3 đính kèm trong CD này.
3.3 Một số lỗi quan trọng
Lỗi gọi sai hàm : Chẳng hạn bạn định nghĩa hàm là init_main(), nhưng trong hàm main.c bạn lại gọi là initmain() (thiếu dấu _ ), thì khi nhấn F7 compile chương trình, file hex vẫn được tạo ra, nhưng khi nạp vào chương trình chạy sai. Bạn nên lưu ý các thông báo của compiler lúc dịch, sẽ có thông báo sau :
Khi gọi sai tên 1 hàm, compiler của KeilC sẽ vẫn tạo ra file hex, bạn nên lưu ý các warning để khắc phục lỗi.
Không gọi hàm đã được định nghĩa : Để 1 module có thể dùng lại, thông thường ta hiện thực nhiều hàm liên quan đến nó, nhưng trong 1 ứng dụng không gọi hết tất cả các hàm đó, sẽ có thông báo về trường hợp này. Tuy nhiên đây không phải là lỗi, file hex được tạo ra vẫn sẽ chạy đúng. Thông báo dạng này như sau :
Như thông báo ở trên, hàm start_timer0() và start_timer1() không được gọi trong bất kì hàm nào.
Bài 4 : Ngắt Timer
Mục đích:
Tìm hiểu ngắt timer của 89V51
Xây dựng module dành cho timer của 89V51 có thể dùng lại được.
Yêu cầu:
Viết chương trình hiển thị từ 0, sau 1 giây tăng lên 1, khi tăng đến 9 thì chuyển sang hiển thị ở led kế tiếp, hiển thị bắt đầu lại từ 0.