找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 15479|回复: 39
打印 上一主题 下一主题
收起左侧

51单片机+AT24C02+按键+Proteus仿真时钟源程序

  [复制链接]
跳转到指定楼层
楼主
   时间很准确,跑了2个小时才慢1S,这可是用Proteus仿真软件仿真哦!而且里面有详细的说明,具体到每一步。还有AT24C02的中文资料,希望对新手有用。不过在调试程序的过程中发现了一点小问题,一直没有找到解决的办法,就是在调节时间时光标移动有时出现问题,但是又并不影响调节,具体在程序中有说明,希望有高手能够指点一下!在此先感谢!


单片机定时器时钟.zip (63.28 KB, 下载次数: 540)



分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:1 发表于 2013-6-17 03:50 | 只看该作者
下面是主程序:
/**************************************
名称: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;
	}	
}
	
	
回复

使用道具 举报

板凳
ID:51343 发表于 2013-7-1 16:06 | 只看该作者
51Hei(51黑)论坛有你更精彩
回复

使用道具 举报

地板
ID:55734 发表于 2013-10-9 03:10 | 只看该作者
看看学习学习
回复

使用道具 举报

5#
ID:52286 发表于 2013-10-13 23:27 | 只看该作者
不错过来看看
回复

使用道具 举报

6#
ID:55815 发表于 2013-10-23 14:16 | 只看该作者
很好  学习  谢谢
回复

使用道具 举报

7#
ID:58854 发表于 2014-1-18 22:55 | 只看该作者
学习学习
回复

使用道具 举报

8#
ID:45225 发表于 2014-8-31 23:03 | 只看该作者
admin 发表于 2013-6-17 03:50
下面是主程序:

/**************************************

好像proteus仿真通不过,检测到没有声明write2402_data子函数,程序中也没有写这个子函数。
回复

使用道具 举报

9#
ID:65699 发表于 2014-9-2 10:19 | 只看该作者
谢谢分享,赞一个
回复

使用道具 举报

10#
ID:55815 发表于 2014-9-2 11:30 | 只看该作者
谢谢 很好
回复

使用道具 举报

11#
ID:66181 发表于 2014-9-15 12:33 | 只看该作者
谢谢分享
回复

使用道具 举报

12#
ID:66338 发表于 2014-9-18 16:18 | 只看该作者
很好  学习  谢谢
回复

使用道具 举报

13#
ID:67068 发表于 2014-10-8 10:18 | 只看该作者
感谢楼主分享
回复

使用道具 举报

14#
ID:67070 发表于 2014-10-8 10:29 | 只看该作者
有图吗
回复

使用道具 举报

15#
ID:67085 发表于 2014-10-8 11:02 | 只看该作者
很好,学习了哈。
回复

使用道具 举报

16#
ID:67370 发表于 2014-10-14 17:51 | 只看该作者
马虎了。
回复

使用道具 举报

17#
ID:72399 发表于 2015-1-30 13:49 | 只看该作者
没有仿真图唉
回复

使用道具 举报

18#
ID:72565 发表于 2015-2-2 01:11 | 只看该作者
51Hei(51黑)论坛有你更精彩
回复

使用道具 举报

19#
ID:29438 发表于 2015-2-2 13:21 | 只看该作者
又学到新东西。
回复

使用道具 举报

20#
ID:85152 发表于 2015-7-9 09:49 | 只看该作者
不知道有没有电路原理图
回复

使用道具 举报

21#
ID:90114 发表于 2015-9-14 21:12 | 只看该作者
时钟的时间如何修改?
回复

使用道具 举报

22#
ID:93891 发表于 2015-10-28 17:23 | 只看该作者
有图么
回复

使用道具 举报

23#
ID:94340 发表于 2015-11-1 19:14 | 只看该作者
非常好
回复

使用道具 举报

24#
ID:102367 发表于 2016-1-14 14:10 | 只看该作者
admin 发表于 2013-6-17 03:50
下面是主程序:

/**************************************

我要认真的好好学习学习!
回复

使用道具 举报

25#
ID:110278 发表于 2016-3-22 22:32 | 只看该作者
不错,有电路图就更好了。
回复

使用道具 举报

26#
ID:110417 发表于 2016-3-23 19:04 | 只看该作者
好东西呀,正在学习,多谢了
回复

使用道具 举报

27#
ID:111074 发表于 2016-3-27 23:19 | 只看该作者
很不错,值得大家学习
回复

使用道具 举报

28#
ID:151629 发表于 2016-12-3 09:36 | 只看该作者
到底有没有仿真
回复

使用道具 举报

29#
ID:153935 发表于 2016-12-11 18:06 | 只看该作者
很好  学习
回复

使用道具 举报

30#
ID:69481 发表于 2016-12-12 14:22 | 只看该作者
学习下,很不错!
回复

使用道具 举报

31#
ID:127421 发表于 2017-1-2 14:47 | 只看该作者
学习了。
回复

使用道具 举报

32#
ID:171173 发表于 2017-3-16 11:26 | 只看该作者
借鉴了一下,对我学习单片机很有作用,多谢
回复

使用道具 举报

33#
ID:169957 发表于 2017-4-5 14:37 | 只看该作者
24c02是干什么用的
回复

使用道具 举报

34#
ID:238731 发表于 2017-10-31 09:06 | 只看该作者
谢谢楼主的教程,回去好好研究一下~~
回复

使用道具 举报

35#
ID:214494 发表于 2018-1-19 15:45 | 只看该作者
学习一下
回复

使用道具 举报

36#
ID:303520 发表于 2018-5-21 10:37 | 只看该作者
谢谢楼主的教程,正研究2402
回复

使用道具 举报

37#
ID:631767 发表于 2019-10-29 19:37 | 只看该作者
很好,收藏了
回复

使用道具 举报

38#
ID:854719 发表于 2020-12-18 13:52 | 只看该作者
向大佬学习学习
回复

使用道具 举报

39#
ID:1097263 发表于 2023-11-25 10:13 | 只看该作者
谢谢坛主的无私分享,都是干货的。
回复

使用道具 举报

40#
ID:34149 发表于 2023-11-25 22:35 | 只看该作者
学习了,依然在学习的路上!感谢版主和楼主的无私奉献!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表