Bài tập lớn môn Vi xử lý - Đề tài 3: Mạch đồng hồ giờ, phút, giây dùng 8051 và LED 7 đoạn, cho phép cài đặt thời gian dùng nút nhấn - Ngô Tiến Đạt
CHƯƠNG III
THIẾT KẾ PHẦN CỨNG VÀ MÔ TẢ HOẠT ĐỘNG
I. THIẾT KẾ PHẦN CỨNG
Linh kiện sử dụng
• 1 IC 89C51
• 1 bộ 6 LED 7 đoạn
• 3 nút nhấn
• 6 cổng NOT
• 3 LED đơn
• 3 trở 100k
• 2 trở 4k7
• Thạch anh 32768 Hz
• 1 nguồn 3V
• 2 tụ 33pF
• 1 IC DS1307
Sơ đồ phần cứng
• LED 7 đoạn
Chân ABCDEFG nối với P0.0 tới P0.6 của IC 89C51
Chân điều khiển 123456 nối với P2.0 tới P2.6 của IC 89C51 thông qua cổng NOT
• IC DS1307
Chân SDA nối với P1.7
Chân SCL nối với P1.6
Đèn LED báo AM nối với P2.6
Đèn LED báo PM nối với P2.7
đã được truyền đi, thiết bị nhận sẽ kéo SDA xuống mức thấp tương ứng một bit ACK tại xung clock thứ 9 trên báo hiệu đã nhận đủ 8 bit. Thiết bị truyền khi nhận được bit ACK sẽ tiếp tục thực hiện quá trình truyền hoặc kết thúc. Định dạng địa chỉ thiết bị: Mỗi thiết bị ngoại vi tham gia vào bus i2c đều có một địa chỉ duy nhất, có độ dài là 7 bit như vậy trên một bus I2C ta có thể phân biệt tối đa 128 thiết bị. Byte đầu tiên được gửi từ Master sẽ bao gồm 7 bit địa chỉ và bit thứ 8 gọi là bit R/W. Bit R/W = 0 : Ghi dữ liệu từ Master vào Slave. Bit R/W = 1 : Đọc dữ liệu từ Slave . Phương thức truyền dữ liệu tới Slave: ‐ Master tạo xung START ‐ Master gửi 7 bit địa chỉ của Slave + bit R/W= 0 (8 clock) ‐ Tại thời điểm clock thứ 9, Master đọc xung ACK từ Slave. ACK = 0 khi Slave có địa chỉ tương ứng đã nhận dạng, Master bắt đầu gửi dữ liệu đến Slave theo từng byte một mất 9 clock do theo sau mỗi byte (8 clock) được gửi từ Master, Slave phải xác nhận bằng một xung ACK=0. ‐Kết thúc quá trình truyền, Master sau khi truyền byte cuối sẽ tạo xung STOP báo hiệu kết thúc. Chế độ đọc dữ liệu từ Slave: ‐ Master tạo xung START ‐ Master gửi 7 bit địa chỉ của Slave + bit R/W = 1 ‐ Sau khi Slave xác nhận địa chỉ và trả về bit ACK=0, Slave sẽ gửi từng byte ra SDA; Master sẽ nhận dữ liệu và cũng trả về bit ACK =0 sau mỗi byte. ‐ Để kết thúc quá trình nhận dữ liệu, Master gửi xung Not‐ACK qua cú pháp i2c_read(1,0) và tạo xung STOP. Phần mềm Gồm Hàm “main”: thực hiện chương trình chính Hàm “EXT0_ISR”: Hàm ngắt ngoài 0 để đọc nút nhấn điều chỉnh giừo , phút Hàm “Timer1_ISR”: ngắt timer1 để hiển thị ra led 7 đoạn bằng phương pháp quét led Hàm “ISR_INIT”: hàm cài đặt ngắt Hàm “delay”: tạo trễ Hàm “dislay”: hiển thị ra led 7 đoạn Hàm “start”: start I2C Hàm “stop”: stop I2C Hàm “send”: ghi 1 byte vào DS1307 Hàm “receive”: nhận 1 byte từ DS1307 Hàm “write”: ghi giá trị vào 1 địa chỉ Hàm “read”: đọc giá trị từ 1 địa chỉ Hàm “read_data”: hàm nhận K byte từ DS1307 Hàm “write_data”: truyền k byte DS1307 Hàm “nut_nhan”: điều chỉnh giờ phút Hàm “chuyển”: Chuyển đổi giữa 2 chế độ 24h và 12h. Lưu đồ giải thuật một số hàm quan trọng: Hàm “NGAT” ĐẶT LẠI GIÁ TRỊ NGẮT COUNTER=6 TĂNG COUNTER START NO YES COUNTER = 0 HIỂN THỊ RA LED 7 ĐOẠN CHƯƠNG TRÌNH CHỈNH GIỜ VÀ PHÚT NÚT CHỈNH GIỜ/PHÚT CHUYỂN ĐỔI 12H/24H NÚT CHUYỂN ĐỌC BIẾN PHÚT ĐỌC BIẾN GIỜ ĐỌC BIẾN GIỜ VÀ BIẾN AM/PM CHẾ ĐỘ ĐỌC GIÁ TRỊ TỪ DS1307 CÀI ĐẶT GIÁ TRỊ ĐẦU CHO DS1307, NGẮT, GIỜ PHÚT GIÂY Hàm “main” 12H 24H CHƯA NHẤN NHẤN CÓ Hàm “chuyen” RET PM=0;AM=0;T=0 HOUR = HOUR+12; TRẢ GIỜ VỀ DS1307 PM=1 T=2 TRẢ GIỜ VỀ DS1307 HOUR>12 T=1 AM=1;PM=0 HOUR=HOUR-12 AM=0;PM=1 Hàm “nut_nhan” GIỜ TĂNG LÊN 1 TRẢ GIỜ LẠI DS1307 NHẤN NÚT TĂNG PHÚT PHÚT TĂNG LÊN 1 TRẢ PHÚT LẠI DS1307 STARTNHẤN NÚT TĂNG PHÚT RET NÚT NHẤN CHỈNH NO YES NO YES Hàm “read” BẮT ĐẦU GIAO TIẾP VỚI DS1307 GỬI ĐỊA CHỈ CẦN ĐỌC GỬI LỆNH GHI START SEND GỬI LỆNH ĐỌC ĐỌC BYTE VỀ NGỪNG GIAO TIẾP VỚI DS1307 RET Hàm “write” RET SEND BẮT ĐẦU GIAO TIẾP VỚI DS1307 NGỪNG GIAO TIẾP VỚI DS1307 GỬI BYTE CẦN GHI GỬI ĐỊA CHỈ CẦN GHI GỬI LỆNH GHI START CHƯƠNG V CODE CHƯƠNG TRÌNH #include #define DOUT P0 #define D1 P2_0 #define D2 P2_1 #define D3 P2_2 #define D4 P2_3 #define D5 P2_4 #define D6 P2_5 #define chedo P3_2 #define tangphut P3_3 #define tanggio P3_4 #define SDA P1_7 #define SCL P1_6 #define portbit P1_0 sbit AM = P2^6; sbit PM = P2^7; unsigned char code_7_segment[10]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; unsigned char data_write[3]={0x00,0x25,0x22}; unsigned char data_read[3]; unsigned char counter,mode,t,hour,minute; void delay(unsigned int t); void start(); void stop(); void send(unsigned char g); unsigned char receive(); void write(unsigned char add,unsigned char gt); unsigned char read(unsigned char add); void read_data(unsigned char k,char *read); void write_data(unsigned char k,char *write); void dislay(void); void DS1307INIT(); void nut_nhan(); unsigned char bcd_dec(unsigned char bcd); unsigned char dec_bcd(unsigned char dec); void chuyen(void); void ISR_INIT(void); ///////////////////// //Ham ngat ngoai 0 de doc nut nhan dieu chinh gio phut void EXT0_ISR(void) interrupt 0 { delay(100); mode++; if(mode==2){ mode=0;} portbit = !portbit; } //ham ngat timer 1 de hien thi ra led 7 doan bang phuong phap quet led void Timer1_ISR(void) interrupt 3 { TR1 = 0; TH1 = ((-6000)&0xFF00)>>8; //dat lai gia tri cho timer TL1= (-6000)&0x00FF; TR1 = 1; counter++; if(counter == 6){counter = 0;}; dislay(); } void main(void) { DS1307INIT(); ISR_INIT() ; write_data(3,data_write); mode = 0; counter = 0; t=0; AM =0; PM =0; while(1) { read_data(3,data_read); //doc 3 byte gio phut giay ve tu DS1307 if(t==1){hour = bcd_dec(data_read[2]&0x1F); //che do 12h if(data_read[2]&0x20) {AM=0;PM=1;} else {AM =1 ;PM =0;} } if(t==0) { hour = bcd_dec(data_read[2]&0x3F); } //che do 24h minute = bcd_dec(data_read[1]);//chuyen byte phut tu bcd sang ma thap phan cho bien minute do DS1307 tra ve so BCD if(!tangphut){t++;delay(200);chuyen();} //kiem tra xem nut chuyen doi giua 2 che do 24h va 12h co nhan hay khong nut_nhan(); } } // Ham cai dat ngat void ISR_INIT(void) { TMOD = 0x11; TH1 = ((-6000)&0xFF00)>>8; TL1 = (-6000)&0x00FF; TR1 = 1; ET1 = 1; EX0 = 1; EA = 1; IT0=1; } void delay(unsigned int t) { unsigned int i,j; for(i=0;i<t;i++)for(j=0;j<125;j++); } /*void delay1(unsigned int t) { unsigned int i,j; for(i=0;i<t;i++)for(j=0;j<30;j++); } */ //ham hien thi ra led 7 doan void dislay(void) { if (counter==0){ D6=1; DOUT=0xff; D1=0; DOUT=code_7_segment[hour/10]; } if (counter==1){ D1=1; DOUT=0xff; D2=0; DOUT=code_7_segment[hour%10]; } if (counter==2){ D2=1; DOUT=0xff; D3=0; DOUT=code_7_segment[minute/10]; } if (counter==3){ D3=1; DOUT=0xff; D4=0; DOUT=code_7_segment[minute%10]; } if (counter==4){ D4=1; DOUT=0xff; D5=0; DOUT=code_7_segment[data_read[0]/16]; } if (counter==5){ D5=1; DOUT=0xff; D6=0; DOUT=code_7_segment[data_read[0]%16]; } } // Ham start I2C void start() { SCL=1; SDA=1; delay(1); SDA=0; delay(1); SCL=0; SDA=1; } // Ham stop I2C void stop() { SDA=0;SCL=1; delay(1); SDA=1; delay(1); } // Ham ghi 1 byte vao DS1307 void send(unsigned char g) { unsigned char tem,i; for(i=0;i<8;i++) { tem=g&0x80; if(tem == 0x80) SDA=1; else SDA=0; SCL=1; delay(1); SCL=0; g=g*2; } SCL=1; delay(1); SCL=0; } // Ham nhan 1 byte unsigned char receive() { unsigned char gt=0,i; for(i=0;i<8;i++) { SCL=1; gt=gt*2; delay(1); gt=gt|SDA; SCL=0; delay(1); } SCL=1; SDA=1; delay(1); SCL=0; return gt; } //Ham ghi gia tri vao 1 dia chi void write(unsigned char add,unsigned char gt) { start(); send(0xd0); send(add); send(gt); stop(); } // Ham doc gia tri tu 1 dia chi unsigned char read(unsigned char add) { unsigned char value; start(); send(0xd0); send(add); start(); send(0xd1); value=receive(); stop(); return value; } void DS1307INIT() { unsigned char check; check = read(0x08); if(check!='c') { write(0x08,'c'); } } //Ham nhan k byte tu DS1307 void read_data(unsigned char k,unsigned char *gt) { unsigned char add,i; add=0x00; for (i=0;i< k;i++) { *(gt+i) = read(add); add++; } } //Ham truyen k byte vao DS1307 void write_data(unsigned char k,unsigned char *gt) { unsigned char add,i; add = 0x00; for (i=0;i<k;i++) { write(add,*(gt+i)); add++; } } //de dieu chinh gio phut void nut_nhan() { while(mode) { if(!tangphut) {delay(300); minute++; if(minute>59) {minute = 0; hour++; if(t == 0){if(hour>23){hour = 0;}data_read[2] = dec_bcd(hour) & 0x3F;} //che do 24h else {if (hour > 12) {hour = 0x01;AM = !AM;PM = !PM;} //che do 12h if((AM == 0)&&(PM==1)){data_read[2]= dec_bcd(hour) | 0x60;} if((PM == 0)&&(AM==1)){data_read[2] = dec_bcd(hour) | 0x20;}} } write(0x02,data_read[2]); //tra bien gio ve DS1307 write(0x01,dec_bcd(minute)); //tra bien phut ve DS1307 } if(!tanggio) {delay(300); hour++; if(t == 0) {if(hour>23){hour = 0;}data_read[2] = dec_bcd(hour) & 0x3F;AM=0;PM=0;} //che do 24h if(t==1) {if (hour > 12) { //che do 12h hour = 1;AM = !AM;PM = !PM; } if((AM == 0)&&(PM==1)){ data_read[2]= dec_bcd(hour) | 0x60; } if((AM == 1)&&(PM==0)) {data_read[2] = dec_bcd(hour) | 0x40; data_read[2] &= 0xDF; } } write(0x02,data_read[2]); //tra bien gio ve DS1307 } } } //Ham chuyen giua 2 che do 24h va 12h void chuyen(void) { if (t==1){ if(hour>12){ hour -= 12; data_read[2] = dec_bcd(hour) | 0x60; //t==1 chuyen tu 24h sang 12h AM = 0;PM =1; } else { if( hour ==0){ hour = 12;} data_read[2] = dec_bcd(hour) | 0x40; PM = 0;AM =1; } } if (t==2){ if ((PM == 1) && ( AM == 0 )) {hour += 12; //t==2 chuyen tu 12h sang 24h sau do cho t ve 0 data_read[2] = dec_bcd(hour)&0x3F; } if ((PM == 0)&&(AM == 1)){ if(hour == 12){hour=0;} data_read[2] = dec_bcd(hour)&0x3F; } PM =0; AM =0; t=0; } write(0x02,data_read[2]); } unsigned char bcd_dec(unsigned char bcd) //ham chuyen ma bcd sang ma thap phan { return((bcd/16)*10+(bcd%16)); } unsigned char dec_bcd(unsigned char dec) // ham chuyen ma thap phan sang bcd { return((dec/10)*16+(dec%10));} CHƯƠNG VI CHƯƠNG KẾT LUẬN ƯU ĐIỂM: Đầy đủ chức năng của 1 đồng hồ thông thường Giaỉ quyết được vấn đề chính xác về thời gian Có nhiều tùy chọn chỉnh giờ Code nhóm tự viết KHUYẾT ĐIỂM Code còn rắc rồi, chưa tưởng mình. Thiếu chế độ hẹn giờ báo thức. Tài liệu tham khảo:
File đính kèm:
- bai_tap_lon_mon_vi_xu_ly_de_tai_3_mach_dong_ho_gio_phut_giay.docx