(65536-50000)/256; 把50000定义为时基,再增加一层时基设置(并存储),这样时钟可以调的很准! 我正在为STC15W408外加AT24C02存储时基头疼!我用的是STC89C52外加AT24C02存储器的程序!嘿嘿! |
学习了,依然在学习的路上!感谢版主和楼主的无私奉献! |
谢谢坛主的无私分享,都是干货的。 |
向大佬学习学习 |
很好,收藏了 |
谢谢楼主的教程,正研究2402 |
学习一下 |
谢谢楼主的教程,回去好好研究一下~~ |
24c02是干什么用的 |
借鉴了一下,对我学习单片机很有作用,多谢 |
![]() |
学习下,很不错! |
很好 学习 |
到底有没有仿真 |
很不错,值得大家学习 |
好东西呀,正在学习,多谢了 |
不错,有电路图就更好了。 |
admin 发表于 2013-6-17 03:50 我要认真的好好学习学习! |
非常好 |
有图么 |
时钟的时间如何修改? |
不知道有没有电路原理图![]() ![]() ![]() ![]() ![]() |
又学到新东西。 |
51Hei(51黑)论坛有你更精彩 |
没有仿真图唉 |
马虎了。 |
很好,学习了哈。 |
有图吗 |
感谢楼主分享 |
很好 学习 谢谢 |
谢谢分享 |
谢谢 很好 |
谢谢分享,赞一个 |
admin 发表于 2013-6-17 03:50 好像proteus仿真通不过,检测到没有声明write2402_data子函数,程序中也没有写这个子函数。 |
学习学习 |
很好 学习 谢谢 |
不错过来看看 |
看看学习学习 |
51Hei(51黑)论坛有你更精彩 |
下面是主程序:
/************************************** 名称:89c52+at24c02+键盘时钟程序 工具:protues仿真软件 作者:kwx618 时间:2011-09-10 **************************************/ #include <reg52.h> #include <intrins.h> #include"at24c02.h" #define uchar unsigned char #define uint unsigned int sbit LCD_RS=P0^0; sbit LCD_RW=P0^1; sbit LCD_EN=P0^2; sbit S1=P1^2; sbit S2=P1^3; sbit S3=P1^4; sbit S4=P1^5; char year,mounth,day,hour,minute,second; uchar num,count; bit write=0; //写2402标志 uchar code nyr_table[]=" 20 - - "; uchar code sfm_table[]=" : : "; /************延时1ms函数***************/ void delay1ms(uint z) { uint x,y; for(x=z;x>0;x--) for(y=112;y>0;y--); } /**************LCD1602程序***********/ void LCD_BUSY() { P2=0x00; LCD_RS=0; LCD_RW=1; LCD_EN=1; while(P2&0x80); LCD_EN=0; } void writeLCD_command(uchar cmd) { LCD_BUSY(); LCD_RS=0; LCD_RW=0; P2=cmd; _nop_(); LCD_EN=1; _nop_(); LCD_EN=0; } void writeLCD_data(uchar date) { LCD_BUSY(); LCD_RS=1; LCD_RW=0; P2=date; _nop_(); LCD_EN=1; _nop_(); LCD_EN=0; } void write_nyrsfm(char add,char date) { char shiwei,gewei; shiwei=date/10; gewei=date%10; writeLCD_command(0x80|add); delay1ms(1); writeLCD_data(0x30+shiwei); delay1ms(1); writeLCD_data(0x30+gewei); delay1ms(1); } void LCD_init() { uchar num1,num2; year=0;mounth=1;day=1; hour=23;minute=59;second=59; LCD_BUSY(); writeLCD_command(0x38);//设置16*2显示,5*7点阵,8位数据接口 delay1ms(5); //此处必须加延时,否则LCD不显示 writeLCD_command(0x0c);//开显示,光标不显示 delay1ms(5); //此处必须加延时,否则光标不会移动 writeLCD_command(0x06);//读或写字符后,光标自动加1,整屏不移动 delay1ms(5); writeLCD_command(0x02);//数据指针清0 delay1ms(5); writeLCD_command(0x80|0x02); for(num1=0;num1<11;num1++) { writeLCD_data(nyr_table[num1]); } writeLCD_command(0x80|0x43); for(num2=0;num2<9;num2++) { writeLCD_data(sfm_table[num2]); } write_nyrsfm(0x80|0x05,year); _nop_(); write_nyrsfm(0x80|0x08,mounth); _nop_(); write_nyrsfm(0x80|0x0b,day); _nop_(); write_nyrsfm(0x80|0x44,hour); _nop_(); write_nyrsfm(0x80|0x47,minute); _nop_(); write_nyrsfm(0x80|0x4a,second); _nop_(); TMOD=0x01; TH0=(65536-50000)/256; TL0=(65536-50000)%256; EA=1; ET0=1; TR0=1; } /************************************************** 名称:按键程序 S1: 设置键 S2:时间加 S3:时间减 **************************************************/ void keyscan() { if(S1==0) { delay1ms(10); if(S1==0) num++; while(!S1); switch(num) { case 1: TR0=0; writeLCD_command(0x80|0x4b); delay1ms(1); writeLCD_command(0x0f); delay1ms(1); break; case 2: TR0=0; writeLCD_command(0x80|0x48); writeLCD_command(0x0f); break; case 3: TR0=0; writeLCD_command(0x80|0x45); writeLCD_command(0x0f); break; case 4: TR0=0; writeLCD_command(0x80|0x0c); writeLCD_command(0x0f); break; case 5: TR0=0; writeLCD_command(0x80|0x09); writeLCD_command(0x0f); break; case 6: TR0=0; writeLCD_command(0x80|0x06); writeLCD_command(0x0f); break; case 7: num=0; writeLCD_command(0x0c); TR0=1; break; default:break; } } } void up_downsetkey() { //keyscan(); if(num!=0) { if(S2==0) { delay1ms(10); if(S2==0) while(!S2); switch(num) { case 1: second++; if(second==60) second=0; write_nyrsfm(0x80|0x4a,second); delay1ms(5); write2402_data(1,second); delay1ms(5); break; case 2: minute++; if(minute==60) minute=0; write_nyrsfm(0x80|0x47,minute); delay1ms(5); write2402_data(2,minute); delay1ms(5); break; case 3: hour++; if(hour==24) hour=0; write_nyrsfm(0x80|0x44,hour); delay1ms(5); write2402_data(3,hour); delay1ms(5); break; case 4: day++; if(day==30) day=0; write_nyrsfm(0x80|0x0b,day); delay1ms(5); write2402_data(4,day); delay1ms(5); break; case 5: mounth++; if(mounth==12) mounth=0; write_nyrsfm(0x80|0x08,mounth); delay1ms(5); write2402_data(5,mounth); delay1ms(5); break; case 6: year++; if(year==99) year=0; write_nyrsfm(0x80|0x05,year); delay1ms(5); write2402_data(6,year); delay1ms(5); break; default:break; } } if(S3==0) { delay1ms(10); if(S3==0) while(!S3); switch(num) { case 1: second--; if(second==-1) second=59; write_nyrsfm(0x80|0x4a,second); delay1ms(1); write2402_data(1,second); break; case 2: minute--; if(minute==-1) minute=59; write_nyrsfm(0x80|0x47,minute); write2402_data(2,minute); break; case 3: hour--; if(hour==-1) hour=23; write_nyrsfm(0x80|0x44,hour); write2402_data(3,hour); break; case 4: day--; if(day==-1) day=30; write_nyrsfm(0x80|0x0b,day); write2402_data(4,day); break; case 5: mounth--; if(mounth==-1) mounth=12; write_nyrsfm(0x80|0x08,mounth); write2402_data(5,mounth); break; case 6: year--; if(year==-1) year=99; write_nyrsfm(0x80|0x05,year); write2402_data(6,year); break; default:break; } } } } /*void display() //开始的时候采用这种边显示边写2402的方式,但是程序写不到2402, { //很郁闷。不过调整时间时光标很正常,一直想找个方法让光标正常而且能写进 if(count==20) // 2402的方法,但是没有想出来 { second++; count=0; if(second==60) { second=0; minute++; if(minute==60) { minute=0; hour++; if(hour==24) { hour=0; day++; if(day==31) { day=0; mounth++; if(mounth==13) { mounth=0; year++; write_nyrsfm(0x80|0x05,year); delay1ms(1); write2402_data(6,year); delay1ms(1); } write_nyrsfm(0x80|0x08,mounth); delay1ms(1); write2402_data(5,mounth); delay1ms(1); } write_nyrsfm(0x80|0x0b,day); delay1ms(1); write2402_data(4,day); delay1ms(1); } write_nyrsfm(0x80|0x44,hour); delay1ms(1); write2402_data(3,hour); delay1ms(1); } write_nyrsfm(0x80|0x47,minute); delay1ms(1); write2402_data(2,minute); delay1ms(1); } write_nyrsfm(0x80|0x4a,second); delay1ms(1); write2402_data(1,second); delay1ms(1); } } */ /************显示程序****************/ void display() { //year=0;mounth=1;day=0; // 开始的时候不写这两句,显示的结果就是2000-0/-0/ 23-0/-0/ , //hour=23;minute=59;second=59; // 解决办法是先在加上这两句,然后把初始化里的那两句屏蔽掉,然后编译显示, write_nyrsfm(0x80|0x05,year); // 在回过头来去掉初始化里的屏蔽,把这两句删掉编译就显示正常了,具体为什么会 delay1ms(1); //这样,我也不清楚,有待解决。 write_nyrsfm(0x80|0x08,mounth); delay1ms(1); write_nyrsfm(0x80|0x0b,day); delay1ms(1); write_nyrsfm(0x80|0x44,hour); delay1ms(1); write_nyrsfm(0x80|0x47,minute); delay1ms(1); write_nyrsfm(0x80|0x4a,second); delay1ms(1); } void main() { init_2402(); delay1ms(5); LCD_init(); delay1ms(5); //此处也必须加延时,否则不会在指定的位置显示 second =read_data(0); //读出24c02保存的值赋于sec if(second>60) //防止首次读出错误数据 second=0; delay1ms(5); minute=read_data(1); //读出24c02保存的值赋于sec if(minute>60) //防止首次读出错误数据 minute=0; delay1ms(5); hour=read_data(2); //读出24c02保存的值赋于sec if(hour>24) //防止首次读出错误数据 hour=0; delay1ms(5); day=read_data(3); //读出24c02保存的值赋于sec if(day>30) //防止首次读出错误数据 day=0; delay1ms(5); mounth=read_data(4); //读出24c02保存的值赋于sec if(mounth>12) //防止首次读出错误数据 mounth=0; delay1ms(5); year=read_data(5); //读出24c02保存的值赋于sec if(year>12) //防止首次读出错误数据 year=0; delay1ms(5); while(1) { display(); delay1ms(1); keyscan(); delay1ms(1); up_downsetkey(); delay1ms(1); if(write==1) { write2402_data(0,second); delay1ms(1); write2402_data(1,minute); delay1ms(1); write2402_data(2,hour); delay1ms(1); write2402_data(3,day); delay1ms(1); write2402_data(4,mounth); delay1ms(1); write2402_data(5,year); delay1ms(1); write=0; //清0 } } } void intputtime0() interrupt 1 { TH0=(65536-50000)/256; TL0=(65536-50000)%256; count++; if(count==16)//此处应该是20,但是用protues仿真时会发现误差很大,所以我调到了16,时间刚好。 { second++; count=0; if(second==60) { second=0; minute++; if(minute==60) { minute=0; hour++; if(hour==24) { hour=0; day++; if(day==31) { day=0; mounth++; if(mounth==13) { mounth=0; year++; } } } } } write=1; } } |