Proteus仿真小闹钟_C51

简介

这个小假期被作业支配了,最近这段时间也在忙其他东西,没时间更新博客了。为了让别人知道我还在用,我就把一些琐碎但花了我时间的东西输出一下吧!!

介绍

这个是老师的一个小作业,出自郭天祥的《51单片机》第一版第14章。里面介绍了一个使用定时器设计的时钟。现加入更多功能。

功能

  • 支持矩阵键盘直接修改
    书上只能增加或减少,但这里可以用键盘直接改
  • 支持光标到每个数位的切换
    书上只能切换到某两位
  • 支持闹钟设置
    设置闹钟后,当到达指定时间会铃响5s。

演示

在这里插入图片描述

注意问题

设计过程中遇到的一些bug。

多文件结构

  • 头文件只声明变量和函数,在c文件定义和实现函数
    声明时内存未开辟空间,定义后变量才真正拥有空间

  • 防止头文件的重复包含以及变量的重复定义
    这里重复是指文件和变量在同一个源文件被包含两次以上,而不是被多个源文件包含文件和变量。
    使用以下方式可以很方便避免重复:

#ifndef ...
#define ...

#endif

结构体

  • c51的结构体不能带有函数
    本人在b站看了个c++视频说结构体和类是基本类似的,它也举了个例子在里面定义函数,然后我也在c51照做gg。

  • Error: different struct/union
    这个bug就是说存在另一个结构体/联合体符合这种情况,也就是你现在的操作是你这个结构体所不能操作的,比如取里面没有的成员。

AT24C02 仿真时序

  • 注意AT24C02的数据写时间
    在这里插入图片描述
    这里显示这个器件写数据的时间需要1ms,因此在写数据停止信号后要留够一定时间来写数据。如:
    void e2p_write_data(u8 addr, u8 dat)
    {
    	u8 com = 0xa0;
    	e2p_start();
    	e2p_write_byte(com);
    	e2p_at_ack();
    	e2p_write_byte(addr);
    	e2p_at_ack();
    	e2p_write_byte(dat);
    	e2p_at_ack();
    	e2p_stop();
    	e2p_delayms(1); //留1ms
    }
    

主要代码

完整代码见github


void keyscan()
{
	u8 i, j, tmp;
	u16 cnt = 0;
	for(i=0; i<2; i++)
	{
		P1 = ~(0x01 << i);
		tmp = 0x10;
		for(j=0; j<4; j++)
		{
			tmp = (~(0x10 << j)) & 0xf0;
			if((P1 & 0xf0) == tmp)
			{
				delayms(5);
				if((P1 & 0xf0) == tmp)
				{
					beep = 1;
					if(time.time_sta[0] | time.time_sta[1])	//set cur_time	0~7
					{
						time.time6[time.time_pos] = j + i*4;
						write_sfm(time6_lcd[time.time_pos], j + i*4);
					}
				}
				while((P1 & 0xf0) == tmp);
				beep = 0;
			}
		}
	}
	P1 = 0xfb; 
	delayms(1);
	for(j=0; j<2; j++)
	{
		tmp = (~(0x10 << j)) & 0xf0;
		if((P1 & 0xf0) == tmp)
		{
			delayms(5);
			if((P1 & 0xf0) == tmp)
			{
				beep = 1;
				if(time.time_sta[0] | time.time_sta[1])	//set cur_time	8~9
				{
					time.time6[time.time_pos] = j + 8;
					write_sfm(time6_lcd[time.time_pos], j+8);
				}
			}
			while((P1 & 0xf0) == tmp);
			beep = 0;
		}
	}

	switch(P1 & 0xf0)	// ??1??
	{
		case 0xb0:
		{
			delayms(5);
			if((P1 & 0xf0) == 0xb0)
			{
				beep = 1;
				if(time.time_sta[0] || time.time_sta[1])	
				{
					tmp = (time.time6[time.time_pos] < 9 ? ++time.time6[time.time_pos] 
					: time.time6[time.time_pos]);
					write_sfm(time6_lcd[time.time_pos], tmp);
				}
			}
			while((P1 & 0xf0) == 0xb0);
			beep = 0;
			break;
		}
		case 0x70:
		{
			delayms(5);
			if((P1 & 0xf0) == 0x70)
			{
				beep = 1;
				if(time.time_sta[0] || time.time_sta[1])	
				{
					tmp = (time.time6[time.time_pos] > 0 ? --time.time6[time.time_pos]
					: time.time6[time.time_pos]);
					write_sfm(time6_lcd[time.time_pos], tmp);
				}
			}
			while((P1 & 0xf0) == 0x70);
			beep = 0;
			break;
		}
	}
	P1 = 0xf7;
	delayms(1);
	switch(P1 & 0xf0)
	{
		case 0xe0:	//change position
		{
			delayms(5);
			if((P1 & 0xf0) == 0xe0)
			{
				beep = 1;
				if(time.time_sta[0] | time.time_sta[1])
					time.time_pos = (time.time_pos + 1) % 6;
				lcd_write_com(0x0c);
				lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
				lcd_write_com(0x0f);
			}
			while((P1 & 0xf0) == 0xe0);
			beep = 0;
			break;
		}
		case 0xd0:
		{
			delayms(5);
			if((P1 & 0xf0) == 0xd0)
			{
				beep = 1;
				if(time.time_sta[0] | time.time_sta[1])
					time.time_pos = ((--time.time_pos) < 0 ? 5 : time.time_pos);
				lcd_write_com(0x0c);
				lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
				lcd_write_com(0x0f);
			}
			while((P1 & 0xf0) == 0xd0);
			beep = 0;
			break;
		}
		case 0xb0:	//funtion key 1: set time
		{
			delayms(5);
			if((P1 & 0xf0) == 0xb0)
			{
				beep = 1;
				if(time.time_sta[1] == 0)
				{
					while((P1 & 0xf0) == 0xb0)
					{
						delayms(1);
						cnt++;
						if(cnt >= 1000)		key1_1s = 1;
					}
					key1_1s = 0;
					
					if(time.time_sta[0])
					{
						time.time_sta[0] = 0;
						time.time_pos = 5;
						lcd_write_com(0x0c);
						if(cnt < 1000)	//press 1						
							time6_time(&time.cur_time, time.time6);	// count time

						TR0 = 1;
					}
					else
					{
						TR0 = 0;
						time_time6(time.cur_time, time.time6);
						time.time_sta[0]++;
						lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
						lcd_write_com(0x0f);
					}
				}
				beep = 0;
					
			}
			break;
		}
		case 0x70:	//function key2 : set clock
		{
			delayms(5);
			if((P1 & 0xf0) == 0x70)
			{
				beep = 1;
				if(time.time_sta[0] == 0)
				{
					
					while((P1 & 0xf0) == 0x70)
					{
						delayms(1);
						cnt++;
						if(cnt > 1000)
							key2_1s = 1;
						if(cnt > 3000)
							key2_3s = 1;
					}
					key2_1s = 0;
					key2_3s = 0;
					if(cnt > 3000)		//press very long --> activate or deactivate clock 
					{
						time.clock_act = (~time.clock_act) & 0x01;
						if(time.clock_act)
							lcd_write_str(2, 10, on);
						else
							lcd_write_str(2, 10, off);
						time.time_sta[1] = 0;
						time.time_pos = 5;
						lcd_write_com(0x0c);
						TR0 = 1;
					}
					else
					{
						if(time.time_sta[1])	//reset and count
						{
							time.time_sta[1] = 0;
							time.time_pos = 5;
							lcd_write_com(0x0c);
							if(cnt < 1000)		//press last for 1s, cansel set time
								time6_time(&time.clo_time, time.time6);

							TR0 = 1;
						}
						else
						{
							TR0 = 0;
							time_time6(time.cur_time, time.time6);
							time.time_sta[1]++;
							lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
							lcd_write_com(0x0f);
							
						}
					}
					
				}
				beep = 0;
			}
			break;
		}
	}
	
}

//------------------------------------------------------------
//-----------------------------main----------------------------
void main()
{
	u8 first_time;
	u8 beeptime = 100;	//10s
	u8 code date[] = "2020-4-3 Fri";
	beep = 0;
	key1_1s = 0;
	key2_1s = 0;
	key2_3s = 0;
	lcd_init();
	e2p_init();
	lcd_write_str(1,2,date);
	lcd_write_str(2, 10, off);
	first_time = e2p_read_data(0);
	if(first_time != 'a')
	{
		e2p_write_data(0, 'a');
		e2p_write_data(1, time.cur_time.hour);
		e2p_write_data(2, time.cur_time.min);
		e2p_write_data(3, time.cur_time.sec);
	}
	else
	{
		time.cur_time.hour = e2p_read_data(1);
		time.cur_time.min = e2p_read_data(2);
		time.cur_time.sec = e2p_read_data(3);
	}
	write_time(time.cur_time);
	
	configTimer0(50);
	while(1)
	{
		keyscan();
		if(time.clock_act)
		{
			if((time.cur_time.hour == time.clo_time.hour)
				&& (time.cur_time.min == time.clo_time.min) 
			&& (time.cur_time.sec == time.clo_time.sec))
			{
				TR0 = 0;
				beep = 1;
				while(beeptime--)	delayms(50);
				beep = 0;
				beeptime = 100;
				TR0 = 1;
				time.clock_act = 0;
				lcd_write_str(2, 10, off);
			}
		}
	}
		
}

void int0() interrupt 1
{
	static u8 cnt = 0;
	
	if(++cnt == 20)	//1s
	{
		cnt = 0;
		time.cur_time.sec++;
		e2p_write_data(3,time.cur_time.sec);
		if(time.cur_time.sec >= 60)
		{
			time.cur_time.sec = 0;
			time.cur_time.min++;
			if(time.cur_time.min >= 60)
			{
				time.cur_time.min = 0;
				time.cur_time.hour++;
				if(time.cur_time.hour >= 24)
					time.cur_time.hour = 0;
				e2p_write_data(1, time.cur_time.hour);
			}
			e2p_write_data(2, time.cur_time.min);
			
		}
		write_time(time.cur_time);
	}

	TH0 = th0;
	TL0 = tl0;
}

  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 6
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值