第六届省赛-温度记录器

文章描述了一个使用DS1302RTC和DS18B20温度传感器的温度记录器设计,通过两个定时器进行数码管显示亮度控制和温度采集。程序中包含了对独立按键的处理、RTC的读写以及温度数据的存储和显示。此外,还涉及到了中断服务函数和数码管显示的实现。
摘要由CSDN通过智能技术生成

第六届省赛-温度记录器
用了两个定时器,DS1302,DS18B20。学小蜜蜂的教程,代码相似。
在这里插入图片描述

/*	数码管末位过亮,用定时器解决。经测试,1ms较好,末位过亮不明显,
温度采集好像又出了点问题
*/
#include <REG52.H>
#include "ds1302.h"  									
#include <onewire.h>

typedef unsigned char u8;
typedef unsigned int u16;

u8 SMGtab[10] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90}; 
u8 Read_RTC_addr[8] = {0x81,0x83,0x85,0x87,0x89,0x8b,0x8d,0x8f};
u8 Write_RTC_addr[8] = {0x80,0x82,0x84,0x86,0x88,0x8a,0x8c,0x8e};
u8 RTC_TimeData[7] = {0x50,0x59,0x23,0x00,0x00,0x00,0x00};	
					 //秒, 分, 时, 日, 月, 周, 年
u16 temperature_Tab[10] = {0};
sfr AUXR=0x8e;		//定义特殊功能寄存器
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;
sbit L1 = P0^0;

void Delay(u16 t)
{
	while(t--);
}

void SelectChannel(u8 Channel)
{
	switch (Channel)
	{
		case 4:P2 = (P2&0x1f)|0x80;break;	//选通LED
		case 5:P2 = (P2&0x1f)|0xA0;break;	//选通蜂鸣器、继电器等
		case 6:P2 = (P2&0x1f)|0xC0;break;	//选通数码管位选
		case 7:P2 = (P2&0x1f)|0xE0;break;	//选通数码管段选
		default:P2 &= 0x1f;break;			//都不选通
	}
}

void SystemInit()		//初始化
{
	SelectChannel(5);P0 &= 0xBF;		//关闭蜂鸣器,开启为P0 |= 0x40;
	SelectChannel(5);P0 &= 0xEF;		//关闭继电器,开启为P0 |= 0x10;
	SelectChannel(4);P0 = 0xFF;		//关闭LED
}
void Timer0Init(void)		//10毫秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TMOD |= 0x01;		//设置定时器模式
	TL0 = 0x00;		//设置定时初始值
	TH0 = 0xDC;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0不计时		
	
	EA = 1;
	ET0 = 1;
}
void Timer1Init(void)		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0x66;		//设置定时初始值
	TH1 = 0xFC;		//设置定时初始值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1计时		
	
//	EA = 1;
	ET1 = 1;
}
/*********************独立按键开始*********************/
u8 flag_time=0;		//时间切换标志位 0,1,2,3,4	
u8 flag_interface=0;//界面切换标志位	0:计时时间		1:RTC时钟		2:读取温度
u16 sec=0;			//采集间隔 0,1,5,30,60
u8 temperature_bit=0;
void BTN()		//独立按键
{
	if(S4==0 && flag_interface==0)	//切换计时时间
	{
		Delay(100);		//延时消抖
		if(S4==0)
		{
			flag_interface = 0;
			flag_time++;
			if(flag_time>4)
			flag_time=1;
			switch (flag_time)
			{
				case 1:sec=1;break;
				case 2:sec=5;break;
				case 3:sec=30;break;
				case 4:sec=60;break;
				default:sec=0;break;
			}
			while(S4==0);		//按下时停在这里,防止按一次键多次触发该函数
		}
	}
	if(S5==0 && flag_interface==0)	//确认并显示RTC,开始采集温度
	{
		Delay(100);
		if(S5==0)
		{
			flag_interface = 1;
			TR0 = 1;	//定时器0开始计时
			while(S5==0);
		}
	}
	if(S6==0 && flag_interface!=0)	//L1熄灭
	{
		Delay(100);
		if(S6==0)
		{
			temperature_bit++;
			if(temperature_bit > 9)
			{
				temperature_bit = 0;
			}
			
			flag_interface = 2;
			TR0 = 0;	//定时器0停止计时
			P0=0xff;
			SelectChannel(4);
			while(S6==0);
		}
	}
	if(S7==0 && flag_interface==2)	//返回采集间隔界面,用于下一次采集
	{
		Delay(100);
		if(S7==0)
		{
			flag_interface = 0;
			while(S5==0);
		}
	}

}
/*********************独立按键结束*********************/
/*********************DS1302开始*********************/
u8 i;
void DS1302_Init()
{
	Write_Ds1302_Byte(Write_RTC_addr[7],0x00 );	//(0x8e,0x00)关闭写保护
	for(i=0;i<6;i++)
	{
		Write_Ds1302_Byte(Write_RTC_addr[i],RTC_TimeData[i] );
	}	
	Write_Ds1302_Byte(Write_RTC_addr[7],0x80 );	//(0x8e,0x80)开启写保护
}
void DS1302_Read()
{
	for(i=0;i<6;i++)
	{
		RTC_TimeData[i] = Read_Ds1302_Byte (Read_RTC_addr[i]);
	}	
}
/*********************DS1302结束*********************/
/*********************DS18B20开始*********************/
u16 temperature;

void Read_DS18B20_temperature()
{
	u8 LSB,MSB;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	Delay(1000);	
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xBE);

	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	
	temperature = MSB;
	temperature = (temperature << 8) | LSB;
	
	if((temperature & 0xf800) == 0x0000)
	{
		temperature >>= 4;
		temperature = temperature*10;
		temperature = temperature + (LSB & 0x0f) * 0.625;	//小数部分转化为浮点数,右移四位,*10,再转换为整型加到温度上
	}
}
/*********************DS18B20结束*********************/
/*********************数码管开始*********************/
bit flag_BlinkBar=1;	//数码管“-”闪烁标志位

void SMGbit(u8 n,u8 value)
{
	SelectChannel(6);P0 = 0x01<<n;		//位选
	SelectChannel(7);P0 = value;		//段选
	Delay(500);						//消影
}

void SMG_Time()
{
	if(flag_interface == 0)		//采集间隔时间显示
	{
		SMGbit(5,0xBF);	//-
	
		SMGbit(6,SMGtab[sec/10]);	//sec十位
		SMGbit(7,SMGtab[sec%10]);	//sec个位
	}
	if(flag_interface == 1)		//RTC时钟
	{
		SMGbit(0,SMGtab[RTC_TimeData[2] >> 4]);		//hour十位
		SMGbit(1,SMGtab[RTC_TimeData[2] & 0x0f]);	//hour个位
		
		if(flag_BlinkBar == 1)
		{
			SMGbit(2,0xBF);	//“-”
		}
		else
		{
			SMGbit(2,0xFF);	//灭
		}
		
		SMGbit(3,SMGtab[RTC_TimeData[1] >> 4]);		//min十位
		SMGbit(4,SMGtab[RTC_TimeData[1] & 0x0f]);	//min个位
		
		if(flag_BlinkBar == 1)
		{
			SMGbit(5,0xBF);	//“-”
		}
		else
		{
			SMGbit(5,0xFF);	//灭
		}
		
		SMGbit(6,SMGtab[RTC_TimeData[0] >> 4]);		//sec十位
		SMGbit(7,SMGtab[RTC_TimeData[0] & 0x0f]);	//sec个位
	}
	if(flag_interface == 2)
	{
		SMGbit(0,0xBF);	//“-”
		SMGbit(1,SMGtab[temperature_bit/10]);		
		SMGbit(2,SMGtab[temperature_bit%10]);		

		
		SMGbit(5,0xBF);	//“-”
		SMGbit(6,SMGtab[(temperature_Tab[temperature_bit]/100)%10]);		//温度十位
		SMGbit(7,SMGtab[(temperature_Tab[temperature_bit]/10)%10]);		//温度个位
	}
}
/*********************数码管结束*********************/

void main()
{
	SystemInit();
	Timer0Init();
	Timer1Init();
	DS1302_Init();
	while(1)
	{
		BTN();
		DS1302_Read();
		Read_DS18B20_temperature();
	}
}

u16 count;		//定时器计数,每10ms加一,以达到预定时间
bit flagLED=1;	//LED亮灭标志位。这样更严谨,因为L1=~L1;有时候会有问题。

void Timer0Int() interrupt 1		//定时器0中断每10ms执行一次该函数
{
		count++;
		if(count%50 == 0)		//if(count == 50)这种写法不是每0.5s执行一次,应该写成if(count%50 == 0)	
		{
			flag_BlinkBar = ~flag_BlinkBar;
		}
		if(count == 100 && sec > 0)
		{
			count=0;
			sec--;
			for(i=0;i<10;i++)
			{
				temperature_Tab[i] = temperature;
			}
		}
		if(count == 50 && sec == 0)
		{
			count=0;
			P0=0xff;
			SelectChannel(4);
			flagLED=~flagLED;
			L1=flagLED;		
		}
		TL0 = 0x00;		//设置定时初始值	
		TH0 = 0xDC;		//设置定时初始值
}

void Timer1Int() interrupt 3		//定时器1中断每1ms执行一次该函数
{
	SMG_Time();
	TL1 = 0x66;		//设置定时初始值		//经测试,1ms较好
	TH1 = 0xFC;		//设置定时初始值
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
蓝桥杯单片机第十一届省赛题目要求参赛选手使用单片机实现一个特定的功能,具体要求可能会随着每一届比赛的不同而有所变化。在回答此问题时,需要明确具体的题目要求和实现功能,并进行详细的说明。 由于没有提供具体的第十一届省赛题目的信息,我无法给出具体的答案。不过,可以给出一个示例性的回答来说明如何回答此类问题。 示例回答: 根据蓝桥杯单片机第十一届省赛题目要求,我们的任务是设计一个智能家居控制系统。该系统需要能够实现以下功能: 1. 控制家中的照明系统:可以通过单片机控制灯的开关,调节灯的亮度和颜色。 2. 控制家中的窗帘系统:可以通过单片机控制窗帘的升降和角度。 3. 监测室内温湿度:单片机需要连接温湿度传感器,实时获取室内的温度和湿度数据,并可以进行显示或记录。 4. 天气预报功能:通过网络模块连接互联网,获取实时的天气数据,并在单片机上进行显示或语音输出。 5. 安全警报系统:单片机需要能够检测门窗是否关闭,若有异常情况,比如门窗未关闭或有人非法进入,则触发警报。 6. 远程控制功能:通过手机APP或网页,可以远程控制智能家居系统。 根据以上的题目要求,我们可以先设计硬件部分,选择合适的传感器和执行器,并将其与单片机进行连接。然后,编写相应的代码,实现上述功能。最后,进行调试和测试,确保系统的正常运行和功能完备。 这仅为一个示例回答,具体的第十一届省赛题目要求可能与此不同。如需了解具体题目要求,请参考官方的赛题公告。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值