Lập trình giao tiếp USART và RS232 với AVR
1. Giới thiệu chuẩn giao tiếp USART và RS232:
USART là một chuẩn truyền thông nối tiếp được tích hợp trong rất nhiều thiết bị, module, vi điều khiển, vi xử lý, cảm biến, các hệ thống tự động hóa... Chuẩn truyền thông USART sử dụng 2 mức logic theo chuẩn TTL tức thể hiện logic 0 (0V) và logic 1 (3-5V). Dữ liệu truyền đi có thể là đồng bộ hoặc không đồng bộ. Ở vi điều khiển chúng ta chỉ sử dụng cách truyền là không đồng bộ tức dữ liệu sẽ được đóng gói thành các khung truyền và có tốc độ truyền (BAUD - bps) được chuẩn hóa và phải giống nhau tốc độ baud. VD: 2400, 4800, 9600, 14400, 19200, 28800,... Tốc độ truyền bây giờ có thể lên đến vài trăm kbps. Thông thường ta thường sử dụng 9600 đề truyền nhằm giảm nhiễu.
RS232 cũng tương tự USART cũng có cùng một khung truyền nhưng khác ở thể hiện mức logic. Logic 0 được quy định là từ +3V đến +12V và logic 1 là từ -12V đến -3V, tín hiệu nằm trong vùng từ -3V đến +3V là vùng cấm không xác định mức logic. RS232 thường được tích hợp trong máy tính để bàn ta thường thấy chính là cổng COM 9 chân ở sau máy.
2. USART trên dòng vi điều khiển AVR:
Họ vi điều khiển AVR được tích hợp sẵn một bộ truyền thông nối tiếp, ta không cần quan tâm nó được chế tạo như thế nào mà chỉ cần biết chân TX và RX nó nằm ở PIN nào. TX là chân truyền dữ liệu đi và RX là chân nhận dữ liệu về. Khi ghép nôi chuẩn giao tiếp ta phải đấu nó theo kiểu bắt chéo tức TX của con này với RX của con kia và TX của con kia với RX của con này, kiểu TX1-RX2 và RX1-TX2.
Tìm hiểu cách ghép nối USART với RS232 tại đây: http://sangtaoclub.net/bai-viet/81-bai-8-lap-trinh-giao-tiep-uart-va-rs232.html
3. Lập trình giao tiếp USART trên vi điều khiển AVR. Các thanh ghi tham gia điều khiển:
* UDR - USART I/O Data Register là 2 thanh ghi dữ liệu cùng một tên truyền và nhận, khi ghi vào 1 byte thì nó sẽ truyền đi byte đó, và khi nhận được một byte thì ta sẽ đọc dữ liệu từ thanh ghi này
* UCSRA là thanh ghi trạng thái của USART:
Các bit trạng thái:
- RXC là bit cờ ngắt nhận dữ liệu từ RX
- TXC là bit cờ ngắt truyền đi một byte ra TX
- UDRE là bit cờ ngắt thanh ghi UDR trống và sẵn sàng ghi dữ liệu mới vào để truyền đi.
- FE là bit báo khung truyền bị lỗi
- DOR là bit báo tràn dữ liệu
- PE là bit báo Parity Error lỗi chẵn lẻ
- U2X là bit set nhân đôi tốc độ truyền
- MPCM là bit set chế độ truyền thông đa xử lý
Trong lập trình chúng ta có thể không cần khai báo thanh ghi này trong lập trình, trừ trong trường hợp muốn nhân đôi tốc độ truyền thì set bit U2X lên 1 là đủ vì các bit khác là bit chỉ đọc (trừ TXC, U2X, MPCM là bit R/W).
* UCSRB là thanh ghi mặt nạ ngắt và điều khiển:
Các bit trạng thái:
- RXCIE là bit set cho phép ngắt nhận
- TXCIE là bit set cho phép ngắt truyền
- UDRIE là bit set cho phép ngắt thanh ghi UDR trống
- RXEN là bit cho phép nhận dữ liệu trên chân RX
- TXEN là bit cho phép truyền dữ liệu trên chân TX
- UCSZ2 là bit chọn kích thước ký tự, kết hợp với 2 bit trong thanh ghi UCSRC
- RXB8 là bit truyền dữ liệu thứ 8 trong chế độ truyền 9bit
- TXB8 là bit nhận dữ liệu thứ 8 trong chế độ truyền 9bit
Trong truyền dữ liệu không đồng bộ ta thường sử dụng ngắt để nhận dữ liệu do vậy ta chỉ cần set các bít sau lên 1: RXCIE=1, RXEN=1, TXEN=1 ta viết ngắn gọn UCSRB=0x98; tương đương UCSRB=0b 1001 1000
* UCSRC là thanh ghi quy định khung truyền và chế độ truyền:
Tuy nhiên, có một rắc rối nho nhỏ là thanh ghi này lại có cùng địa chỉ với thanh ghi UBRRH (thanh ghi chứa byte cao dùng để xác lập tốc độ baud), nói một cách khác 2 thanh ghi này là 1. Vì thế bit 7 trong thanh ghi này, tức bit URSEL là bit chọn thanh ghi. Khi URSEL=1, thanh ghi này được chip AVR hiểu là thanh ghi điều khiển UCSRC, nhưng nếu bit URSEL=0 thì thanh ghi UBRRH sẽ được sử dụng.
- Bit UMSEL là bit chọn chế độ truyền thông đồng bộ hay không đồng bộ. Khi UMSEL=1 là chế độ đồng bộ và UMSEL=0 là chế độ không đồng bộ, trong ứng dụng này ta đặt UMSEL=0 tức chế độ không đồng bộ.
- Hai bit UPM1 và UPM0 là 2 bit chọn kiểu Parity (chẵn lẻ) ta có bảng sau:
UPM1 |
UPM0 |
Chức năng |
0 |
0 |
Không sử dụng Parity |
0 |
1 |
Dự trữ không dùng |
1 |
0 |
Parity chẵn được chọn |
1 |
1 |
Parity lẻ được chọn |
- Bit USBS là bit chọn sử dụng một hay 2 bit Stop. Nếu USBS=1 thì là 2 bit Stop và khi USBS=0 là 1 bit Stop
- Hai bit UCSZ1 và UCSZ0 kết hợp với bit UCSZ2 từ thanh ghi UCSRB ta được 3bit chọn độ dài dữ liệu truyền:
UCSZ2 |
UCSZ1 |
UCSZ0 |
Kích thước truyền |
0 |
0 |
0 |
5 bit |
0 |
0 |
1 |
6 bit |
0 |
1 |
0 |
7 bit |
0 |
1 |
1 |
8 bit |
1 |
0 |
0 |
Dự trữ |
1 |
0 |
1 |
Dự trữ |
1 |
1 |
0 |
Dự trữ |
1 |
1 |
1 |
9 bit |
- Bit UCPOL là bit chỉ tích cực của xung clock trong chế độ truyền đồng bộ. Nếu bạn sử dụng chế độ không đồng bộ thì để bit này bằng 0.
Kết luận lại ta sẽ cần có các bit sau được set (cho chế độ truyền không đồng bộ): URSEL=1, UCSZ1=1, UCSZ0=1 ta được UCSRC=0x86 tương đương UCSRC=0b 1000 0110 (8bit USART, 1 stop, no parity)
* Phần cuối cùng là thiết lập tốc độ truyền BAUD được quy định bởi 2 thanh ghi UBRRH và UBRRL. Do dữ liệu cài đặt lớn hơn 255 lên nó được mở rộng thêm 4bit trên thanh ghi UBRRH
Ta sẽ có các bit từ UBRR[11:0] để cài đặt tốc độ BAUD theo bảng sau, ở đây ta sử dụng thạch anh 11.0592MHz để tạo tốc độ BAUD với sai số 0%
UBRRH |
UBRRL |
Tốc độ BAUD |
Bit U2X (UCSRA) |
0x01 |
0x1F |
2400 |
0 |
0 |
143 |
4800 |
0 |
0 |
71 |
9600 |
0 |
0 |
47 |
14400 |
0 |
0 |
35 |
19200 |
0 |
0 |
23 |
28800 |
0 |
0 |
17 |
38400 |
0 |
Như bảng trên ta để UBRRH mặc định không cần khai báo, còn UBRRL sẽ bằng các giá trị trên tương ứng với tốc độ BAUD đó. Trừ BAUD = 2400 phải nạp 2 giá trị trên vào 2 thanh ghi UBRRH và UBRRL
Code này có tác dụng nhận dữ liệu nhập từ máy tính gửi xuống hiển thị lên LCD16x2. Để truyền được dữ liệu lên máy tính ta cần cấu hình như sau:
UCSRB=0x98;//Ngắt RX, cho phép RX va TX
UCSRC=0x86;//8bit uart, 1bit stop, no parity
UBRRL=71;//baud 9600bps
Xây dựng hàm gửi dữ liệu: send(“nội dung”); và xoa_buf(); để xóa bộ đệm
-----------------------------------CODE---------------------------------------
#include
#include <delay.h>
#include <alcd.h>
#include <string.h>
unsigned char y=0, u_data, ktra=0, buf[32];
/***Chuong trinh gui du lieu qua TX***/
void send1(unsigned char udata){//Ham gui 1 ky tu ASCII
while(!(UCSRA & (1<
UDR=udata;//Send 1 byte
}
void send(unsigned char *u){//Ham gui mot chuoi ky tu
unsigned char n,i;
n=strlen(u); //Dem so ky tu
for(i=0;i
}
void xoa_buf(){//Ham xoa bo dem
unsigned char u;
for(u=0;u<32;u++) buf[u]=0;
}
/***Ham ngat xu ly nhan du lieu qua RX***/
interrupt [USART_RXC] void rx_isr(){
u_data=UDR; //Lay du lieu ASCII
if((u_data==0x57 || u_data==0x77) && ktra==0){//Phim W hoac phim w
lcd_clear();//Xoa LCD
lcd_gotoxy(0,0);
xoa_buf(); //Xoa buffer
lcd_puts("Dang nhap...");
send(" Moi nhap noi dung hien thi: Toi da 32 ky tu - Enter de hien thi Text> ");
ktra=1;
}else if(u_data==13 && ktra==1){//Phim Enter
send(" Send to LCD...");
lcd_clear();
lcd_gotoxy(0,0);
lcd_puts(buf);//Gui len LCD
send(" Nhan phim W de nhap moi... ");
ktra=0; y=0;
}else if(u_data==8 && ktra==1){ //Nut xoa BackSpace
if(y>0)y--; else send(" Text> ");
buf[y]=0;
}else if(ktra==1){
//Kiem tra ky tu nhap va luu vao buffer
if(u_data>31 && y<31) buf[y++]=u_data;
}//end if
}
/*****************Chuong trinh chinh************/
void main(){
UCSRB=0x98;//Ngat RX, cho phep RX va TX
UCSRC=0x86;//8bit uart, 1bit stop, no parity
UBRRL=71;//baud 9600bps
lcd_init(16); //LCD16x2 init
lcd_puts("TEST USART AVR!");//Gui chuoi len LCD
delay_ms(500);//Tre 0.5s
lcd_gotoxy(0,1);//Dong 2
lcd_puts("SangTaoClub.Net");
delay_ms(1000);
send("Nhan phim W de nhap noi dung! ");
#asm("sei") //Ngat cuc bo
while(1); //Khong lam gi ca
}//THE END
-----------------------------------PROTEUS---------------------------------------
Code và mô phỏng tải về trong phần đính kèm cuối bài viết..!
Chúc các bạn học tốt :)
Tải về đính kèm: