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

