Mục lục MỞ ĐẦU 1 CHƯƠNG 1: CƠ SỞ LÝ THUYẾT 3 1.1.Cách tính thời gian theo lịch dương và lịch âm. 3 1.1.1.Cách tính thời gian dương lịch. 3 1.1.2.Cách tính thời gian âm lịch. 4 1.1.3.Năm nhuận. 4 1.1.4.Tháng nhuận. 5 1.1.5.Cách tính âm lịch, dương lịch trong đồng hồ. 5 1.2.IC cảm biến nhiệt độ DS18B20. 6 1.3.IC thời gian DS1307. 7 1.4.Vi điều khiển PIC 16F877A. 8 1.4.1. PIC là gì? 8 1.4.2. Các dòng PIC và cách lựa chọn vi điều khiển PIC 8 1.4.3.Cấu trúc vi điều khiển PIC16F877A 9 1.4.4. Tổ chức bộ nhớ. 14 1.5. LED 7 thanh. 18 CHƯƠNG 2: THIẾT KẾ VÀ CHẾ TẠO MẠCH 21 2.1.Sơ đồ khối. 21 2.1.1. Sơ đồ. 21 2.1.2.Phân tích chức năng các khối. 21 2.2. Sơ đồ toàn mạch. 22 2.2. Sơ đồ chi tiết các khối. 24 2.4.Lưu đồ thuật toán. 28 2.5.Chương trình điều khiển. 32 2.5.Mô hình sản phẩm. 53 CHƯƠNG 3: KẾT LUẬN 54 PHỤ LỤC 55
Mục lục Danh mục hình vẽ MỞ ĐẦU Lý chọn đề tài • Ngày khoa học cơng nghệ đại có bước tiến nhanh xa theo thành tựu ứng dụng lĩnh vực đời sống, công nghiệp Kỹ thuật điều khiển tiến trình hồn thiện lý thuyết tạo cho nhiều phát triển có ý nghĩa Bây nhắc tới điều khiển người dường hình dung tới độ xác, tốc độ xử lý thuật tốn thơng minh đồng nghĩa lượng chất xám cao Hiện thị trường có nhiều loại vi điều khiển 8051, Motorola 68HC, AVR, ARM, Ngoài họ 8051 hướng dẫn cách môi trường đại học, chúng em chọn vi điều khiển PIC để mở rộng vốn kiến thức phát triển ứng dụng công cụ nguyên nhân sau: Họ vi điều khiển tìm mua dễ dàng thị trường Việt Nam Có đầy đủ tính vi điều khiển hoạt động độc lập Là bổ sung tốt kiến thức ứng dụng cho họ vi điều khiển mang • tính truyền thống: họ vi điều khiển 8051 Giá thành không đắt Sự hỗ trợ nhà sản xuất trình biên dịch, cơng cụ lập trình, nạp chương • trình từ đơn giản tới phức tạp Các tính đa dạng vi điều khiển PIC tính khơng ngừng • phát triển Số lượng người sử dụng họ vi điều khiển PIC giới Việt Nam nhiều.Đã tạo thuận lợi trình tìm hiểu phát triển ứng dụng như: số lượng tài liệu, số lượng ứng dụng mở phát triển, dễ dàng trao đổi, học tập, dễ dàng tìm hỗ trợ gặp khó khăn Vì vậy, sau thời gian học tập tìm hiểu tài liệu với giảng dạy thầy cô giáo Cùng với dẫn dắt nhiệt tình giáo viên hướng dẫn thầy giáo Nguyễn Văn Vĩnh Chúng em chọn đề tài: “Thiết Kế Và Chế Tạo Lịch Vạn Niên” làm đồ án Đối tượng nghiên cứu • Với đề tài chúng em tập trung vào: Tìm hiểu vi điều khiển PIC 16F877A • Nghiên cứu IC thời gian thực DS1307 • • Nghiên cứu cảm biếm nhiệt độ DS18B20 Mục đích nghiên cứu • Khi nghiên cứu đồ án chúng em đã: Hiểu cách thức chế độ hoạt động VĐK PIC 16F877A • Hiểu cách thức hoạt động DS1307 • Thiết kế, chế tạo mạch hiển thị thứ ,ngày ,tháng , năm dùng PIC 16F877A Phương pháp nghiên cứu Do đồ án sản phẩm, nên chúng em áp dụng phương pháp nghiên cứu lý thuyết, nghiên cứu thực nghiệm trực tiếp sản phẩm thật, chạy thử hồn thiện chương trình Ý nghĩa nghiên cứu • Như nói thực thành công đề tài mang lại ý nghĩa thực tiễn lý luận Ý nghĩa lý luận: • Tồn chương trình thuyết minh đề tài trở thành tài liệu, tham khảo nhanh, dễ hiểu, thiết thực cho bạn sinh viên, người thích tìm hiểu đề tài chúng em Ý nghĩa thực tiễn: Với thành cơng đề tài góp phần giúp cho bạn sinh viên nói chung bạn sinh viên khoa Điện Điện Tử nói riêng thấy rõ ý nghĩa thực tế thêm yêu thích chuyên ngành chọn Do kiến thức trình độ lực hạn hẹp nên việc thực đề tài khơng thể tránh thiếu sót, kính mong nhận thơng cảm góp ý thầy giáo, giáo bạn để đồ án hoàn chỉnh Chúng em xin trân thành cảm ơn! Sinh viên thực hiện: Nguyễn Thị Thu Thảo CHƯƠNG 1: CƠ SỞ LÝ THUYẾT 1.1 Cách tính thời gian theo lịch dương lịch âm Hình 1.1: Hệ Mặt Trời 1.1.1 Cách tính thời gian dương lịch Trái đất quay quanh Mặt trời 365+ 1/4 ngày (hay giờ) Nhưng theo quy ước năm có 365 ngày, nên năm dương lịch lệch với thời gian thực 1/4 ngày Điều có nghĩa sau năm dương lịch dư ngày, vậy, năm có năm 366 ngày, gọi năm nhuận Năm nhuận theo quy ước rơi vào tháng hai (tức tháng có 29 ngày) Độ dài trung bình năm dương lịch (còn gọi Tân lịch hay lịch Gregorius) 365.2425 365.25 (365 1/4), độ dài 365 1/4 độ dài Cựu lịch (lịch Julius), lịch không sử dụng giới từ năm 1582 Giáo hoàng Gregorius XIII ban hành sắc lệch cải cách lịch Dương lịch người La Mã cổ đại Trái Đất quay xung quanh Mặt trời năm họ có 304 ngày (được chia thành 10 tháng 12 tháng) 1.1.2 Cách tính thời gian âm lịch Chu kỳ Mặt trăng quay quanh Trái đất vòng hết 29,5 ngày Âm lịch loại lịch dựa chu kỳ tuần trăng Loại lịch thực tế túy sử dụng âm lịch lịch Hồi Giáo, năm chứa 12 tháng Mặt Trăng Đặc trưng âm lịch túy, trường hợp lịch Hồi Giáo, chỗ lịch chu kỳ trăng tròn hồn tồn khơng gắn liền với mùa Vì năm âm lịch Hồi Giáo ngắn năm dương lịch khoảng 11 hay 12 ngày, trở lại vị trí ăn khớp với năm dương lịch sau 33 34 năm Hồi Giáo Do âm lịch túy có 12 tháng âm lịch ( tháng giao hội ) năm, nên chu kỳ (354 ngày) gọi năm âm lịch 1.1.3 Năm nhuận Tính năm nhuận theo Dương lịch Muốn biết năm Dương lịch năm nhuận ta cần lấy số biểu năm đem chia cho mà vừa đủ năm năm Dương lịch có nhuận tháng thêm ngày thành 29 ngày Vì thơng thường tháng Dương lịch có 28 ngày mà thơi Nhưng lưu ý năm tròn Thế Kỷ ( tức số biểu năm có số khơng cuối ta phải lấy số đầu số biểu để chia cho Nếu chia vừa đủ năm năm Nhuận Tính năm nhuận theo Âm lịch Đối với năm Nhuận Âm lịch có tháng nhuận Tháng âm lịch phải lấy ngày Nhật Nguyệt hợp sóc làm đầu ( tức ngày Mặt Trời, Mặt Trăng, Trái Đất trục đường thẳng) Hai lần hợp sóc cách 29,5 ngày Cho nên tháng Âm lịch đủ 30 ngày tháng thiếu 29 ngày Vì cách tính vậy, nên Âm lich bắt đầu vào ngày “ sóc” kề với “ tiết” Lập xuân Sai số năm thực 11 ngày năm Dồn năm lại dơi 33 ngày Cho nên qua năm phải nhuận tháng, dồn năm 25 ngày gần nhuận tháng Tính bình qn 19 năm có tháng nhuận Trong tháng bình thường có ngày “tiết” ngày “khí” Số ngày tiết ngày khí bình qn 30,4 ngày Do ngày tháng Âm lịch có 29,5 ngày Cho nên sau 2,3 năm có tháng có ngày tiết mà khơng có ngày khí dùng tháng làm tháng Nhuận Âm lịch Nói vào tính cụ thể tháng năm nhuận âm lịch tháng nhuận phức tạp mà ta phải hiểu lịch pháp tính khơng tính dễ dàng tháng nhuận năm Dương lịch Nhưng tính năm âm lịch có nhuận khơng khó Cụ thể tính sau: Đếm số biểu năm Dương lịch tương ứng với năm âm lịch chia cho 19, số dư số : 0, 3, 6, 11, 14, 17 năm âm lịch có tháng nhuận 1.1.4 Tháng nhuận Dương lịch năm thêm ngày thứ 29 tháng Âm lịch năm thêm tháng 1.1.5 Cách tính âm lịch, dương lịch đồng hồ Cách tính âm lịch theo phương pháp tra bảng: Tính ngày âm lịch Nếu ( ngày Dương lịch tương ứng với ngày đầu tháng Âm lịch) ( ngày tại) ngày Âm lịch ( ngày Dương lịch tương ứng với ngày đầu tháng Âm lịch ) trừ ( ngày ) Nếu khơng có nhớ ngày âm lịch ngày Dương lịch cộng ngày Âm lịch đầu tháng Dương lịch trừ Nếu có nhớ ngày âm lich ngày Dương lịch trừ ngày Âm lịch đầu tháng Dương lịch cộng1 Tính tháng âm lịch Bằng cách lấy ngày Dương lịch tương ứng với đầu tháng âm lịch tháng trừ ngày Nếu khơng có nhớ tháng Âm lịch = tháng Âm lịch đầu tháng Dương lịch Nếu có nhớ tháng Âm lịch = tháng Âm lịch ngày đầu tháng Âm lịch Tính năm âm lịch Bằng cách lấy tháng Dương lịch trừ cho tháng Âm lịch Nếu nhớ năm Âm lịch = năm Dương lịch Nếu có nhớ năm Âm lịch = năm Dương lịch -1 1.2 IC cảm biến nhiệt độ DS18B20 DS18B20 linh kiện điện tử thuộc loại cảm biến nhiệt độ kỹ thuật số giao tiếp 1-Wire (1 dây nhất), bên IC tích hợp sẵn cảm biến nhiệt chuyển đổi, khối xử lý, giao tiếp wire, nhớ ROM, EEPROM, báo thức nhiệt độ đạt ngưỡng IC cảm biến nhiệt độ, bao gồm chân, đóng gói dạng TO-92 hay dạng SMD chân Hình 1.2 Cảm biến nhiệt độ DS18B20 Đặc điểm bật: Thời gian chuyển đổi nhiệt độ tối đa 750ms cho độ phân giải 12 bit • • • 1.3 Lấy nhiệt độ theo giao thức dây Cung cấp nhiệt độ với độ phân giải config 9, 10, 11, 12 bit, tùy theo sử dụng trường hợp khơng có config tự động chế độ 12 bit 0 • khoảng nhiệt độ từ -10 C đến +85 C độ xác ±0.5°C Điện áp sử dụng: 3- 5.5V IC thời gian DS1307 DS1307 chip đồng hồ thời gian thực (RTC : Real-time clock), khái niệm thời gian thực dùng với ý nghĩa thời gian tuyệt đối mà người sử dụng, tình giây, phút, giờ…DS1307 sản phẩm Dallas Semiconductor (một công ty thuộc Maxim Integrated Products) Chip có ghi 8-bit chứa thời gian là: giây, phút, giờ, thứ (trong tuần), ngày, tháng, năm Ngoài DS1307 có ghi điều khiển đầu phụ 56 ghi trống dùng RAM DS1307 đọc ghi thông qua giao diện nối tiếp I2C (TWI AVR) nên cấu tạo bên ngồi đơn giản DS1307 xuất gói SOIC DIP có chân hình 1.3: Hình 1.3 Hai gói cấu tạo chip DS1307 - - - Các chân DS1307 cấu tạo sau: X1 X2: đầu kết nối với thạch anh 32.768KHz làm nguồn tạo dao động cho chip VBAT: cực dương nguồn pin 3V nuôi chip GND: chân mass chung cho pin 3V Vcc Vcc: nguồn cho giao diện I2C, thường 5V dùng chung với vi điều khiển Chú ý Vcc không cấp nguồn V BAT cấp DS1307 hoạt động ( khơng ghi đọc được) SQW/ OUT: đầu tạo xung vuông ( Square Wave/ Output Driver), tần số xung tạo lập trình Như chân không liên quan đến chức DS1307 đồng hồ thời gian thực, bỏ trống chân nối mạch SCL SDA đường giao xung nhịp liệu giao diện I2C mà tìm hiểu TWI AVR Hình 1.3: Sơ đồ kết nối DS1307 mạch điện đơn giản 1.4 • - • - Vi điều khiển PIC 16F877A 1.4.1 PIC gì? PIC viết tắt “Programable Intellingent Computer”, tạm dịch “máy tính thơng minh khả trình” hãng Genenral Instrument đặt tên cho vi điều khiển họ Hãng Micrchip tiếp tục phát triển sản phẩm hãng tạo gần 100 loại sản phẩm khác 1.4.2 Các dòng PIC cách lựa chọn vi điều khiển PIC Các kí hiệu vi điều khiển PIC: PIC12xxxx: độ dài lệnh 12 bit PIC16xxxx: độ dài lệnh 14 bit PIC18xxxx: độ dài lệnh 16 bit C: PIC có nhớ EPROM (chỉ có 16C84 EEPROM) F: PIC có nhớ flash LF: PIC có nhớ flash hoạt động điện áp thấp LV: tương tự LF, kí hiệu cũ Bên cạnh số vi điệu khiển có kí hiệu xxFxxx EEPROM, có thêm chữ A cuối flash (ví dụ PIC16F877 EEPROM, PIC16F877A flash) Ngồi có thêm dòng vi điều khiển PIC dsPIC Ở Việt Nam phổ biến họ vi điều khiển PIC hãng Microchip sản xuất Cách lựa chọn vi điều khiển PIC phù hợp: Trước hết cần ý đến số chân vi điều khiển cần thiết cho ứng dụng Có nhiềuvi điều khiển PIC với số lượng chân khác nhau, chí có vi điều khiển - - - - có chân, ngồi có vi điều khiển 28, 40, 44, … chân Cần chọn vi điều khiển PIC có nhớ flash để nạp xóa chương trình nhiều lần Tiếp theo cần ý đến khối chức tích hợp sẵn vi điều khiển,các chuẩn giao tiếp bên Sau cần ý đến nhớ chương trình mà vi điều khiển cho phép Ngồi thơng tin cách lựa chọn vi điều khiển PIC tìm thấy sách “Select PIC guide” nhà sản xuất Microchip cung cấp Do thời gian làm đồ án có hạn nên chúng em tập trung tìm hiểu tính PIC 16F877A có liên quan đến đề tài 1.4.3.Cấu trúc vi điều khiển PIC16F877A PIC 16F877A dòng PIC phổ biến, đầy đủ tính phục vụ cho hầu hết tất ứng dụng thực tế Đây dòng PIC dễ cho người làm quen với PIC học tập tạo tảng họ vi điều khiển PIC PIC 16F877A thuộc họ vi điều khiển 16Fxxx có đặc tính ngoại vi sau: Ngơn ngữ lập trình đơn giản với 35 lệnh có độ dài 14 bit Tất câu lệnh thực chu kì lệnh ngoại trừ số câu lệnh rẽ nhánh thực hai chu kì lệnh Chu kì lệnh lần chu kì dao động thạch anh Bộ nhớ chương trình Flash 8Kx14 words, với khả ghi xóa khoảng 100 ngàn lần Bộ nhớ chương trình 8Kx14 bit, nhớ liệu 368x8byte RAM nhớ liệu EEPROM với dung lượng 256x8 byte Số PORT I/O với 33pin I/O Khả ngắt (lên tới 14 nguồn ngắt ngắt ngoài) Ngăn nhớ Stack chia làm mức Truy cập nhớ địa trực tiếp gián tiếp Dải điện hoạt động rộng: 2.0V đến 5.5V Nguồn sử dụng 25mA Công suất tiêu thụ thấp:5&&l27)x1=0; } void scankey() { s1=s2;s2=ra0; if(!s2&&s1){ setup++; if(setup>6){ds1307_set_date_time(day,mon,yr,thu,h,min,0);setup=0;} } cc++; if(cc>100){cc=0; if(ra1==0){ if(setup==1){h++;if(h>23)h=0;} if(setup==2){min++;if(min>59)min=0;} if(setup==3){day++;if(day>31)day=0;} if(setup==4){mon++;if(mon>12)mon=0;} if(setup==5){yr++;if(yr>99)yr=0;} if(setup==6){thu++;if(thu>8)thu=2;} } if(ra2==0){ if(setup==1){h ;if(h>254)h=23;} if(setup==2){min ;if(min>254)min=59;} if(setup==3){day ;if(day>254)day=31;} if(setup==4){mon ;if(mon>254)mon=12;} if(setup==5){yr ;if(yr>254)yr=99;} if(setup==6){thu ;if(thu160){count=0;} scankey(); 41 hien_thi(); } void main() {SET_TRIS_A(0xff); SET_TRIS_B(0); ds1307_init(0); setup_timer_0(RTCC_INTERNAL|RTCC_DIV_256);//64 set_timer0(228); enable_interrupts(INT_TIMER0); enable_interrupts(GLOBAL); while(TRUE) { if(setup==0){ ds1307_get_time(h,min,s); ds1307_get_date(day,mon,yr,thu);} lunar_calculate(day,mon,yr); value=ds1820_read(); if(value>5){ temp=(char)value-4;} delay_ms(500); } } DS1307.C /// Driver for Real Time Clock /// /// /// /// /// ds1307_init() - Enable oscillator without clearing the seconds register -/// /// used when PIC loses power and DS1307 run from 3V BAT /// /// - Disable squarewave output /// /// /// /// ds1307_set_date_time(day,mth,year,dow,hour,min,sec) Set the date/time /// /// /// /// ds1307_get_date(day,mth,year,dow) Get the date /// /// /// /// ds1307_get_time(hr,min,sec) Get the time /// 42 /// /// //////////////////////////////////////////////////////////////////////////////// #define RTC_SDA PIN_C4 #define RTC_SCL PIN_C3 #use i2c(master, sda=RTC_SDA, scl=RTC_SCL) BYTE bin2bcd(BYTE binary_value); BYTE bcd2bin(BYTE bcd_value); void ds1307_init(char rs) { rs&=3; rs|=0x10; rs|=0x80; BYTE seconds = 0; i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x00); // REG i2c_start(); i2c_write(0xD1); // RD from RTC seconds = bcd2bin(i2c_read(0)); // Read current "seconds" in DS1307 i2c_stop(); seconds &= 0x7F; delay_us(3); i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x00); // REG i2c_write(bin2bcd(seconds)); // Start oscillator with current "seconds value i2c_start(); i2c_write(0xD0); // WR to RTC i2c_write(0x07); // Control Register i2c_write(rs); // Disable squarewave output pin i2c_stop(); } 43 void ds1307_set_date_time(BYTE day, BYTE mth, BYTE year, BYTE dow, BYTE hr, BYTE min, BYTE sec) { char rs=0; rs&=3; rs|=0x10; rs|=0x80; sec &= 0x7F; hr &= 0x3F; i2c_start(); i2c_write(0xD0); // I2C write address i2c_write(0x00); // Start at REG - Seconds i2c_write(bin2bcd(sec)); // REG i2c_write(bin2bcd(min)); // REG i2c_write(bin2bcd(hr)); // REG i2c_write(bin2bcd(dow)); // REG i2c_write(bin2bcd(day)); // REG i2c_write(bin2bcd(mth)); // REG i2c_write(bin2bcd(year)); // REG i2c_write(rs); // REG - Disable squarewave output pin i2c_stop(); } void ds1307_get_date(BYTE &day, BYTE &mth, BYTE &year, BYTE &dow) { i2c_start(); i2c_write(0xD0); i2c_write(0x03); // Start at REG - Day of week i2c_start(); i2c_write(0xD1); dow = bcd2bin(i2c_read() & 0x7f); // REG day = bcd2bin(i2c_read() & 0x3f); // REG mth = bcd2bin(i2c_read() & 0x1f); // REG year = bcd2bin(i2c_read(0)); // REG 44 i2c_stop(); } void ds1307_get_time(BYTE &hr, BYTE &min, BYTE &sec) { i2c_start(); i2c_write(0xD0); i2c_write(0x00); // Start at REG - Seconds i2c_start(); i2c_write(0xD1); sec = bcd2bin(i2c_read() & 0x7f); = bcd2bin(i2c_read() & 0x7f); hr = bcd2bin(i2c_read(0) & 0x3f); i2c_stop(); } BYTE bin2bcd(BYTE binary_value) { BYTE temp; BYTE retval; temp = binary_value; retval = 0; while(TRUE) { // Get the tens digit by doing multiple subtraction // of 10 from the binary value if(temp >= 10) { temp -= 10; retval += 0x10; } else // Get the ones digit by adding the remainder { retval += temp; break; } } 45 return(retval); } // Input range - 00 to 99 BYTE bcd2bin(BYTE bcd_value) { BYTE temp; temp = bcd_value; // Shifting upper digit right by is same as multiplying by temp >>= 1; // Isolate the bits for the upper digit temp &= 0x78; // Now return: (Tens * 8) + (Tens * 2) + Ones return(temp + (temp >> 2) + (bcd_value & 0x0f)); } float ds1820_read() { int8 busy=0, temp1, temp2; signed int16 temp3; float result; onewire_reset(); onewire_write(0xCC); onewire_write(0x44); while (busy == 0) busy = onewire_read(); onewire_reset(); onewire_write(0xCC); onewire_write(0xBE); temp1 = onewire_read(); temp2 = onewire_read(); temp3 = make16(temp2, temp1); 46 //result = (float) temp3 / 2.0; //Calculation for DS18S20 with 0.5 deg C resolution result = (float) temp3 / 16.0; //Calculation for DS18B20 with 0.1 deg C resolution // delay_ms(200); return(result); } /* -1-wire definitions -*/ #define ONE_WIRE_PIN PIN_C0 /*******************1-wire communication functions********************/ / ************onewire_reset**************************************** *********/ /*This function initiates the 1wire bus */ /* */ /*PARAMETERS: */ /*RETURNS: */ / *************************************************************** ******/ void onewire_reset() // OK if just using a single permanently connected device { output_low(ONE_WIRE_PIN); delay_us( 400 ); // pull 1-wire low for reset pulse output_float(ONE_WIRE_PIN); // float 1-wire high delay_us( 400 ); // wait-out remaining initialisation window output_float(ONE_WIRE_PIN); } /*********************** onewire_write() ********************************/ 47 /*This function writes a byte to the sensor.*/ /* */ /*Parameters: byte - the byte to be written to the 1-wire */ /*Returns: */ / *************************************************************** ******/ void onewire_write(int data) { int count; for (count=0; count