Nếu như hiểu hết 5 bài trước thì chắc chắn các bạn đã có thể tự thiết kế đồng hồ matrix cho riêng mình rồi. Tuy nhiên bài này mình sẽ làm 1 demo nho nhỏ là đồng hồ matrix 8×40 có hiệu ứng lật trang đơn giản
Mình sẽ làm demo 1 cái đồng hồ có các chức năng cơ bản sau
- Hiện thị giờ – phút – giây
- Lật trang mỗi khi giây thay đổi
- Cứ 20s sẽ chạy thứ ngày tháng năm 1 lần
Do nâng cấp thêm 1 con led matrix 8×8 nữa nên số độ phân giải bây giờ là 8×40. Mình sẽ thêm 1 chiều nữa cho bộ đệm hiển thị
1 |
unsigned char Buffer_display[8][5]; |
Do đã thêm 1 led nên hàm ngắt hiển thị cũng sẽ bổ sung thêm 1 dòng gửi data ra nữa
1 |
hc595_out(Buffer_display[z][4]); //lay du lieu trong bo dem hien thi ra man hinh matrix 5 |
Vậy là xong, còn lại hầu như không thay đổi gì so với bài trước
Do cần đọc thời gian nên ta sẽ phải giao tiếp với ic ds1307, tuy nhiên phạm trù tus này chỉ nói về code cho matrix và cách giao tiếp với ds1307 hay chuẩn I2C đã có rất nhiều trên mạng nên mình không đề cập đền nữa. Mình đã viết sẵn 1 thư viện ds1307 nên giờ chỉ cần gọi ra thôi
1 2 |
#include "ds1307.h" #include "stdio.h" |
Trong thư viện này thì chỉ cần chú trọng vào 3 hàm cơ chính
1 2 3 |
void ghi(unsigned char add, unsigned char dat); // ghi dữ liệu vào địa chỉ ( dữ liệu có dang BCD) unsigned char doc(unsigned char add); // đọc dữ liệu từ địa chỉ ( dữ liệu dang BCD) void DS1307_get_TIME_and_Date(unsigned char s[7]); // đọc 7 giá trị thời gian( yêu cầu nạp vào mảng 7 phần tử) |
Khai bảo mảng 7 phần tử lưu thời gian theo thứ tự
Giây, phút, giờ, thứ, ngày, tháng, năm
1 biến old_time để đựng giá trị giây trước đó ( mục đích phát hiện 1s đã trôi qua)
Và 1 mảng 30 phần tử lưu data chữ chạy ngày tháng năm
1 2 |
unsigned char time[7],old_time; unsigned char Date[30]; |
Xây dựng hàm in dữ liệu giờ – phút – giây ra màn hình
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
void display_Time(char hienthiGiay) { Matrix_chonvitri(-1,1); Matrix_guikitu(time[2]/10+48); Matrix_guikitu(time[2]%10+48); //hien thi gio Matrix_setpx(12,2,1);Matrix_setpx(12,6,1); // hien thi dau : Matrix_chonvitri(13,1); Matrix_guikitu(time[1]/10+48); Matrix_guikitu(time[1]%10+48); //hien thu ngay Matrix_setpx(26,2,1);Matrix_setpx(26,6,1); // hien thi dau : if(hienthiGiay) { Matrix_chonvitri(27,1); //hien thi giay Matrix_guikitu(time[0]/10+48); Matrix_guikitu(time[0]%10+48); //display Second } } |
Hàm này có 1 giá trị nạp vào, nếu nạp vào 1 thì sẽ in cả giây ra, còn không thì in mỗi Giờ và phút thôi (để không anh hưởng đến hiệu ứng lật trang)
Xây dựng hàm lật trang cho giây
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
void latgiay(char kt) { char x,y,giay,h; giay=time[0]; if(giay==0)giay=59; else giay--; if(kt==0) //lat don vi { for(h=1;h<5;h++) { Matrix_chonvitri(33,0);for(x=33;x<39;x++)for(y=0;y<8;y++)Matrix_setpx(x,y,0); //clear man hinh giay Matrix_chonvitri(33,h);Matrix_guikitu(giay%10+48);delay(30); //hien thi giay cu ra man hinh } for(;h<13;h++) { Matrix_chonvitri(33,0);for(x=33;x<39;x++)for(y=0;y<8;y++)Matrix_setpx(x,y,0); //clear man hinh giay Matrix_chonvitri(33,h-11);Matrix_guikitu(time[0]%10+48); //hien thi giay moi ra man hinh if(h<8){Matrix_chonvitri(33,h);Matrix_guikitu(giay%10+48);} //hien thi giay cu ra man hinh delay(30); } } else //lat chuc + don vi { for(h=1;h<5;h++) { Matrix_chonvitri(27,0);for(x=27;x<39;x++)for(y=0;y<8;y++)Matrix_setpx(x,y,0); //clear man hinh giay Matrix_chonvitri(27,h);Matrix_guikitu(giay/10+48);Matrix_guikitu(giay%10+48);delay(30); //hien thi giay cu ra man hinh } for(;h<13;h++) { Matrix_chonvitri(27,0);for(x=27;x<39;x++)for(y=0;y<8;y++)Matrix_setpx(x,y,0); //clear man hinh giay Matrix_chonvitri(27,h-11);Matrix_guikitu(time[0]/10+48);Matrix_guikitu(time[0]%10+48); //hien thi giay moi ra man hinh if(h<8){Matrix_chonvitri(27,h);Matrix_guikitu(giay/10+48);Matrix_guikitu(giay%10+48);} //hien thi giay cu ra man hinh delay(30); } } } |
Hàm này cũng có 1 giá trị nạp vào, nếu nạp vào 1 thì lật cả 2 số hàng Chục và Đơn Vị. Ngược lại thì chỉ lật hàng đơn vị thôi
Việc lật trang sẽ có ba giai đoạn chính
- Cuộn số cũ xuống vài dòng ( số mới chưa xuất hiện) ( h chạy từ 1 đến 5)
- Vừa cuộn số cũ vữa cuốn số mới ( h chạy từ 5 đến 8 )
- Cuộn số mới đến hết ( h chạy từ 8 đến 13 )
Do vậy mình khởi tạo 1 biến giây, mục đích là trừ nó đi 1 để nó thành số cũ. Nếu là 0 thì set thành 59. Các hàm bên trong vòng for thực thi việc in kí tự cũ và mới ra ở các vị trí trục Y khác nhau nên cao độ của chữ cũng sẽ thay đổi. Sau mỗi lần in mình delay cho mắt kịp nhìn và xóa hoàn toàn phần dữ liệu ở chỗ lật đi bằng hàm Matrix_clear. Sau đó tiền hành vẽ lại
Trong hàm main, trước khi nhảy vào while 1 sẽ cho đọc dữ liệu từ DS1307 ra bằng hàm DS1307_get_TIME_and_Date(time); và in toàn bộ Giờ – Phút – Giây ra bằng hàm display_Time(1); (tham số 1 ám chỉ in đẩy đủ cả Giờ – phút -giây)
Trong vòng lặp while, sử dụng biến old_time so sánh với time[0] ( giây mà mình đọc trong ds ra). Nếu khác nhau tức là giây dã thay đổi. Gọi hàm latgiay với tham số 0 nếu chỉ cần lật đơn vị, hoặc tham số 1 nếu muốn lật cả 2 chữ số ( bằng cách chia lấy dư cho 10)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
while(1) { DS1307_get_TIME_and_Date(time); if(old_time != time[0]) //neu 1s da troi qua thi lat trang { old_time=time[0]; if(time[0] == 0)display_Time(0); if(time[0] % 10 != 0)latgiay(0); else latgiay(1); } if(time[0] == 10 || time[0] == 30 || time[0] == 50 ) //giay thu 10 se chay ngay thang nam { if(time[3] != 1) sprintf(Date,"T.%i %i/%i/20%i ",(int)time[3],(int)time[4],(int)time[5],(int)time[6]); else sprintf(Date,"CN %i/%i/20%i ",(int)time[4],(int)time[5],(int)time[6]); Matrix_Clear(); //xoa man hinh for(x=31;x>-70;x--) { Matrix_chonvitri(x,1); Matrix_guichuoi(Date); delay(20); } Matrix_Clear(); //xoa man hinh display_Time(1); } } |
Phần còn lại là kiểm tra nếu giây đạt các mốc 10 30 50 thì sẽ cho chạy thời gian thứ ngay tháng năm. Hàm sprintf sẽ đưa các dữ liệu thời gian vào mảng Date và chỉ việc in ra bằng vòng lặp for như bài trước là ta sẽ có hiệu ứng chạy chữ. ( trước và sau khi chạy sẽ clear hết màn đi để tránh các pixel không cần thiết vẫn bị sáng)
PS: Project này mình không sử dụng bộ đệm đôi, lí do phần mềm keilC của mình không phải bản quyền nên chỉ biên dịch được với 50% Ram. Dẫn tới k đủ Ram để chạy 2 bộ đệm. Các bạn hãy thư nâng cấp lên 2 bộ đệm để các hiệu ứng đẹp mắt nhất
File cho project này các bạn tải ở đây
Project đồng hồ matrix 8×40 này chưa có mode cài đặt thời gian. Các bạn tự phát triển các chức năng cần thiết cho mình nhé !
hay
@Dao Nguyen..I’ve read your code, but I’m confused.Which part should I change?
I mean, I want to change the day with the words sunday, monday, etc.any solution..thank’s,best site to learn…
char code *date_string[7]={“sunday”,”monday”,””,””,””,””,””,””};
sprintf(buff,”%s”, date_string[ time[3] – 1];
mình biên dịch code của bạn nó báo limit, code dài quá ko biên dịch đc bạn à,bạn có cách nào ko giúp minh với
Build target ‘Target 1’
compiling c.c…
c.c(195): warning C318: can’t open file ‘ds1307.h’
C.C(265): warning C206: ‘get_TIME_and_Date’: missing function-prototype
C.C(265): error C267: ‘get_TIME_and_Date’: requires ANSI-style prototype
Target not created
của mình nó báo như này b ơi
làm sao để chia thành 2 zone 1 bên hiển thị nhiệt độ 1 bên chạy chữ nhập từ serial ạ
mình biên dịch code của bạn nó báo limit, code dài quá ko biên dịch đc bạn à,bạn có cách nào ko giúp minh với