蓝桥杯单片机第六届省赛试题温度记录器

蓝桥杯单片机第六届省赛试题温度记录器_第1张图片
用到的驱动程序有onewire ds1302,均为官方驱动的改造使用,调用关系如图,具体需要注意的问题均有注释
蓝桥杯单片机第六届省赛试题温度记录器_第2张图片

#include 
#include "onewire.h"
#include "ds1302.h"
#define uchar unsigned char
#define uint unsigned int
uchar code tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF};
//0 1 2 3 4 5 6 7 8 9 - 灭
uchar code dottab[]={0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0X10};
//带小数点的数字,程序主要用第二位,第六位 0. 1. 2. 3. 4. 5. 6. 7. 8. 9.
uchar yi,er,san,si,wu,liu,qi,ba;
uchar tem[10];//用来存储10个温度数据
uchar tem_n=0;//第n个温度数据
uchar s5=0,s6=0,s7=0;//标志位  s5多种状态 0不采集 1开始采集 2控制led 3空状态
uchar count=1;//循环计数s4 实现温度采集间隔调整
uchar jiange=0;//间隔 1 5 30 60
uchar wendu=0;//温度中间变量
uint  tt=0;//定时器计数,最大计数60*200=12000使用uint
uchar led1=0;
uchar flag1=0;//提示符标志位led1闪烁

void Delay1ms(uchar ms);
void display1(uchar yi,uchar er);
void display2(uchar san,uchar si);
void display3(uchar wu,uchar liu);
void display4(uchar qi,uchar ba);
void allinit();
void keyscan();
void Timer0Init(void);	


void main()
{
	allinit();//板子上电初始化
	Ds1302_init();//时钟初始化
  Timer0Init();//定时器0初始化
	while(1)
	{
		wendu=temget();
		keyscan();//按键扫描
		switch(count)//时间间隔选择
		{
			case 1:jiange=1;break;
			case 2:jiange=5;break;
			case 3:jiange=30;break;
			case 4:jiange=60;count=0;break;
		}
		
		if(s5==0)
		{
		yi=11,er=11,san=11,si=11,wu=11,liu=10,qi=jiange/10,ba=jiange%10;
		}
		 
		if(s5==1)
		{
			Ds1302_gettime();
			yi=time[2]/10;er=time[2]%10;san=10;//提示符1
			si=time[1]/10;wu=time[1]%10;liu=10;//提示符2
			qi=time[0]/10;ba=time[0]%10;
			
			if(time[0]%2==0)//判断时间秒 偶数显示- 奇数灭 实现闪烁
			{
			san=10;liu=10;
			}
			else
			{
			san=11;liu=11;
			}	
			
		}

	 display1( yi, er);
	 display2( san, si);
	 display3( wu, liu);
	 display4( qi, ba);

	}
}

void Delay1ms(uchar ms)		//@12.000MHz  最多延时255ms
{
	unsigned char i, j;
  uchar k;
	for(k=ms;k>0;k--)
	{
	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
	
	}

}




void keyscan()
{
	if(P30==0)//s7
	{
	  Delay1ms(5);//延时消抖
		if(P30==0)
		{
			s5=0;
		}
		while(!P30);
	}
	
	else if(P31==0)//s6
	{
	  Delay1ms(5);
		if(P31==0)
		{
			
			led1=0;				
		}
		while(!P31);
	}
	
	else if(P32==0)//s5
	{
	  Delay1ms(5);
		if(P32==0)
		{
					if(s5==0)
					{
						s5=1;
						tt=0;
						count=1;//重置
					}
		}
		while(!P32);
	}
	
	else if(P33==0)//s4
	{
	 Delay1ms(5);
		if(P33==0)
		{
			count++;
		}
		while(!P33);
	}
	
}

void Timer0Init(void)		//5毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xA0;		//设置定时初值
	TH0 = 0x15;		//设置定时初值
	TF0 = 0;		 //清除TF0标志
	TR0 = 1;		//定时器0开始计时
	EA=1;//开定时器0
	ET0=1;
}

void Timer0() interrupt 1		
{
	tt++;
	if((tt==jiange*200)&&(s5==1))//tt==200一秒,乘对应间隔实现不同采集时间控制
	{
		tt=0;
		tem[tem_n]=wendu;
		tem_n++;
		if(tem_n==10)
		{
			tem_n=0;			
			s5=2;led1=1;//标志位
			yi=10;liu=10;
			si=11;wu=11;
			er=0;san=0;
			qi=tem[0]/10;ba=tem[0]%10;
		}	

	}
	
		if((s5==2)&&(tt==200))
			{
				tt=0;
				if(led1==1)
				{
								if(flag1==0)
								{
									flag1=1;
									P2=0X80;
									P0=0XFE;//LED1开
								}
								else if(flag1==1)
								{
									flag1=0;
									P2=0X80;
									P0=0XFF;//LED1关
								}				
				} 
		    else if(led1==0)
				{
							yi=10;liu=10;
							si=11;wu=11;
							er=tem_n/10;san=tem_n%10;
							qi=tem[tem_n]/10;ba=tem[tem_n]%10;
							tem_n++;
							if(tem_n==10)
							{
								tem_n=0;	
								s5=3;
								
							}		   
				}

				
			}
			
		
}
void display1(uchar yi,uchar er)
{
	P2=0XC0;
	P0=0X01;
	P2=0XE0;
	P0=tab[yi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X02;
	P2=0XE0;
	P0=tab[er];
	Delay1ms(1);
}

void display2(uchar san,uchar si)
{
	P2=0XC0;
	P0=0X04;
	P2=0XE0;
	P0=tab[san];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X08;
	P2=0XE0;
	P0=tab[si];
	Delay1ms(1);

}

void display3(uchar wu,uchar liu)
{
	P2=0XC0;
	P0=0X10;
	P2=0XE0;
	P0=tab[wu];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X20;
	P2=0XE0;
	P0=tab[liu];
	Delay1ms(1);
}

void display4(uchar qi,uchar ba)
{
	P2=0XC0;
	P0=0X40;
	P2=0XE0;
	P0=tab[qi];
	Delay1ms(1);
	
	P2=0XC0;
	P0=0X80;
	P2=0XE0;
	P0=tab[ba];
	Delay1ms(1);
	
  P2=0XC0;//位选
	P0=0XFF;
	P2=0XE0;//段选
	P0=0XFF;//将所有数码管关闭,使其亮度一致,都点亮1ms

}
void allinit()
{
	P2=0X80;
	P0=0XFF;//关LED
	
	P2=0XC0;
	P0=0XFF;
	P2=0XE0;
	P0=0XFF;//关数码管
	
	P2=0XA0;
	P0=0X00;//关蜂鸣器 继电器	
}


onewire

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台
  日    期: 2011-8-9
*/

#include "onewire.h"

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

//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;
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
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;
}
unsigned char temget(void)//添加函数
{
  unsigned char temp;
	unsigned char low,high;
	Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	Delay_OneWire(200);
	
	Init_DS18B20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=((high<<4)|(low>>4));
	return temp;
}



#ifndef _ONEWIRE_H
#define _ONEWIRE_H

#include 

#define OW_SKIP_ROM 0xcc
#define DS18B20_CONVERT 0x44
#define DS18B20_READ 0xbe

//IC引脚定义
sbit DQ = P1^4;

//函数声明
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
bit Init_DS18B20(void);
unsigned char Read_DS18B20(void);
//自己定义函数
unsigned char temget(void);

#endif

ds1302

#include "ds1302.h"
unsigned char time[7];
unsigned char ds[7]={50,59,23,0,0,0,0};
/********************************************************************/ 
/*单字节写入一字节数据*/
void Write_Ds1302_Byte(unsigned char dat) 
{
	unsigned char i;
	SCK = 0;
	for (i=0;i<8;i++) 
	{ 
		if (dat & 0x01) 	// 等价于if((addr & 0x01) ==1) 
		{
			SDA_SET;		//#define SDA_SET SDA=1 /*电平置高*/
		}
		else 
		{
			SDA_CLR;		//#define SDA_CLR SDA=0 /*电平置低*/
		}		 
		SCK_SET;
		SCK_CLR;		
		dat = dat >> 1; 
	} 
}
/********************************************************************/ 
/*单字节读出一字节数据*/
unsigned char Read_Ds1302_Byte(void) 
{
	unsigned char i, dat=0;	
	for (i=0;i<8;i++)
	{	
		dat = dat >> 1;
		if (SDA_R) 	  //等价于if(SDA_R==1)    #define SDA_R SDA /*电平读取*/	
		{
			dat |= 0x80;
		}
		else 
		{
			dat &= 0x7F;
		}
		SCK_SET;
		SCK_CLR;
	}
	return dat;
}

/********************************************************************/ 
/*向DS1302 单字节写入一字节数据*/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{ 

	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;			/*启动DS1302总线,RST=1电平置高 */
	addr = addr & 0xFE;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
	Write_Ds1302_Byte((dat/10<<4)|(dat%10));	 /*写入数据:dat*/
	RST_CLR;				 /*停止DS1302总线*/
}

/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr) 
{ 
	unsigned char temp;
	unsigned char dat1,dat2;
	RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
	SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

	RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
	addr = addr | 0x01;	 
	Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
	temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
	RST_CLR;	/*停止DS1302总线*/
	
	dat1=temp/16;
	dat2=temp%16;
	temp=dat1*10+dat2;
	

//	RST_CLR;	/*读取完一个字节必须停止DS1302总线,否则出错*/
//	SDA_CLR;
   SD=0;	//(即使IO口P2^3=0)
	
	return temp;
}

void Ds1302_init(void)
{
	unsigned char i,add;
	add=0x80;
	Ds1302_Single_Byte_Write(0x8e, 0x00);
	for(i=0;i<7;i++)
{
  Ds1302_Single_Byte_Write(add,ds[i]);
//	add+=2;
	add=add+2;

}
	Ds1302_Single_Byte_Write(0x8e, 0x80);

}

void Ds1302_gettime(void)
{
	unsigned char i,add;
	add=0x81;
	Ds1302_Single_Byte_Write(0x8e, 0x00);
	for(i=0;i<7;i++)
{
  time[i]=Ds1302_Single_Byte_Read(add);
//	add+=2;
  add=add+2;
}
	Ds1302_Single_Byte_Write(0x8e, 0x80);

}



#ifndef  __DS1302_H__
#define  __DS1302_H__

#include 
#include
/********************************************************************/ 
sbit SCK=P1^7;		
sbit SD=P2^3;		
sbit RST=P1^3;
/********************************************************************/ 
/*复位脚*/
#define RST_CLR	RST=0	/*电平置低*/
#define RST_SET	RST=1	/*电平置高*/
/*双向数据*/
#define SDA_CLR	SD=0	/*电平置低*/
#define SDA_SET	SD=1	/*电平置高*/
#define SDA_R	SD	/*电平读取*/	
/*时钟信号*/
#define SCK_CLR	SCK=0	/*时钟信号*/
#define SCK_SET	SCK=1	/*电平置高*/
/********************************************************************/ 
#define ds1302_sec_addr			0x80		//秒数据地址
#define ds1302_min_addr			0x82		//分数据地址
#define ds1302_hr_addr			0x84		//时数据地址
#define ds1302_date_addr		0x86		//日数据地址
#define ds1302_month_addr		0x88		//月数据地址
#define ds1302_day_addr			0x8A		//星期数据地址
#define ds1302_year_addr		0x8C		//年数据地址

#define ds1302_control_addr		0x8Ee		//写保护命令字单元地址
#define ds1302_charger_addr		0x90 		//涓电流充电命令字地址			 
#define ds1302_clkburst_addr	0xBE		//日历、时钟突发模式命令字地址
/********************************************************************/ 

/********************************************************************/ 
/*单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/ 
/*单字节读出一字节数据*/
extern unsigned char Read_Ds1302_Byte(void);
  
/********************************************************************/ 
/********************************************************************/ 
/*向DS1302单字节写入一字节数据*/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/ 
/*从DS1302单字节读出一字节数据*/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);

//自己添加函数
extern void Ds1302_init(void);
extern void Ds1302_gettime(void);

extern unsigned char ds[7];
extern unsigned char time[7];//此处仅对两个数组声明

#endif	 
/********************************************************************/
//		     	END FILE
/********************************************************************/

你可能感兴趣的:(蓝桥杯)