蓝桥杯单片机第五届省赛简易温度采集与控制装置

蓝桥杯单片机第五届省赛简易温度采集与控制装置_第1张图片
主要设计对DS18B20官方驱动的改动和矩阵键盘的逻辑操作,难度不大,主要涉及逻辑问题。
DS18B20官方驱动的改动后如下

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

#include "onewire.h"

//单总线延时函数
//void Delay_OneWire(unsigned int t)
//{
//	unsigned char i =0;
//  	while(t--)
//   		for(i=0;i<12;i++);//扩大12倍延时
//}

void Delay_OneWire(unsigned int t)
{
    t=12*t;//扩大12倍延时
  	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;
}


void Delay1ms()		//@12.000MHz
{
	unsigned char i, j;

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

unsigned char temget(void)//温度获取
{
	unsigned char temp;
	unsigned char low,high;
	
	Init_DS18B20();
    Write_DS18B20(0xcc);//忽略rom指令
	Write_DS18B20(0x44);//开始温度转换
    Delay1ms();//等待1ms温度转换

	Init_DS18B20();
    Write_DS18B20(0xcc);//忽略rom指令
	Write_DS18B20(0xbe);//读取暂存器直到9字节
	low=Read_DS18B20();//温度数据16位存储,小数部分在低四位,符号在高四位。在此均不需要
	high=Read_DS18B20();
	
	temp=((high<<4)|(low>>4));//DS18B20数据存储为低位到高位
	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);//温度获取
void Delay1ms();		//@12.000MHz
#endif
#include 
#include "onewire.h"
#define uchar unsigned char
#define uint unsigned int

uchar code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xbf,0xff};
uchar yi,er,san,si,wu,liu,qi,ba;
uchar temp;//矩阵键盘中间变量
uchar tmax=30,tmin=20;
uchar led1=0;//指示灯和继电器标志位
uchar tt=0;//计数
uchar open=0;//L1打开标志位
uchar num=0;
uchar set=0;//设置
uchar clean=0;//清除
uchar flag=0;//按键是否按下标志位

void allinit();
void Delay1ms(uchar z);
void displayer1(uchar yi,uchar er);
void displayer2(uchar san,uchar si);
void displayer3(uchar wu,uchar liu);
void displayer4(uchar qi,uchar ba);
void Timer0Init(void);
void keyscan16();



void main()
{
	uchar tem;//温度
	allinit();//板子初始化
	Timer0Init();//定时器初始化
	EA=1;//开总中断
	ET0=1;//开定时器0
	
	while(1)
 {
		keyscan16();//矩阵键盘
		if(set==0)
		{
				tem=temget();//获取温度
				if(tem=tmin)&&(tem<=tmax))		
				{
				// er=1;
				 led1=1;
				}
				else if(tem>tmax)
				{
				//er=2;
				led1=2;
				}
		    yi=10,er=led1,san=10,si=11,wu=11,liu=11,qi=tem/10,ba=tem%10;//温度状态显示				
							
		}
		else if(set==1)
		{		
			if(clean==1)
			{
				clean=0;
				yi=10,er=11,san=11,si=11,wu=11,liu=10,qi=11,ba=11;//按下清除按键进入设置界面
			
			}
					if((er==11)&&(flag==1))//获取按键值
					{
					 flag=0;
					 er=num;
					}
					else	if((san==11)&&(flag==1))
					{
					 flag=0;
					 san=num;
					}
					else	if((qi==11)&&(flag==1))
					{
					 flag=0;
					 qi=num;
					}
					else if((ba==11)&&(flag==1))
					{
					 flag=0;
					 ba=num;
					 if((er*10+san)<(qi*10+ba))//确保tmax>tmin
					 {
						yi=10,er=11,san=11,si=11,wu=11,liu=10,qi=11,ba=11;//如果tmax0;k--)
	{
	i = 12;
	j = 169;
	do
	{
		while (--j);
	} while (--i);
	
	}

}


void displayer1(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 displayer2(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 displayer3(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 displayer4(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 Timer0Init(void)		//5毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xA0;		//设置定时初值
	TH0 = 0x15;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
}

void timer0() interrupt 1//中断服务函数
{
	tt++;
	if(led1==0)
	{
	P2=(P2&0x1f)|0xa0;
	P0=0X00;//关闭继电器
	P2=P2&0x1f;
	   if(tt==160)
		{
			 tt=0;
			 if(open==0)
					 {
					 open=1;
					 P2=(P2&0x1f)|0x80;
					 P0=0XFE;//打开L1
					 P2=P2&0x1f;
					 }
			 else
					 {
						open=0;
						P2=(P2&0x1f)|0x80;
						P0=0XFF;//关闭L1
						P2=P2&0x1f;
					 } 
		 }
	}
	if(led1==1)
	{
	P2&=0X1F;
	P2=(P2&0x1f)|0xa0;
	P0=0X00;//关闭继电器
			P2=P2&0x1f;
	   if(tt==80)
		{
			 tt=0;
			 if(open==0)
					 {
					 open=1;
					 P2=(P2&0x1f)|0x80;
					 P0=0XFE;//打开L1
						 	P2=P2&0x1f;
					 }
			 else
					 {
						open=0;
						P2=(P2&0x1f)|0x80;
						P0=0XFF;//关闭L1
						P2=P2&0x1f;
					 } 
		 }
	}
	
	if(led1==2)
	{
	P2=(P2&0x1f)|0xa0;
	P0=0X10;//开继电器
			P2=P2&0x1f;
	   if(tt==40)
		{
			 tt=0;
			 if(open==0)
					 {
					 open=1;
					 P2=(P2&0x1f)|0x80;
					 P0=0XFE;//打开L1
					 P2=P2&0x1f;
					 }
			 else
					 {
						open=0;
						P2=(P2&0x1f)|0x80;
						P0=0XFF;//关闭L1
						P2=P2&0x1f;
					 } 
		 }
	}

}

//矩阵键盘模块
void keyscan16()
{
	//第一列
	P3=0X7F;P4=0XEF;//P44=0
	temp=P3;
	temp=temp&0X0F; //0111 1111&0000 1111=0000 1111
	if(temp!=0X0F)
	{
		Delay1ms(5);
		temp=P3;
	  temp=temp&0X0F; //0111 1111&0000 1111=0000 1111
										//判断后四位是否发生变化
		if(temp!=0X0F)//如果变化
		{
			temp=P3;//重新判断P3的值
					switch(temp)
				{
					case 0x7e :num=0;flag=1;break;
					case 0x7d :num=3;flag=1;break;
					case 0x7b :num=6;flag=1;break;
					case 0x77 :num=9;flag=1;break;
				}	
					while(temp!=0x0f)
					{
						temp=P3;
						temp=temp&0x0f;
					}
		}
	}
	
	//第二列
	P3=0XBF;P4=0XFB;//P42=0
	temp=P3;
	temp=temp&0X0F; 
	if(temp!=0X0F)
	{
		Delay1ms(5);
		temp=P3;
	  temp=temp&0X0F; 
										//判断后四位是否发生变化
		if(temp!=0X0F)//如果变化
		{
			temp=P3;//重新判断P3的值
				  switch(temp)
				{
					case 0xbe :num=1;flag=1;
				    break;
					case 0xbd :num=4;flag=1;
	          break;
					case 0xbb :num=7;flag=1;
						break;
					case 0xb7 :
					{
								if(set==0)
								{
									set=1;
									EA=0;ET0=0;//关闭中断
									P2=(P2&0x1f)|0x80;
									P0=0XFF;//关闭L1
									P2=(P2&0x1f)|0xa0;
									P0=0x00;//关闭数码管
									yi=10,er=11,san=11,si=11,wu=11,liu=10,qi=11,ba=11;//设置界面
								}
								else if(set==1)
								{
								  set=0;
									EA=1;ET0=1;
									P2=0x80;
									P0=0xff;
									tmax=(er*10+san);//将设置温度存储
									tmin=(qi*10+ba);
								}
					}
					      break;
				}	

					while(temp!=0x0f)
					{
						temp=P3;
						temp=temp&0x0f;
					}
		}
	}
	
	//第三列
	P4=0XFF;
	P3=0XDF;
	temp=P3;
	temp=temp&0X0F; //0111 1111&0000 1111=0000 1111
	if(temp!=0X0F)
	{
		Delay1ms(5);
		temp=P3;
	  temp=temp&0X0F; 
										//判断后四位是否发生变化
		if(temp!=0X0F)//如果变化
		{
			temp=P3;//重新判断P3的值
				switch(temp)
				{
					case 0xde :num=2;flag=1;break;
					case 0xdd :num=5;flag=1;break;
					case 0xdb :num=8;flag=1;break;
					case 0xd7 :clean=1;break;
				}	
					while(temp!=0x0f)
					{
						temp=P3;
						temp=temp&0x0f;
					}
		}
	}
	 
}

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