Hướng dẫn sử dụng kit 89

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 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 Bài 13 : Giao tiếp PS2 với bàn phím 74 13.1 Nguyên lý giao tiếp PS2 74 13.2 Kết nối phần cứng . 75 13.3 Viết chương trình 76 Bài 14 : PWM điều khiển motor . 77 14.1 Khái niệm PWM 77 14.2 Lập trình PWM trên 89V51 78 Bài 15 : Giao tiếp LCD character . 79 15.1 Chức năng các chân của LCD . 79 15.2 Kết nối màn hình LCD 80 15.3 Các vùng nhớ của LCD . 80 15.3.1 Display Data Ram (DDRAM) 80 15.3.2 Character Generator Ram (CGRAM) 80 15.3.3 Bộ nhớ CGROM 81 15.4 Các lệnh cơ bản của LCD 82 15.5 Kết nối LCD với vi điều khiển 83 15.6 Khởi tạo LCD 84 15.7 Kết nối phần cứng . 86 15.8 Viết chương trình 87 15.8.1 Các hàm cơ bản 87 15.8.2 Khởi tạo LCD chế độ 4 bit . 87 15.8.3 Xoá màn hình . 88 15.8.4 Thiết lập vị trí con trỏ . 88 15.8.5 In kí tự ra màn hình . 89 Bài 16 : Giao tiếp I2C – DS1307 90 16.1 Các đặc điểm của DS1307 90 16.2 Nguyên lý hoạt động . 90 16.3 Các tín hiệu Input và Output . 91 16.4 RTC và sơ đồ địa chỉ Ram 92 16.5 Thông tin thời gian và lịch 92 16.6 Thanh ghi điều khiển (Control Register) . 93 16.7 Bus dữ liệu nối tiếp. 93 16.8 Giao thức I2C và RTC DS1307 . 94 16.8.1 Start và Stop truyền dữ liệu 94 16.8.2 Truyền 1 byte dữ liệu . 96 16.8.3 Giao tiếp với DS1307 . 97

pdf99 trang | Chia sẻ: tlsuongmuoi | Lượt xem: 2449 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Hướng dẫn sử dụng kit 89, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
.bkit4u.com 54 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) Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 55 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 56 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ị. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 57 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: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 58 while(1) { alphabet_index = (alphabet_index + 8) % 216; update_display_led_matrix(); delay_ms(1000); } Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 59 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ý chy chA 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 60 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 #include 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) Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 61 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 62 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 ng2t 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 63 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--; } Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 64 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 65 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 66 Để 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 67 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 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. goes out last goes out first Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 68 12.2 Giao ti"p UART vHi 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 69 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 SCON.7 SM0/FE 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à 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) Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 70 SCON.6 SM1 Cùng với SM0, xác định chế độ làm việc của cổng nối tiếp SM0, SM1 Chế độ UART UART 0 Baud Rate 0 0 0: thanh ghi dịch CCLK/16 (chế độ mặc định sau khi RESET) 0 1 1: UART 8-bit Thay đổi 1 0 2: UART 9-bit CCLK/32 hoặc CCLK/16 1 1 3: UART 9-bit Thay đổi SCON.5 SM2 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) là ‘0’. Ở Mode 0, SM2 nên bằng ‘0’, ở mode 1, SM2 phải bằng ‘0’. SCON.4 REN Cho phép thu ở cổng nối tiếp. Thiết lập bởi phần mềm để cho 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. SCON.3 TB8 Bit dữ liệu thứ 9 được phát ở mode 2 và 3, lập/xóa bởi phần mềm khi muốn. SCON.2 RB8 Bit dữ liệu thứ 9 được nhận ở mode 2 và 3. Ở mode 1(SM2=0), RB8 là bit dừng được nhận, ở mode 0, RB8 không được định nghĩa. SCON.1 TI 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 xóa bằng phần mềm. (Xem thêm bit INTL0 ở thanh ghi SSTAT) SCON.0 RI 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, 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) RxD(P3.0) CLOCK Shift register Data Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 71 • 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 InitTimer1ForUart() sẽ thiết lập Timer1 tạo tốc độ baud cho truyền nối tiếp void InitTimer1ForUart() { TMOD |= 0x20; // Timer 1 mode 2-autoreload TL1 = 0; /* if PCON.7 = 0, TH1 = 256 - ((Crystal / 384) / Baud) */ PCON &= ~(1 << 7); //TH1 = (-48); // baudrate 600 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 72 //TH1 = (-24); // baudrate 1200 //TH1 = (-12); // baudrate 2400 //TH1 = (-6); // baudrate 4800 TH1 = (-3); // baudrate 9600 /* if PCON.7 = 1, baud is double, TH1 = 256 - ((Crystal / 192) / Baud) */ //PCON |= (1 << 7); //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 TR1 = 1; //timer1 run } 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,REN = 1 EA = 1; //enable interrupt } 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) { trans_busy = 1; SBUF = c; while(trans_busy); } Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 73 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 74 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: P3.4kb_Data kb_Clock R3 22K R4 22K VCC P3.3VCC J3 PS/2 CIR 7-R 1 2 3 4 5 6 7 kb_Vcc VCC kb_Ground kb_Shield 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: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 75 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 76 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 77 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 niLm 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 : Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 78 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). Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 79 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 cQa 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 Control Operation 4 RS 0 D0-D7 là command 1 D0-D7 là Data 5 R/W 0 Write 1 Read 6 E 0 Disable 1 Normal Từ 1 xuống 0 Truyền Data hoặc Command xuống LCD Data/Command 7 D0 0|1 Bit 0 LSB 8 D1 0|1 Bit 1 9 D2 0|1 Bit 2 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 80 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 nhH cQa 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). Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 81 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: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 82 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 lLnh c$ b%n cQa 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: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 83 Lệnh RS RW D7 D6 D5 D4 D3 D2 D1 D0 Thời gian 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 control 0 0 0 0 0 0 1 D C B 37µs Cursor/Display shift 0 0 0 0 0 1 S/ C R/ L * * 37µs Function set 0 0 0 0 1 DL N F * * 37µs Set CGRAM address 0 0 0 1 CGRAM address 37µs Set DDRAM address 0 0 1 DDRAM address 37µs Read BUSY flag (BF) 0 1 BF DDRAM address 0µs Write to DDRAM or CGRAM 1 0 D7 D6 D5 D4 D3 D2 D1 D0 43µs Read from DDRAM or CGRAM 1 1 D7 D6 D5 D4 D3 D2 D1 D0 43µs 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 vHi 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 84 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 KhTi to LCD Quá trình khởi tạo LCD ở chế độ 8 bit như sau: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 85 Quá trình khởi tạo ở chế độ 4 bit như sau: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 86 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 87 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 88 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); Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 89 } 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 90 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 cQa 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ý hot đ*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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 91 16.3 Các tín hiLu 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, Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 92 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$ đW đXa chY 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à lXch 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). Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 93 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 dA liLu 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. Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 94 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: Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 95 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; } Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 96 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; Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 97 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)); Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 98 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 Hướng dẫn sử dụng Kit 89 BKIT HARDWARE CLUB – www.bkit4u.com 99 *(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 } }

Các file đính kèm theo tài liệu này:

  • pdfHướng dẫn sử dụng kit 89.pdf
Tài liệu liên quan