单片机----第四届蓝桥杯国赛

题目

在这里插入图片描述

我的解答

DS1302

DS1302.h
#ifndef __DS1302_H__
#define __DS1302_H__
extern unsigned char DS1302_Time[3];
void DS1302_Init();
void SetTime();
void ReadTime();
#endif
DS1302.C
#include <STC15F2K60S2.H>

#define DS1302_Sec 0x80
#define DS1302_Min 0x82
#define DS1302_Hou 0x84
#define DS1302_WP  0x8E

sbit DS1302_SCLK=P1^7;
sbit DS1302_IO=P2^3;
sbit DS1302_CE=P1^3;
unsigned char DS1302_Time[3]={11,50,59};
void DS1302_Init()
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
void DS1302_Write(unsigned char Command,Data)
{
	unsigned char k;
	DS1302_CE=1;
	for(k=0;k<8;k++)
	{
		DS1302_IO=Command&(0x01<<k);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(k=0;k<8;k++)
	{
		DS1302_IO=Data&(0x01<<k);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	DS1302_CE=0;
}
unsigned char DS1302_Read(unsigned char Command)
{
	unsigned char k,Data=0x00;
	Command|=0x01;
	DS1302_CE=1;
	for(k=0;k<8;k++)
	{
		DS1302_IO=Command&(0x01<<k);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(k=0;k<8;k++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<k);};
	}
	DS1302_IO=0;
	DS1302_CE=0;
	
	return Data;
}
void SetTime()
{
	unsigned char Temp;
	DS1302_Write(DS1302_WP,0x00);
	
	Temp=DS1302_Time[0];
	DS1302_Write(DS1302_Hou,Temp/10*16+Temp%10);
	
	Temp=DS1302_Time[1];
	DS1302_Write(DS1302_Min,Temp/10*16+Temp%10);
	
	Temp=DS1302_Time[2];
	DS1302_Write(DS1302_Sec,Temp/10*16+Temp%10);
	
	DS1302_Write(DS1302_WP,0x80);
}
void ReadTime()
{
	unsigned char Temp;
	Temp=DS1302_Read(DS1302_Hou);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_Read(DS1302_Min);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_Read(DS1302_Sec);
	DS1302_Time[2]=Temp/16*10+Temp%16;
}

iic

iic.h
#ifndef __IIC_H__
#define __IIC_H__

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendAck(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 
void AT24C02_Write(unsigned char Address,Data);
unsigned char AT24C02_Read(unsigned char Address);
void Delay1ms(unsigned int x);
#endif
iic.c
/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台 8051,12MHz
  日    期: 2011-8-9
*/

#include "reg52.h"
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
    SDA = 0;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//发送应答
void IIC_SendAck(bit ackbit)
{
    SCL = 0;
    SDA = ackbit;  					// 0:应答,1:非应答
    IIC_Delay(DELAY_TIME);
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SCL = 0; 
    SDA = 1;
    IIC_Delay(DELAY_TIME);
}

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
    unsigned char i, da;
    for(i=0; i<8; i++)
    {   
    	SCL = 1;
	IIC_Delay(DELAY_TIME);
	da <<= 1;
	if(SDA) da |= 1;
	SCL = 0;
	IIC_Delay(DELAY_TIME);
    }
    return da;    
}

void AT24C02_Write(unsigned char Address,Data)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(Address);
	IIC_WaitAck();
	IIC_SendByte(Data);
	IIC_WaitAck();
	IIC_Stop();
}
unsigned char AT24C02_Read(unsigned char Address)
{
	unsigned char Data;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(Address);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	Data=IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return Data;
}
void Delay1ms(unsigned int x)		//@12.000MHz
{
	unsigned char i, j;

	while(x--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);		
	}

}

Timer

Timer.h
#ifndef __Timer_H__
#define __Timer_H__
void Timer0Init(void);
void Timer1Init(void);
#endif
Timer.c
#include <STC15F2K60S2.H>

void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR = 0xc0;		//定时器时钟1T模式
	TMOD = 0x00;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	
	EA=1;
	ET0=1;
}

void Timer1Init(void)		//1毫秒@12.000MHz
{
	AUXR = 0xc0;		//定时器时钟1T模式
	TMOD = 0x00;		//设置定时器模式
	TL1 = 0x00;		//设置定时初值
	TH1 = 0x00;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 0;		//定时器1开始计时
}

主程序

main.c
#include <STC15F2K60S2.H>
#include "Timer.h"
#include "DS1302.h"
#include "iic.h"
typedef unsigned char u8;
typedef unsigned int u16;
	
sbit A1=P1^0;
sbit B1=P1^1;
u8 code ledguan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 wei_xuan,disp[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};

u8 KN,KTN,KeyN;
u8 Key();
u8 GetState();
void Key_Loop();

u16 length=999,time,wave_count,length_din=300;
void Start();
void delay(u8 i);
void Pros();
void Wave_Rec();

bit Mode=0,xiugai_t;
u8 DS_an_count=0;
bit Wave_an_count=0;
u8 hour,min,sec;
u16 led_count=0;
bit led;

bit fmq,fmqq;
u16 fmq_count;
void main()
{
	P2=0x80;P0=0xfe;P2=0x00;
	P2=0xc0;P0=0xff;P2=0x00;
	P2=0xe0;P0=0x00;P2=0x00;
	P2=0xa0;P0=0x40;P2=0x00;
	Delay1ms(1000);
	P2=0X80;P0=0xff;P2=0x00;
	P2=0xc0;P0=0xff;P2=0x00;
	P2=0xe0;P0=0xff;P2=0x00;
	P2=0xa0;P0=0x00;P2=0x00;
	
	Timer0Init();
	Timer1Init();
	DS1302_Init();
	SetTime();
	
//	ET0=0;
//	AT24C02_Write(1,12);
//	Delay1ms(10);
//	KN=AT24C02_Read(1);
//	ET0=1;
//	
//	disp[0]=ledguan[KN/10%10];
//	disp[1]=ledguan[KN%10];
	while(1)
	{
		Wave_Rec();
		KN=Key();
		if(KN)
		{
			switch(KN)
			{
				case 7:
					Mode=!Mode;
				break;
				case 6:
					if(!Mode)
					{
						if(DS_an_count==0)
						{
							hour=DS1302_Time[0];
							min=DS1302_Time[1];
							sec=DS1302_Time[2];							
						}
						xiugai_t=1;
						DS_an_count++;
						DS_an_count%=3;
						if(DS_an_count==0)
						{
							xiugai_t=0;
							DS1302_Time[0]=hour;
							DS1302_Time[1]=min;
							DS1302_Time[2]=sec;
							SetTime();
						}
					}
					else
					{
						if(Wave_an_count)
						{
							AT24C02_Write(1,(u8)length_din);
							Delay1ms(10);
						}
						Wave_an_count=!Wave_an_count;
					}
						break;
				case 5:
					if(!Mode&&DS_an_count)
					{
						if(DS_an_count==1)
						{
							hour++;
							hour%=24;
						}
						else if(DS_an_count==2)
						{
							min++;
							min%=60;
						}
					}
					else if(Mode&&Wave_an_count)
					{
						length_din++;
					}
					break;
				case 4:
					if(!Mode&&DS_an_count)
					{
						if(DS_an_count==1)
						{
							if(hour==0)hour=23;
							else hour--;
						}
						else if(DS_an_count==2)
						{
							if(min==0)min=59;
							else min--;
						}
					}
					else if(Mode&&Wave_an_count)
					{
						length_din--;
					}
				default:
					break;
			}
		}		
		if(!Mode)
		{
			ET0=0;
			ReadTime();
			ET0=1;

			if(!xiugai_t)
			{
				disp[0]=ledguan[DS1302_Time[0]/10%10];
				disp[1]=ledguan[DS1302_Time[0]%10];	
				disp[2]=0xbf;
				disp[3]=ledguan[DS1302_Time[1]/10%10];
				disp[4]=ledguan[DS1302_Time[1]%10];				
				disp[5]=0xbf;
				disp[6]=ledguan[DS1302_Time[2]/10%10];
				disp[7]=ledguan[DS1302_Time[2]%10];					
			}
			else
			{
				if(DS_an_count==1&&DS1302_Time[2]%2)
				{
					disp[0]=0xff;
					disp[1]=0xff;
				}
				else
				{
					disp[0]=ledguan[hour/10%10];
					disp[1]=ledguan[hour%10];						
				}
				disp[2]=0xbf;
				
				if(DS_an_count==2&&DS1302_Time[2]%2)
				{
					disp[3]=0xff;
					disp[4]=0xff;
				}
				else
				{
					disp[3]=ledguan[min/10%10];
					disp[4]=ledguan[min%10];						
				}
				disp[5]=0xbf;
				disp[6]=ledguan[sec/10%10];
				disp[7]=ledguan[sec%10];
			}
		}
		else
		{
			
			if(!Wave_an_count)
			{
				
				disp[0]=ledguan[length/100%10];
				disp[1]=ledguan[length/10%10]&0x7f;
				disp[2]=ledguan[length%10];		
				disp[3]=0xff;			
				disp[4]=0xff;
				disp[5]=0xff;
				disp[6]=0xff;
				disp[7]=0xff;				
			}
			else
			{
				disp[0]=0xff;			
				disp[1]=0xff;
				disp[2]=0xff;				
				disp[3]=0xbf;			
				disp[4]=0xbf;
				disp[5]=ledguan[length_din/100%10];
				disp[6]=ledguan[length_din/10%10]&0x7f;
				disp[7]=ledguan[length_din%10];	
			}

		}
		if(length<length_din)
		{
			fmq=1;			
		}
		
		else
		{
			fmq=0;
		}
		if(fmq)fmqq=1;
		if(fmq_count<1000&&fmqq)
		{
			P2=0xa0;P0=0x40;P2=0X00;
		}
		else if(fmq_count>=1000)
		{
			if(!fmq)
			{
				fmq_count=0;
				fmqq=0;
				P2=0xa0;P0=0x00;P2=0X00;
			}
			
		}
		if(length<(u16)(1.2*length_din))led=1;
		else {led=0;led_count=0;}
		if(led_count<500)
		{
			P2=0x80;P0=0xff;P2=0x00;
		}
		else if(led_count<1000)
		{
			P2=0x80;P0=0xfe;P2=0x00;
		}
		else
		{
			led_count=0;
		}
	}
}
u8 Key()
{
	u8 Temp;
	Temp=KeyN;
	KeyN=0;
	return Temp;
}
u8 GetState()
{
	u8 State=0;
	if(P30==0)State=7;
	if(P31==0)State=6;
	if(P32==0)State=5;
	if(P33==0)State=4;
	return State;
}
void Key_Loop()
{
	static u8 Now,Last;
	Last=Now;
	Now=GetState();
	if(!Now&&Last)
	{
		KeyN=Last;
	}
}

void Start()
{
	u8 k;
	A1=0;
	for(k=0;k<10;k++)
	{
		A1^=1;
		delay(1);
	}

}
void delay(u8 i)
{
	u8 k;
	while(i--)
		for(k=0;k<12;k++);
}
void Pros()
{
	if(TF1)
	{
		TF1=0;
		length=999;
	}
	else
	{
		time=(TH1<<8)|TL1;
		length=(u16)time*0.17;
		length/=12;
	}
	TH1=0;
	TL1=0;
}
void Wave_Rec()
{
	if(wave_count>350)
	{
		wave_count=0;
		Start();
		TR1=1;
		while(B1&&!TF1);
		TR1=0;
		Pros();
	}

}
void Timer0_R() interrupt 1
{
	static u8 smg_count,key_count;
	smg_count++;key_count++;wave_count++;
	if(smg_count==2)
	{
		smg_count=0;
		P2=0xc0;P0=1<<wei_xuan;P2=0x00;
		P2=0xe0;P0=0xff;P2=0x00;
		P2=0xe0;P0=disp[wei_xuan++];P2=0x00;
		wei_xuan%=8;
	}
	if(key_count>=20)
	{
		key_count=0;
		Key_Loop();
	}
	if(led)
	{
		led_count++;
	}
	if(fmqq)
	{
		fmq_count++;
	}
}
	

总结

与自己以前的代码相比

定时器初始化函数更新

	AUXR = 0xc0;		//定时器时钟1T模式
	TMOD = 0x00;		//设置定时器模式

由于我同时用了定时器1和定时器0,所以这样写会好一点

做题目中的一些思考

本届题目比第三届题目还简单,但是我手里的这个pdf版本的题目看起来不像是正版题目,不管那么多了,做就完事了。

我把警报设置为达到条件之后蜂鸣器响一秒钟,实现的方式是定时器计时。

if(length<length_din)//如果满足条件
		{
			fmq=1;			//蜂鸣器响一秒钟
		}
		
		else
		{
			fmq=0;//否则不响
		}
		if(fmq)fmqq=1;//响一秒钟,即使在一秒钟内不符合条件也会响
		if(fmq_count<1000&&fmqq)//如果<1s且该响
		{
			P2=0xa0;P0=0x40;P2=0X00;//响
		}
		else if(fmq_count>=1000)//>1s
		{
			if(!fmq)//再次判断是否需要响
			{
				fmq_count=0;//不要响,计时归零
				fmqq=0;
				P2=0xa0;P0=0x00;P2=0X00;//不响
			}
			
		}

与此同时,在定时器中断中。

	if(fmqq)
	{
		fmq_count++;
	}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值