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

第七届蓝桥杯国赛

我的解答

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);
unsigned char PCF8591_Read(unsigned char Address);
void Delay(unsigned char 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;
}
unsigned char PCF8591_Read(unsigned char Address)
{
	unsigned char Data;
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(Address);
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	Data=IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return Data;
}
void Delay(unsigned char x)		//@12.000MHz
{
	unsigned char i, j;
	while(x--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);		
	}
}

ds1302

下面展示一些 内联代码片

ds1302.h
#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]={23,59,55};
	
void DS1302_Init()
{
	DS1302_CE=0;
	DS1302_SCLK=0;
}
void DS1302_WriteByte(unsigned char Command,Data)
{
	unsigned char i;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_IO=Data&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	DS1302_CE=0;
}
unsigned char DS1302_ReadByte(unsigned char Command)
{
	unsigned char i,Data=0x00;
	Command|=0x01;
	DS1302_CE=1;
	for(i=0;i<8;i++)
	{
		DS1302_IO=Command&(0x01<<i);
		DS1302_SCLK=0;
		DS1302_SCLK=1;
	}
	for(i=0;i<8;i++)
	{
		DS1302_SCLK=1;
		DS1302_SCLK=0;
		if(DS1302_IO){Data|=(0x01<<i);};
	}
	DS1302_IO=0;
	DS1302_CE=0;
	return Data;
}
void SetTime()
{
	unsigned char Temp;
	
	DS1302_WriteByte(DS1302_WP,0x00);
	Temp=DS1302_Time[0];
	DS1302_WriteByte(DS1302_Hou,Temp/10*16+Temp%10);
	Temp=DS1302_Time[1];
	DS1302_WriteByte(DS1302_Min,Temp/10*16+Temp%10);
	Temp=DS1302_Time[2];
	DS1302_WriteByte(DS1302_Sec,Temp/10*16+Temp%10);
	DS1302_WriteByte(DS1302_WP,0x80);
}
void ReadTime()
{
	unsigned char Temp;
	Temp=DS1302_ReadByte(DS1302_Hou);
	DS1302_Time[0]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_Min);
	DS1302_Time[1]=Temp/16*10+Temp%16;
	Temp=DS1302_ReadByte(DS1302_Sec);
	DS1302_Time[2]=Temp/16*10+Temp%16;
}

main

main.c
#include <STC15F2K60S2.H>
#include "iic.h"
#include "ds1302.h"
sbit L1=P3^0;
sbit L2=P3^1;
sbit L3=P3^2;
sbit L4=P3^3;

sbit C1=P4^4;
sbit C2=P4^2;
sbit C3=P3^5;
sbit C4=P3^4;
typedef unsigned char u8;
typedef unsigned int u16;
/*----------数码管----------*/
u8 code ledguan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
u8 weixuan,disp[8]={0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff};
/*----------按键----------*/
u8 KN,KTN;
u8 Key();
u8 GetState();
void Key_Loop();
/*----------Rb2----------*/
u8 Rb2,Rb2_count;
/*----------AT24C02----------*/
u8 EEP;
/*----------555测频率----------*/
u16 frq,time;
u16 zheng,fan,zheng_now,fan_now;
bit flag_frq;
/*----------主程序----------*/
u8 Mode;//0:时钟模式 1:电压测量 2:频率测量 3:查询
u8 an_4_count;//按下S4的次数
u8 hour,min,sec;//用于修改的时间

u8 VH=20,VL=10;//V的最大值和最小值

u8 shijian=0;//判断事件是0还是1
u8 sj_hour,sj_min,sj_sec;//事件发生的时间

void Timer0Init(void);
void Timer1Init(void);
void main()
{
	/*----------初始化----------*/
	P2=0x80;P0=0xff;P2=0x00;//LED灯熄灭
	//DS1302初始化
	DS1302_Init();
	SetTime();
//把作品交上去之前先更新一下
//	AT24C02_Write(1,20);
//	Delay(5);
//	AT24C02_Write(2,10);
//	Delay(5);
	
	//EEPROM读取
	ET0=0;
	VH=AT24C02_Read(1);
	VL=AT24C02_Read(2);
	
	shijian=AT24C02_Read(3);
	sj_hour=AT24C02_Read(4);
	sj_min=AT24C02_Read(5);
	sj_sec=AT24C02_Read(6);
	ET0=1;

	//定时器初始化读取
	Timer0Init();
	Timer1Init();
	while(1)
	{
		//时间读取
		ET0=0;
		ReadTime();
		ET0=1;
		/*----------按键模块----------*/
		KTN=Key();
		if(KTN)
		{
			/*----------按下S7----------*/
			if(KTN==7)
			{
				Mode=0;//时钟模块
				//在已经按过S4的前提下,更新时间数据
				if(an_4_count)
				{
					DS1302_Time[0]=hour;
					DS1302_Time[1]=min;
					DS1302_Time[2]=sec;
					SetTime();					
				}
				//S4按键按下次数清零
				an_4_count=0;
			}
			/*----------按下S6----------*/
			if(KTN==6)
			{
				Mode=1;//电压测量模式
				//在已经按过S4的前提下,更新电压阈值数据
				if(an_4_count)
				{
					AT24C02_Write(1,VH);
					Delay(5);
					AT24C02_Write(2,VL);
					Delay(5);
				}
				//S4按键按下次数清零
				an_4_count=0;
			}
			/*----------按下S5----------*/
			if(KTN==5)
			{
				Mode=2;//频率测量模式
				an_4_count=0;//S4按键按下次数清零
			}
			/*----------按下S4----------*/
			if(KTN==4)
			{
				//时钟模式下
				if(Mode==0)
				{
					//第一次按下
					if(an_4_count==0)
					{
						//数码管显示当前数据,时间停止 The World!
						hour=DS1302_Time[0];
						min=DS1302_Time[1];
						sec=DS1302_Time[2];
					}
					//S4anxia次数增加
					an_4_count++;
					//0 1 2 3 1 2 3 1
					if(an_4_count==4)an_4_count=1;
				}
				//频率测量模式下
				if(Mode==1)
				{
					an_4_count++;
					if(an_4_count==3)an_4_count=1;
				}
				//查看模式下
				if(Mode==3)
				{
					an_4_count++;
					if(an_4_count==3)an_4_count=1;
				}
			}
			//如果按下S9,进入查询模式
			if(KTN==9)
			{
				Mode=3;
				an_4_count=0;
			}
			//如果按下S11
			if(KTN==11)
			{
				//如果按过S4,并且时钟模式
				if(an_4_count&&!Mode)
				{
					//如果按过一次,小时增加
					if(an_4_count==1)
					{
						hour++;
						if(hour>=24)
							hour=0;
					}
					//如果按过俩次,分钟增加
					if(an_4_count==2)
					{
						min++;
						if(min>=60)
							min=0;
					}
					//如果按过仨次,分钟增加
					if(an_4_count==3)
					{
						sec++;
						if(sec>=60)
							sec=0;
					}
				}
				//如果按过S4,并且电压测量模式
				if((Mode==1)&&an_4_count)
				{
					//如果按过一次,电压最高阈值增加
					if(an_4_count==1)
					{
						VH+=5;
					}
					//如果按过俩次,电压最低阈值增加
					if(an_4_count==2)
					{
						VL+=5;
					}
				}
				
			}
			//同理
			if(KTN==10)
			{
				if(an_4_count&&!Mode)
				{
					if(an_4_count==1)
					{
						if(hour==0)hour=23;
						else hour--;
					}
					if(an_4_count==2)
					{
						if(min==0)min=59;
						else min--;
					}
					if(an_4_count==3)
					{
						if(sec==0)sec=59;
						else sec--;
					}
				}
				if((Mode==1)&&an_4_count)
				{
					if(an_4_count==1)
					{
						VH-=5;
					}
					if(an_4_count==2)
					{
						VL-=5;
					}
				}
			}
		}
		//时钟模式
		if(!Mode)
		{
			disp[2]=0xbf;
			disp[5]=0xbf;
			//如果按过S4
			if(an_4_count)
			{
				//按一次,闪烁
				if(an_4_count==1)
				{
					if(DS1302_Time[2]%=2)
					{
						disp[0]=ledguan[hour/10%10];
						disp[1]=ledguan[hour%10];		
					}
					else
					{
						disp[0]=0xff;
						disp[1]=0xff;		
					}
				}
				else
				{
					disp[0]=ledguan[hour/10%10];
					disp[1]=ledguan[hour%10];		
				}
				//同理
				if(an_4_count==2)
				{
					if(DS1302_Time[2]%=2)
					{
						disp[3]=ledguan[min/10%10];
						disp[4]=ledguan[min%10];		
					}
					else
					{
						disp[3]=0xff;
						disp[4]=0xff;		
					}
				}
				else
				{
					disp[3]=ledguan[min/10%10];
					disp[4]=ledguan[min%10];		
				}
				//同理
				if(an_4_count==3)
				{
					if(DS1302_Time[2]%=2)
					{
						disp[6]=ledguan[sec/10%10];
						disp[7]=ledguan[sec%10];		
					}
					else
					{
						disp[6]=0xff;
						disp[7]=0xff;		
					}
				}
				else
				{
					disp[6]=ledguan[sec/10%10];
					disp[7]=ledguan[sec%10];		
				}
			}
			else
			{
				disp[0]=ledguan[DS1302_Time[0]/10%10];
				disp[1]=ledguan[DS1302_Time[0]%10];		
				disp[3]=ledguan[DS1302_Time[1]/10%10];
				disp[4]=ledguan[DS1302_Time[1]%10];
				disp[6]=ledguan[DS1302_Time[2]/10%10];
				disp[7]=ledguan[DS1302_Time[2]%10];							
			}
		}
		//电压测量模式
		if(Mode==1)
		{
			if(Rb2_count==200)
			{
				Rb2_count=0;
				Rb2=PCF8591_Read(0x03);
				Rb2=(u8)(Rb2*50.0/255.0);
			}
			if(an_4_count)
			{
				//同理
				if(an_4_count==1)
				{
					if(DS1302_Time[2]%=2)
					{
						disp[0]=ledguan[VH/10%10];
						disp[1]=ledguan[VH%10];
						disp[2]=ledguan[0];
						disp[3]=ledguan[0];
					}
					else
					{
						disp[0]=0xff;
						disp[1]=0xff;
						disp[2]=0xff;
						disp[3]=0xff;
					}
				}
				else
				{
					disp[0]=ledguan[VH/10%10];
					disp[1]=ledguan[VH%10];
					disp[2]=ledguan[0];
					disp[3]=ledguan[0];
				}
				//同理
				if(an_4_count==2)
				{
					if(DS1302_Time[2]%=2)
					{
						disp[4]=ledguan[VL/10%10];
						disp[5]=ledguan[VL%10];
						disp[6]=ledguan[0];
						disp[7]=ledguan[0];
					}
					else
					{
						disp[4]=0xff;
						disp[5]=0xff;
						disp[6]=0xff;
						disp[7]=0xff;
					}
				}
				else
				{
						disp[4]=ledguan[VL/10%10];
						disp[5]=ledguan[VL%10];
						disp[6]=ledguan[0];
						disp[7]=ledguan[0];
				}
			}
			else
			{
				if(Rb2>VH)
				{
					shijian=1;
					sj_hour=DS1302_Time[0];
					sj_min=DS1302_Time[1];
					sj_sec=DS1302_Time[2];
					
					AT24C02_Write(3,1);
					Delay(5);
					AT24C02_Write(4,sj_hour);
					Delay(5);
					AT24C02_Write(5,sj_min);
					Delay(5);
					AT24C02_Write(6,sj_sec);
					Delay(5);
				}
				if(Rb2<VL)
				{
					shijian=0;
					sj_hour=DS1302_Time[0];
					sj_min=DS1302_Time[1];
					sj_sec=DS1302_Time[2];
					
					AT24C02_Write(3,0);
					Delay(5);
					AT24C02_Write(4,sj_hour);
					Delay(5);
					AT24C02_Write(5,sj_min);
					Delay(5);
					AT24C02_Write(6,sj_sec);
					Delay(5);
				}
				
				disp[0]=0xbf;
				disp[1]=ledguan[1];
				disp[2]=0xbf;
				disp[3]=0xff;
				disp[4]=ledguan[Rb2/10%10];
				disp[5]=ledguan[Rb2%10];
				disp[6]=ledguan[0];
				disp[7]=ledguan[0];
			}
		}
		//频率测量
		if(Mode==2)
		{
			disp[0]=0xbf;
			disp[1]=ledguan[2];
			disp[2]=0xbf;
			disp[3]=ledguan[frq/10000%10];
			disp[4]=ledguan[frq/1000%10];
			disp[5]=ledguan[frq/100%10];
			disp[6]=ledguan[frq/10%10];
			disp[7]=ledguan[frq%10];			
		}
		//查询
		if(Mode==3)
		{

			if(an_4_count==2)
			{
				disp[0]=ledguan[sj_hour/10%10];
				disp[1]=ledguan[sj_hour%10];
				disp[2]=0xbf;
				disp[3]=ledguan[sj_min/10%10];
				disp[4]=ledguan[sj_min%10];
				disp[5]=0xbf;
				disp[6]=ledguan[sj_sec/10%10];
				disp[7]=ledguan[sj_sec%10];	
			}
			else
			{
				disp[0]=0xff;
				disp[1]=0xff;
				disp[2]=0xff;
				disp[3]=0xff;
				disp[4]=0xff;
				disp[5]=0xff;
				disp[6]=ledguan[0];
				disp[7]=ledguan[shijian];	
			}
		}
	}
	
}
u8 Key()
{
	u8 Temp;
	Temp=KN;
	KN=0;
	return Temp;
}
u8 GetState()
{
	u8 State=0;
	C1=0;C2=1;C3=1;C4=1;
	if(L1==0)State=7;
	if(L2==0)State=6;
	if(L3==0)State=5;
	if(L4==0)State=4;
	C1=1;C2=0;C3=1;C4=1;
	if(L1==0)State=11;
	if(L2==0)State=10;
	if(L3==0)State=9;
	return State;
}
void Key_Loop()
{
	static u8 Now,Last;
	Last=Now;
	Now=GetState();
	if(!Now&&Last)
	{
		KN=Last;
	}
}
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)		//5微秒@12.000MHz
{
	AUXR = 0xc0;		//定时器时钟1T模式
	TMOD = 0x00;		//设置定时器模式
	TL1 = 0xC4;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 0;		
}


void Timer0_R() interrupt 1
{
	
	static u8 smg_count,key_count;
	static u16 frq_count;
	smg_count++;key_count++;Rb2_count++;
	if(Mode==2)
	{
		frq_count++;
	}
	else
	{
		frq_count=0;
	}
	
	if(smg_count==2)
	{
		smg_count=0;
		P2=0xC0;P0=1<<weixuan;P2=0x00;
		P2=0xE0;P0=0xff;P2=0x00;
		P2=0xE0;P0=disp[weixuan++];P2=0x00;
		weixuan%=8;
	}
	if(key_count==20)
	{
		key_count=0;
		Key_Loop();
	}
	if(frq_count>969)
	{
		TR1=1;
		ET1=1;
		if(frq_count>999)
		{
			frq_count=0;
			TR1=0;
			ET1=0;
			time=5*(zheng_now+fan_now);
			frq=1000000/time;
		}
	}
}
void Timer1_R() interrupt 3
{
	if(P34==1)
	{
		zheng++;
		if(flag_frq)
		{
			flag_frq=0;
			fan_now=fan;
			fan=0;
		}
	}
	if(P34==0)
	{
		fan++;
		if(!flag_frq)
		{
			flag_frq=1;
			zheng_now=zheng;
			zheng=0;
		}
	}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值