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;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章