You are on page 1of 110

HƯỚNG DẪN SỬ DỤNG KIT 8051

Mục lục

Giới thiệu kit thí nghiệm BK89IT ...................................................................................... 4


Mô hình lập trình C trong vi điều khiển ............................................................................. 5
Bài 1 : Hướng dẫn cài đặt Keil C và Flash Magic.......................................................... 6
1.1 Cài đặt Keil C ........................................................................................................... 6
1.2 Cài đặt Flash Magic ................................................................................................ 11
1.3 Cấu hình cho Flash Magic ...................................................................................... 16
Bài 2 : Truy xuất Port I/O............................................................................................. 22
2.1 Tạo project trên Keil C ........................................................................................... 22
2.2 Viết chương trình đơn giản ..................................................................................... 32
2.2.1 Kết nối phần cứng............................................................................................ 32
2.2.2 Viết chương trình ............................................................................................. 33
2.2.3 Nạp chương trình ............................................................................................. 34
2.2.4 Các lỗi xảy ra khi nạp chương trình................................................................. 35
Bài 3 : Điều khiển đơn giản Led 7 đoạn....................................................................... 38
3.1 Kết nối phần cứng:.................................................................................................. 38
3.2 Viết chương trình .................................................................................................... 39
3.2.1 Hàm init_main()............................................................................................... 39
3.2.2 Hàm main() ...................................................................................................... 39
3.3 Một số lỗi lập trình quan trọng ............................................................................... 41
Bài 4 : Ngắt Timer........................................................................................................ 42
4.1 Khai báo ngắt timer................................................................................................. 42
4.2 Viết chương trình .................................................................................................... 43
4.2.1 Hàm init_timer1() ............................................................................................ 43
4.2.2 Hàm start_timer1()........................................................................................... 43
4.2.3 Hàm timer1_isr().............................................................................................. 43
4.2.4 Hàm delay_ms(unsigned int duration)............................................................. 44
4.2.5 Hàm stop_timer1()........................................................................................... 44
Bài 5 : Dùng ngắt timer viết ứng dụng LED RIVER ................................................... 45
5.1 Kết nối phần cứng................................................................................................... 45
5.2 Viết chương trình .................................................................................................... 45
Bài 6 : Chống rung cho phím ....................................................................................... 47
6.1 Nguyên lý chống rung............................................................................................. 47
6.2 Kết nối phần cứng................................................................................................... 48
6.3 Viết chương trình .................................................................................................... 49
6.3.1 Hàm initKey() .................................................................................................. 49
6.3.2 Hàm getKey() .................................................................................................. 49
Bài 7 : Quét led điều khiển Led 7 đoạn ........................................................................ 51
7.1 Nguyên lý quét led 7 đoạn ...................................................................................... 51
7.2 Kết nối phần cứng................................................................................................... 52
7.3 Viết chương trình .................................................................................................... 52
7.3.1 Hàm init_led7()................................................................................................ 52
7.3.2 Hàm clear_led7() ............................................................................................. 53
7.3.3 Hàm set_position(unsigned int pos) ................................................................ 53
7.3.4 Hàm get_position() .......................................................................................... 53

BKIT HARDWARE CLUB www.bkit4u.com 1


HƯỚNG DẪN SỬ DỤNG KIT 8051

7.3.5 Hàm put_Number(unsigned int num) .............................................................. 54


7.3.6 Hàm put_string(char strNum[]) ....................................................................... 54
7.3.7 Hàm scan_led7................................................................................................. 54
Bài 8 : Điều khiển Ma trận led ..................................................................................... 56
8.1 Nguyên lý điều khiển ma trận led........................................................................... 56
8.2 Kết nối phần cứng................................................................................................... 56
8.3 Viết chương trình .................................................................................................... 56
8.3.1 Hàm init_led_matrix() ..................................................................................... 57
8.3.2 Hàm scan_led_matrix().................................................................................... 57
8.3.3 Hàm update_display_led_matrix() .................................................................. 57
Bài 9 : Chạy chữ trên Ma trận led ................................................................................ 59
9.1 Nguyên lý chạy chữ trên ma trận led ...................................................................... 59
9.2 Kết nối phần cứng................................................................................................... 60
9.3 Viết chương trình .................................................................................................... 60
9.3.1 Hàm set_message(char strMsg[]) .................................................................... 60
9.3.2 Hàm main() ...................................................................................................... 61
Bài 10 : Ngắt ngoài..................................................................................................... 62
10.1 Nguyên lý điều khiển ngắt ngoài .......................................................................... 62
10.2 Kết nối phần cứng................................................................................................. 62
10.3 Viết chương trình .................................................................................................. 62
10.3.1 Hàm init_ext_int0()........................................................................................ 62
10.3.2 Hàm init_ext_int1()........................................................................................ 62
10.3.3 Hàm ext0_isr() ............................................................................................... 63
10.3.4 Hàm ext1_isr() ............................................................................................... 63
Bài 11 : Điều khiển encoder ....................................................................................... 64
11.1 Nguyên lý điều khiển encoder .............................................................................. 64
11.2 Kết nối phần cứng................................................................................................. 65
11.3 Viết chương trình .................................................................................................. 65
Bài 12 : Giao tiếp UART............................................................................................ 67
12.1 Nguyên lý giao tiếp UART................................................................................... 67
12.2 Giao tiếp UART với máy tính .............................................................................. 68
12.3 Viết chương trình .................................................................................................. 69
12.3.1 Thanh ghi điều khiển truyền nhận nối tiếp .................................................... 69
12.3.2 Dùng Timer1 tạo Baud rate ........................................................................... 71
12.3.3 Chương trình truyền nhận UART trên 8051.................................................. 71
12.4 Kiểm tra truyền nhận UART ................................................................................ 74
12.5 Xây dựng chương trình trên PC ............................................................................ 74
12.5.1 Load các cổng COM của PC lên ComboBox ................................................ 78
12.5.2 Kết nối cổng với cổng COM.......................................................................... 79
12.5.3 Gửi dữ liệu ..................................................................................................... 80
12.5.4 Nhận dữ liệu................................................................................................... 81
Bài 13 : Giao tiếp PS2 với bàn phím .......................................................................... 85
13.1 Nguyên lý giao tiếp PS2 ....................................................................................... 85
13.2 Kết nối phần cứng................................................................................................. 86
13.3 Viết chương trình .................................................................................................. 87
Bài 14 : PWM điều khiển motor................................................................................. 88

BKIT HARDWARE CLUB www.bkit4u.com 2


HƯỚNG DẪN SỬ DỤNG KIT 8051

14.1 Khái niệm PWM ................................................................................................... 88


14.2 Lập trình PWM trên 89V51 .................................................................................. 89
Bài 15 : Giao tiếp LCD character ............................................................................... 90
15.1 Chức năng các chân của LCD............................................................................... 90
15.2 Kết nối màn hình LCD.......................................................................................... 91
15.3 Các vùng nhớ của LCD......................................................................................... 91
15.3.1 Display Data Ram (DDRAM) ....................................................................... 91
15.3.2 Character Generator Ram (CGRAM) ............................................................ 91
15.3.3 Bộ nhớ CGROM ............................................................................................ 92
15.4 Các lệnh cơ bản của LCD ..................................................................................... 93
15.5 Kết nối LCD với vi điều khiển ............................................................................. 94
15.6 Khởi tạo LCD ....................................................................................................... 95
15.7 Kết nối phần cứng................................................................................................. 97
15.8 Viết chương trình .................................................................................................. 98
15.8.1 Các hàm cơ bản.............................................................................................. 98
15.8.2 Khởi tạo LCD chế độ 4 bit............................................................................. 98
15.8.3 Xoá màn hình................................................................................................. 99
15.8.4 Thiết lập vị trí con trỏ .................................................................................... 99
15.8.5 In kí tự ra màn hình..................................................................................... 100
Bài 16 : Giao tiếp I2C – DS1307.............................................................................. 101
16.1 Các đặc điểm của DS1307 .................................................................................. 101
16.2 Nguyên lý hoạt động........................................................................................... 101
16.3 Các tín hiệu Input và Output............................................................................... 102
16.4 RTC và sơ đồ địa chỉ Ram.................................................................................. 103
16.5 Thông tin thời gian và lịch.................................................................................. 103
16.6 Thanh ghi điều khiển (Control Register) ............................................................ 104
16.7 Bus dữ liệu nối tiếp............................................................................................. 104
16.8 Giao thức I2C và RTC DS1307 ......................................................................... 105
16.8.1 Kết nối phần cứng........................................................................................ 105
16.8.2 Start và Stop truyền dữ liệu ......................................................................... 105
16.8.3 Truyền 1 byte dữ liệu................................................................................... 107
16.8.4 Giao tiếp với DS1307 .................................................................................. 108

BKIT HARDWARE CLUB www.bkit4u.com 3


HƯỚNG DẪN SỬ DỤNG KIT 8051

Giới thiệu kit thí nghiệm BK89IT

Các chức năng của board thí nghiệm BK89IT :


v 8 nút nhấn : nối với P3.
v 8 led 7 đoạn : hỗ trợ quét led, P0 để gửi dữ liệu và P2 để chọn led.
v Led ma trận 2 màu : P0 gửi dữ liệu mà đỏ, P2 gửi dữ liệu xanh, P1 để chọn cột hiển
thị.
v Giao tiếp với bàn phím PS2.
v Giao tiếp COM
v 4 chân dùng để kết nối encoder.
v Cấu hình bằng switch : Switch 1 cho Port 1, 2 cho Port 3, 3 cho led ma trận và 4
cho led 7 đoạn.
v Cấp nguồn ngoài hoặc USB.
v Mạch nạp onboard.

BKIT HARDWARE CLUB www.bkit4u.com 4


HƯỚNG DẪN SỬ DỤNG KIT 8051

Mô hình lập trình C trong vi điều khiển

timer.h timer.c
#ifndef __TIMER_H_ #include "timer.h"
#define __TIMER_H_ int counter0;
int counter1;
#include "LED7\led7.h" void init_tim er0();
{
extern int counter0; IE |= 0x20;
void init_timer0(); TR0 = 1;
void init_timer1(); ..........................
............... }
void init_tim er1()
#endif {
..........................
}
main.c
void private_function()
#include "TIMER\timer.h" {
#include "LED7\led7.h" ..........................
#include <REG51F.H> }

void main()
{
init_main();
init_timer0();
....................
while1(){}
}
led7.h led7.c
#ifndef __LED7_H_ #include "led7.h"
#define __LED7_H_ unsigned char led7_buff[8];

void init_led7(); void init_led7();


void scan_led7(); {
............... P0 = 0x00;
T2 = 0x00;
#endif ..........................
}
void scan_led7()
{
..........................
}
void private_function()
{
..........................
}

Để có thể tổ chức tốt chương trình, thông thường mỗi module ta sẽ chia làm 2
file:
v File .h : Khai các hàm và extern các biến toàn cục.
v File .c : Hiện thực các hàm được khai báo trong file .h.
Khi muốn sử dụng module này, ta chỉ cần include file .h là có thể gọi được các
hàm được khai báo trong file .h.

BKIT HARDWARE CLUB www.bkit4u.com 5


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 1 : Hướng dẫn cài đặt Keil C và Flash Magic


Mục đích :
Cài đặt Keil C để soạn thảo chương trình.
Cài đặt Flash Magic để nạp chương trình.
Cấu hình cho Flash Magic.

1.1 Cài đặt Keil C


Keil C là chương trình hỗ trợ khá đầy đủ để người dùng soạn thảo chương trình
dành cho các vi điều khiển thuộc họ 8051. Để cài đặt bạn tiến hành theo các bước như
sau:

Bước 1 : Click vào file c51v815.exe trong CD đi kèm, màn hình sau sẽ xuất hiện

BKIT HARDWARE CLUB www.bkit4u.com 6


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 2 : Chọn Next, màn hình sau sẽ xuất hiện.

Bước 3 : Click chọn I agree và chọn Next, màn hình sau sẽ xuất hiện.

BKIT HARDWARE CLUB www.bkit4u.com 7


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 4 : Bạn có thể để mặc định và chọn Next. Tuy nhiên bạn có thể thay đổi
Destinatioin Folder, là thư mục chứa 1 số thư viện hỗ trợ trong việc lập trình trên Keil C.
Màn hình sau xuất hiện để bạn điền 1 số thông tin cá nhân.

BKIT HARDWARE CLUB www.bkit4u.com 8


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 5 : Chọn Next để bắt đầu cài đặt

Bước 6 : Khi cài đặt xong, màn hình sau xuất hiện và bạn nhấn Finish để hoàn tất
quá trình cài đặt.

BKIT HARDWARE CLUB www.bkit4u.com 9


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 7 : Trang web sau hiển thị để giới thiệu về KeilC phiên bản này.

Các bước cấu hình cho Keil C để dịch chương trình ra file Hex sẽ được trình bày
trong bài thực hành tiếp theo.

BKIT HARDWARE CLUB www.bkit4u.com 10


HƯỚNG DẪN SỬ DỤNG KIT 8051

1.2 Cài đặt Flash Magic

Đây là chương trình dùng để nạp file Hex cho 89V51. Để cài đặt bạn làm theo các
bước sau :
Bước 1 : Double click vào file FlashMagic.exe, màn hình sau sẽ xuất hiện

Bước 2 : Chọn Next

BKIT HARDWARE CLUB www.bkit4u.com 11


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 3 : Click chọn I accept và chọn Next

BKIT HARDWARE CLUB www.bkit4u.com 12


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 4 : Bạn có thể để mặc định và chọn Next, hoặc thay đổi đường dẫn của thư mực cài
đặt nếu bạn muốn. Khi click Next màn hình sau sẽ xuất hiện.

Bước 5 : Để mặc định và chọn Next

BKIT HARDWARE CLUB www.bkit4u.com 13


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 6 : Chọn Next.

BKIT HARDWARE CLUB www.bkit4u.com 14


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 7 : Chọn Install để cài đặt.

Bước 8 : Khi cài đặt xong màn hình sau sẽ xuất hiện, bạn nhấn Finish để kết thúc cài đặt.

BKIT HARDWARE CLUB www.bkit4u.com 15


HƯỚNG DẪN SỬ DỤNG KIT 8051

1.3 Cấu hình cho Flash Magic

Bước 1 : Khởi động Flash Magic từ màn hình Desktop (hoặc vào Start\Program
Files\Flash Magic và chọn Flash Magic), màn hình sau sẽ xuất hiện

BKIT HARDWARE CLUB www.bkit4u.com 16


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 2 : Bạn chọn Baud Rate là 9600, Device là chip tương ứng mà bạn dùng.
Check chọn Verify after programming và Erase blocks used by Hex File.

BKIT HARDWARE CLUB www.bkit4u.com 17


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 3 : Chọn menu Option và chọn Advance Option, màn hình sau sẽ xuất hiện :

BKIT HARDWARE CLUB www.bkit4u.com 18


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 4 : Chọn qua tab Hardware Config và check chọn Assert DTR and RTS
while COM Port open. Nhấn OK để đóng cửa số này lại.

Bước 5 : Xem cổng COM đang là cổng nào. Bạn thu nhỏ Flash Magic lại, trên
màn hình Desktop, từ biểu tượng My Computer, click phải chuột và chọn Manage.

BKIT HARDWARE CLUB www.bkit4u.com 19


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 6 : Màn hình sau xuất hiện, bạn chọn Device Manager.

Bước 7 : Cắm dây cổng COM nếu bạn đang dùng USB to COM, mở rộng Ports
(COM &LPT), bạn sẽ biết được tên cổng COM đang dùng (trong ví dụ này là COM 9).

BKIT HARDWARE CLUB www.bkit4u.com 20


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 9 : Kích hoạt lại Flash Magic và chọn cổng COM tương ứng.

BKIT HARDWARE CLUB www.bkit4u.com 21


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 2 : Truy xuất Port I/O


Mục đích:
Tạo project đơn giản trong Keil C và cấu hình cho Keil C.
Điều khiển Port 1 và Port 3.
Nạp chương trình bằng Flash Magic.
Yêu cầu:
Viết chương trình để nhấn nút 1 đèn thứ 1 sáng, nút 2 đèn thứ 2 sáng,….

2.1 Tạo project trên Keil C

Bước 1 : Kích hoạt Keil uVision3, cửa sổ Keil C hiện ra.

Bước 2 : Chọn Project và chọn New uVision Project…

BKIT HARDWARE CLUB www.bkit4u.com 22


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 3 : Chọn đường dẫn và gõ tên project và khung File name, chọn Save,
khung cửa số sau đây xuất hiện.

BKIT HARDWARE CLUB www.bkit4u.com 23


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 4 : Chọn chip tương ứng với board của bạn, trong board của chúng tôi sử
dụng 89V51RB2. Browse tới NXP, và chọn P89V51RB2

BKIT HARDWARE CLUB www.bkit4u.com 24


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 5 : Sau khi nhấn OK, màn hình sau sẽ xuất hiện, bạn chọn No

Bước 6 : Project được tạo ra như sau:

BKIT HARDWARE CLUB www.bkit4u.com 25


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 7 : Cấu hình để tạo ra file Hex, bạn chọn menu Project, chọn Option for
Target

BKIT HARDWARE CLUB www.bkit4u.com 26


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 8 : Màn hình sau xuất hiện

BKIT HARDWARE CLUB www.bkit4u.com 27


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 9 : Chọn tab Output, và click chọn Click Hex File

Bước 10 : Chép thư file REG51F.H (nếu cài mặc định sẽ nằm trong thư mục
C:\Keil\C51\INC\Philips hoặc bạn có thể copy trong CD đi kèm) là file define các thanh
ghi của 89V51 vào cùng cấp với file project.

BKIT HARDWARE CLUB www.bkit4u.com 28


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 11 : Bạn có thể chọn và nhấn Delete Source Group1 do Keil C tự tạo ra, và
tự tạo Group mới cho mình. Chọn Target, click phải chuột và chọn New Group, 1 group
mới được tạo ra, đổi tên thành Main cho gợi nhớ. Trong tất cả các bài demo, group này sẽ
chứa file main.c, là file chính để chạy chương trình.

BKIT HARDWARE CLUB www.bkit4u.com 29


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 11 : Tạo mới 1 file bằng cách chọn menu File rồi chọn New. Chọn tiếp
menu File rồi chọn Save, khung cửa sổ sau sẽ hiện lên, bạn nhập tên file vào và nhấn
Save.

Bước 12 : Click phải vào group Main, và chọn Add Files to Group Main

BKIT HARDWARE CLUB www.bkit4u.com 30


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 13 : Chỉ đường dẫn đển file main.c mà bạn vừa tạo, nhấn Add rồi nhấn tiếp
Close.

BKIT HARDWARE CLUB www.bkit4u.com 31


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 14 : Click vào dấu + của Main, bạn sẽ thấy file main.c đã được thêm vào
project

2.2 Viết chương trình đơn giản


Keil C hỗ trợ compiler của C chuẩn, nên cấu trúc chương trình của nó hoàn toàn
giống C chuẩn. Bạn có thể tìm hiểu thêm về lập trình C để nâng cao khả năng tổ chức 1
chương trình C. Tuy nhiên, đi theo trình tự của các bài thí nghiệm này, bạn cũng có thể
nắm được 1 cấu trúc của chương trình C chuẩn viết cho 89V51.
Yêu cầu của bài thí nghiệm này là với nút 1 được nhất, thì đèn led 1 sáng, nút 2
được nhấn thì đèn 2 sáng,….

2.2.1 Kết nối phần cứng


Gạt switch 1 lên ON để kích hoạt Port 1.
Gạt switch 2 lên ON để kích hoạt Port 3.

Các nút nhấn được nối với P3 (Port 3) của vi điều khiển theo trình tự nút 1 nối với
P3.0, nút 2 nối với P3.1, v.v…. Các nút nhấn tích cực 0.

BKIT HARDWARE CLUB www.bkit4u.com 32


HƯỚNG DẪN SỬ DỤNG KIT 8051

Đây là kiểu kết nối phím đơn giản nhất, các giải pháp kết nối phím khác tốt hơn
sẽ được trình bày ở bài chống rung cho phím.
Các đèn led được nối với P1 (Port 1) của vi điều khiển, đèn 1 nối với P1.0, đèn 2
nối với P1.1, v,v…. Các đèn tích cực mức 1.

2.2.2 Viết chương trình


Trong file main.c, bạn viết code như sau :
#include <REG51F.H>

void main()
{
while(1)
{
P1 = ~P3;
}
}
Do P3 tích cực mức 0, nút 1 được nhấn giá trị của nó sẽ là 1111 1110 = 0xFE,
~P3 lúc đó sẽ là 0000 0001 = 0x01. P1 tích cực mức 1 nên P1 = 0x01 thì đèn 1 sẽ sáng.
Chọn menu Project và chọn Build Target hoặc nhấn F7 để dịch chương trình. Nếu
có lỗi, Keil C sẽ thông báo để bạn sửa, nếu không có lỗi file Hex sẽ được tạo ra cùng cấp
với file project.

BKIT HARDWARE CLUB www.bkit4u.com 33


HƯỚNG DẪN SỬ DỤNG KIT 8051

2.2.3 Nạp chương trình


Bước 1 : Kết nối mạch nạp với board thông qua jack 4, với chân số 1 là VCC,
chân 2 là GND, chân 3 là TX và chân 4 là RX.
Bước 2 : Gắn nguồn cho kit thí nghiệm.
Bước 3 : Khởi động Flash Magic.
Bước 4 : Chọn menu ISP và chọn Erase Flash Pages để xoá code cũ trong
89V51RB2. Bạn cần phải làm bước này trước khi nạp chương trình cho các dòng 8051
không tự xoá. Màn hình sau sẽ hiện lên :

Bạn dùng thêm tổ hợp phím Shift để có thể chọn được nhiều Pages, và nhấn
Erase. Khi màn hình sau hiện lên, bạn nhấn nút Reset trên board để tiếp tục (nên nhấn và
giữ trong khoảng 2 giây).

Bước 5 : Khi cửa sổ sau hiện lên, nhấn OK để tiếp tục

BKIT HARDWARE CLUB www.bkit4u.com 34


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bước 6 : Nhấn Browse để chọn đường dẫn tới file Hex cần nạp rồi nhấn Start.

Bước 7 : Khi thấy Status là Finished, bạn có thể nhấn nút Reset trên board để bắt
đầu chạy chương trình của bạn.

2.2.4 Các lỗi xảy ra khi nạp chương trình


Dưới đây là 1 số lỗi phổ biến khi nạp chương trình. Kinh nghiệm để tìm lỗi là
kiểm tra qua hết các lỗi thông dụng dưới đây hoặc dựa vào các thông báo lỗi để phán
đoán.
Chưa cấu hình Flash Magic

BKIT HARDWARE CLUB www.bkit4u.com 35


HƯỚNG DẪN SỬ DỤNG KIT 8051

Để khắc phục lỗi này, bạn chọn vào menu Opition/ Advance Option , chọn qua
tab Hardware Config và check chọn Assert DTR and RTS while COM Port open. Nhấn
OK để đóng cửa số này lại.

Chọn sai cổng COM

Chọn sai tốc độ Baud

Ở lỗi này, Flash Magic hiển thị thông báo yêu cầu bạn nhấn reset, nhưng khi nhấn
reset thì thông báo trên xuất hiện, bạn chỉnh lại tốc độ Baud là 9600.

BKIT HARDWARE CLUB www.bkit4u.com 36


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chọn sai chip

Ở lỗi này, Flash Magic cũng chạy được tới phần chờ nhấn nút Reset, sau khi ấn
nút Reset thì thông báo này xuất hiện.

Xung đột ở Port 3


Lỗi này xuất hiện là do người lập trình can thiệp đến Port 3, nên Flash Magic
không thể giao tiếp được với vi điều khiển để nạp chương trình. Khi bị lỗi này thông báo
sau đây sẽ xuất hiện (tương tự như thông báo chọn sai cổng COM) :

Để khắc phục lỗi này, trước khi nạp bạn nhấn đè nút Reset, mọi thao tác vẫn diễn
ra bình thường cho đến khi cửa sổ yêu cầu bạn nhấn nút Reset, bạn giữa thêm vài giây rồi
thả ra. Cách thứ 2 là rút nguồn của board ra, cho đến khi Flash Magic yêu cầu bạn nhấn
Reset thì cắm nguồn vào.
Nếu như đã kiểm tra qua hết các lỗi kia mà chương trình vẫn chưa nạp được, thì
nguyên nhân có thể là bạn cắm ngược chiều mạch nạp, phần mềm Flash Magic bị lỗi, IC
MAX 232 bị hư hoặc hư vi điều khiển.

BKIT HARDWARE CLUB www.bkit4u.com 37


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 3 : Điều khiển đơn giản Led 7 đoạn


Mục đích:
Nắm nguyên lý điều khiển led 7 đoạn.
Yêu cầu:
Viết chương trình nhấn nút 1 sẽ hiển thị số 0 ở led 7 đoạn ngoài cùng, nút 2 sẽ
hiện thị số 1 ở led 7 đoạn kế tiếp, v.v…

3.1 Kết nối phần cứng:


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

BKIT HARDWARE CLUB www.bkit4u.com 38


HƯỚNG DẪN SỬ DỤNG KIT 8051

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.3 : d P2.0 : Led 4

BKIT HARDWARE CLUB www.bkit4u.com 39


HƯỚNG DẪN SỬ DỤNG KIT 8051

//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;
}
else if((P3 & 0x20) == 0) // P3 = 1101 1111
{
P0 = led7_data[5];
P2 = 0x20;
}
else if((P3 & 0x40) == 0) // P3 = 1011 1111
{
P0 = led7_data[6];

BKIT HARDWARE CLUB www.bkit4u.com 40


HƯỚNG DẪN SỬ DỤNG KIT 8051

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 lập trình 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.

BKIT HARDWARE CLUB www.bkit4u.com 41


HƯỚNG DẪN SỬ DỤNG KIT 8051

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.

4.1 Khai báo ngắt timer


Trình tự là cho phép ngắt toàn cục, cho phép ngắt timer và thiết lập chế độ hoạt
động cho timer:

IE = 0x80; //enable global interrupt

IE &= ~(0x02);// enable timer 0


IE |= 0x02;

TMOD &= ~(0x01);// setup mode for timer 0


TMOD |= 0x01;

TH0 = (-10000/256); //10 ms


TL0 = (-10000%256);

TR0 = 1;//start timer0

Hàm phục vụ ngắt sẽ được khai báo như sau:

void timer0_isr() interrupt 1


{
TR0 = 0;//stop timer 0

// reinitialize
TH0 = (-10000/256);
TL0 = (-10000%256);

//Add your code here

TR0 = 1;//start timer 0


}

BKIT HARDWARE CLUB www.bkit4u.com 42


HƯỚNG DẪN SỬ DỤNG KIT 8051

4.2 Viết chương trình


Vì mục đích là tạo ra module Timer có khả năng dùng lại, nên chương trình sẽ
gồm group TIMER có 2 file timer.h và timer.c. File timer.h đặc tả các hàm của module
này còn file timer.c sẽ hiện thực các hàm đó. Các hàm trong timer.h bao gồm:

void init_timer0(); //init timer 0, interrupt after 10ms


void init_timer1(); //init timer 1, interrupt after 1ms

void start_timer0();
void start_timer1();

void stop_timer0();
void stop_timer1();

void delay_ms(unsigned int duration);//using timer1 to delay in ms

4.2.1 Hàm init_timer1()


Hàm này làm nhiệm vụ khởi tạo ngắt timer1 sau mỗi 1ms, khi khởi tạo ngắt
timer1 xong, ta phải hiện thực hàm phục vụ ngắt quãng cho nó, nếu không chương trình
sẽ chạy sai.
void init_timer1()
{
IE &= ~(0x08);// enable timer 1
IE |= 0x08;

TMOD &= ~(0x10);// setup mode for timer 1


TMOD |= 0x10;

TH1 = (-1000/256); //1 ms


TL1 = (-1000%256);

TR1 = 1; //start timer1

4.2.2 Hàm start_timer1()


void start_timer1()
{
TR1 = 1;
}

4.2.3 Hàm timer1_isr()


Đây là hàm phục vụ ngắt quãng của timer1, được khai báo và định nghĩa như sau:

BKIT HARDWARE CLUB www.bkit4u.com 43


HƯỚNG DẪN SỬ DỤNG KIT 8051

void timer1_isr() interrupt 3


{

TR1 = 0;//stop timer 1

// reinitialize
TH1 = (-1000/256);
TL1 = (-1000%256);

//Add your code here


if(counter1!= 0)
{
counter1--;
}
//End your code

TR1 = 1;//start timer 1


}

4.2.4 Hàm delay_ms(unsigned int duration)


Hàm này chỉ cần cài đặt giá trị cho biến counter1, giá trị này sẽ tự động giảm nhờ
đoạn code trong hàm phục vụ ngắt quãng của timer1. Vòng lặp while để chờ cho đến khi
counter1 bằng 0.
void delay_ms(unsigned int duration)
{
counter1 = duration;
while(counter1 !=0)
{
}
}

4.2.5 Hàm stop_timer1()


void stop_timer1()
{
TR1 = 0;
}

Phần hiện thực các bạn xem trong project Bai 4 để biết thêm chi tiết.

BKIT HARDWARE CLUB www.bkit4u.com 44


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 5 : Dùng ngắt timer viết ứng dụng LED RIVER


Mục đích:
Nắm vững ngắt timer.
Sử dụng ngắt timer để viết ứng dụng LED RIVER.
Yêu cầu:
Viết chương trình led river đơn giản, 1 led chạy từ P0.0 sang P1.1, đến P0.7
chuyển sang P3.7, P3.6. Khi tới P3.0 thì trở về P0.0. Thời gian chuyển qua trạng thái mới
là 1s

5.1 Kết nối phần cứng


Gạt switch 1 lên ON để kích hoạt Port 1 (các led đơn).
Gạt switch 2 lên ON để kích hoạt Port 3 (các led đơn và nút nhấn).

5.2 Viết chương trình


Đối với led chạy như yêu cầu, ta thấy có 16 trạng thái của P1 và P3 như sau
P0.0 sáng : P1 = 0x01, P3 = 0x00
P0.1 sáng : P1 = 0x02, P3 = 0x00
……
P0.7 sáng : P1 = 0x80, P3 = 0x00
P3.7 sáng : P1 = 0x00, P3 = 0x80
P3.6 sáng : P1 = 0x00, P3 = 0x40
……
P3.0 sáng : P1 = 0x00, P3 = 0x01
Như vậy, ta sẽ khai báo 2 mảng, mỗi mảng 16 phần tử cho P1 và P3, rồi cho 1
biến index tự động tăng lên sau 1s, khi index bằng 16 thì gán lại index bằng 0, để quá
trình được lặp lại.
Đối với led river có nhiều trạng thái hơn, bạn chỉ cần khai báo ra tất cả các trạng
thái vào 1 mảng, rồi lần lượt định kì xuất nó ra.
Việc delay giữa các trạng thái, ta sẽ sử dụng lại hàm delay_ms(unsigned int
duration) đã làm ở bài thí nghiệm trước.
Đối với yêu cầu của bài led river này, chúng tôi chỉ sử dụng 1 mảng 16 phần tử
dùng cho cả 2 Port. Index của P1 sẽ tăng dần từ 0 đến 15, Index của P3 sẽ giảm dần từ 15
đến 0.

//led_river : mảng 16 phần tử


//INDEX_MAX = 16
//duration = 1000ms
while(1)
{
P3 = led_river[INDEX_MAX - index-1];
P1 = led_river[index++];
if(index == INDEX_MAX)
index = 0;

BKIT HARDWARE CLUB www.bkit4u.com 45


HƯỚNG DẪN SỬ DỤNG KIT 8051

delay_ms(duration);
}
Chi tiết code của bài thí nghiệm này, bạn xem thêm trong thư mục Bài 5 trong CD
đi kèm.

BKIT HARDWARE CLUB www.bkit4u.com 46


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 6 : Chống rung cho phím


Mục đích:
Nắm vững kĩ thuật chống rung cho phím.
Yêu cầu:
Viết chương trình xuất số đếm ra led 7 đoạn với giá trị khởi tạo là 0. Khi nhấn nút
1 (được nối với P3.0) thì giá trị này tăng lên 1, tăng đến 9 thì quay trở lại 0.

6.1 Nguyên lý chống rung

Hình trên minh hoạ mức điện áp của 1 phím nhấn tích cực mức 0, ở trạng thái
bình thường, điện áp vi điều khiển nhận vào là 5V còn khi nhấn là 0V. Tuy nhiên, do độ
rung cơ học của phím, tại thời điểm vừa nhấn xuống, điện áp sẽ không ổn định trong 1
khoảng thời gian, trước khi ổn định ở mức 0V. Hiệu tượng này gọi là rung phím.
Mặc dù khoảng thời gian điện áp ở mức 0 trong giai đoạn rung phím là nhỏ nhưng
cũng đủ để vi điều khiển nhận được. Vì vậy khi ta xét nếu điện áp là 0 thì gọi hàm func()
thì hàm này sẽ được gọi rất nhiều lần, là điều mà ta không mong muốn. Để khác phục
hiện tượng rung phím, có 2 hướng giải quyết : dùng phần cứng và phần mềm.
Về giải pháp phần cứng : thay vì mắc đơn giản như kit thí nghiệm này (xem lại sơ
đồ ở Bài 2), ta có thể dùng thêm tụ điện để hạn chế việc thay đổi điện áp đột ngột, sơ đồ
nguyên lý như sau:

BKIT HARDWARE CLUB www.bkit4u.com 47


HƯỚNG DẪN SỬ DỤNG KIT 8051

Ở sơ đồ trên, khi không nhấn là mức 1, khi nhấn là mức 0. Phím nhấn trên tích
cực mức 0. Mạch ở trên còn gọi là mạch RC.
Nếu nút nhấn có 2 cực (3 chân), ta có thể chọn giải pháp dùng mạch RS flip flop,
đây là mạch phần cứng chống rung tốt nhất, sơ đồ nguyên lý như sau:

Về giải pháp phần mềm : Ta sẽ định kì đọc tín hiệu từ nút nhấn, cho đến khi nào
chúng trùng nhau n lần thì mới xử lý. Hình dưới đây minh hoạ trong trường hợp 2 lần là 0
thì mới xác nhận là phím được nhấn và mới xử lý tác vụ mà ta mong muốn.

Khoảng thời gian giữa 2 lần đọc là khoảng 10ms, ta sẽ hiện thực hàm đọc này và
gọi nó trong timer. Giải thuật đơn giản để xử lý chống rung có thể hiện thực như sau:
previous_key = current_key;
current_key = Port_key;
If(previous_key == current_key)
effective_key = current_key;
Trong đó :
previous_key : biến lưu giá trị phím trước đó.
current_key : biến lưu giá trị phím hiện tại.
Port_key : Port của vi điều khiển kết nối với phím.
effective_key : giá trị phím hợp lệ (giá trị trong giai đoạn ổn định)
Để tăng tính chính xác, ta có thể dùng nhiều biến previous_key để lưu lại các giá
trị và so sánh nhiều lần. Đoạn code trên chỉ so sánh trùng nhau 2 lần.

6.2 Kết nối phần cứng


Sơ đồ nguyên lý của phím trong kit này như sau :

BKIT HARDWARE CLUB www.bkit4u.com 48


HƯỚNG DẪN SỬ DỤNG KIT 8051

Phím nhấn này tính cực mức 0, được kết nối khá đơn giản, nên ta sẽ dùng phần
mềm để chống rung. Ta sẽ dùng 3 biến để so sánh 2 lần trùng nhau, 2 lần liên tiếp cách
nhau 10ms.
Trong trường hợp nhấn đè 1 phím, ta sẽ dùng biến TimeOutForKeyPress để xác
định thời gian tích cực tiếp theo. Biến này sẽ quan trọng trong trường hợp ta viết 1 ứng
dụng chẳng hạn như soạn thảo văn bản. Nếu không có biến này để quản lý, nếu ta đè thì
trong 1s có tới 100 lần tích cực. Trong ví dụ của Bài 6, thời gian TimeOutForKeyPress =
100 tương ứng với 1s (100*10 = 1000ms = 1s).

6.3 Viết chương trình


Module này có 2 hàm như sau :
void initKey() : Khởi động các thông số ban đầu
void getKey() : Hàm này được gọi trong timer0, dùng để quét phím.
void SubKeyProcess() : Hàm này hiện thực tác vụ bạn cần thực hiện khi
nhấn phím.
Ở kit thí nghiệm này, các nút nhấn được nối với port 3, nên ta có định nghĩa sau ở
đầu file key.c :
#define KEY_PORT P3

6.3.1 Hàm initKey()


void initKey()
{
KeyReg0 = 0x00;
KeyReg1 = 0x00;
KeyReg2 = 0x00;
KeyReg3 = 0x00;
}
Trong đó KeyReg0, KeyReg1, KeyReg2 dùng để lưu 3 lần liên tiếp. Khi 3 biến
này bằng nhau, biến KeyReg3 mới được cập nhật. Biến KeyReg3 là giá trị hợp lệ của
phím nhấn.

6.3.2 Hàm getKey()


Hàm này được chia làm 2 phần, phần đầu là để chống rung phím dùng 2 lần so
sánh trùng nhau. Phần thứ 2 xử lý khi 1 phím được đè, phải sau 1 khoảng thời gian
TimeOutForKeyPress mới được tính cực.

BKIT HARDWARE CLUB www.bkit4u.com 49


HƯỚNG DẪN SỬ DỤNG KIT 8051

void getKey()
{
KeyReg2 = KeyReg1;
KeyReg1 = KeyReg0;
KeyReg0 = KEY_PORT;// Cho phep nut nhan nao duoc tich cuc.

if ((KeyReg1 == KeyReg0) && (KeyReg1 == KeyReg2))


{
TimeOutForKeyPress --;
if (TimeOutForKeyPress == 0)
{
KeyReg3 = 0x00;
}
if (KeyReg2 != KeyReg3)
{
KeyReg3 = KeyReg2;
if (FlagFirstTimeKeyPress == 1)// Day la lan dau phim
duoc nhan.
{
TimeOutForKeyPress = 100;
SubKeyProcess();
FlagFirstTimeKeyPress = 0;
}
else
{
if (KeyReg2 == 0x00)
FlagFirstTimeKeyPress = 1;
else
{
TimeOutForKeyPress = 100;
SubKeyProcess();
}
}
}

}
}

BKIT HARDWARE CLUB www.bkit4u.com 50


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 7 : Quét led điều khiển Led 7 đoạn


Mục đích:
Nắm vững kĩ thuật quét Led.
Ứng dụng quét Led vào việc điều khiển 8 led 7 đoạn.
Yêu cầu:
Viết module điều khiển Led 7 đoạn có thể dùng lại cho các ứng dụng khác.
Đưa ra hàm xuất giá trị số nguyên ra led 7 đoạn tại bất kì vị trí nào.

7.1 Nguyên lý quét led 7 đoạn


Để hiện thị 1 led 7 đoạn, ta cần 8 chân để gửi dữ liệu cho nó. Như vậy, với 8 led 7
đoạn, theo kết nối bình thường,ta cần tổng cộng 56 đường tín hiệu để thắp sáng 8 led
cùng lúc.
Để khắc phục việc tốn tài nguyên này, người ta dùng kĩ thuật quét led. Tại 1 thời
điểm, chỉ có 1 led sáng. Tại thời điểm t1 chỉ có led 1 sáng, tại thời điểm t2 = t1 + t0 chỉ có
led 2 sáng, khi t0 rất nhỏ, mắt người không thể nhận biết được độ nhấp nháy giữa 2 lần
luân chuyển, và sẽ có cảm giác là 2 đèn sáng cùng lúc.

Để quét led, sơ đồ nguyên lý sẽ được mắc như trên. Port 2 gọi là port dữ liệu, dữ
liệu này sẽ được nối với tất cả các led. Port 1 dùng để chọn led, cực E của transitor được
nối với chân mass của led 7 đoạn.
Port 1 bằng 1 tại bit nào thì transitor tương ứng sẽ dẫn. Giả sử Port 1 = 0x80,
transitor T4 dẫn, dòng data sẽ đi qua led 7 đoạn nối với T4 xuống đất, và led này sẽ sáng,
các led còn lại thì không.

BKIT HARDWARE CLUB www.bkit4u.com 51


HƯỚNG DẪN SỬ DỤNG KIT 8051

Khi số lượng led càng nhiều, ta phải tính toán để tìm ra số t0 hợp lý.Thông
thường, khoảng thời gian tối đa giữa led đầu tiên và led cuối cùng trong khi quét led phải
nhỏ hơn 1/50 giây (50Hz).
Để quét 8 led 7 đoạn trong bài thí nghiệm này, ta sẽ dùng 1 buffer có 8 phần tử,
rồi định kì xuất từng phần tử ra led 7 đoạn tương ứng. Việc thay đổi dữ liệu trong buffer
này sẽ do các hàm được cung cấp cho người dùng sử dụng cập nhật.
Ta sẽ dùng ngắt timer để định kì gọi hàm scan_led7(), hàm này có chức năng xuất
1 giá trị trong buffer ra led tưng ứng, sau mỗi lần gọi, index sẽ tăng lên 1, đến khi bằng 8
sẽ quay trở về 0.

7.2 Kết nối phần cứng


Gạt switch 4 lên ON để kích hoạt led 7 đoạn.

7.3 Viết chương trình


Để module này có thể dùng lại cho các ứng dụng khác, ta sẽ hiện thực các hàm
dưới đây :
void init_led7() : Khởi tạo các thông số ban đầu
void clear_led7() : Xoá dữ liệu đang hiển thị trên led 7 đoạn
void set_position(unsigned int pos) : Thiết lập vị trí xuất dữ liệu, vị trí 0 là led
ngoài cùng bên trái.
unsigned int get_position() : Truy xuất vị trí đang xuất dữ liệu.
void put_number(unsigned int num) : Xuất giá trị num (là số unsigned int) ra led
7 đoạn từ vị trí hiện tại.
void put_string(char strNum[]) : Xuất giá trị strNum (là giá trị char) ra led 7
đoạn từ vị trí hiện tại.
void scan_led7() : Xuất dữ liệu từ buffer ra led 7 đoạn.
Các hàm interface này được khai báo trong file led7.h. File led7.c sẽ hiện thực các
hàm này.

7.3.1 Hàm init_led7()


void init_led7()
{
P0 = 0x00; //data port
P2 = 0x00; //selected port
position = 0; //output index
led7_index = 0; //scan index
is_valid_data = 1; //flag to check if data is valid
}

P0 : Port để xuất dữ liệu cho led 7 đoạn, khởi tạo 0x00 tức là không có led nào
trong led 7 đoạn sáng.
P2 : Port để chọn led 7 đoạn nào trong 8 led sẽ nhận data từ Port 0, tức cực mức 1,
P2 = 0x01 (0000 0001)tức là led 7 đoạn ngoài cùng bên trái sẽ sáng, P2 = 0x20 (0000
0010) tức là led thứ 2 tính từ trái sẽ sáng.

BKIT HARDWARE CLUB www.bkit4u.com 52


HƯỚNG DẪN SỬ DỤNG KIT 8051

position : vị trí bắt đầu hiển thị giá trị, chẳng hạn người dùng mún hiển thị số 123
từ vị trí thứ 2 tính từ trái thì phải thiết lập position là 1 (position = 0 là led ngoài cùng bên
trái). Biến position này người dùng phải dùng hàm set_positon thì mới thay đổi được (chi
tiết xem bên dưới).
led7_index : vị trí sẽ xuất data, biến này được dùng trong hàm scan_led, người
dùng không can thiệp vào biến này được.
is_valid_data : biến dùng trong hàm scan_led, biến này để tạm dừng việc quét led
trong khi đang thay đổi buffer hiển thị, người dùng cũng không can thiệp được vào biến
này.

7.3.2 Hàm clear_led7()


void clear_led7()
{
led7_buffer[0] = 0x00;
led7_buffer[1] = 0x00;
led7_buffer[2] = 0x00;
led7_buffer[3] = 0x00;

led7_buffer[4] = 0x00;
led7_buffer[5] = 0x00;
led7_buffer[6] = 0x00;
led7_buffer[7] = 0x00;

}
Hàm này chỉ đơn giản là xoá buffer 8 phần tử, lúc đó toàn bộ các led sẽ tắt. Buffer
này dùng để chứa dữ liệu của 8 led 7 đoạn, dữ liệu của từng led sẽ được định kì đưa ra
led tương ứng.

7.3.3 Hàm set_position(unsigned int pos)


void set_position(unsigned int pos) //set position to begin output
{
position = pos;
}
Hàm này sẽ lấy thông số từ người dùng để cập nhật cho biến position.

7.3.4 Hàm get_position()


unsigned int get_position() //get current position
{
return position;
}

Hàm này trả về vị trí đang xuất dữ liệu.

BKIT HARDWARE CLUB www.bkit4u.com 53


HƯỚNG DẪN SỬ DỤNG KIT 8051

7.3.5 Hàm put_Number(unsigned int num)

void put_number(unsigned int num)


{
int i;

is_valid_data = 0; //disable scan led

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


{

if(i>=0)
{
led7_buffer[i] = led7_data[num % 10];
}
num = num / 10;
if(num == 0)
break;
}
position = i;
is_valid_data = 1; //enable scan led
}

Hàm này dùng để cắt từng chữ số của số num để bỏ vào buffer tương ứng. Vòng
lập for dùng để hiện thực tác vụ này, chữ số hàng đơn vị của num sẽ được bỏ vào buffer
vị trí position.

7.3.6 Hàm put_string(char strNum[])


Hàm này cũng gần giống với hàm put_Number, chỉ khác là đối số là kiểu char[].
Việc thao tác trên dữ liệu kiểu char[] cần phải include thêm thư viện string.h (ở đầu file
led7.c). Việc hiện thực hàm này phức tạp hơn, các bạn có thể tham khảo thêm trong code
mẫu ở thư mục Bài 7 được đính kèm trong CD. Mục đích của hàm này cũng là lấy từng
phần tử trong mảng strNum bỏ vào buffer cho đúng vị trí.

7.3.7 Hàm scan_led7


void scan_led7()
{
if(is_valid_data)
{
P2 = 0x00; //remove noise
P0 = led7_buffer[led7_index]; //data for the next led
P2 = 1 << led7_index; //enable data

led7_index++; //update new index


if(led7_index == 8)

BKIT HARDWARE CLUB www.bkit4u.com 54


HƯỚNG DẪN SỬ DỤNG KIT 8051

led7_index = 0;
}
}
Đây là hàm dùng để quét led, và sẽ được ngắt timer gọi. Mục đích của hàm này là
xuất dữ liệu ra led ở vị trí tiếp theo.
Port 2 dùng để chọn led, và để tránh hiện tượng bóng mờ khi quét led, bạn phải
gán nó về 0x00 trước.
led7_index là biến chỉ vị trí của led hiện tại chuẩn bị nhận dữ liệu.
Hàm scan_led7() được gọi trong ngắt timer0.

Với các hàm đã thiết kế ở trên, để xuất số 1234 tại vị trí thứ 2 tính từ trái sang ta
viết trong hàm main() như sau:
void main()
{
init_main();
init_timer0();
init_led7();
set_position(1);
put_Number(1234);
while(1){};
}
Hàm main() trong ví dụ của Bài 7 xuất các số 123 và 4321 tại các vị trí liên tiếp
nhau, thời gian giữa 2 lần xuất là 1s (1000ms), ta sẽ có cảm giác là dòng số này chạy qua
các led 7 đoạn.

BKIT HARDWARE CLUB www.bkit4u.com 55


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 8 : Điều khiển Ma trận led


Mục đích:
Ứng dụng quét Led để điều khiển Ma trận led 2 màu.
Yêu cầu:
Viết chương trình định kì 1s xuất các chữ cái in hoa từ A-Z ra ma trận led.

8.1 Nguyên lý điều khiển ma trận led


Ma trận led 2 màu được cấu tạo gồm những điểm sáng, mỗi điểm sáng có 2 bóng
đèn đỏ và xanh lá bên trong. Khi cả 2 đèn này cùng sáng cho ta cảm giác màu vàng.
Nguyên lý điều khiển ma trận led cũng tương tự như led 7 đoạn, ta dùng Port1 để
chọn cột, Port0 và Port2 dùng để gửi dữ liệu đỏ và xanh cho hàng đó. Các kĩ thuật điều
khiển ở ma trận led hoàn toàn tương tự như led 7 đoạn.

8.2 Kết nối phần cứng


Gạt switch 3 lên ON để kích hoạt ma trận led.

8.3 Viết chương trình


Chương trình được tổ chức gồm 3 module : MAIN để chứa file main.c, TIMER
để gọi hàm quét ma trận led và LED MATRIX để chứa các hàm liên quan đến ma trận
led.
Các hàm về ma trận led như sau :
void init_led_matrix(); //Khởi tạo ma trận led
void scan_led_matrix(); //Quét ma trận led, hàm này được gọi trong
timer.
void update_display_led_matrix(); //Cập nhật buffer hiển thị.

BKIT HARDWARE CLUB www.bkit4u.com 56


HƯỚNG DẪN SỬ DỤNG KIT 8051

8.3.1 Hàm init_led_matrix()


void init_led_matrix()
{
P0 = 0x00; //red data
P2 = 0x00; //green data
index_led_matrix = 0; //index use to scan led
alphabet_index = 208;// in the initial, led matrix doesn't display
anything
}
Trong đó :
P0 : Port để xuất dữ liệu đỏ cho ma trận led.
P2 : Port để xuất dữ liệu xanh cho ma trận led.
index_led_matrix : biến dùng để quét dữ liệu hiển thị trên ma trận led, ta dùng
biến này để lấy dữ liệu trong 2 buffer (mỗi buffer 8 phần tử) để hiển thị và chọn cột.
alphabet_index : biến dùng để lấy dữ liệu cần hiển thị, bỏ vào 2 buffer đỏ và
xanh. Mảng dữ liệu này thường khá lớn và được khai báo trong file table_led_matrix.h.

8.3.2 Hàm scan_led_matrix()


Hàm này được gọi trong timer, có nhiệm vụ xuất buffer hiển thị ra ma trận led,
định kì xuất từng phần tử của buffer ra cột tương ứng.
void scan_led_matrix()
{
P1 = 0; //remove noise
P0 = red_buff[index_led_matrix];
P2 = green_buff[index_led_matrix];
P1 = 1 << index_led_matrix;

index_led_matrix = (index_led_matrix + 1) % 8; //next column


}

8.3.3 Hàm update_display_led_matrix()


Hàm này dùng để thay đổi nội dung hiển thị, các ứng dụng của người dùng chủ
yếu là thay đổi code ở hàm này.
void update_display_led_matrix()
{
char i;

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


{
red_buff[i]=alphabet_upcase_led_matrix[i+alphabet_index ];
green_buff[i]=alphabet_upcase_led_matrix[i+alphabet_index];
}
}
Hàm main chỉ việc thay đổi alphabet_index (dữ liệu của chữ cái kế tiếp) rồi gọi
hàm update_display_led_matrix(), định kì 1s sau đó thay đổi chữ kế tiếp:

BKIT HARDWARE CLUB www.bkit4u.com 57


HƯỚNG DẪN SỬ DỤNG KIT 8051

while(1)
{
alphabet_index = (alphabet_index + 8) % 216;
update_display_led_matrix();
delay_ms(1000);
}

BKIT HARDWARE CLUB www.bkit4u.com 58


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 9 : Chạy chữ trên Ma trận led


Mục đích:
Nắm vững nguyên lý điều khiển ma trận led. Xây dựng ứng dụng trên ma trận led.
Yêu cầu:
Viết chương trình chữ chạy trên ma trận led, cung cấp interface giúp người dùng
có thể thay đổi dễ dàng.

9.1 Nguyên lý chạy chữ trên ma trận led

Để chạy 1 dòng chữ qua ma trận led, bạn sẽ có 1 buffer lưu toàn bộ dòng chữ đó.
Buffer này thường là 1 mảng các byte. Chương trình sẽ định kì cắt 1 phần trong buffer
này đổ dữ liệu vào buffer nhỏ hơn dùng để quét led. Chương trình quét led sẽ hiển thị ra
led ma trận.
Tại thời điểm T1, dữ liệu đổ vào buffer quét led là chữ “H”. Tại thời điểm T2, 1
phần chữ H và E được đổ vào buffer này, và tại thời điểm T3 là chữ “E”. Nếu khoảng
cách giữa các thời điểm nhỏ lại, bạn sẽ thấy hiệu ứng dòng chữu chạy qua ma trận led.
Để sinh ra được buffer chứa toàn bộ dòng chữ, bạn phải xử lý dữ liệu đã lưu sẵn
(tạm gọi là font chữ), ghép nối chúng sao cho đẹp mắt. Chẳng hạn muốn hiện chữ
“HELLO WORLD”,bạn phải làm như sau:
Ø Lấy font của chữ “H”, bỏ những cột trống ở đầu và cuối, phần còn lại bỏ vào
buffer.
Ø Lấy font của chữ “E”, bỏ những cột trống ở đầu và cuối,thêm 1 byte 0x00 vào
buffer (tạo 1 nét rời giữa H và E) rồi bỏ dữ liệu của E vào.
Ø Tương tự, hết chữ “O”, bạn thêm khoảng 3 byte 0x00.
Tuỳ vào tài nguyên của hệ thống, bạn định nghĩa ra độ dài tối đa của buffer này.
Trong quá trình sinh ra buffer, chương trình sẽ cập nhật độ dài hiện tại và sẽ dừng việc
ghép chữ nếu độ dài là quá mức cho phép.

BKIT HARDWARE CLUB www.bkit4u.com 59


HƯỚNG DẪN SỬ DỤNG KIT 8051

9.2 Kết nối phần cứng


Gạt switch 3 lên ON để kích hoạt ma trận led.

9.3 Viết chương trình


Chương trình sẽ gồm 3 group là TIMER, LED MATRIX và MAIN. Các group
TIMER và LED MATRIX được dùng lại. Trong file led_matrix.h ta khai báo thêm 1 hàm
cung cấp cho người dùng:
void set_message(char strMsg[]);
Hàm này cho phép người dùng thay đổi nội dung chữ chạy qua ma trận led. Ví dụ
gọi set_message(“HELLO WORLD”).
Để xử lý chuỗi trong KeilC, bạn include thêm 2 thư viện sau ở đầu file
led_matrix.c:
#include <stdlib.h>
#include <string.h>
Dữ liệu của buffer lớn gồm có 100 cột, biến total_length dùng để lưu độ dài hiện
tại của mảng buffer này:
unsigned char data_buff[100];
int total_length;
Mảng alphabet_upcase_led_matrix là dữ liệu font của các chữ cái in hoa. Trong
chương trình này chỉ hiển thị được các chữ cái in hoa, không bao gồm các chữ cái thường
và các kí tự số.

9.3.1 Hàm set_message(char strMsg[])


void set_message(char strMsg[])
{
int length;
int i;
int j;
int index_char;

length = strlen(strMsg);

//fill data into data_buff


for(i=0;i<length;i++)
{
index_char = (strMsg[i] - 'A')*8; //position to get font data
if(strMsg[i] != ' ') //is not blank character
{
for(j=index_char;;j++)//remove 0x00 at the begining
{
if(alphabet_upcase_led_matrix[j] != 0x00)
break;
}

for(;j<8 + index_char;j++)//copy data to data_buff


{
if(total_length != 100)

BKIT HARDWARE CLUB www.bkit4u.com 60


HƯỚNG DẪN SỬ DỤNG KIT 8051

data_buff[total_length++]=
alphabet_upcase_led_matrix[j];
}
}
else //blank character,add 3 bytes 0x00
{
if(total_length != 100)
data_buff[total_length++] = 0x00;
if(total_length != 100)
data_buff[total_length++] = 0x00;
if(total_length != 100)
data_buff[total_length++] = 0x00;
}
}
}

9.3.2 Hàm main()


void main()
{
init_main();
init_timer0(); //use for scan led
init_timer1(); //use for delay_ms() function
init_led_matrix(); //initiate led matrix
set_message("HELLO WORLD");
while(1)
{
delay_ms (300);
update_display_led_matrix();
}
}
Hàm update_display_led_matrix() tăng con trỏ alphabet_index để lấy dữ liệu
trong data_buff bỏ vào red_buff và green buff. Biến alphabet_index được khởi tạo là -8
với ý nghĩa ở trạng thái đầu tiên màn hình led 7 đoạn không hiển thị gì cả. Khi hiện thực
hàm này bạn chú ý kiểm tra điều kiện của alphabet_index để lấy dữ liệu cho đúng. Chi
tiết của chương trình các bạn tham khảo tại thư mục Bai 9.

BKIT HARDWARE CLUB www.bkit4u.com 61


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 10 : Ngắt ngoài


Mục đích:
Nắm vững kĩ thuật điều khiển ngắt ngoài.
Yêu cầu:
Viết chương trình khi có ngắt ngoài 0 thì tăng biến đếm lên 1, ngắt ngoài 1 thì
giảm đi 1, xuất giá trị ra led 7 đoạn.

10.1 Nguyên lý điều khiển ngắt ngoài


Ngắt ngoài có 2 loại : Ngắt cạnh và ngắt mức.
Ø Ngắt cạnh cũng có 2 loại : ngắt cạnh lên xảy ra khi có sự chuyển tín hiệu từ
mức thấp lên mức cao ở chân ngắt ngoài. Tương tự ngắt cạnh xuống xảy ra khi có
sự chuyển tín hiệu từ mức cao xuống mức thấp.
Ø Ngắt mức cũng có 2 loại : ngắt mức cao và mức thấp. Ngắt mức cao xảy ra
khi tín hiệu tại chân ngắt ngoài ở mức cao trong tối thiểu 1 chu kì.
Trong vi điều khiển P89V51RB2, hỗ trợ 2 loại ngắt ngoài : ngắt cạnh xuống và
ngắt mức thấp. Việc cấu hình cho ngắt ngoài dựa vào bit ITn trong thanh ghi TCON.

10.2 Kết nối phần cứng


Hai ngắt ngoài được mắc vào nút nhấn, tại chân P3.2 là ngắt ngoài 0 và P3.3 là
ngắt ngoài 1.
Gạt switch 4 lên ON để kích hoạt led 7 đoạn.

10.3 Viết chương trình


Module ngắt ngoài khá đơn giản, gồm các hàm khởi tạo được khai báo trong file
ext_int.h :
void init_ext_int0();
void init_ext_int1();
Các hàm này được hiện thực trong file ext_int.c cùng với 2 hàm phục vụ ngắt ngắt
ngoài. Code xử lý trong bài mẫu này khá đơn giản, chỉ là việc cộng và trừ biến count rồi
dùng biến này để hiển thị giá trị tương ứng ra led 7 đoạn.

10.3.1 Hàm init_ext_int0()


void init_ext_int0()
{
IE &= ~(0x01);// enable external interrupt 0
IE |= 0x01;
IT0 = 1;
}

10.3.2 Hàm init_ext_int1()


void init_ext_int1()
{
IE &= ~(0x04);// enable external interrupt 1

BKIT HARDWARE CLUB www.bkit4u.com 62


HƯỚNG DẪN SỬ DỤNG KIT 8051

IE |= 0x04;

IT1 = 1;
}

10.3.3 Hàm ext0_isr()


Đây là hàm phục vụ ngắt ngoài 0.
void ext0_isr() interrupt 0
{
//Add your code here
if(count<9)
count++;

10.3.4 Hàm ext1_isr()


Đây là hàm phục vụ ngắt ngoài 1.
void ext0_isr() interrupt 1
{
//Add your code here
if(count>0)
count--;

BKIT HARDWARE CLUB www.bkit4u.com 63


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 11 : Điều khiển encoder


Mục đích:
Hiểu được nguyên lý hoạt động của encoder. Nắm vững kĩ thuật điều khiển
encoder bằng ngắt ngoài.
Yêu cầu:
Xây dựng chương trình đọc số xung encoder và hiển thị giá trị ra led 7 đoạn.

11.1 Nguyên lý điều khiển encoder


Encoder là thiết bị cảm biến được dùng phổ biến trong các ứng dụng cần đo
khoảng cách, vận tốc hoặc trong các ứng dụng cần độ chính xác cao. Hình dạng thực tế
của encoder như sau:

Cấu tạo của encoder gồm 1 vòng tròn, trên đó xẻ nhiều rãnh (còn gọi là đĩa), và 1
mạch cảm biến để phát xung

Số rãnh trên đĩa gọi là độ phân giải hay số xung của encoder. Đối với encoder có
độ phân giải thấp (dưới 200 xung) thì đĩa này là đĩa thép. Đối với các encoder có độ phân
giải cao, cỡ 1000 xung, thì đĩa này được làm bằng đĩa từ, encoder như vậy còn gọi là
encoder quang.

BKIT HARDWARE CLUB www.bkit4u.com 64


HƯỚNG DẪN SỬ DỤNG KIT 8051

Tín hiệu trả về của encoder có 3 kênh A, B và Z. Thông thường ta sử dụng 2 kênh
A và B là đủ thông tin cho quãng đường và chiều quay của encoder. Tín hiệu trả về trên 2
kênh này như sau :

Như vậy nếu ta đưa tín hiệu A vào chân ngắt ngoài và cấu hình là ngắt
cạnh lên, thì khi tín hiệu B ở mức cao là chiều quay thuận của encoder, khi
B ở mức thấp là chiều quay ngược lại.

11.2 Kết nối phần cứng


Gạt switch 4 lên ON để kích hoạt led 7 đoạn.
Kết nối với encoder gồm 4 chân : VCC, GND, A và B vào board. Tín
hiệu A được nối vào P3.2 gây ra ngắt ngoài 0, tín hiệu B nối với P3.5

11.3 Viết chương trình


Chương trình gồm có 3 group : TIMER dùng để quét led, hiển thị giá
trị encoder ra led 7 đoạn; EXT_INT dùng để cập nhật giá trị encoder mỗi khi
có ngắt ngoài 0 ở chân P3.2, MAIN chứa file main.c là chương trình chính
để chạy.
Chương trình trong bài này hoàn toàn tương tự như bài trước, đoạn
code trong hàm phục vụ ngắt ngoài sửa đổi lại như sau:
void ext0_isr() interrupt 0
{
if(P3 & (1 << 5))
pulse ++;
else
pulse --;
}
Biến pulse được khai báo là unsigned int, dùng để lưu trữ giá trị của
encoder.

BKIT HARDWARE CLUB www.bkit4u.com 65


HƯỚNG DẪN SỬ DỤNG KIT 8051

Để xuất giá trị encoder ra led 7 đoạn, ta thêm 2 dòng lệnh sau trong
hàm phục vụ ngắt timer 0:
set_position(2);
put_number(pulse);
Hàm main() chỉ đơn giản là khởi tạo các thông số cần thiết và sau đó loop vô tận.
Tất cả mọi công việc sẽ do các hàm phục vụ ngắt quãng thực hiện. Đây là 1 mô hình lập
trình cơ bản của vi điều khiển trong các ứng dụng thực tế. Chi tiết code các bạn xem thêm
trong thư mục Bài 11.

BKIT HARDWARE CLUB www.bkit4u.com 66


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 12 : Giao tiếp UART


Mục đích:
Nắm vững giao tiếp Uart.
Yêu cầu:
Xây dựng ứng dụng giao tiếp giữa board 89 và máy tính thông qua cổng COM.

12.1 Nguyên lý giao tiếp UART


Uart RS232 là chuẩn giao tiếp khá phổ biến và được hỗ trợ ở hầu hết các dòng vi
điều khiển vì khoảng cách xa và chi phí thấp. Dòng 8051 hỗ trợ 1 kênh giao tiếp uart.
Dữ liệu được truyền đi trên chân TX gồm 1 start bit (mức 0), data và 1 stop bit
(mức 1).
Tốc độ truyền : đơn vị bit per second (bps) còn gọi là Baud (số lần thay đổi tín
hiệu trong 1 giây – thường sử dụng cho modem). Đối với đường truyền thì Baud và bps
là như nhau.
UART là phương thức truyền nhận bất đồng bộ. nghĩa là bên nhận và bên phát
không cần phải có chung tốc độ xung clock (ví dụ : xung clock của vi điều khiển khác
xung clock của máy tính) . Khi đó bên truyền muốn truyền dữ liệu sẽ gửi start bit (bit 0)
để báo cho bên thu biết để bắt đầu nhận dữ liệu và khi truyền xong dữ liệu thì stop bit (bit
1) sẽ được gửi để báo cho bên thu biết kết thúc quá trình truyền.
Khi có start bit thì cả hai bên sẽ dùng chung 1 xung clock (có thể sai khác một ít)
với độ rộng 1 tín hiệu (0 hoặc 1) được quy định bởi baud rate, ví dụ baud rate = 9600bps
nghĩa là độ rộng của tín hiệu 0(hoặc 1) là 1/9600 = 104 ms và khi phát thì bên phát sẽ
dùng baud rate chính xác (ví dụ 9600bps) còn bên thu có thể dùng baud rate sai lêch 1
ít(9800bps chẳng hạn).
Truyền bất đồng bộ sẽ truyển theo từng frame và mỗi frame có cấu trúc như sau:
Stop bit--B7--B6-- B5-- B4-- B3-- B2-- B1-- B0-- Start bit

goes out last goes out first


Ngoài ra trong frame truyền có thể có thêm bit odd parity (bit lẻ) hoặc even
parity (bit chẵn) để kiểm tra lỗi trong quá trình truyền. Bit parity này có đặc điểm nếu
sử dụng odd parity thì số các bit 1 + odd parity bit sẽ ra 1 số lẻ còn nếu sử dụng even
parity thì số các bit 1 + even parity bit sẽ ra 1 số chẵn.

BKIT HARDWARE CLUB www.bkit4u.com 67


HƯỚNG DẪN SỬ DỤNG KIT 8051

12.2 Giao tiếp UART với máy tính


Để giao tiếp COM giữa vi điều khiển và máy tính, ta kết nối mạch theo sơ đồ như
sau:

Do mức điện áp của tín hiệu logic 1/0 ở cổng COM của máy tính khác với vi điều
khiển, nên MAX 232 có tác dụng chuẩn hoá mức điện áp giữa máy tính và điều khiển
trong quá trình truyền nhận dữ liệu. Nếu giao tiếp trực tiếp giữa 2 vi điều khiển, ta không
cần phải sử dụng MAX 232.

BKIT HARDWARE CLUB www.bkit4u.com 68


HƯỚNG DẪN SỬ DỤNG KIT 8051

12.3 Viết chương trình


12.3.1 Thanh ghi điều khiển truyền nhận nối tiếp
Vi điều khiển 8051 có hai chân dùng trong truyền nhận nối tiếp là RxD(nhận dữ
liệu ứng với chân P3.0) và TxD(phát dữ liệu ứng với chân P3.1), ngoài ra còn sử dụng bộ
đệm SBUF để lưu dữ liệu thu khi nhận và dữ liệu phát khi truyền và thanh ghi
SCON(Serial Control) để truy xuất port nối tiếp.
Bộ đệm SBUF có địa chỉ byte là 99h, thực tế có hai bộ đệm là bộ đệm thu (chi
đọc) dùng trong nhận dữ liệu và bộ đệm phát (chỉ ghi) dùng trong phát dữ liệu.
Thanh ghi SCON có địa chỉ byte là 98h là thanh ghi có thể định địa chỉ từng bit
dùng để thiết lập chế độ hoạt động của port nối tiếp và các bit trạng thái chỉ sự kết thúc
việc thu hoặc phát dữ liệu.

Bit Kí hiệu Chức năng


Cách dùng của bit này được định nghĩa bằng giá trị của bit
SMOD0 trong thanh ghi PCON, nếu SMOD=0, bit này được
đọc và viêt là SM0, nó với bit SM1 định nghĩa chế độ hoạt
động của cổng nối tiếp. Nếu SMOD0=1, bit này được đọc và
SCON.7 SM0/FE viết là FE (khung lỗi). FE được set trong quá trình nhận khi
phát hiện bit dừng không hợp lệ, và nó chỉ được xóa bởi phần
mềm. (chú ý rằng các chế độ UART nên được lập trình(thông
qua SM0 và SM1) khi SMOD0=’0’-chế độ mặc định sau các
quá trình RESET)

BKIT HARDWARE CLUB www.bkit4u.com 69


HƯỚNG DẪN SỬ DỤNG KIT 8051

SM1 Cùng với SM0, xác định chế độ làm việc của cổng nối tiếp
SM0,
Chế độ UART UART 0 Baud Rate
SM1
CCLK/16 (chế độ mặc định sau khi
SCON.6 00 0: thanh ghi dịch
RESET)
01 1: UART 8-bit Thay đổi
10 2: UART 9-bit CCLK/32 hoặc CCLK/16
11 3: UART 9-bit Thay đổi
Cho phép truyền thông đa xử lý. Ở Mode 2 và 3, nếu SM2
được lập, RI sẽ không tích cực nếu bit dữ liệu nhận thứ 9 (RB8)
SCON.5 SM2
là ‘0’. Ở Mode 0, SM2 nên bằng ‘0’, ở mode 1, SM2 phải bằng
‘0’.
Cho phép thu ở cổng nối tiếp. Thiết lập bởi phần mềm để cho
SCON.4 REN phép thu. Xóa bởi phần mềm khi không cho phép thu,REN = 1
trong tất cả 4 chế độ tuyền nhận.
Bit dữ liệu thứ 9 được phát ở mode 2 và 3, lập/xóa bởi phần
SCON.3 TB8
mềm khi muốn.
Bit dữ liệu thứ 9 được nhận ở mode 2 và 3. Ở mode 1(SM2=0),
SCON.2 RB8 RB8 là bit dừng được nhận, ở mode 0, RB8 không được định
nghĩa.
Cờ ngắt phát(truyền nối tiếp), lập bởi phần cứng ở cuối bit thứ
8 ở mode 0, hay là ở bit dừng của các chế độ còn lại, phải được
SCON.1 TI
xóa bằng phần mềm. (Xem thêm bit INTL0 ở thanh ghi
SSTAT)
Cờ ngắt thu, lập bởi phần cứng ở cuối bit thứ 8 trong mode 0,
hay khoảng giữa bit dừng ở mode 1. với mode 2 và mode 3,
SCON.0 RI nếu SMOD0=0, nó được lập gần khoảng giữa bit dữ liệu thứ 9
(bit 8). Nếu SMOD0=1, nó được lập gần khỏang giữa bit dừng.
Phải được xóa bởi phần mềm.

Các chế độ truyền nối tiếp:


· Chế độ 0: ở chế độ này chân RxD sẽ vửa làm nhiệm vụ thu và phát dữ liệu
còn chân TxD làm nhiệm vụ phát xung dịch bit(Shift Clock) vói tốc độ sung
bằng 1/12 tốc độ xung của XTAL.Dữ liệu truyền đi gồm 8 bit với bit LSB
được truyền hoặc nhận trước. Ứng dụng của chế độ này là mở rộng ngõ ra
cho 8051 từ 2 đường TxD,RxD sẽ tạo ra 8 đường mở rộng.

8051
TxD(P3.1)
CLOCK Shift register
Data

RxD(P3.0)

BKIT HARDWARE CLUB www.bkit4u.com 70


HƯỚNG DẪN SỬ DỤNG KIT 8051

· Chế độ 1: là chế độ truyền với mỗi frame có 10 bits (bit start – 8 bits data –
bit stop) ,tốc độ baud rate có thể thay đổi được tùy vào cách khởi tạo ban
đầu.Có thể nhân đôi tốc độ truyền bằng cách bật PCON.7 = 1.
· Chế độ 2: là chế độ truyền với mỗi frame có 11 bits (bit start – 8 bits data –
bit parity – bit stop),bit parity được đặt trong TB8 khi phát và được đặt
trong RB8 khi thu, tốc độ baud rate ở chế độ này không thay đổi được và
bằng 1/64 dao động của XTAL (1/32 dao động của XTAL nếu PCON.7 =
1).
· Chế độ 3: có chức năng tương tự như chế độ 2 nhưng tốc độ baud rate có
thể thay đổi được như ở chể độ 1.

Tốc độ Baud : Tốc độ (Baud) của cổng 8051 phải phù hợp với máy tính: 100,
150, 300, 600, 1200, 2400, 4800, 9600, 19200. Khuyến cáo dùng thạch anh có tần số
11.0592Mhz để có thể tạo ra tốc độ Baud với sai số thấp (gần như là 0).

12.3.2 Dùng Timer1 tạo Baud rate


Timer 1 được dùng để tạo tốc độ baud cho truyền nối tiếp ,cần phải đặt Timer 1 ở
Mode 2 – 8 bit tự nạp lại, nếu đặt ở chế độ khác sẽ tốn vài chu kỳ máy cho quá trình thiết
lập lại giá trị cho TH1,TL1.
Đặt TH1 theo bảng sao để có tốc độ Baud tương ứng với SMOD = 0 (bit D7 trong
thanh ghi PCON, XTAL = 11.0592 MHz) :

Tốc độ Baud TH1 (Thập phân) TH1 (Hexa)


9600 -3 ED
4800 -6 FA
2400 -12 F4
1200 -24 E8

Tốc độ Baud rate sẽ nhân đôi khi SMOD = 1.

12.3.3 Chương trình truyền nhận UART trên 8051


v Hàm init_timer1() sẽ thiết lập Timer1 tạo tốc độ baud cho truyền nối tiếp

void init_timer1()
{
TMOD &= ~(0x20);// setup mode for timer 1
TMOD |= 0x20;

// Baud rate = 9600


// PCON.7 = 0, without increasing baud rate 2 times
TL1 = 0xFD; //-3

BKIT HARDWARE CLUB www.bkit4u.com 71


HƯỚNG DẪN SỬ DỤNG KIT 8051

TH1 = 0xFD; //-3

TR1 = 1; //start timer1

}
Tốc độ truyền nhận UART được quy định như sau :
Nếu PCON.7 = 0 : TH1 = 256 - ((Crystal / 384) / Baud)
TH1 = (-48); // baudrate 600
TH1 = (-24); // baudrate 1200
TH1 = (-12); // baudrate 2400
TH1 = (-6); // baudrate 4800
TH1 = (-3); // baudrate 9600

Nếu PCON.7 = 1, baud is double, TH1 = 256 - ((Crystal / 192) / Baud)


TH1 = (-96); // baudrate 600
TH1 = (-48); // baudrate 1200
TH1 = (-24); // baudrate 2400
TH1 = (-12); // baudrate 4800
TH1 = (-6); // baudrate 9600
TH1 = (-4); // baudrate 14400
TH1 = (-3); // baudrate 19200
TH1 = (-2); // baudrate 28800

v Hàm initUart() sẽ thiết lập chế độ hoạt động của port nối tiếp

void initUart()
{
//IE = 0xb0;
//SCON: SM0 SM1 SM2 REN TB8 RB8 TI RI
ES = 1; // enable UART
IP = 0x10; // set priority for serial port
SCON = 0x50; // Uart mode 1
}

v Hàm sendChar(unsigned char c)


Để truyền dữ liệu đi, ta chỉ cần ghi giá trị cần truyền vào thanh ghi SBUF. Khi
quá trình truyền kết thúc, cờ ngắt TI sẽ bật lên. Ta sẽ dùng 1 biến cờ trans_busy để nhận
biết khi nào quá trình truyền kết thúc, và sẽ xoá biến cờ này trong hàm phục vụ ngắt
truyền nối tiếp.

void sendChar(unsigned char c)


{

BKIT HARDWARE CLUB www.bkit4u.com 72


HƯỚNG DẪN SỬ DỤNG KIT 8051

trans_busy = 1;
SBUF = c;
while(trans_busy);
}

v Hàm uart_isr() là hàm phục vụ ngắt của truyền nhận nối tiếp :

void uart_isr(void) interrupt 4


{
if (TI == 1) // Truyền dữ liệu
{
/*
Các câu lệnh xử lý khi truyền dữ liệu
*/
trans_busy = 0; //cờ báo hiệu truyền kết thúc
TI = 0; // xoá cờ ngắt TI , kết thúc truyền dữ liệu
}
if (RI == 1) //Nhận dữ liệu
{
/*
Các câu lệnh xử lý khi nhận dữ liệu
*/
data_recv[index] = SBUF; // nhận dữ liệu
RI = 0; // xoá cờ ngắt RI, kết thúc nhận dữ liệu
}
}
Dữ liệu truyền tới vi điều khiển được lưu trong thanh ghi SBUF và khi vi điều
khiển nhận đủ dữ liệu, cờ ngắt RI sẽ bật lên.

BKIT HARDWARE CLUB www.bkit4u.com 73


HƯỚNG DẪN SỬ DỤNG KIT 8051

12.4 Kiểm tra truyền nhận UART


Để kiểm tra việc truyền nhận uart có đúng hay không ta thường dùng 1 số ứng
dụng hyper terminal để kiểm tra. Lúc này máy tính của chúng ta sẽ là đối tượng dùng để
giao tiếp với Kit89. Trong đĩa CD này có phần mềm hyper terminal khá thông dụng chứa
trong thư mục Terminal, bạn chỉ cần double click vào file Terminal.exe là khởi động
được chương trình.

Công việc còn lại là cấu hình cho cổng COM truyền nhận uart cho tương thích với
giao thức truyền nhận của board 89. Các thông số thông thường là Baud rate 9600, Data
bit 8bit, không có Parity (chọn none) và 1 Stop bit. Nhấn nút Connect để kết nối. Kể từ
đây nếu board 89 có gửi dữ liệu lên, dữ liệu này sẽ nằm trong phần Receive. Ngược lại,
muốn gửi dữ liệu xuống board 89 ta gõ vào textbox và ấn Send.

12.5 Xây dựng chương trình trên PC


Trong mục này, chúng tôi sẽ trình bày từng bước để xây dựng 1 software trên PC
giao tiếp với vi điều khiển bằng Visual .NET 2005 và ngôn ngữ C#.
Khởi động Visual .NET 2005, màn hình sau sẽ hiện lên

BKIT HARDWARE CLUB www.bkit4u.com 74


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chọn vào menu File, chọn New Project như hình trên, màn hình dưới đây sẽ hiện ra.

Bạn chọn loại project là Visual C#, Windows Application và đặt tên cho project
tại mục Name. Sau khi chọn xong nhấn OK. Project sẽ được load lên để bắt đầu thiết kế

BKIT HARDWARE CLUB www.bkit4u.com 75


HƯỚNG DẪN SỬ DỤNG KIT 8051

giao diện. Nếu xài hệ điều hành Windows Vista, thông báo sau có thể xuất hiện và bạn
chọn Load Project Normally.

Cửa sổ thiết kế giao diện hiện ra như sau

BKIT HARDWARE CLUB www.bkit4u.com 76


HƯỚNG DẪN SỬ DỤNG KIT 8051

Để thiết kế giao diện, bạn chỉ cần kéo thả các đối tượng giao diện vào form và thay đổi
thuộc tính của nó. Trong ví dụ này dùng các đối tượng Label, ComboBox,
TextBox,SerialPort và Command Button.

Chọn control SerialPort, kéo thả vào form và sửa thuộc tính Name thành
serialPort, kết quả như hình dưới đây:

Điều chỉnh thuộc tính của các đối tượng như sau:
v Chỉnh thuộc tính Name của ComboxBox là cboPorts. ComboBox này dùng để list ra
các cổng COM mà máy hỗ trợ.
v Nút Connect có thuộc tính Name là btnConnect, Caption là Connect.
v Nút Send có thuộc tính Name là btnSend, Caption là Send.
v Textbox dùng để chứa dữ liệu truyền có tên là txtSend và textbox dùng để hiển thị dữ
liệu nhận tên txtReceive, thuộc tính Multiple lines chỉnh thành true.

BKIT HARDWARE CLUB www.bkit4u.com 77


HƯỚNG DẪN SỬ DỤNG KIT 8051

12.5.1 Load các cổng COM của PC lên ComboBox


Chức năng này được hiện thực trong thủ tục Form Load, để tạo ra sự kiện này,
bạn chỉ cần double vào form đang thiết kế hoặc chọn trong cửa sổ thuộc tính sự kiện này
rồi double click vào ô tương ứng như sau :

Chọn tab sự
Chọn Form kiện

Double Click tại đây


để tạo hàm xử lý sự
kiện Form Load

Cửa sổ viết code sẽ hiện ra như sau :

BKIT HARDWARE CLUB www.bkit4u.com 78


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chi tiết hiện thực như sau :

private void frmMain_Load(object sender, EventArgs e)


{
string[] ports = SerialPort.GetPortNames();
// Add all port names to the combo box:
foreach (string port in ports)
{
cboComPorts.Properties.Items.Add(port);
}
}

12.5.2 Kết nối cổng với cổng COM


Chuyển qua lại cửa sổ thiết kế giao diện bằng cách double click vào Form1 trong
cửa sổ project explore :

Màn hình thiết kế giao diện hiện ra, bạn nhấp đôi vào button Connect để tạo hàm
xử lý sự kiện Click cho nó. Hàm được tạo ra và bạn hiện thực code như sau :

private void btnConnect_Click(object sender, EventArgs e)


{
if (serialPort.IsOpen) serialPort.Close();
serialPort.PortName = cboComPorts.Text;
try
{
serialPort.Open();
MessageBox.Show("Đã kết nối cổng COM!");
}
catch
{

BKIT HARDWARE CLUB www.bkit4u.com 79


HƯỚNG DẪN SỬ DỤNG KIT 8051

MessageBox.Show("Chưa kết nối được cổng COM!");


}
}

12.5.3 Gửi dữ liệu


Chuyển qua lại cửa sổ thiết kế giao diện bằng cách double click vào Form1 trong
cửa sổ project explore :

Để gửi dữ liệu, ta tạo hàm xử lý cho sự kiện click nút Send bằng cách double
click vào nút đó trên form thiết kế giao diện, hàm này sẽ được tự động tạo ra như sau:

BKIT HARDWARE CLUB www.bkit4u.com 80


HƯỚNG DẪN SỬ DỤNG KIT 8051

Hàm này có chức năng truyền 1 string gồm nhiều kí tự qua cổng UART, việc hiện
thực hàm này như sau :

private void btnSend_Click(object sender, EventArgs e)


{
serialPort.Write(txtSend.Text);
}

12.5.4 Nhận dữ liệu


Chuyển sang cửa sổ thiết kế giao diện, chọn vào đối tượng serialPort, chọn tab sự
kiện và tạo hàm cho sự kiện nhận bằng cách double click vào dòng DataReceived :

BKIT HARDWARE CLUB www.bkit4u.com 81


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chọn tab sự kiện

Chọn cổng COM


Double
Click

Hàm sẽ được tạo ra như sau :

Do khi dữ liệu được gửi đến máy tính sẽ được chia thành nhiều phần. Ví dụ 1
chuỗi 10byte gửi, máy tính có thể lần 1 nhận được 8 byte, lần 2 mới nhận 2 byte còn lại.
Vì lý do này, việc nhận dữ liệu sẽ bị xung đột với thread vẽ màn hình giao diện của
chương trình mà chúng ta đang viết. Để khác phục vấn đề này, C#.NET đưa ra khái niệm

BKIT HARDWARE CLUB www.bkit4u.com 82


HƯỚNG DẪN SỬ DỤNG KIT 8051

hàm gọi bất đồng bộ, khi sự kiện nhận UART bị xung đột với thread màn hình, nó sẽ bị
delay lại và không bị mất.
Ta khai báo hàm gọi bất đồng bộ ở đầu chương trình như sau :

Hiện thực hàm SetText() như sau :


private void SetText(string text)
{
//InvokeRequired required compares the thread ID of the
//calling thread to the thread ID of the creating
thread.
// If these threads are different, it returns true.

if (this.txtReceive.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(SetText);
this.Invoke(d, new object[] { text });
}
else
{
//process incoming data + return character
txtReceive.Text += text + Environment.NewLine ;
}
}

BKIT HARDWARE CLUB www.bkit4u.com 83


HƯỚNG DẪN SỬ DỤNG KIT 8051

Cuối cùng ta hiện thực hàm nhận dữ liệu:

private void serialPort_DataReceived(object sender,


SerialDataReceivedEventArgs e)
{
InputData = serialPort.ReadExisting();
if (InputData != String.Empty)
{
SetText(InputData);
}
}

Chi tiết code bạn có thể xem thêm trong project RS232Demo đi kèm trong đĩa CD
này. Để chạy chương trình bạn nhấn F5 hoặc tổ hợp phím Ctrl và F5. Ở máy tính khác
không cài Visual 2005, bạn cần phải cài dotnetframework 2.0 rồi chép file
RS232Demo.exe trong thư mục bin\Debug. Bạn có thể tham khảo thêm trên mạng để tạo
ra file setup cho ứng dụng này để sinh ra file cài đặt giống như khi bạn mua đĩa CD và cài
đặt ứng dụng.

BKIT HARDWARE CLUB www.bkit4u.com 84


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 13 : Giao tiếp PS2 với bàn phím


Mục đích:
Nắm vững giao tiếp PS2 với bàn phím.
Yêu cầu:
Hiện thực chương trình giao tiếp với bàn phím, hiển thị kí tự được nhấn ra ma
trận led .

13.1 Nguyên lý giao tiếp PS2


Dữ liệu trong giao tiếp PS2 cũng được truyền nối tiếp từng bit như uart. Khi 1
phím được nhấn, 11 bit bao gồm Start bit, 8 bit dữ liệu (bit trọng số thấp truyền trước), 1
bit parity và 1 stop bit sẽ được gửi đi :

Ta sẽ lấy dữ liệu tại cạnh xuống của clock, chân của clock được nối vào chân ngắt
ngoài 1 của vi điều khiển (P3.3) như sau:
kb_Shield VCC VCC

R3 R4
7

J3 22K 22K
6
VCC 5 kb_Clock P3.3
kb_Vcc 4

3 kb_Ground
2
1 kb_Data P3.4

PS/2 CIR 7-R

Khi 1 phím được nhấn xuống, mã make_code sẽ được gửi lên. Trong khoảng thời
gian phím đó được đè xuống thì mã make_code vẫn được định kì gửi lên. Khi thả phím ra
thì bàn phím gửi lên mã break_code và make_code.
Bảng mã make_code và break_code của các phím như sau:

BKIT HARDWARE CLUB www.bkit4u.com 85


HƯỚNG DẪN SỬ DỤNG KIT 8051

Dễ dàng nhận ra mã break_code của 1 phím gồm 0xF0 và mã make_code của


phím đó.

13.2 Kết nối phần cứng


Chân clock của bàn phím nối với P3.3.
Chân data từ bàn phím nới với P3.4.
Ứng dụng xuất kí tự ra ma trận led, nên ta gạt switch 3 lên ON.

BKIT HARDWARE CLUB www.bkit4u.com 86


HƯỚNG DẪN SỬ DỤNG KIT 8051

13.3 Viết chương trình


Phần chính của bài thực hành này là lấy cho được dữ liệu truyền lên từ bàn phím.
Quá trình dịch từng bit để lấy data 8 bit trong chuỗi 10 bit được hiện thực trong hàm phục
vụ ngắt ngoài 1. DATA chính là chân P3^4
void ext1_isr() interrupt 2
{
count_bit_input++;
if(count_bit_input == 1) //start to get data
scan_code = 0x00;

// getting data when the key pressed


// ignore start bit, parity bit and stop bit
// just getting 8 data bits
if(count_bit_input > 1 && count_bit_input < 10)
{
scan_code >>= 1;
if(DATA)
scan_code |= 0x80;
}

if(count_bit_input > 10)


{
//Add your code here
count_bit_input = 0; //reset
}

}
Biến count_bit_input dùng để đếm số bit gửi về, khi count_bit_input = 11 ta sẽ
có được dữ liệu scan_code từ bàn phím truyền lên. Bạn sẽ phải xử lý để phân loại đây là
mã make_code hay break_code, có được nhấn kèm với phím shift hay caps lock hay
không để chuyển sang mã ascii cho kí tự được nhấn. Chi tiết code bạn xem thêm trong
Bai 13.

BKIT HARDWARE CLUB www.bkit4u.com 87


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 14 : PWM điều khiển motor


Mục đích:
Nắm vững kĩ thuật điều xung PWM.
Yêu cầu:
Viết ứng dụng điều khiển motor chạy ở nhiều tốc độ khác nhau.

14.1 Khái niệm PWM


PWM viết tắt của từ Pulse Width Modulation. PWM được sử dụng nhiều trong hệ
thống điều khiển tự động ngày nay. Nó được ứng dụng trong điều khiển tốc độ động cơ,
độ sáng tối của led, màn hình LCD, pha màu cho bang quang báo, sử dụng trong các
thuật toán điều khiển vận tốc cho Robot như PI, PD, PID …
Hiểu đơn giản PWM hoạt động như một công tác đóng mở rất nhiều lần trong 1
giây. Nếu tần số đóng mở càng nhanh thì điện áp cấp trung bình càng lớn.

Một số khái niệm cơ bản của PWM :

v Tần số (Hz, Khz…).

v Chu kỳ T, thời gian xung mức cao TH + thời gian xung mức thấp TL.

v Duty Cycle: tỉ lệ thời gian xung mức và thời gian xung mức thấp.

Như hình trên ta có Duty Cycle lần lượt là 0%, 25%, 50%, 75%, 100%.
Một số công thức :

BKIT HARDWARE CLUB www.bkit4u.com 88


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chu kì : TTotal = TOn + TOff


Duty Cycle : D = TOn/TOff
Volt Output : V = Vinput x D

Khi đó nếu TOn = 0 thì VoltOutput = 0 (V) còn TOn = TTotal thì VoltOutput = VoltInput .
Trong thực tế ta có IC chuyên dụng để dùng cho việc điều xung và có các vi điều
khiển có tích hợp sẵn PWM bên trong. Vi điều khiển 89V51 hỗ 5 kênh điều xung (P1.3 –
P1.7) được sử dụng khá linh hoạt cho việc điều xung, người dùng chỉ cần ghi giá trị thích
hợp vào các thanh ghi để có được tín hiện PWM mong muốn.

14.2 Lập trình PWM trên 89V51


Khởi tạo 5 kênh điều xung như sau:

void initPWM()
{
CCAPM0 = 0x42; //set P1.3 pwm mode
CCAPM1 = 0x42; //set P1.4 pwm mode
CCAPM2 = 0x42; //set P1.5 pwm mode
CCAPM3 = 0x42; //set P1.6 pwm mode
CCAPM4 = 0x42; //set P1.7 pwm mode
CMOD = 0x00; // setup to devide frequency by 6

CCAP0H = 0xff;
CCAP1H = 0xff;
CCAP2H = 0xff;
CCAP3H = 0xff;
CCAP4H = 0xff;
CCON |= (1<<6); // set registry PCA
}
Sau khi khởi tạo, mức điện áp ở 5 chân điều xung là 0V. Muốn thay đối giá trị
điện áp ta chỉ cần thay đối nội dung trong thanh ghi CCAPnH, 0x00 tương ứng với 100%
duty cycle, 0xFF tương ứng với 0% duty cycle. Motor được nối với P1.3 tương ứng với
kênh điều xung 0. Motor được tích cực mức 0 nên giá trị trong thanh ghi CCAP0H càng
lớn thì motor quay càng chậm (duty cycle nhỏ thì motor quay nhanh).

BKIT HARDWARE CLUB www.bkit4u.com 89


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 15 : Giao tiếp LCD character


Mục đích:
Nắm vững kĩ thuật điều khiển LCD character theo 2 chế độ 8 bit và 4 bit.
Yêu cầu:
Xây dựng chương trình xuất dữ liệu ra LCD theo chế độ 4 bit.

15.1 Chức năng các chân của LCD

LCD thường sử dụng 14 chân, chế độ 16 chân khi cần điều khiển đèn nền. Chức
năng của các chân như sau:

Chức năng Thứ tự Tên Mức Logic Mô tả


Ground 1 VSS - 0V
Power Supply 2 Vdd - +5V
Contrast 3 Vee - 0-Vdd
4 RS 0 D0-D7 là command
1 D0-D7 là Data
Control 5 R/W 0 Write
Operation 1 Read
0 Disable
1 Normal
6 E Từ 1 xuống 0 Truyền Data hoặc
Command xuống LCD
7 D0 0|1 Bit 0 LSB
8 D1 0|1 Bit 1
9 D2 0|1 Bit 2
Data/Command 10 D3 0|1 Bit 3
11 D4 0|1 Bit 4
12 D4 0|1 Bit 5
13 D6 0|1 Bit 6
14 D7 0|1 Bit 7 MSB

BKIT HARDWARE CLUB www.bkit4u.com 90


HƯỚNG DẪN SỬ DỤNG KIT 8051

15.2 Kết nối màn hình LCD

Hình trên mô tả kết nối LCD với chế độ 16 chân, 2 chân K và A dùng để kết nối
với đèn nền.

15.3 Các vùng nhớ của LCD


15.3.1 Display Data Ram (DDRAM)
Lưu trữ mã ký tự hiển thị ra màn hình. Mã này giống với mã ASCII. Có tất cả 80
ô nhớ DDRAM. Vùng hiển thị tương ứng với cửa sổ gồm 16 ô nhớ hàng đầu tiên và 16 ô
nhớ hàng thứ hai. Chúng ta có thể tạo hiệu ứng dịch chữ bằng cách sử dụng lệnh dịch ,
khi đó cửa sổ hiển thị sẽ dịch đem lại hiệu ứng dịch chữ.

15.3.2 Character Generator Ram (CGRAM)


Lưu trữ tám mẫu ký tự do người dùng định nghĩa. Tám mẫu ký tự này tương ứng
với các mã ký tự D7-D0 = 0000*D2D1D0 (* mang giá trị tùy định 0 hay 1).

BKIT HARDWARE CLUB www.bkit4u.com 91


HƯỚNG DẪN SỬ DỤNG KIT 8051

15.3.3 Bộ nhớ CGROM


Bộ nhớ dùng để lưu trữ các kí tự hiển thị trên LCD. Các giá trị lưu trong bộ nhớ
này như sau:

BKIT HARDWARE CLUB www.bkit4u.com 92


HƯỚNG DẪN SỬ DỤNG KIT 8051

Chúng ta muốn hiển thị chữ “CE” ở giữa hàng đầu tiên, giả sử cửa sổ hiển thị
đang bắt đầu từ vị trí đầu tiên (hàng thứ nhất hiển thị dữ liệu của ô nhớ từ 0x00 đến 0x0f,
hàng thứ hai hiển thị dữ liệu của ô nhớ từ 0x40 đến 0x4f, đây là vị trí home). Giá trị của ô
nhớ 0x07 là 0x43 (ký tự C), của ô nhớ 0x08 là 0x45 (ký tự E).
Chúng ta muốn hiển thị chữ “®” ở giữ hàng thứ hai, giả sử cử sổ hiển thị đang ở
vị trí home. Trong bảng mẫu ký tự chúng ta thấy không có mẫu “®”. Lúc này chúng ta
phải định nghĩa mẫu “®” 5x8 điểm, gồm có 8 byte, sau đó lưu vào vị trí của mẫu ký tự
CGRAM thứ nhất. Lúc này giá trị của ô nhớ 0x47 là 0x00 hoặc 0x08 (vị trí của mẫu ký
tự CGRAM thứ nhất “®”).

15.4 Các lệnh cơ bản của LCD


Để truyền lệnh cho LCD thì chân RS = 0, khi đó các tín hiện trên D0-D7 được
xem là lệnh. Ý nghĩa của các lệnh điều khiển LCD như sau:

BKIT HARDWARE CLUB www.bkit4u.com 93


HƯỚNG DẪN SỬ DỤNG KIT 8051

Thời gian
Lệnh RS RW D7 D6 D5 D4 D3 D2 D1 D0
thực thi
Clear display
0 0 0 0 0 0 0 0 0 1 1.52ms
Return home
0 0 0 0 0 0 0 0 1 * 1.52ms
Entry mode set
0 0 0 0 0 0 0 1 I/D RL 37µs
Display on/off
0 0 0 0 0 0 1 D C B 37µs
control
Cursor/Display S/ R/
0 0 0 0 0 1 * * 37µs
shift C L
Function set
0 0 0 0 1 DL N F * * 37µs
Set CGRAM
0 0 0 1 CGRAM address 37µs
address
Set DDRAM
0 0 1 DDRAM address 37µs
address
Read BUSY flag
0 1 BF DDRAM address 0µs
(BF)
Write to
DDRAM or 1 0 D7 D6 D5 D4 D3 D2 D1 D0 43µs
CGRAM
Read from
DDRAM or 1 1 D7 D6 D5 D4 D3 D2 D1 D0 43µs
CGRAM

I/D 1 = Increment (by 1) RL 1 = Shift right


0 = Decrement (by 1) 0 = Shift left

S 1 = Display shift on DL 1 = 8-bit interface


0 = Display shift off 0 = 4-bit interface

D 1 = Display on N 1 = Display in two lines


0 = Display off 0 = Display in one line

U 1 = Cursor on F 1 = Character format 5x10 dots


0 = Cursor off 0 = Character format 5x7 dots

B 1 = Cursor blink on D/C 1 = Display shift


0 = Cursor blink off 0 = Cursor shift

15.5 Kết nối LCD với vi điều khiển


LCD có 2 chế độ 8 bit và 4 bit. Ở chế độ 8 bit, ta dùng toàn bộ 8 chân D0-D7 để
giao tiếp. Ở chế độ 4 bit, ta chỉ dùng 4 bit cao D4-D7 để giao tiếp với LCD. Dữ liệu gửi

BKIT HARDWARE CLUB www.bkit4u.com 94


HƯỚNG DẪN SỬ DỤNG KIT 8051

cho LCD ở chế độ này bao gồm 4bit cao gửi trước, sau đó sẽ đến 4bit thấp. Sơ đồ kết nối
ở 2 chế độ như sau:

Nếu muốn tiết kiệm chân, R/W có thể nối xuống GND. Ở chế độ 4bit thì 4 bit
thấp của LCD có thể nối xuống GND.

15.6 Khởi tạo LCD


Quá trình khởi tạo LCD ở chế độ 8 bit như sau:

BKIT HARDWARE CLUB www.bkit4u.com 95


HƯỚNG DẪN SỬ DỤNG KIT 8051

Quá trình khởi tạo ở chế độ 4 bit như sau:

BKIT HARDWARE CLUB www.bkit4u.com 96


HƯỚNG DẪN SỬ DỤNG KIT 8051

15.7 Kết nối phần cứng


LCD được kết nối với Port 3 của vi điều khiển như sau:
LED_BACKLIGHT = P3^0
PIN_RS : P3^1
PIN_RW : P3^2
PIN_EN : P3^3
D4 : P3^4
D5 : P3^5
D6 : P3^6
D7 : P3^7

BKIT HARDWARE CLUB www.bkit4u.com 97


HƯỚNG DẪN SỬ DỤNG KIT 8051

15.8 Viết chương trình


15.8.1 Các hàm cơ bản
Để quá trình điều khiển LCD hiệu quả, ta định nghĩa 1 số hàm cơ bản như sau
v Hàm delay: trung bình 89V51 thực hiện 1 lệnh mất 1us.
void lcd_delay(int time)
{
while(--time);
}
v Hàm ghi dữ liệu ra LCD:
//Ghi 4 bit
void lcd_write_4bits(unsigned char dat)
{
RW(WRITE); //kéo chân RW xuống 0
EN(SET); //set chân Enable lên 1
LCD_DATA_OUT(dat & 0xF0); //Gửi data ra
lcd_delay(10);
EN(CLR); //kéo chân Enable xuống 0
lcd_delay(10);
}
//Ghi 1 byte : ghi 4 bit 2 lần
void lcd_write_cmd(unsigned char cmd){
lcd_wait_busy();

RS(CMD);
lcd_write_4bits(cmd);
lcd_write_4bits(cmd << 4);
}

v Một số macro trong file lcd.h, ví dụ như:

#define RS(x) ( (x) ? ( LCD_PORT |= 0x02 ) : ( LCD_PORT &= 0xFD ) )

Nếu x = 1 thì thực hiện lệnh LCD_PORT |=0x02, x=0 thì thực hiện LCD_PORT
&=0xFD.

15.8.2 Khởi tạo LCD chế độ 4 bit

void init_lcd() {
lcd_delay(15000); //1
RS(CMD); //2
lcd_write_4bits(0x03 << 4); //3
lcd_delay(4100); //4
lcd_write_4bits(0x03 << 4); //5
lcd_delay(100); //6

BKIT HARDWARE CLUB www.bkit4u.com 98


HƯỚNG DẪN SỬ DỤNG KIT 8051

lcd_write_4bits(0x03 << 4); //7


lcd_write_4bits(0x02 << 4); //8
lcd_write_cmd(0x28) ; //9
lcd_write_cmd(0x0C); //10
lcd_write_cmd(0x06); //11

}
Ý nghĩa các lệnh trên như sau:
v Lệnh 1 : gọi hàm lcd_delay(15000) để delay 15ms.
v Lệnh 2 : kéo chân RS (nối với LCD_PORT tại bit 1) xuống 0. Lệnh này được
định nghĩa là 1 macro trong file lcd.h:
#define RS(x) ( (x) ? ( LCD_PORT |= 0x02 ) : ( LCD_PORT &= 0xFD ) )
CMD được define là 0 nên lệnh RS(CMD) sẽ có điều kiện (x) là false và sẽ thực
hiện phần thứ 2 của lệnh trên : LCD_PORT & 0xFD (kéo bit 1 xuống 0 : 1111 1101).
v Lệnh 3 : thực hiện trạng thái đầu tiên sau khi chờ 15ms, ghi D7 D6 D5 D4 =
0011. Các chân này được nối với 4 bit cao của vi điều khiển nên ta phải dịch trái giá trị
0x03 4 bit.
v Lệnh 4 : delay khoảng 41ms.
v Lệnh 5,6,7,8 : Thực hiện các trạng thái 2,3 và 4. Sau lệnh 7 thì LCD đã
chuyển sang chế độ 4 bit, và để gửi 1 byte, ta sẽ gửi 2 lần 4 bit cao trước rồi tới 4 bit thấp.
v Lệnh 9 : gọi hàm lcd_write_cmd để ghi 4 bit 2 lần, giá trị 0x28 tương ứng với
N = 1 (hiển thị trên 2 hàng của LCD) và B = 0 (font định dạng 5x7 điểm).
v Lệnh 10 : thực hiện lệnh display on (xem thêm trong bảng lệnh), D = 1.
v Lệnh 11 : thực hiện lệnh entry set mode, 0x06 tương ứng với chế độ dịch phải
tăng dần.

15.8.3 Xoá màn hình


Hàm này chỉ đơn giản là gửi lệnh clear màn hình lcd (xem thêm trong bảng lệnh
của LCD).
void lcd_clear()
{
lcd_write_cmd(0x01);
lcd_goto_xy(0, 0);
}

15.8.4 Thiết lập vị trí con trỏ


Hàm này thiết lập vị trí bắt đầu xuất dữ liệu trên màn hình LCD 2 hàng 16 cột. Để
hiện thực hàm này ta phải tính được địa chỉ tương ứng với toạ độ (row,col) và dùng lệnh
SET DDRAM ADDRESS (bit 7 của lệnh này bằng 1).
char lcd_goto_xy(unsigned char row, unsigned char col) {
unsigned char addr = 0x00;
if(col >= 20 || row >= 4)
return FALSE;
if(row < 2) {
addr = (row * 0x40) + col;
addr = 0x80 | (addr & 0x7F);

BKIT HARDWARE CLUB www.bkit4u.com 99


HƯỚNG DẪN SỬ DỤNG KIT 8051

}
else {
addr = (row * 0x40) + col;
addr = 0x94 | (addr & 0x7F);
}
lcd_write_cmd(addr);

current_row = row;
current_col = col;
return TRUE;
}

15.8.5 In kí tự ra màn hình


Hàm này nhận thông số là 1 kí tự và hiển thị kí tự đó ra màn hình LCD. Việc hiện
thực hàm này khá đơn giản, ta chỉ cần kéo chân RS xuống 0 là LCD sẽ hiểu các bit D7-
D4 là dữ liệu.
void lcd_print_char(unsigned char dat)
{
lcd_wait_busy();
//find next position
if(current_row == 0 && current_col == 16)
lcd_goto_xy(1,0);

if(current_row == 1 && current_col ==16)


lcd_goto_xy(0,0);

RS(DAT); //RS = 0
lcd_write_4bits(dat);
lcd_write_4bits(dat << 4);

current_col ++; //update new position

}
Từ những hàm cơ bản này, bạn có thể hiện thực thêm các hàm để xuất 1 string
hay 1 giá trị số ra màn hình LCD. Code chi tiết có thể xem thêm trong thư mục Bài 15.

BKIT HARDWARE CLUB www.bkit4u.com 100


HƯỚNG DẪN SỬ DỤNG KIT 8051

Bài 16 : Giao tiếp I2C – DS1307


Mục đích:
Nắm vững giao tiếp I2C
Yêu cầu:
Xây dựng ứng dụng giao tiếp với DS1307 để lấy dữ liệu ngày tháng năm, giờ phút
giây.

16.1 Các đặc điểm của DS1307


Real time clock đếm giờ, phút, giây, tháng, ngày của
tháng, ngày của tuần, năm kể cả năm nhuận (đến năm 2100).
56 byte Ram để lưu trữ dữ liệu, nhưng dữ liệu không bị
mất khi tắt nguồn.
Sử dụng 2 dây tín hiệu để truyền dữ liệu theo giao thức
I2C.
Có thể lập trình được để xuất tín hiệu xung vuông.
Tự động phát hiện ra nguồn cung cấp bị lỗi (ngắt nguồn) và chuyển qua
mạch bảo vệ sử dùng nguồn pin dự trữ.

16.2 Nguyên lý hoạt động


DS1307 hoạt động như một slaver trên bus dữ liệu nối tiếp. Để truy xuất
nội dung ta phải thiết lập một điều kiện Start và cung cấp mã nhận dạng của IC
(Device Identification Code) theo sau bởi thanh ghi địa chỉ. Các thanh ghi theo sau
được truy xuất tuần tự cho đến khi gặp tín hiệu Stop.
Khi VCC = 1.25Vbat thì DS1307 sẽ kết thúc việc truy xuất và reset lại bộ
đếm địa chỉ. Các Input sẽ không được nhận ra tại thời điểm này để ngăn ngừa một
số lượng lớn dữ liệu được ghi tới DS1307 từ hệ thống bên ngoài. Khi VCC < Vbat
thì ic này sẽ chuyển sang mode sử dụng pin dự trữ. Khi nguồn chính được bật lên
thì IC này sẽ chuyển từ dùng nguồn pin sang dùng nguồn chính. Hình sau mô tả
những phần chính của DS1307.

BKIT HARDWARE CLUB www.bkit4u.com 101


HƯỚNG DẪN SỬ DỤNG KIT 8051

16.3 Các tín hiệu Input và Output


VCC, GND : Nguồn DC được cung cấp cho IC qua những chân này. Khi
gắn vào nguồn 5V thì IC này có thể đọc ghi bình thường. Nhưng khi nguồn giảm
xuống còn 3V thì việc đọc ghi sẽ không được phép. Tuy nhiên, các chức năng của
timer vẫn tiếp tục với nguồn cung cấp thấp. Khi Vcc giảm xuống dưới VBAT thì
RAM và timekeeper được chuyển qua sử dụng nguồn cung cấp tại VBAT.
VBAT : Cung cấp nguồn dữ trữ 3V. Để hoạt động ở chế độ sử dụng nguồn
Vbat thì 2.0V < Vbat < 3.5V. Khi VCC gần bằng 1.25VBAT thì chúng ta sẽ
không được phép truy xuất vào RTC (Real time clock) và Ram bên trong của IC.
SCL (Serial Clock Input) : SCL được dùng để đồng bộ dữ liệu trên đường
truyền nối tiếp.
SDA (Serial Data Input/Output) : SDA là chân I/O. SDA là chân Open
drain nên cần có điện trở kéo lên ở bên ngoài.
SQW/OUT (Square Wave/Output Driver) : Khi được bật lên, thì bit SQWE
set lên 1, và chân này sẽ output ra 1 trong 4 tần số sóng vuông là 1hz, 4khz, 8khz,

BKIT HARDWARE CLUB www.bkit4u.com 102


HƯỚNG DẪN SỬ DỤNG KIT 8051

32khz. Chân này cũng là chân Open drain nên cũng yêu cầu có điện trở kéo lên
nguồn ở bên ngoài. SQW/OUT sẽ hoạt động khi có nguồn cung cấp vào cho dù đó
là nguồn VCC hay là VBAT.
X1, X2 : Kết nối với thạch anh 32.768Khz. Mạch tạo xung bên trong được
thiết kế để hoạt động với thạch anh và tụ CL = 12.5 pF.

16.4 RTC và sơ đồ địa chỉ Ram


Sơ đồ địa chỉ của RTC và các thanh ghi Ram của DS1307 như ở hình dưới.
Các thanh ghi RTC được định địa chỉ từ 00h đến 07h. Các thanh ghi Ram được
định địa chỉ tiếp theo sau đó và từ 08h đến 3fh. Trong khi truy suất nhiều byte và
khi con trỏ địa chỉ chỉ tới ô 3fh, vị trí cuối của vùng nhớ Ram, thì nó sẽ quay lại
địa chỉ 00h để truy xuất tiếp.

16.5 Thông tin thời gian và lịch


Thông tin thời gian và lịch được chứa trong trong các thanh ghi tương ứng.
Các thanh ghi RTC như ở hình trên. Thời gian và lịch được set hoặc khởi tạo bằng
cách ghi ra các byte thanh khi tương ứng. Nội dung của các thanh ghi thời gian và
lịch được định dạng theo kiểu BCD. Bit 7 của thanh ghi 0 là clock halt bit (CH).
Khi bít này được set lên 1 thì mạch dao động sẽ bị ẩn không được sử dụng nữa,
khi clear xuống 0 thì mạch dao động sẽ được kích hoạt trở lại.
DS1307 có thể chạy ở chế độ 12h hay 24h. Bít thứ 6 của thanh ghi hours
được định nghĩa để set xem sử dụng IC này ở chế độ nào. Khi bit này bằng 1 thì
chế độ 12h được chọn. Trong chế độ 12h thì bit 5 chỉ AM/PM (PM khi bit này là
1). Trong chế độ 24h, thì bít 5 là bít thứ 2 của 10hour (20:23).

BKIT HARDWARE CLUB www.bkit4u.com 103


HƯỚNG DẪN SỬ DỤNG KIT 8051

16.6 Thanh ghi điều khiển (Control Register)


Thanh ghi điều khiển của DS1307 được sử dụng để điều khiển hoạt động
của chân SQW/OUT.

Out (Output control) : Bít này điều khiển mức logic xuất ra trên chân
SQW/OUT khi mà sóng vuông không được kích hoạt. Nếu SQWE = 0, thì mức
logic trên chân SQW/OUT là 1 nếu OUT = 1, và là 0 nếu OUT = 0.
SQWE (Square Wave Enabel) : Bít này khi được set lên mức 1 thì sẽ kích
hoạt mạch dao động xuất ra ngoài. Tần số của sóng vuông phụ thuộc vào giá trị ở
bít RS0 và RS1. Với sóng vuông xuất ra 1Hz thì thanh ghi clock sẽ cập nhập dữ
liệu khi có cạnh xuống của xung vuông.
RS (Rate select) : Những bit này điều khiển tần số của sóng vuông được
xuất ra trên chân SQW/OUT. Bảng sau liệt kê ra các tần số có thể được chọn bởi 2
bit RS này.

16.7 Bus dữ liệu nối tiếp.


DS1307 hỗ trợ truyền dữ liệu 2 chiều và giao thức truyền dữ liệu I2C trên 2
dây này. Thiết bị gởi dữ liệu trên bus gọi là transmitter và thiết bị nhận dữ liệu gọi
là receiver. Thiết bị điều khiển các message gọi là master. Thiết bị được điều
khiển bởi master thì gọi là slaver.
Bus dữ liệu được điều khiển bởi master. Bên cạnh đó nó cũng có nhiệm vụ
tạo xung clock trên đường tín hiệu SCL, điều khiển truy xuất bus, và tạo các tín
hiệu Start, Stop. DS1307 hoạt động như một slave trên đường bus này.

BKIT HARDWARE CLUB www.bkit4u.com 104


HƯỚNG DẪN SỬ DỤNG KIT 8051

Các trạng thái của bus:


Bus không bận : khi cả 2 đường giữ tín hiệu ở mức high.
Bắt đầu truyền dữ liệu (start condition) : Thay đổi trạng thái trên đường dữ
liệu từ High xuống Low, trong khi đường clock ổn định ở mức high được định
nghĩa là một tín hiệu Start.
Kết thúc truyền dữ liệu (stop condition) : Thay đổi trạng thái trên đường dữ
liệu từ Low lên High, trong khi đường clock ổn định ở mức high thì được định
nghĩa là một tín hiệu Stop.
Dữ liệu hợp lệ : Trạng thái của đường dữ liệu biểu diễn dữ liệu hợp lệ khi
theo sau bởi tín hiệu START, đường dữ liệu ổn định trong khoảng thời gian mà tín
hiệu clock ở mức High. Dữ liệu trên đường dữ liệu phải được thay đổi trong
khoảng thời gian mà tín hiệu clock ở mức Low.
Mỗi khi truyền dữ liệu điều được bắt đầu bởi một tín hiệu Start và kết thúc
việc truyền bằng một tín hiệu Stop. Số byte dữ liệu truyền giữa 2 tín hiệu Start và
Stop là không hạn chế và được xác định bởi master. Thông tin được truyền và mỗi
lần truyền receiver gởi thêm ack ở bít thứ 9. Để cho biết là đã nhận xong một byte
dữ liệu.

16.8 Giao thức I2C và RTC DS1307


16.8.1 Kết nối phần cứng
Gạt switch 1 và 2 lên ON để kích hoạt P1 và P3.
SDA được nối với P1.0.
SCL được nối với P1.1.

16.8.2 Start và Stop truyền dữ liệu


Việc truyền dữ liệu được bắt đầu bởi một tín hiệu Start và kết thúc việc
truyền bằng một tín hiệu Stop. Số byte dữ liệu truyền giữa 2 tín hiệu Start và Stop
là không hạn chế và được xác định bởi master.
Giản đồ xung cho điều kiện Start như sau:

BKIT HARDWARE CLUB www.bkit4u.com 105


HƯỚNG DẪN SỬ DỤNG KIT 8051

Dựa vào giản đồ trên ta hiện thực hàm để Start I2C như sau :
void start_I2C()
{
SCL = 1;
SDA = 1;
nop();nop();
SDA = 0;
SCL = 0;
nop();nop();
}
Tốc độ clock chuẩn của giao thức I2C là 100KHz. Khi truyền ở tốc độ cao có thể
hoạt động ở clock 1MHz. Tuy nhiên bạn nên delay vài uS để đảm bảo tính đúng đắn của
dữ liệu.
Giản đồ xung cho điều kiện Stop như sau

Hàm để Stop I2C được hiện thực như sau:


void stop_I2C()
{
SCL = 1;
SDA = 0;
nop();nop();
SDA = 1;
}

BKIT HARDWARE CLUB www.bkit4u.com 106


HƯỚNG DẪN SỬ DỤNG KIT 8051

16.8.3 Truyền 1 byte dữ liệu


Khi truyền 1 byte dữ liệu, bit có trọng số cao nhất (bit 7) sẽ được truyền trước.
Khi bit cuối cùng (bit 0) được truyền, sẽ có thêm bit ACK báo hiệu kết thúc 1 byte dữ
liệu.

Truyền từ master xuống slave:


Ở chế độ này, master sẽ gửi 8 bit dữ liệu, sau khi nhận xong 8 bit này, slave sẽ tự
động gửi lại 1 bit ACK và master phải tạo ra thêm 1 clock để nhận bit ACK này.
//write I2C
void write_I2C(unsigned char data2send)
{
int i;
for (i=0;i<8;i++)
{
SDA = (data2send & 0x80) ? 1:0;
SCL=1;
nop();
SCL=0;
data2send<<=1;
nop();
}
//clock to receive ACK from slave
SCL = 1;
nop();nop();
SCL = 0;
}
Truyền từ slave lên master
Ở chế độ này, master sẽ nhận vào 8 bit dữ liệu, và sau khi nhận xong, master phải
gửi 1 bit ACK xuống slave. Trong quá trình đọc 1 chuỗi byte từ slave, master gửi bit
ACK. Đối với byte cuối cùng, master sẽ gửi bit NO ACK và sau đó gửi tín hiệu stop.
Hàm đọc 1 byte sau đây có tham số là ACK_Bit, dùng để phân biệt ACK và NACK.
unsigned char read_I2C(bit ACK_Bit)
{
unsigned char Data=0;
int i;
SDA = 1;
for (i=0;i<8;i++)
{
SCL = 1;
Data<<= 1;
Data = (Data | SDA);
SCL = 0;

BKIT HARDWARE CLUB www.bkit4u.com 107


HƯỚNG DẪN SỬ DỤNG KIT 8051

nop();
}

if (ACK_Bit == 1)
SDA = 0; // Send ACK
else
SDA = 1; // Send NO ACK

nop();nop();

//clock to send (N)ACK


SCL = 1;
nop();nop();
SCL = 0;

return Data;
}

16.8.4 Giao tiếp với DS1307


Ghi dữ liệu vào DS1307

Đây là quá trình truyền dữ liệu từ master xuống slave. Khi master gửi xong 1
byte, slave sẽ gửi lại bit ACK. Quá trình giao tiếp như sau:
v Master gửi tín hiệu Start.
v Master gửi địa chỉ của DS1307 (1101 000) và bit R/W, trong trường hợp
này là 0. Byte đầu tiên mà master gửi xuống sau khi start là D0.
v Master gửi địa chỉ pointer dữ liệu cần ghi, chẳng hạn là 0x00 (register
pointer, word address)
v Master gửi các byte data cần ghi.
v Master gửi tín hiện stop.
Code hiện thực cho quá trình này như sau
void write_RTC(unsigned char *buff)
{
start_I2C();
write_I2C(0xD0);
write_I2C(0x00);

write_I2C(*(buff+0));
write_I2C(*(buff+1));
write_I2C(*(buff+2));

BKIT HARDWARE CLUB www.bkit4u.com 108


HƯỚNG DẪN SỬ DỤNG KIT 8051

write_I2C(*(buff+3));
write_I2C(*(buff+4));
write_I2C(*(buff+5));
write_I2C(*(buff+6));
stop_I2C();
}
buff là 1 mảng có 7 phần tử, tương ứng với các giá trị giây, phút, giờ, thứ, ngày,
tháng và năm.
Đọc dữ liệu từ DS1307

Đây là quá trình truyền dữ liệu từ slave lên master. Như đã trình bày ở phần trước,
khi gửi nhận từng byte, sẽ có bit ACK đi kèm ngoại trừ byte cuối cùng trước khi stop.
Để có thể đọc chính xác giá trị mong muốn, thông thường ta phải ghi vào thanh
ghi địa con trỏ dữ liệu (register pointer). Quá trình này chính là trình truyền dữ liệu từ
master xuống slave nên R/W bit sẽ là 0. Sau khi ghi dữ liệu và register pointer xong, quá
trình đọc dữ liệu mới bắt đầu, và bit R/W sẽ là 1.
Từng bước đọc dữ liệu từ DS1307 như sau:
v Master gửi tín hiệu start.
v Master gửi địa chỉ DS1307 + R/W = 0 : 0xD0.
v Master gửi byte ghi vào register pointer : 0x00.
v Master gửi tín hiệu start
v Master gửi địa chỉ DS1307 + R/W = 1 : 0xD1.
v Master đọc các byte dữ liệu và gửi bit ACK. Byte cuối cùng trước khi stop,
master gửi bit NACK.
v Master gửi tín hiện stop.
Code hiện thực cho quá trình này như sau
void read_RTC(unsigned char * buff)
{
//send address to slave and reset pointer
start_I2C();
write_I2C(0xD0); //address + direction
write_I2C(0x00); //pointer data

//start read operation


start_I2C();
write_I2C(0xD1);
*(buff+0)=read_I2C(ACK); // Second
*(buff+1)=read_I2C(ACK); // Minute
*(buff+2)=read_I2C(ACK); // hour
*(buff+3)=read_I2C(ACK); // Day

BKIT HARDWARE CLUB www.bkit4u.com 109


HƯỚNG DẪN SỬ DỤNG KIT 8051

*(buff+4)=read_I2C(ACK); // date
*(buff+5)=read_I2C(ACK); // month
*(buff+6)=read_I2C(NO_ACK); // year
stop_I2C();
}
Hàm main() dưới đây minh hoạ cho việc sử dụng các hàm trong module RTC
DS1307:
void main()
{
P1 = P3 = 0x00;

RTC_ARR[0] = 0x12; //second = 12


RTC_ARR[1] = 0x55; // minute = 55
RTC_ARR[2] = 0x05; // hour = 05 ,24-hour mode(bit 6=0)
RTC_ARR[3] = 0x01; // Day = 1 or sunday
RTC_ARR[4] = 0x01; // Date = 01
RTC_ARR[5] = 0x08; // month = August
RTC_ARR[6] = 0x05; // year = 05 or 2005

write_RTC(&RTC_ARR[0]); // Set RTC

while(1)
{
read_RTC(&RTC_ARR[0]); //read 7 bytes RTC

P3=RTC_ARR[0]; //out second to P3


delay();; // delay about 1 second
}
}

BKIT HARDWARE CLUB www.bkit4u.com 110

You might also like