蓝桥杯单片机第八届省赛电子钟(菜鸡的个人纪录)

本程序借鉴了小蜜蜂老师的代码风格。

记录下自己学习过程中的代码。

由于本人水平有限,这也是我做的第一套真题,所以代码可能显得有点蠢,部分地方也比较繁琐,好在功能大体上是实现了(不过在时间和闹钟相同的那一秒里按什么按键都无法停止闪烁,这一点我也懒得改了,其他的地方问题不大)

代码

        main.c

#include "reg52.h"
#include "ds1302.h"
#include "onewire.h"
sfr AUXR=0x8e;
unsigned char write[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char read[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};
unsigned char time[7]={0x55,0x59,0x23,0x15,0x02,0x03,0x24};
unsigned char temp[3]={0x50,0x59,0x23};           //时间初始化
unsigned char temp2[3]={0x00,0x00,0x00};          //闹钟初始化
unsigned char code SMG_NoDot[18]={0xc0,0xf9,
    0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
    0x88,0x80,0xc6,0xc0,0x86,0x8e,0xbf,0x7f};
void HC573(unsigned char a,unsigned char b)
{
	P0=b;
	switch(a)
	{
		case 4:
			P2=(P2&0x1f)|0x80;
		break;
		case 5:
			P2=(P2&0x1f)|0xa0;
		break;
		case 6:
			P2=(P2&0x1f)|0xc0;
		break;
		case 7:
			P2=(P2&0x1f)|0xe0;
		break;
		case 0:
			P2=(P2&0x1f)|0x00;
		break;
	}
	P2=(P2&0x1f)|0x00;
}
void Delay(unsigned int t)       //延时
{
	while(t--);
}
void DisplaySMG(unsigned char pos,unsigned char dat)       //单个数码管显示
{
	HC573(6,(0x01<<pos));
	HC573(7,dat);
	Delay(500);
	HC573(6,(0x01<<pos));
	HC573(7,0xff);
}
void Init1()             //时钟初始化
{
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++)
	{
		Write_Ds1302_Byte(write[i],time[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}
void Read1()           //读取时间
{
	unsigned char i;
	for(i=0;i<7;i++)
	{
		time[i]=Read_Ds1302_Byte(read[i]);
	}
}
unsigned char temperature=0;
void Read_Tem()          //读取温度
{
	unsigned char MSB,LSB;
	unsigned int tem=0;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay(1000);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB=Read_DS18B20();
	MSB=Read_DS18B20();
	tem=MSB;
	tem=(tem<<8)|LSB;
	if((tem&0xf800)==0x0000)
		temperature=tem*0.0625;
}
unsigned char mode=1;        //显示状态
unsigned char n1=0;          //时钟选择位
unsigned char smg=0;         //数码管闪烁
unsigned char led=0xff;      //led状态
unsigned char n2=0;          //闹钟选择位
unsigned char shan=0;        //led闪烁控制
void Display()
{
	switch(mode)
	{
		case 1:             //时间显示
			Read1();
			DisplaySMG(0,SMG_NoDot[(time[2]/16)]);
			DisplaySMG(1,SMG_NoDot[(time[2]%16)]);
			DisplaySMG(2,SMG_NoDot[16]);
			DisplaySMG(3,SMG_NoDot[(time[1]/16)]);
			DisplaySMG(4,SMG_NoDot[(time[1]%16)]);
			DisplaySMG(5,SMG_NoDot[16]);
			DisplaySMG(6,SMG_NoDot[(time[0]/16)]);
			DisplaySMG(7,SMG_NoDot[(time[0]%16)]);
		break;
		case 2:            //时间设置
			if(n1==1)        //选中小时
			{
				if(smg)
				{
					DisplaySMG(0,SMG_NoDot[(temp[2]/16)]);
					DisplaySMG(1,SMG_NoDot[(temp[2]%16)]);
				}
				else
				{
					DisplaySMG(0,0xff);
					DisplaySMG(1,0xff);
				}
			}
			else
			{
				DisplaySMG(0,SMG_NoDot[(temp[2]/16)]);
				DisplaySMG(1,SMG_NoDot[(temp[2]%16)]);
			}
			DisplaySMG(2,SMG_NoDot[16]);
			if(n1==2)       //选中分钟
			{
				if(smg)
				{
					DisplaySMG(3,SMG_NoDot[(temp[1]/16)]);
					DisplaySMG(4,SMG_NoDot[(temp[1]%16)]);
				}
				else
				{
					DisplaySMG(3,0xff);
					DisplaySMG(4,0xff);
				}
			}
			else
			{
				DisplaySMG(3,SMG_NoDot[(temp[1]/16)]);
				DisplaySMG(4,SMG_NoDot[(temp[1]%16)]);
			}
			DisplaySMG(5,SMG_NoDot[16]);
			if(n1==3)          //选中秒钟
			{
				if(smg)
				{
					DisplaySMG(6,SMG_NoDot[(temp[0]/16)]);
					DisplaySMG(7,SMG_NoDot[(temp[0]%16)]);
				}
				else
				{
					DisplaySMG(6,0xff);
					DisplaySMG(7,0xff);
				}
			}
			else
			{
				DisplaySMG(6,SMG_NoDot[(temp[0]/16)]);
				DisplaySMG(7,SMG_NoDot[(temp[0]%16)]);
			}
		break;
		case 3:               //闹钟设置
			if(n2==1)        //选中小时
			{
				if(smg)
				{
					DisplaySMG(0,SMG_NoDot[(temp2[2]/16)]);
					DisplaySMG(1,SMG_NoDot[(temp2[2]%16)]);
				}
				else
				{
					DisplaySMG(0,0xff);
					DisplaySMG(1,0xff);
				}
			}
			else
			{
				DisplaySMG(0,SMG_NoDot[(temp2[2]/16)]);
				DisplaySMG(1,SMG_NoDot[(temp2[2]%16)]);
			}
			DisplaySMG(2,SMG_NoDot[16]);
			if(n2==2)       //选中分钟
			{
				if(smg)
				{
					DisplaySMG(3,SMG_NoDot[(temp2[1]/16)]);
					DisplaySMG(4,SMG_NoDot[(temp2[1]%16)]);
				}
				else
				{
					DisplaySMG(3,0xff);
					DisplaySMG(4,0xff);
				}
			}
			else
			{
				DisplaySMG(3,SMG_NoDot[(temp2[1]/16)]);
				DisplaySMG(4,SMG_NoDot[(temp2[1]%16)]);
			}
			DisplaySMG(5,SMG_NoDot[16]);
			if(n2==3)          //选中秒钟
			{
				if(smg)
				{
					DisplaySMG(6,SMG_NoDot[(temp2[0]/16)]);
					DisplaySMG(7,SMG_NoDot[(temp2[0]%16)]);
				}
				else
				{
					DisplaySMG(6,0xff);
					DisplaySMG(7,0xff);
				}
			}
			else
			{
				DisplaySMG(6,SMG_NoDot[(temp2[0]/16)]);
				DisplaySMG(7,SMG_NoDot[(temp2[0]%16)]);
			}
		break;
		case 4:                //显示温度
			Read_Tem();
			DisplaySMG(5,SMG_NoDot[temperature/10]);
			DisplaySMG(6,SMG_NoDot[temperature%10]);
			DisplaySMG(7,SMG_NoDot[12]);
		break;
	}		
}
void Init2(void)		//50毫秒@11.0592MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x00;		//设置定时初值
	TH0 = 0x4C;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;
	ET0=1;
}

unsigned char t1=0,t2=0,t3=0;
void Service() interrupt 1
{
	if(shan==1)
	{
		t1++;
		if(t1==4)         //0.2s
		{
			if((led&0x01)==0x01)
				led&=~0x01;
			else
				led|=0x01;
			t1=0;
		}
		t2++;
		if(t2==100)       //5s
		{
			shan=0;
			t2=0;
		}
	}
	if((mode==2)||(mode==3))
	{
		t3++;
		if(t3==20)        //1s
		{
			smg=~smg;
			t3=0;
		}
	}
}
void Add()           //加法
{
	if(mode==2)
	{
		switch(n1)
		{
			case 1:
				temp[2] = (temp[2]/16)*10 + temp[2]%16;    //BCD码转十进制
				temp[2]++;
				if(temp[2]>23)
					temp[2]=0;
				temp[2]=(temp[2]/10)*16+temp[2]%10;        //十进制转BCD码
			break;
			case 2:
				temp[1] = (temp[1]/16)*10 + temp[1]%16;     
				temp[1]++;
				if(temp[1]>59)
					temp[1]=0;
				temp[1]=(temp[1]/10)*16+temp[1]%10;
			break;
			case 3:
				temp[0] = (temp[0]/16)*10 + temp[0]%16;  
				temp[0]++;
				if(temp[0]>59)
					temp[0]=0;
				temp[0]=(temp[0]/10)*16+temp[0]%10;
			break;
		}
	}
	if(mode==3)
	{
		switch(n2)
		{
			case 1:
				temp2[2] = (temp2[2]/16)*10 + temp2[2]%16;
				temp2[2]++;
				if(temp2[2]>23)
					temp2[2]=0;
				temp2[2]=(temp2[2]/10)*16+temp2[2]%10;
			break;
			case 2:
				temp2[1] = (temp2[1]/16)*10 + temp2[1]%16;
				temp2[1]++;
				if(temp2[1]>59)
					temp2[1]=0;
				temp2[1]=(temp2[1]/10)*16+temp2[1]%10;
			break;
			case 3:
				temp2[0] = (temp2[0]/16)*10 + temp2[0]%16;
				temp2[0]++;
				if(temp2[0]>59)
					temp2[0]=0;
				temp2[0]=(temp2[0]/10)*16+temp2[0]%10;
			break;
		}
	}
}
void Sub()           //减法
{
	if(mode==2)
	{
		switch(n1)
		{
			case 1:
				temp[2] = (temp[2]/16)*10 + temp[2]%16;
				temp[2]--;
				if(temp[2]==255)
					temp[2]=23;
				temp[2]=(temp[2]/10)*16+temp[2]%10;
			break;
			case 2:
				temp[1] = (temp[1]/16)*10 + temp[1]%16;
				temp[1]--;
				if(temp[1]==255)
					temp[1]=59;
				temp[1]=(temp[1]/10)*16+temp[1]%10;
			break;
			case 3:
				temp[0] = (temp[0]/16)*10 + temp[0]%16;
				temp[0]--;
				if(temp[0]==255)
					temp[0]=59;
				temp[0]=(temp[0]/10)*16+temp[0]%10;
			break;
		}
	}
	if(mode==3)
	{
		switch(n2)
		{
			case 1:
				temp2[2] = (temp2[2]/16)*10 + temp2[2]%16;
				temp2[2]--;
				if(temp2[2]==255)
					temp2[2]=23;
				temp2[2]=(temp2[2]/10)*16+temp2[2]%10;
			break;
			case 2:
				temp2[1] = (temp2[1]/16)*10 + temp2[1]%16;
				temp2[1]--;
				if(temp2[1]==255)
					temp2[1]=59;
				temp2[1]=(temp2[1]/10)*16+temp2[1]%10;
			break;
			case 3:
				temp2[0] = (temp2[0]/16)*10 + temp2[0]%16;
				temp2[0]--;
				if(temp2[0]==255)
					temp2[0]=59;
				temp2[0]=(temp2[0]/10)*16+temp2[0]%10;
			break;
		}
	}
}

void LED_Shan()          //led闪烁
{
	if(shan==1)
	{
		HC573(4,led);
	}
	else
		HC573(4,0xff);
}
void Alarm()            //闹钟判断
{
	if((temp[2]==temp2[2])&&(temp[1]==temp2[1])&&(temp[0]==temp2[0]))  //闹钟与时间相同
	{
			shan=1;
	}
	LED_Shan();
}
sbit S4=P3^3;
sbit S5=P3^2;
sbit S6=P3^1;
sbit S7=P3^0;
void Scan()          //按键检测
{
	int i=0;
	if(S7==0)
	{
		Delay(100);
		if(S7==0)
		{
			shan=0;    
			if(shan==0)
			{
				if(mode==1)
					mode=2;                   //时钟设置
				if(mode==2)
				{
					n1++;
					if(n1==4)
					{
						n1=0;
						mode=1;       
						Write_Ds1302_Byte(0x8e,0x00);
						for(i=0;i<3;i++)
						{
							Write_Ds1302_Byte(write[i],temp[i]);        //将设置的时间写入
						}
						Write_Ds1302_Byte(0x8e,0x80);
					}
				}
			}
			while(S7==0)
				Display();
		}
	}
	if(S6==0)
	{
		Delay(100);
		if(S6==0)
		{
			shan=0;
			if(shan==0)
			{
				if(mode==1)
					mode=3;
				if(mode==3)           //闹钟设置
				{
					n2++;
					if(n2==4)
					{
						mode=1;
						n2=0;
						Write_Ds1302_Byte(0x8e,0x00);
						for(i=0;i<3;i++)
						{
							Write_Ds1302_Byte(write[i],temp[i]);    //将设置闹钟前的时间写入
						}
						Write_Ds1302_Byte(0x8e,0x80);
					}
				}
			}
				while(S6==0)
					Display();
		}
	}
	if(S5==0)
	{
		Delay(100);
		if(S5==0)
		{
			shan=0;
			if(shan==0)
				Add();           //加一
			while(S5==0)
			{
				Display();
			}
		}
	}
	if(S4==0)
	{
		Delay(100);
		if(S4==0)
		{
			shan=0;
			if(shan==0)
				Sub();            //减一
			while(S4==0)
			{
				if(mode==1)
				{
					mode=4;       //显示温度
				}
				Display();
			}
			if(mode==4)
				mode=1;
		}
	}
}
void Init()
{
	HC573(0,0x00);
	HC573(5,0x00);
	HC573(4,0xff);
	HC573(6,0xff);
	HC573(7,0xff);
	Init1();
	Init2();
}
void App()
{
	Read1();
	if(mode==1)                    //实时更新状态2下需要设置的时间
	{
		temp[0]=time[0];
		temp[1]=time[1];
		temp[2]=time[2];
	}
	Alarm();              
}
void main()
{
	Init();
	while(1)
	{
		Scan();
		App();
		Display();
	}
}

        onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

#include "reg52.h"

sbit DQ = P1^4;  

unsigned char rd_temperature(void);  
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);
#endif

        onewire.c

        记得修改延时函数

#include "onewire.h"

//单总线内部延时函数
void Delay_OneWire(unsigned int t)  
{
	t*=12;
	while(t--);
}

//单总线写操作
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//单总线读操作
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//DS18B20初始化
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

        ds1302.h

#ifndef __DS1302_H
#define __DS1302_H

#include <reg52.h>
#include <intrins.h>

sbit SCK = P1^7;		
sbit SDA = P2^3;		
sbit RST = P1^3; 

void Write_Ds1302(unsigned char temp);
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte( unsigned char address );

#endif

        ds1302.c

include "ds1302.h"  									

//写字节
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//向DS1302寄存器写入数据
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

//从DS1302寄存器读出数据
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

  • 11
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值