蓝桥杯之单片机设计与开发(30)——2011_第二届_国信长天杯_省赛——“温度监控器”

好了,今天一口气写了三年的题,这一周不会再写程序了,该好好复习高数了。

下周周日比赛,等下一周再把国赛题写一下,一个就差不多了。

还是自己最喜欢的那句话:让结局不留遗憾,让过程更加完美。

1、题目

蓝桥杯之单片机设计与开发(30)——2011_第二届_国信长天杯_省赛——“温度监控器”_第1张图片

蓝桥杯之单片机设计与开发(30)——2011_第二届_国信长天杯_省赛——“温度监控器”_第2张图片

2、代码

程序可以直接在这里下载:

main.c

#include 
#include "sys.h"

bit flag_200ms = 0;
bit flag_pwm = 0, flag_relay = 0;
bit flag_write = 0;
u8 temper_low = 20, temper_high = 30;
int Real_temper = 0;

void main(void)
{
	int tem = 0;
	static u8 index = 0;
	
	AllInit();
	Timer0Init();
	Start18B20();
	if(Read_E2PROM(0x02) == 0x23)
	{
		temper_high = Read_E2PROM(0x00);
		temper_low = Read_E2PROM(0x01);
	}
	EA = 1;
	while(1)
	{
		//读取温度程序
		if(flag_200ms)
		{
			flag_200ms = 0;
			Get18B20Temp(&tem);
			tem >>= 4;					//分离温度整数部分
			if((tem > 0) && (tem < 99))
				Real_temper = tem;
			Start18B20();
			
			if(flag_write)
			{
				if(index == 0)
					Write_E2PROM(0x00, temper_high);
				else if(index == 1)
					Write_E2PROM(0x01, temper_low);
				else if(index == 2)
					Write_E2PROM(0x02, 0x23);
				else if(index == 3)
					flag_write = 0;
				index ++;
			}
			else
				index = 0;
		}
		
		if(Real_temper > temper_high)
			flag_pwm = 1;
		else if(Real_temper < temper_low)
			flag_relay = 1;
		else
		{
			PWM = 1;
			flag_pwm = 0;
			flag_relay = 0;
		}
		
		KeyPress();
		TubeShow();
	}
}

sys.c

#include "sys.h"

void AllInit(void)
{
	P2 = (P2 & 0x1f) | 0x80;
	P0 = 0xff;
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = 0x00;
	P2 = (P2 & 0x1f) | 0xa0;
	P0 = 0x00;
	P2 = P2 & 0x1f;
}

void Timer0Init(void)		//[email protected]
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xAE;		//设置定时初值
	TH0 = 0xFB;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
}

void Timer0(void) interrupt 1
{
	static u16 T0count1 = 0;
	static u8 Tocount2 = 0;
	static u8 index = 0;
	
	index ++;
	T0count1 ++;
	Tocount2 ++;
	if(T0count1 >= 2000)	//200ms
	{
		T0count1 = 0;
		flag_200ms = 1;
	}
	
	if(Tocount2 >= 20)		//2ms
	{
		Tocount2 = 0;
		KeyScan();
		TubeScan();
	}
	
	//P34输出PWM控制程序
	if(flag_pwm == 1)
	{
		if(index < 3)
			PWM = 1;
		else if(index >= 3)
		{
			PWM = 0;
			if(index >= 10)
				index = 0;
		}		
	}
	else
		index = 0;
	
	//继电器控制程序
	if(flag_relay)
	{
		P0 = 0x00;
		P2 = (P2 & 0x1f) | 0xa0;
		P04 = 1;
		P2 = P2 & 0x1f;
	}
	else
	{
		P0 = 0x00;
		P2 = (P2 & 0x1f) | 0xa0;
		P04 = 0;
		P2 = P2 & 0x1f;
	}
}

sys.h

#ifndef _SYS_H_
#define _SYS_H_

typedef unsigned char u8;
typedef unsigned int u16;
typedef unsigned long u32;

#include 
#include 
#include "ds18b20.h"
#include "iic.h"

extern bit flag_200ms;
extern bit flag_pwm, flag_relay;
extern bit flag_write;
extern u8 temper_low, temper_high;
extern int Real_temper;

//function
void AllInit(void);
void Timer0Init(void);

void TubeScan(void);
void TubeShow(void);

void KeyScan(void);
void KeyAction(unsigned char key);
void KeyPress(void);

//pin
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;
sbit PWM = P3^4;

#endif


display.c

#include "sys.h"

unsigned char code table[]={0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 
                            0x80, 0x90, 0x88, 0x83, 0xc6, 0xa1, 0x86, 0x8e,
														0xff, 0xbf};
u8 TubeBuff[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
u8 smg1, smg2, smg3, smg4, smg5, smg6, smg7, smg8;

void TubeScan(void)
{
	static u8 index = 0;
	
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = 0xff;
	P2 = (P2 & 0x1f) | 0xc0;
	P0 = (0x01 << index);
	P2 = (P2 & 0x1f) | 0xe0;
	P0 = TubeBuff[index];
	P2 = P2 & 0x1f;
	
	index ++;
	index &= 0x07;
}

void TubeShow(void)
{	
	smg1 = temper_high / 10;
	smg2 = temper_high % 10;
	smg3 = temper_low / 10;
	smg4 = temper_low % 10;
	smg5 = smg6 = 16;
	smg7 = Real_temper / 10;
	smg8 = Real_temper % 10;
	
	TubeBuff[0] = table[smg1];
	TubeBuff[1] = table[smg2];
	TubeBuff[2] = table[smg3];
	TubeBuff[3] = table[smg4];
	TubeBuff[4] = table[smg5];
	TubeBuff[5] = table[smg6];
	TubeBuff[6] = table[smg7];
	TubeBuff[7] = table[smg8];
}

key.c

#include "sys.h"
 
u8 KeySta[] = {1, 1, 1, 1};
u8 KeyBackup[] = {1, 1, 1, 1};
u8 KeyBuff[] = {0xff, 0xff, 0xff, 0xff};
 
void KeyScan(void)
{
	u8 i;
	
	KeyBuff[0] = (KeyBuff[0] << 1) | S7;
	KeyBuff[1] = (KeyBuff[1] << 1) | S6;
	KeyBuff[2] = (KeyBuff[2] << 1) | S5;
	KeyBuff[3] = (KeyBuff[3] << 1) | S4;
	
	for(i = 0; i < 4; i ++)
	{
		if(KeyBuff[i] == 0xff)				//Key release
			KeySta[i] = 1;
		else if(KeyBuff[i] == 0x00)		//Key press
			KeySta[i] = 0;
		else
		{}
	}
}
 
void KeyAction(unsigned char key)
{
	if(key == 0)					//S7  减下限
	{
		if(temper_low > 0)
			temper_low --;
		else
			temper_low = 0;
	}
	else if(key == 1)			//S6  减上限
	{
		if(temper_high > temper_low)
			temper_high --;
		else
			temper_high = temper_low;
	}
	else if(key == 2)			//S5  加下限
	{
		if(temper_low < temper_high)
			temper_low ++;
		else
			temper_low = temper_high;
	}
	else if(key == 3)			//S4  加上限
	{
		if(temper_high < 99)
			temper_high ++;
		else
			temper_high = 99;
	}
	flag_write = 1;
}
 
void KeyPress(void)
{
	u8 i;
	
	for(i = 0; i < 4; i ++)
	{
		if(KeySta[i] != KeyBackup[i])
		{
			if(KeySta[i] == 0)					//action when key press
				KeyAction(i);
			KeyBackup[i] = KeySta[i];
		}
	}
}
 

ds18b20.c

 #include "sys.h"

sbit DS18B20_IO = P1^4;

void Delayus(unsigned int us)
{
	do{
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
		_nop_();
	}while(--us);
}

bit Get18B20Ack(void)
{
	bit ack;
	
	DS18B20_IO = 0;			//产生500us的复位脉冲
	Delayus(500);
//	EA = 0;							//禁止总中断
	ET0 = 0;
	DS18B20_IO = 1;			//延时60us
	Delayus(60);
//	EA = 1;							//重新使能总中断
	ET0 = 1;
	ack = DS18B20_IO;		//读取存在脉冲
	while(!DS18B20_IO);	//等待存在脉冲结束
	
	return ack; 	
}

void DS18B20Write(unsigned char dat)
{
 	unsigned char mask;
						
	for(mask = 0x01; mask != 0; mask <<= 1)	//低位在先,依次移出8个bit
	{
//		EA = 0;
		ET0 = 0;
		DS18B20_IO = 0;				//产生2us低电平脉冲
		Delayus(2);
	 	if(dat & mask)				//输出该bit值
		 	DS18B20_IO = 1;
		else
		 	DS18B20_IO = 0;
//		EA = 1;
		ET0 = 1;
		Delayus(60);					//延时60us
		DS18B20_IO = 1;				//拉高通信引脚
	}
}

unsigned char DS18B20Read(void)
{
 	unsigned char mask, dat = 0;
	
	for(mask = 0x01; mask != 0; mask <<= 1)	//低位在先,依次采集8个bit
	{
//		EA = 0;
		ET0 = 0;
		DS18B20_IO = 0;				//产生2us低电平脉冲
		Delayus(2);
		DS18B20_IO = 1;				//结束低电平脉冲,等待18B20输出数据
		Delayus(2);						//延时2us
	 	if(DS18B20_IO)				//读取通信引脚上的值
		 	dat |= mask;
//		EA = 1;
		ET0 = 1;
		Delayus(60);					//再延时60us
	}
	
	return dat;	
}

bit Start18B20()
{
 	bit ack;
	static bit flag = 1;

	ack = Get18B20Ack();		//执行总线复位,并获取18B20应答
	if(ack == 0)						//如18B20正确应答,则启动一次转换
	{
		DS18B20Write(0xCC);		//跳过ROM操作
		
		if(flag)
		{
			flag = 0;
			DS18B20Write(0x4e);			//写暂存器指令4E
			DS18B20Write(0x63);			//写高速缓存器TH高温限值99度
			DS18B20Write(0x00);			//写高速缓存器TL低温限值0度
			DS18B20Write(0x1f);			//写配置寄存器4
															//0x1f : 0.5000°C  转换时间93.75ms
															//0x3f : 0.2000°C  转换时间187.5ms
															//0x5f : 0.1250°C  转换时间375ms
															//0x7f : 0.0625°C  转换时间750ms
		}
		
		ack = Get18B20Ack();		//执行总线复位,并获取18B20应答
		if(ack == 0)						//如18B20正确应答,则启动一次转换
		{
			DS18B20Write(0xCC);		//跳过ROM操作
			DS18B20Write(0x44);		//启动一次温度转换
		}
	}

	return ~ack;						//ack == 0 表示操作成功,所以返回值对其取反
}

bit Get18B20Temp(int *temp)
{
 	bit ack;
	unsigned char LSB, MSB;			//16bit温度值的低字节和高字节

	ack = Get18B20Ack();				//执行总线复位,并获取18B20应答
	if(ack == 0)								//如18B20正确应答,则读取温度值
	{
	 	DS18B20Write(0xCC);				//跳过ROM操作
		DS18B20Write(0xBE);				//发送读命令
		LSB = DS18B20Read();			//读温度值的低字节
		MSB = DS18B20Read();			//读温度值的高字节
		*temp = ( MSB << 8) + LSB;	//合成16bit的整数
	}

	return ~ack;								//ack == 0 表示操作应答,所以返回值为1其取反值
} 

ds18b20.h

#ifndef __DS18B20_H
#define __DS18B20_H


//单总线延时函数
void Delayus(unsigned int us);
bit Get18B20Ack(void);
void DS18B20Write(unsigned char dat);
unsigned char DS18B20Read(void);
bit Start18B20();
bit Get18B20Temp(int *temp);


#endif

iic.c

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

#include "sys.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}    


#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

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


//总线启动条件
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

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

//应答位控制
void IIC_Ack(bit ackbit)
{
	if(ackbit) 
	{	
		SDA = 0;
	}
	else 
	{
		SDA = 1;
	}
	somenop;
	SCL = 1;
	somenop;
	SCL = 0;
	SDA = 1; 
	somenop;
}

//等待应答
bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

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

void Write_E2PROM(unsigned char add, unsigned char dat)
{
//	EA = 0;
	ET0 = 0;
  IIC_Start();
  IIC_SendByte(0xa0);	//发送器件地址
  IIC_WaitAck();
  IIC_SendByte(add);	//发送操作地址
  IIC_WaitAck();
  IIC_SendByte(dat);	//写一字节
  IIC_WaitAck();
  IIC_Stop();
  somenop;
//	EA = 1;
	ET0 = 1;
}

unsigned char Read_E2PROM(unsigned char add)
{
  unsigned char d;
	
	IIC_Start();
	IIC_SendByte(0xa0); 	//发送器件地址
	IIC_WaitAck();
	IIC_SendByte(add);		//发送要操作的地址
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0xa1);		//发送读操作
	IIC_WaitAck();
	d = IIC_RecByte();	//读一字节
	IIC_Ack(0);
	IIC_Stop();
	return d;
}

iic.h

#ifndef _IIC_H
#define _IIC_H

//函数声明
void IIC_Start(void); 
void IIC_Stop(void);  
void IIC_Ack(bit ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 
void Write_E2PROM(unsigned char add, unsigned char dat);
unsigned char Read_E2PROM(unsigned char add);

#endif

 

 

 

 

 

你可能感兴趣的:(蓝桥杯,第十届蓝桥杯)