Bài 7: Giao tiếp UART với 8051.
Chào các bạn!
Giao tiếp UART là chuẩn giao tiếp nối tiếp được sử dụng phổ biến trong các dòng VĐK. Mặc dù có tốc độ truyền không cao, nhưng ngược lại giao tiếp UART có phần cứng gọn nhẹ, dễ thiết kế và giá thành thấp. Giao tiếp UART được sử dụng nhiều trong các ứng dụng như giao tiếp máy tinh, giao tiếp module SIM, module GPS...Hôm nay mình xin hướng dẫn các cấu hình sử dụng UART trong VĐK 8051.
I. Các thanh ghi cấu hình giao tiếp UART trong VĐK 8051.
1. Thanh ghi cấu hình cổng nối tiếp SCON.
Đây là thanh ghi 8 bit, chứa các bit sử dụng để cài đặt chế độ của giao tiếp UART và các bit cờ báo trạng thái truyền và nhận.
Các bit của thanh ghi được mô tả như sau.
Hình 1.1: Thanh ghi SCON.
SM0, SM1: Đây là 2 bit sử dụng để xác định các chế độ làm việc. Có 4 chế độ truyền UART trong 8051, được miêu tả trong bảng sau.
Hình 1.2: Các chế độ hoạt động của UART.
SM2: Đây là bit sử dụng cho truyền thông giữa các bộ vi điều khiển.
REN: Bit cho phép nhận dữ liệu, khi sử dụng chức năng nhận dữ liệu qua cổng UART, phải bật bit này lên 1.
TB8, RB8: Bit thứ 9 của truyền/nhận trong chế độ truyền 9 bit.
TI, RI: Cờ báo ngắt truyền, ngắt nhận.
2. Thanh ghi sử dụng cài đặt tốc độ Baudrate: TMOD, TH1.
Như các bạn thấy trong hình 1.2, tùy vào chế độ hoạt động mà tốc độ baudrate có cách tính khác nhau. Với chế độ được sử dụng thông dụng nhất, chế độ 1, 8 bit dữ liệu, 1 bit start, 1 bit stop. Tốc độ baudrate được xác định qua timer 1.
Trước hết để sử dụng timer 1 để xác định tốc độ baudrate chúng ta cần cài đặt timer 1 ở chế độ 8 bit tự nạp lại. Do đó, cần gán giá trị 0x20 cho thanh ghi TMOD (TMOD = 0x20).
Giá trị gán vào thanh ghi TH1 để xác định tốc độ baudrate được tính như sau.
TH1 =256 - (F(crystal)/12/32/baudrate). (Với F(crystal) tính bằng đơn vị Hz).
Ví dụ: Muốn truyền UART với tốc độ baudrate là 9600 ta cần gán cho TH1 giá trị sau.
TH1 =256 - (F(crystal)/12/32/9600).
Nếu mạch sử dụng thạch anh 11.0592 MHz = 11059200 Hz, ta sẽ có:
TH1 = 256 - (11059200/12/32/9600) = 253.
Như vậy gán cho thanh ghi TH1 giá trị 253 (TH1 = 253), là ta đã cài đặt giao tiếp UART với tốc độ baudrate 9600.
3. Bit nhân đôi tốc độ baudrate.
Trong 8051 có một bit được sử dụng để nhân đôi tốc độ truyền của giao tiếp UART. Đó là bit SMOD (bit thứ 7) trong thanh ghi PCON. Khi set bit SMOD lên 1, tốc độ truyền của giao tiếp UART sẽ được nhân đôi.
Trở lại với ví dụ ở mục 2 phía trên, nếu như chúng ta muốn sử dụng tốc độ baudrate 19200 thì giá trị gán cho TH1 phải là bao nhiêu? Mạch vẫn sử dụng thạch anh 11.0592 MHz.
Theo công thức tính đã cho ở trên ta sẽ có:
TH1 = 256 - (11059200/12/32/19200) = 254.5
Nhưng số cần gán cho TH1 phải là một số nguyên, nếu chúng ta gán 254 hoặc 255 thì vẫn không đúng tốc độ baudrate 19200.
Vậy để có được tốc độ baudrate 19200, chúng ta cần sử dụng bit nhân đôi tốc độ SMOD. Gán giá trị 253 cho thanh ghi TH1 (để có baudrate 9600), và set bit SMOD lên 1 để nhân đôi tốc độ lên 19200.
4. Thanh ghi truyền/nhận dữ liệu: SBUF.
SBUF là thanh ghi 8 bit, được sử dụng chung cho cả truyền và nhận dữ liệu trong UART.
Để truyền dữ liệu, chúng ta chỉ cần ghi dữ liệu vào thanh ghi SBUF.
Để nhận dữ liệu chúng ta đọc giá trị từ thanh ghi SBUF.
II. Các bước thiết lập để truyền/nhận dữ liệu qua UART với 8051.
1. Thiết lập chế độ truyền, tốc độ baudrate.
1. Ghi giá trị 0x20 vào thanh ghi TMOD để cài đặt sử dụng timer 1 ở chế độ 8 bit, tự nạp lại (TMOD = 0x20).
2. Ghi vào thanh ghi TH1 giá trị thích hợp để chọn tốc độ baudrate. Giá trị này được tính dựa vào công thức đã cho ở mục 2 trong phần I.
3. Ghi vào thanh ghi SCON giá trị 0x50 để thiết lập chế độ truyền 8 bit, 1 bit start, 1 bit stop (SCON = 0x50 (SM0 = 0, SM1 = 1, REN = 1)).
4. Bật bit TR1 để khởi động timer 1.
TMOD = 0x20; //Timer 1, 8bit tu nap lai
TH1 = 253; //Buadrate: 9600
SCON = 0x50; //SM0 = 0, SM1 = 1; REN = 1;
TR1 = 1; // khoi dong timer 1
2. Truyền 1 ký tự.
1. Ghi ký tự vào thanh ghi SBUF để truyền đi.
2. Chờ cho cờ TI được bật.
3. Xóa cờ TI để sử dụng cho lần truyền ký tự tiếp theo.
Hàm truyền 1 ký tự được viết như sau.
/*Ham truyen 1 ky tu*/
void UART_PutChar(unsigned char chr)
{
SBUF = chr; //ghi ky tu vao SBUF de truyen
while(TI == 0); //Cho cho co TI bat len 1
TI = 0;
}
3. Nhận 1 ký tự.
1. Chờ cờ RI được bật báo có dữ liệu đến. 2. Đọc dữ liệu từ thanh ghi SBUF.
3. Xóa cờ TI để sử dụng cho lần truyền ký tự tiếp theo.
Hàm truyền 1 ký tự được viết như sau.
/*Ham truyen 1 ky tu*/ void UART_PutChar(unsigned char chr) { SBUF = chr; //ghi ky tu vao SBUF de truyen while(TI == 0); //Cho cho co TI bat len 1 TI = 0; }
3. Xóa cờ RI cho lần nhận dữ liệu tiếp theo.
Hàm nhận dữ liệu không dùng ngắt được viết như sau.
/*Ham nhan 1 ky tu*/ unsigned char UART_GetChar(void) { unsigned char temp; while(RI == 0); //Cho co RI duoc bat len 1 bao co du lieu den temp = SBUF; // doc du lieu RI = 0; // xoa co RI de lan nhan tiep theo return temp; }
4. Nhận dữ liệu sử dụng ngắt.
Thông thường, với một công việc thụ động như nhận dữ liệu qua UART thì việc sử dụng ngắt sẽ tiện lợi hơn rất nhiều. VĐK 8051 cho phép thiết lập ngắt UART bằng cách bật 2 bit ES và EA trong thanh ghi IE lên 1.
Sau đó chúng ta có thể sử dụng hàm ngắt nhận dữ liệu như sau để nhận dữ liệu.
/*ISR UART*/ void ISR_UART(void) interrupt 4 { if(RI == 1) //Kiem tra xem la ngat nhan hay truyen { chr_isr = SBUF; //nhan du lieu RI = 0; } }
Các bạn có thể tham khảo source code và mô phỏng Tại Đây.