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

(萌新一枚。连肝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

  • 10
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值