第五届蓝桥杯单片机组 简易温度采集与控制系统(省赛)

(萌新一枚。连肝4个小时,在这里分享给大家。)
这一届的题目总体来说,难度不大。但第一次也是唯一一次考到了矩阵键盘,足以引起我们的注意。我在写代码的过程,主要遇到的障碍就是矩阵键盘的使用过于粗糙。希望矩阵键盘没有怎么练习过的,只会运用最基础的操作的小伙伴能进一步加强这一块的学习,防止比赛暴雷。。。。
如果你发现了程序需要优化的地方,请一定要告诉我!在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

onewire.c

/*
  程序设计:单总线驱动程序
  软件环境:Keil uVision 4.10
  硬件环境:CT107单片机综合实训平台(外部晶振12MHz)IAP15F2K61S2
  日期:2011-8-9
*/
#include "reg52.h"
#include "onewire.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
    
    
	t *= 10;//时间扩大十倍
	while(t--);
}

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

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

uchar read_temperatuer(void)
{
    
    
	uchar LSB, MSB;
	uchar temp;
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	Delay_OneWire(100);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	LSB = Read_DS18B20();
	MSB = Read_DS18B20();
	init_ds18b20();
	
	temp = (MSB << 8)|LSB;
	temp >>= 4;//右移4位,只取整数部分
	
	return temp;
}

onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H
#define uchar unsigned char
#define uint unsigned int
	
extern uchar read_temperatuer(void);
void Delay_OneWire(unsigned int t);
void Write_DS18B20(unsigned char dat);
unsigned char Read_DS18B20(void);
bit init_ds18b20(void);

#endif

main.c

#include <REGX52.H>
#include <onewire.h>

sfr P4 = 0xc0;

sbit P42 = P4^2;
sbit P44 = P4^4;

sbit L1 = P0^0;
sbit L2 = P0^1;

void Delay(uint t);
void Init_hc573(uint s);
void key_scan(void);
void inputdat(uint key);//输入数据
void save_t(void);//保存输入的数据
void Init_Timer0(void);
void DisplaySMG_Dat(uint pos, uint dat);
void DisplaySMG_all(void);//清空所有数码管
void DisplaySMG(void);

uint code Shu[] = 
{
    
    0xc0,0xf9,0xa4,0xb0,
0x99,0x92,0x82,0xf8,0x80,0x90,//0-9 
0xbf, 0xff};//-和灭

uint yi=11,er=11,san=11,si=11, wu=11, liu=11, qi=11, ba=11;
uint temperature;//温度
uint set;//控制显示界面标志位
uint set_t1, set_t2, set_t3, set_t4;//设置温度的临时数据
uint Tmax = 30, Tmin = 20;
uint level;//温度等级
uint sel;//选择要修改的数据
uint flag;//计算设置按键按下的次数
uint clear;//清空数据标志位
uint count_0;//定时器时间控制
uint count_1;
uint count_2;

void main(){
    
    
	Init_hc573(4);
	P0 = 0xff;
	Init_hc573(5);
	P0 = 0x00;
	Init_Timer0();
	while(1){
    
    
		key_scan();
		if(temperature < Tmin){
    
    
			level = 0;
			Init_hc573(5);
			P0 = 0x00;
		}
		else if((temperature >= Tmin)&&(temperature <= Tmax)){
    
    
			level = 1;
			Init_hc573(5);
			P0 = 0x00;
		}
		else
		{
    
    
			level = 2;
			Init_hc573(5);
			P0 = 0x10;
		}
		
		if(set== 0){
    
    
			EA = 1;
			ET0 = 1;
			temperature =  read_temperatuer();
			
			yi = 10;er = level;san = 10;
			si = 11;wu = 11;liu = 11;
			qi = temperature/10;ba = temperature%10;
		}
		else{
    
    
			//关闭定时器并清空数据
			EA = 0;
			ET0 = 0;
			count_0 = 0;
			count_1 = 0;
			count_2 = 0;
			yi = 10;er = set_t1;san = set_t2;
			si = 11;wu = 11;liu = 10;
			qi = set_t3;ba = set_t4;
		}
		
		DisplaySMG();
	}
}

void Delay(uint t){
    
    
	while(t --);
}

void Init_hc573(uint s){
    
    
	switch(s){
    
    
		case 4:P2 = (P2 &0x1f)|0x80;break;//LED
		case 5:P2 = (P2 &0x1f)|0xa0;break;//蜂鸣器和继电器
		case 6:P2 = (P2 &0x1f)|0xc0;break;//数码管com端口
		case 7:P2 = (P2 &0x1f)|0xe0;break;//段码
	}
}
static uint key;
void key_scan(void){
    
    
	
	uint temp;
	P3 = 0x7f;P42 = 1;P44 = 0;//扫描第一列
	temp = P3;
	temp &= 0x0f;//判断第四位是否发生变化 0111 1111&0000 1111 = 0000 1111
	if(temp != 0x0f){
    
    
		Delay(200);
		if(temp != 0x0f){
    
    
			temp = P3;
			switch(temp)//便于直接控制到每个按键
			{
    
    
				case 0x7e:if(set == 1){
    
    sel ++;key = 0;inputdat();}break;
				case 0x7d:if(set == 1){
    
    sel ++;key = 3;inputdat();}break;
				case 0x7b:if(set == 1){
    
    sel ++;key = 6;inputdat();}break;
				case 0x77:if(set == 1){
    
    sel ++;key = 9;inputdat();}break;
			}
			while(temp != 0x0f){
    
    //重新判断,否则temp永远不能等于0x0f
				temp = P3;
				temp &= 0x0f;//若松开,则temp = 0x0f;
			}
		}
	}
	
	P3 = 0xbf;P42 = 0;P44 = 1;//判断第二列
	temp = P3;
	temp &= 0x0f;//判断第四位是否发生变化
	if(temp != 0x0f){
    
    
		Delay(200);
		if(temp != 0x0f){
    
    
			temp = P3;
			switch(temp)
			{
    
    
				case 0xbe:if(set == 1){
    
    sel ++;key = 1;inputdat();}break;
				case 0xbd:if(set == 1){
    
    sel ++;key = 4;inputdat();}break;
				case 0xbb:if(set == 1){
    
    sel ++;key = 7;inputdat();}break;
				case 0xb7:set = 1;flag ++;if(flag == 2){
    
    save_t();}break;
			}
			while(temp != 0x0f){
    
    
				temp = P3;
				temp &= 0x0f;
			}
		}
	}
	
	P3 = 0xdf;P42 = 1;P44 = 1;//扫描第三列
	temp = P3;
	temp &= 0x0f;
	if(temp != 0x0f){
    
    
		Delay(200);
		if(temp != 0x0f){
    
    
			temp = P3;
			switch(temp)
			{
    
    
				case 0xde:if(set == 1){
    
    sel ++;key = 2;inputdat();}break;
				case 0xdd:if(set == 1){
    
    sel ++;key = 5;inputdat();}break;
				case 0xdb:if(set == 1){
    
    sel ++;key = 8;inputdat();}break;
				case 0xd7:if(set == 1){
    
    sel ++;clear = 1;inputdat();}break;
			}
			while(temp != 0x0f){
    
    
				temp = P3;
				temp &= 0x0f;
			}
		}
	}
}

void inputdat(void){
    
    
	if(clear == 0){
    
    
		switch(sel){
    
    
			case 1:set_t1 = key;break;
			case 2:set_t2 = key;break;
			case 3:set_t3 = key;break;
			case 4:set_t4 = key;break;
		}
	}
	else{
    
    //清空数据
		set_t1 = 0;
		set_t2 = 0;
		set_t3 = 0;
		set_t4 = 0;
		sel = 0;//重新输入
		clear = 0;
	}
}
void save_t(void){
    
    
	if((set_t1*10+ set_t2) > (set_t3*10+ set_t4)){
    
    
		Tmin = set_t3*10+ set_t4;
		Tmax = set_t1*10+ set_t2;
		sel = 0;
		set = 0;
		
		Init_hc573(4);
		L2 = 1;
	}
	else{
    
    //输入错误,重新输入
		set_t1 = 0;
		set_t2 = 0;
		set_t3 = 0;
		set_t4 = 0;
		sel = 0;
		set = 1;
		
		Init_hc573(4);
		L2 = 0;
	}
	flag = 0;//清空设置按键标志位
}


void Init_Timer0(void){
    
    //@12MHz
	TMOD = 0x01;
	TH0 = (65535 -20000)/256;
	TL0 = (65535- 20000)%256;
	
//  EA = 1;
//  ET0 = 1;
	TR0 = 1;
}

void service_Timer0(void) interrupt 1{
    
    
	TH0 = (65535 -20000)/256;
	TL0 = (65535- 20000)%256;
	
	count_0 ++;
	count_1 ++;
	count_2 ++;
	if(count_0 == 4){
    
    
		count_0 = 0;
		if(level == 0){
    
    
			if(L1 == 0){
    
    
				Init_hc573(4);
				P0 = 0xff;//避免其他LED闪烁
				L1 = 1;
			}
			else
			{
    
    
				Init_hc573(4);
				P0 = 0xff;
				L1 = 0;
			}
		}
	}
	if(count_1 == 2){
    
    
		count_1 = 0;
		if(level == 1){
    
    
			if(L1 == 0){
    
    
				Init_hc573(4);
				P0 = 0xff;
				L1 = 1;
			}
			else{
    
    
				Init_hc573(4);
				P0 = 0xff;
				L1 = 0;
			}
		}
	}
	if(count_2 == 1){
    
    
		count_2 = 0;
		if(level == 2){
    
    
			if(L1 == 0){
    
    
				Init_hc573(4);
				P0 = 0xff;
				L1 = 1;
			}
			else{
    
    
				Init_hc573(4);
				P0 = 0xff;
				L1 = 0;
			}
		}
	}
}

void DisplaySMG_Dat(uint pos, uint dat){
    
    
	Init_hc573(6);
	P0 = 0x01 << pos;
	Init_hc573(7);
	P0 = dat;
	
	Delay(50);
	P0 = 0xff;
}

void DisplaySMG_all(void){
    
    
	Init_hc573(6);
	P0 = 0xff;
	Init_hc573(7);
	P0 = 0xff;
}

void DisplaySMG(void){
    
    
	DisplaySMG_Dat(0, Shu[yi]);
	Delay(100);
	DisplaySMG_Dat(1, Shu[er]);
	Delay(100);
	DisplaySMG_Dat(2, Shu[san]);
	Delay(100);
	DisplaySMG_Dat(3, Shu[si]);
	Delay(100);
	DisplaySMG_Dat(4, Shu[wu]);
	Delay(100);
	DisplaySMG_Dat(5, Shu[liu]);
	Delay(100);
	DisplaySMG_Dat(6, Shu[qi]);
	Delay(100);
	DisplaySMG_Dat(7, Shu[ba]);
	Delay(100);
	
	DisplaySMG_all();
}

end

猜你喜欢

转载自blog.csdn.net/prefer_study/article/details/114435450