基于51单片机的家用数字钟温度表仿真

仿真图:

在这里插入图片描述

芯片/模块的特点:

AT89C52简介:
AT89C52是一款经典的8位单片机,是意法半导体(STMicroelectronics)公司生产的一系列单片机之一。它基于8051内核,并具有许多与其兼容的特性。

AT89C52的主要特点如下:

内部存储器:AT89C52具有8KB的闪存(Flash)存储器,可用于存储用户程序和数据。这些存储器的内容可以通过编程器进行编程和擦除。

RAM存储器:AT89C52配备了256字节的随机存取存储器(RAM),用于暂存数据和程序的变量。

外部扩展性:AT89C52支持多种外部扩展设备的连接,包括外部存储器(如RAM、EEPROM)和外设(如ADC、LCD、UART等),通过外部硬件连接,可以扩展单片机的功能和应用。

通用I/O引脚:AT89C52拥有32个可编程的通用输入/输出引脚,可用于连接外部设备和与其他芯片进行通信。

定时器/计数器:AT89C52内置了3个16位定时器/计数器和一个可编程的串行定时器/计数器。这些计时器/计数器可用于实现定时功能、生成脉冲信号、测量时间间隔等。0

串行通信:AT89C52支持串行通信接口,包括UART(串行异步通信)和SPI(串行外设接口),便于与其他设备进行数据通信和交互。

低功耗模式:AT89C52具有多种低功耗模式,如空闲模式和电源下模式,在不需要执行任务的时候可以将CPU进入低功耗状态以节省能量。

宽电源电压范围:AT89C52的工作电压范围通常为4.0V至5.5V,可以满足大多数应用需求。
DS1302特点:
高精度时间计数:DS1302能够提供高精度的实时时钟计数,可以记录年、月、日、星期、小时、分钟和秒等时间信息。它内部集成了晶体振荡器,提供稳定的时钟信号。

低功耗设计:DS1302采用低功耗设计,可以在低功耗模式下运行,有效延长电池寿命。即使在停电情况下,它也能保持时间数据,并通过外部连接电池继续提供计时功能。

串行接口:DS1302通过串行实时时钟接口(SPI)进行通信和控制。使用少数几个引脚,可以与主控器件进行数据交换和时钟同步。

容易集成:DS1302集成了时钟计数和RAM存储器功能,并具有简单的接口和命令,容易与各种微控制器和单片机集成。它不需要复杂的控制信号,可以通过简单的读写命令进行操作。

可编程控制功能:DS1302具有可编程的控制功能,可以设置闹钟、写保护等特殊功能。它还支持多种时间格式的选择,例如24小时制或12小时制。

温度补偿:DS1302内置温度补偿功能,可以校正温度对时钟频率的影响,提高时钟计数的准确性。

高稳定性和抗震动能力:DS1302具有高稳定性和抗震动能力,适用于各种工业和消费类应用场景。

DS18B20特点:

  1. 单总线接口:DS18B20使用单总线接口进行通信,只需要一个引脚就可以连接多个传感器,简化了电路设计和连接。
  2. 数字输出:DS18B20以数字形式输出温度值,不需要额外的模数转换器。它使用12位的分辨率来表示温度值,可以实现高精度的温度测量。
  3. 高精度:DS18B20可以提供从-55°C到+125°C的温度测量范围,并具有±0.5°C的温度精度。因此,在许多应用中,它可以提供可靠和准确的温度测量结果。
  4. 多功能性:除了测量温度,DS18B20还可以执行其他功能,如温度报警功能。它可以设置上下限温度阈值,并在温度超过或低于这些阈值时触发报警。
  5. 低功耗:DS18B20采用低功耗设计,工作电流极低,只需要很少的能量来进行温度测量和通信。
  6. 耐用性:DS18B20具有良好的耐用性和可靠性,其封装材料和结构设计使其适用于各种环境条件下的应用。

主程序:

#include <reg52.h>
#include <intrins.h>
#include "delay.h"
#include "lcd1602.h"
#include "ds1302.h"
#include "eeprom52.h"

#define uchar unsigned char
#define uint unsigned int
#define LCDIO P0

//管脚定义
sbit LCD_RS = P2^0;
sbit LCD_RW = P2^1;
sbit LCD_EN = P2^2;
sbit LED_STATUS = P2^5;
sbit BUZZER = P3^5;
sbit DQ = P1^0; //ds18b20与单片机连接口
sbit KEY_TIMESET = P2^3; //菜单
sbit KEY_ADD = P2^6;	   //加一
sbit KEY_SUB = P2^4;
sbit KEY_ALARMSET = P2^7;
sbit KEY_STOPWATCH = P3^6;

//变量定义
int time10MsCnt = 0, timeSecondCnt = 0, timeMinuteCnt = 0;
uint tempValue; //温度值
uchar data dispTempData[5];
bit isNegative;
bit AlarmSwitch = 0;
uchar row0[] = {"20  -  -  "};
uchar row1[] = {"  :  :  "};
char alarmTime[3] = {0, 0, 0};
unsigned char isNew = 0;
unsigned char g_mode = 0;
unsigned char g_setLocation = 0;
bit refreshTempFlag = 1;
// bit stopwatchFlag = 0;

//函数声明
void DispStopwatch();
void Timer_Init();
void DispTime();
void DS18B20_Delay(unsigned int i);
void DS18B20_Rst();
uchar DS18B20_Read();
void DS18B20_Write(uchar wdata);
uint ReadTemp();
void DispTemp();
void DispAlarmTime();
void KeyScan();
void SetAlarmTime();
void SetTime();

void main()
{
	Init_EEPROM();
    if (!isNew)
    {
        DS1302_Read_Time();
    }
    else
    {
		DS1302_Init();
    }
	LCD_Init();
	LCD_Clear();
	LCD_Write_String(0, 0, row0);
	LCD_Write_String(0, 1, row1);

	Timer_Init();
	//	Init_DS1302();       //将1302初始化
	BUZZER = 1;
	
	while (1)
	{
		if (g_mode == 0) //正常显示时间
		{
			DS1302_Read_Time();
			DispTime();
			if (refreshTempFlag) // 2s刷新一次温度
			{
				TR1 = 0;
				ReadTemp(); //读取温度
				refreshTempFlag = 0;
				TR1 = 1;
			}
			DispTemp(); //显示温度
		}
		else if (g_mode == 1) //显示秒表
		{
			DispStopwatch();
		}
		else if (g_mode == 2) //显示闹钟时间
		{
			SetAlarmTime();
		}
		else if (g_mode == 3) //设置时间
		{
			SetTime();
		}
		else ;

		if (AlarmSwitch == 1)
		{
			if (timeBufDec[4] == alarmTime[0] && timeBufDec[5] == alarmTime[1] && timeBufDec[6] == alarmTime[2])
			{
				BUZZER = 0;
			}
		}

		KeyScan();


	}

}

void DispStopwatch()
{
	LCD_Write_String(0, 0, "    Stopwatch   ");
	LCD_Write_Char(4, 1, timeMinuteCnt / 10 + '0');
	LCD_Write_Char(5, 1, timeMinuteCnt % 10 + '0');
	LCD_Write_Char(6, 1, ':');
	LCD_Write_Char(7, 1, timeSecondCnt / 10 + '0');
	LCD_Write_Char(8, 1, timeSecondCnt % 10 + '0');
	LCD_Write_Char(9, 1, ':');
	LCD_Write_Char(10, 1, time10MsCnt / 10 + '0');
	LCD_Write_Char(11, 1, time10MsCnt % 10 + '0');
}

void DispTime()
{
	row0[2]  = '0' + timeBufDec[1] / 10;
	row0[3]  = '0' + timeBufDec[1] % 10;
	row0[5]  = '0' + timeBufDec[2] / 10;
	row0[6]  = '0' + timeBufDec[2] % 10;
	row0[8]  = '0' + timeBufDec[3] / 10;
	row0[9] = '0' + timeBufDec[3] % 10;

	row1[0]  = '0' + timeBufDec[4] / 10;
	row1[1]  = '0' + timeBufDec[4] % 10;
	row1[3]  = '0' + timeBufDec[5] / 10;
	row1[4]  = '0' + timeBufDec[5] % 10;
	row1[6]  = '0' + timeBufDec[6] / 10;
	row1[7] = '0' + timeBufDec[6] % 10;

	LCD_Write_String(0, 0, row0);
	LCD_Write_String(0, 1, row1);

	switch (timeBufDec[7])
	{
    case 1: LCD_Write_String(12, 0, " Sun"); break;
	case 2: LCD_Write_String(12, 0, " Mon"); break;	
	case 3: LCD_Write_String(12, 0, "Tues"); break;	
	case 4: LCD_Write_String(12, 0, " Wed"); break;	
	case 5: LCD_Write_String(12, 0, "Thur"); break;	
	case 6: LCD_Write_String(12, 0, " Fri"); break;	
	case 7: LCD_Write_String(12, 0, " Sat"); break;		
	}
}

void DS18B20_Rst() /*ds1820复位*/
{
	unsigned char ack = 0;
	DQ = 0;			  //DQ拉低
	DelayUs10x(50); //精确延时 大于 480us 小于960us
	DQ = 1;			  //拉高
	DelayUs10x(6);  //等待电阻上拉
    ack = DQ;       //如果ack=0则初始化成功, ack=1则初始化失败
    while(!DQ);
}

uchar DS18B20_Read() /*读数据*/
{
	unsigned char i = 0;
	unsigned char dat = 0;
	for (i = 8; i > 0; i--)
	{
		DQ = 0; //给脉冲信号
		dat >>= 1;
		DQ = 1; //给脉冲信号
		if (DQ)
			dat |= 0x80;
		DelayUs10x(6); //再延时60us
	}
	return (dat);
}

void DS18B20_Write(uchar wdata) /*写数据*/
{
	unsigned char i = 0;
	for (i = 8; i > 0; i--)
	{
		DQ = 0;
		DQ = wdata & 0x01;
		DelayUs10x(6); //再延时60us
		DQ = 1;
		wdata >>= 1;
	}
}

uint ReadTemp() /*读取温度值并转换*/
{
	uchar a, b;
	DS18B20_Rst();
	DS18B20_Write(0xcc); //*跳过读序列号*/
	DS18B20_Write(0x44); //*启动温度转换*/
	DS18B20_Rst();
	DS18B20_Write(0xcc); //*跳过读序列号*/
	DS18B20_Write(0xbe); //*读取温度*/
	a = DS18B20_Read();
	b = DS18B20_Read();
	tempValue = b;
	tempValue <<= 8;
	tempValue = tempValue | a;
	if (tempValue < 0x0fff)
		isNegative = 0;
	else
	{
		tempValue = ~tempValue + 1;
		isNegative = 1;
	}
	tempValue = tempValue * (0.625); //温度值扩大10倍,精确到1位小数
	return (tempValue);
}

void DispTemp() //温度值显示
{
	uchar flagdat;
	dispTempData[0] = tempValue / 1000 + '0';		 //百位数
	dispTempData[1] = tempValue % 1000 / 100 + '0'; //十位数
	dispTempData[2] = tempValue % 100 / 10 + '0';	 //个位数
	dispTempData[3] = tempValue % 10 + '0';		 //小数位

	if (isNegative == 0)
		flagdat = 0x20; //正温度不显示符号
	else
		flagdat = 0x2d; //负温度显示负号:-

	if (dispTempData[0] == 0x30)
	{
		dispTempData[0] = 0x20; //如果百位为0,不显示
		if (dispTempData[1] == 0x30)
		{
			dispTempData[1] = 0x20; //如果百位为0,十位为0也不显示
		}
	}
	LCD_Write_Char(9, 1, flagdat);
	LCD_Write_Char(10, 1, dispTempData[0]);
	LCD_Write_Char(11, 1, dispTempData[1]);
	LCD_Write_Char(12, 1, dispTempData[2]);
	LCD_Write_Char(13, 1, '.');
	LCD_Write_Char(14, 1, dispTempData[3]);
	LCD_Write_Char(15, 1, 'C');
}

void DispAlarmTime()
{
	if (AlarmSwitch)
	{
		LCD_Write_String(0, 0, " AlarmClock  On ");
	}
	else
	{
		LCD_Write_String(0, 0, " AlarmClock  Off");
	}
	LCD_Write_Char(4, 1, alarmTime[0] / 10 + '0');
	LCD_Write_Char(5, 1, alarmTime[0] % 10 + '0');
	LCD_Write_Char(6, 1, ':');
	LCD_Write_Char(7, 1, alarmTime[1] / 10 + '0');
	LCD_Write_Char(8, 1, alarmTime[1] % 10 + '0');
	LCD_Write_Char(9, 1, ':');
	LCD_Write_Char(10, 1, alarmTime[2] / 10 + '0');
	LCD_Write_Char(11, 1, alarmTime[2] % 10 + '0');

}

void SetAlarmTime()
{
	TR1 = 0;
	LcdWriteCommand(0x0F, 0);
    switch (g_setLocation)
    {
        case 1: LcdWriteCommand(0x80 + 0x40 + 5, 0); break;
        case 2: LcdWriteCommand(0x80 + 0x40 + 8, 0); break;
        case 3: LcdWriteCommand(0x80 + 0x40 + 11, 0); break;
        case 4: LcdWriteCommand(0x0C, 0); DelayMs(5); LCD_Clear(); Write_EEPROM(); g_setLocation = 0; g_mode = 0; break;
		default: ;
    }
	TR1 = 1;
}

void SetTime()
{
	TR1 = 0;
	LcdWriteCommand(0x0F, 0);
    switch (g_setLocation)
    {
        case 1: LcdWriteCommand(0x80 + 3, 0); break;
        case 2: LcdWriteCommand(0x80 + 6, 0); break;
        case 3: LcdWriteCommand(0x80 + 9, 0); break;
        case 4: LcdWriteCommand(0x80 +15, 0); break;
        case 5: LcdWriteCommand(0x80 + 0x40 + 1, 0); break;
        case 6: LcdWriteCommand(0x80 + 0x40 + 4, 0); break;
        case 7: LcdWriteCommand(0x80 + 0x40 + 7, 0); break;
        case 8: LcdWriteCommand(0x0C, 0); DelayMs(5); LCD_Clear(); DS1302_Write_Time(); g_setLocation = 0; g_mode = 0; break;
		default: ;
    }
	TR1 = 1;
}

void KeyScan()
{
	if (!KEY_STOPWATCH) //进入倒计时
	{
		DelayMs(5);
		if (!KEY_STOPWATCH)
		{
			if (g_mode == 0)
			{
				LCD_Clear();
				g_mode = 1;
			}
			else if (g_mode == 1)
			{
				LCD_Clear();
				g_mode = 0;
			}
		}
		while (!KEY_STOPWATCH);
	}

	if (!KEY_TIMESET) //进入倒计时
	{
		DelayMs(5);
		if (!KEY_TIMESET)
		{
			if (g_mode == 0)
			{
				g_mode = 3;
				g_setLocation = 1;
			}
			else if (g_mode == 2)
			{
				AlarmSwitch = ~AlarmSwitch;
			}
			else if (g_mode == 3)
			{
				g_setLocation++;
			}
		}
		while (!KEY_TIMESET);
	}

	if (!KEY_ALARMSET) //进入倒计时
	{
		DelayMs(5);
		if (!KEY_ALARMSET)
		{
			if (g_mode == 0)
			{
				LCD_Clear();
				g_mode = 2;
				g_setLocation = 1;
			}
			else if (g_mode == 1)
			{
				LED_STATUS = 1;
				time10MsCnt = 0;
				timeSecondCnt = 0;
				timeMinuteCnt = 0;
			}
			else if (g_mode == 2)
			{
				g_setLocation++;
			}
		}
		while (!KEY_ALARMSET);
	}


	if (!KEY_ADD)
	{
		DelayMs(5);
		if (!KEY_ADD)
		{
			if (g_mode == 1)
			{
				TR0 = 1;
			}
			else if (g_mode == 2)
			{
				switch (g_setLocation)
				{
					case 1: 
					{
						alarmTime[0]++;
						if (alarmTime[0] > 23)
						{
							alarmTime[0] = 0;
						}
						break;
					}
					case 2: 
					{
						alarmTime[1]++;
						if (alarmTime[1] > 59)
						{
							alarmTime[1] = 0;
						}
						break;
					}
					case 3: 
					{
						alarmTime[2]++;
						if (alarmTime[2] > 59)
						{
							alarmTime[2] = 0;
						}
						break;
					}
				}
			}
			else if (g_mode == 3)
			{
				switch (g_setLocation)
				{
					case 1: 
					{
						timeBufDec[1]++;
						if (timeBufDec[1] > 99)
						{
							timeBufDec[1] = 0;
						}
						break;
					}
					case 2: 
					{
						timeBufDec[2]++;
						if (timeBufDec[2] > 12)
						{
							timeBufDec[2] = 1;
						}
						break;
					}
					case 3: 
					{
						timeBufDec[3]++;
						if (timeBufDec[3] > YDay(timeBufDec[1], timeBufDec[2]))
						{
							timeBufDec[3] = 1;
						}
						break;
					}
					case 4: 
					{
						timeBufDec[7]++;
						if (timeBufDec[7] > 7)
						{
							timeBufDec[7] = 1;
						}
						break;
					}
					case 5: 
					{
						timeBufDec[4]++;
						if (timeBufDec[4] > 23)
						{
							timeBufDec[4] = 0;
						}
						break;
					}
					case 6: 
					{
						timeBufDec[5]++;
						if (timeBufDec[5] > 59)
						{
							timeBufDec[5] = 0;
						}
						break;
					}
					case 7: 
					{
						timeBufDec[6]++;
						if (timeBufDec[6] > 59)
						{
							timeBufDec[6] = 0;
						}
						break;
					}
				}
			}
		}
		else
		{
			BUZZER = 1;
		}
		while (!KEY_ADD);
	}

	if (!KEY_SUB)
	{
		DelayMs(5);
		if (!KEY_SUB)
		{
			if (g_mode == 1)
			{
				TR0 = 0;
			}
			else if (g_mode == 2)
			{
				switch (g_setLocation)
				{
					case 1: 
					{
						if (alarmTime[0] <= 0)
						{
							alarmTime[0] = 24;
						}
						alarmTime[0]--;
						break;
					}
					case 2: 
					{

						if (alarmTime[1] <= 0)
						{
							alarmTime[1] = 60;
						}
						alarmTime[1]--;
						break;
					}
					case 3: 
					{
						if (alarmTime[2] <= 0)
						{
							alarmTime[2] = 60;
						}
						alarmTime[2]--;
						break;
					}
				}
			}
			else if (g_mode == 3)
			{
				switch (g_setLocation)
                    {
                    case 1:
                    {
                        if (timeBufDec[1] == 0)
                        {
                            timeBufDec[1] = 100;
                        }
                        timeBufDec[1]--;
                        break;
                    }
                    case 2:
                    {
                        timeBufDec[2]--;
                        if (timeBufDec[2] < 1)
                        {
                            timeBufDec[2] = 12;
                        }
                        break;
                    }
                    case 3:
                    {
                        timeBufDec[3]--;
                        if (timeBufDec[3] < 1)
                        {
                            timeBufDec[3] = YDay(timeBufDec[1], timeBufDec[2]);
                        }
                        break;
                    }
                    case 4:
                    {
						timeBufDec[7]--;
                        if (timeBufDec[7] < 1)
                        {
                            timeBufDec[7] = 7;
                        }
                        break;
                    }
                    case 5:
                    {
                        if (timeBufDec[4] == 0)
                        {
                            timeBufDec[4] = 24;
                        }
                        timeBufDec[4]--;
                        break;
                    }
                    case 6:
                    {
                        if (timeBufDec[5] == 0)
                        {
                            timeBufDec[5] = 60;
                        }
                        timeBufDec[5]--;
                        break;
                    }
                    case 7:
                    {
                        if (timeBufDec[6] == 0)
                        {
                            timeBufDec[6] = 60;
                        }
						timeBufDec[6]--;
                        break;
                    }
                    default:;
                    }
			}
			else
			{
				BUZZER = 1;
			}
		}
		while (!KEY_SUB);
	}
}

void Timer_Init()
{
	TMOD = 0x11; //T0为定时器方式1 T1为定时器方式1 
	TH0 = (65536 - 9216) / 256;
	TL0 = (65536 - 9216) % 256;
	TH1 = (65536 - 9216) / 256;
	TL1 = (65536 - 9216) % 256;
	ET0 = 1; 
	ET1 = 1;
	TR1 = 1;
	EA = 1;
}

void Timer0_Interrupt() interrupt 1
{
	TH0 = (65536 - 9216) / 256; //10ms
	TL0 = (65536 - 9216) % 256;
	time10MsCnt++;
	if (time10MsCnt >= 100)
	{
		time10MsCnt = 0;
		LED_STATUS = ~LED_STATUS;
		timeSecondCnt = timeSecondCnt + 1;
		if (timeSecondCnt > 59)
		{
			timeSecondCnt = 0;
			timeMinuteCnt = timeMinuteCnt + 1;
			if (timeMinuteCnt > 59)
				timeMinuteCnt = 0;
		}
	}
}

void Timer1_Interrupt() interrupt 3
{
	static unsigned char cnt = 0;
	static unsigned char cnt1 = 0;
	
	TH1 = (65536 - 9216) / 256; //10ms
	TL1 = (65536 - 9216) % 256;

	if (g_mode == 2)
	{
		if (cnt1 >= 10)
		{
			DispAlarmTime();
			cnt1 = 0;
		}
		else
		{
			cnt1++;
		}
	}
	else if (g_mode == 3)
	{
		if (cnt1 >= 10)
		{
			DispTime();
			cnt1 = 0;
		}
		else
		{
			cnt1++;
		}
	}

	if (g_mode == 0)
	{
		if (cnt >= 200)
		{
			refreshTempFlag = 1;
			cnt = 0;
		}
		else
		{
			cnt++;
		}
	}
}

设计文件:

链接:https://pan.baidu.com/s/131u1m-vcKF6w9xOm_RpzwQ?pwd=2mcd

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值