蓝桥杯单片机设计与开发决赛-第十一届

这里的代码是主文件的代码,其他的头文件之前已经提供,下面的代码仅提供思路,不提供原理,如有错误请及时留言提醒。

#include <stc15f2k60s2.h>
#include <intrins.h>
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
typedef unsigned int uint;

code uchar TAB[] = {0xc0, 0xf9, 0xa4, 0xb0, 0x99, 0x92, 0x82, 0xf8, 0x80, 0x90, 0xff, 0xbf, 0xc6, 0x86, 0x8c};//显示1-9 灭 - C E P
uchar tab1, tab2, tab3, tab4, tab5, tab6, tab7, tab8;

uchar key, sec, min, hour, AD;
uint temp;

uint dat_t;
bit AD_state, time_state, temp_state;

uchar function;//显示功能变量
bit light;//亮,暗状态

bit set;//数据参数界面切换标志位
uchar hour_set = 17, temp_set = 25, led_set = 4;//小时参数为17   温度参数为25  LED指示灯参数为4

uchar led = 0xff;//存放led的状态
bit use = 1;//数据界面标志位,为0时处于参数界面,应题目要求所以参数均在退出参数界面时生效

uint time_3s;//持续时间计时
bit time3, time, light_tem;//达到3s时间标志位,开始计时标志位,临时存放上一个亮暗状态(方便比较)


void delay(uint z)//延时函数
{
	uint x, y;
	for(x=z; x>0; x--)
		for(y=845; y>0; y--);
}

void timer_int()//定时器初始,一般是手写放在这里面
{
	EA = 1; 
	TR0 = 1;//定时器0,16位,定时1ms,定时中断
	ET0 = 1;
	TMOD |= 0X01;
	TH0 = (65536-1000)/256;
	TL0 = (65536-1000)%256;
}

void display()//显示函数,配合定时器0中断使用,达到循环扫描
{
	static uchar i;//定义静态变量i
	switch(i)
	{
		case 0: P2=0XC0; P0=0X01; P2=0XE0; P0=TAB[tab1]; i=1; break;
		case 1: P2=0XC0; P0=0X02; P2=0XE0; P0=TAB[tab2]; i=2; break;
		case 2: P2=0XC0; P0=0X04; P2=0XE0; 
		if(function==2) P0=TAB[tab3]&0x7f;  else P0=TAB[tab3];//判断处于亮暗状态显示界面下,在第3位数码管上增加小数点
		i=3; break;
		case 3: P2=0XC0; P0=0X08; P2=0XE0; P0=TAB[tab4]; i=4; break;

		case 4: P2=0XC0; P0=0X10; P2=0XE0; P0=TAB[tab5]; i=5; break;
		case 5: P2=0XC0; P0=0X20; P2=0XE0; P0=TAB[tab6]; i=6; break;
		case 6: P2=0XC0; P0=0X40; P2=0XE0; 
		if(function==1) P0=TAB[tab7]&0x7f; else P0=TAB[tab7];//判断处于温度显示界面下,在第7位数码管上增加小数点
		i=7; break;
		case 7: P2=0XC0; P0=0X80; P2=0XE0; P0=TAB[tab8]; i=0; break;
	}
}

void key_scan()//四分之一 矩阵键盘扫描,常用需要理解记住
{
	key = 0;//按键标志清零,每循环一次清除一次,在判断按键里面就不用再清零
	P44 = 1; P42 = 1; P33 = 0; P32 = 0;
	if((P44==0)|(P42==0))
	{
		P44 = 1; P42 = 1; P33 = 0; P32 = 0;//当控制的IO口不多时,可以直接位操作
		delay(2);
		if((P44==0)|(P42==0))	//判断纵列按键
		{
			if(P44==0) key = 4;
			if(P42==0) key = 8;
		}
		P44 = 0; P42 = 0; P33 = 1; P32 = 1;
		if((P33==0)|(P32==0))
		{
			P44 = 0; P42 = 0; P33 = 1; P32 = 1;
			delay(2);
			if((P33==0)|(P32==0))	//判断行列按键
			{
				if(P33==0) key += 0;
				if(P32==0) key += 1;
			}
		}
		while((P33==0)|(P32==0));//判断抬手
	}
}

void time_read()//时间读取函数
{
	EA = 0;//读取时间时,要关闭中断
	Write_Ds1302_Byte(0x8e,0x00);
	sec = Read_Ds1302_Byte(0x81);
	min = Read_Ds1302_Byte(0x83);
	hour = Read_Ds1302_Byte(0x85);
	Write_Ds1302_Byte(0x8e,0x80);
	EA = 1;//读取完成,必须打开中断
}

void initialize()//初始化函数
{
	P2=0XA0; P0=0X00; P2=0X80; P0=0XFF;

	Write_Ds1302_Byte(0x8e,0x00);//写入DS1302,时间 16-59-50
	Write_Ds1302_Byte(0x80,50);
	Write_Ds1302_Byte(0x82,59);
	Write_Ds1302_Byte(0x84,16);
	Write_Ds1302_Byte(0x8e,0x80);

	timer_int();//定时器0初始化	
}

void key_function()//按键功能函数
{
	key_scan();//按键扫描
	if(key==5)//切换按键
	{
		if(set==0)//切换数据界面
		{
			if(function==0) function = 1;
			else if(function==1) function = 2;
			else if(function==2) function = 0;
		}
		else //切换参数界面
		{
			if(function==3) function = 4;
			else if(function==4) function = 5;
			else if(function==5) function = 3;	
		}
	}
	else if(key==4)//界面按键
	{
		if(set==0) { set = 1; function = 3; use = 0; }//每次从数据界面进入参数界面,默认当前为时间参数
		else { set = 0; function = 0; use = 1; }//每次从参数界面进入数据界面,默认当前为世界数据
	}
	else if(key==8)//减按键
	{
		if(function==3) { if(hour_set!=0) hour_set--; }//注意设置下限
		else if(function==4) { if(temp_set!=0) temp_set--; }
		else if(function==5) { if(led_set!=4) led_set--; }
	}
	else if(key==9)//加按键
	{
		if(function==3) { if(hour_set!=23) hour_set++; }//注意设置上限
		else if(function==4) { if(temp_set!=99) temp_set++; }
		else if(function==5) { if(led_set!=8) led_set++; }	
	}		
}

void dat_read()//定时读取数据函数
{
	if(time_state==1) //定时读取时间
	{ 
		time_state = 0; time_read(); 
		if(use==1)
		{
			if((hour_set<=hour)|(hour<=8)) { P2 = 0X80; led &= 0xfe; P0 = led; }//判断当前时间处于小时参数整点至下一个8时之间
			else { P2 = 0X80; led |= 0x01; P0 = led; }
		}
	}
	else if(AD_state==1) //定时读取电压
	{
		AD_state = 0; AD = AD_read(0x01); 
		if(AD>=100)  //判断是否未遮挡
		{
			light = 0; //亮状态
			if(use==1)
			{
				switch(led_set)//指定的LED指示灯熄灭
				{
						case 4:	P2 = 0X80; led |= 0x08; P0 = led; break; 
						case 5:	P2 = 0X80; led |= 0x10; P0 = led; break;
						case 6:	P2 = 0X80; led |= 0x20; P0 = led; break;
						case 7:	P2 = 0X80; led |= 0x40; P0 = led; break;
						case 8:	P2 = 0X80; led |= 0x80; P0 = led; break;
				}
			}
		}
		else  //判断是否遮挡
		{
			light = 1; //暗状态
			if(use==1)
			{
				switch(led_set)//指定的LED指示灯点亮
				{
						case 4:	P2 = 0X80; led &= 0xf7; P0 = led; break; 
						case 5:	P2 = 0X80; led &= 0xef; P0 = led; break;
						case 6:	P2 = 0X80; led &= 0xdf; P0 = led; break;
						case 7:	P2 = 0X80; led &= 0xbf; P0 = led; break;
						case 8:	P2 = 0X80; led &= 0x7f; P0 = led; break;
				}
			}
		} 

		if(time3==1)//判断是否持续时间超过3s
		{
			time3 = 0;
			if(light==1) { P2 = 0X80; led &= 0xfb; P0 = led; }//点亮L3
			else  { P2 = 0X80; led |= 0x04; P0 = led; }	//熄灭L3
		}

		if(light_tem!=light) time = 1;//判断状态改变,开始在定时器0中断中计时,第一次判断要是环境处于暗状态,才能看到现象
		else { time_3s = 0; time = 0; }//其他情况清零,为下次判断做准备
				
	}
	else if(temp_state==1) //定时读取温度
	{ 
		temp_state = 0; temp = temp_read(); 
		if(use==1)
		{
			if(temp<(temp_set*10)) { P2 = 0X80; led &= 0xfd; P0 = led; }//判断采集到的温度数据小于温度参数
			else { P2 = 0X80; led |= 0x02; P0 = led; }
		}
	}	
}

void dat_display()//数据显示函数
{
	if(function==0)//时间显示界面
	{
		tab1=hour/10; tab2=hour%10; tab3=11; tab4=min/10; tab5=min%10; tab6=11; tab7=sec/10; tab8=sec%10;	
	}
	else if(function==1)//温度数据 显示界面
	{
		tab1=12; tab2=10; tab3=10; tab4=10; tab5=10; tab6=temp/100; tab7=temp%100/10; tab8=temp%10;	
	}
	else if(function==2)//亮,暗状态 显示界面
	{
		tab1=13; tab2=10; tab3=AD/100; tab4=AD%100/10; tab5=AD%10; tab6=10; tab7=10; tab8=light;	
	}
	else if(function==3)//时间参数 设置界面
	{
		tab1=14; tab2=1; tab3=10; tab4=10; tab5=10; tab6=10; tab7=hour_set/10; tab8=hour_set%10;
	}
	else if(function==4)//温度参数 设置界面
	{
		tab1=14; tab2=2; tab3=10; tab4=10; tab5=10; tab6=10; tab7=temp_set/10; tab8=temp_set%10;
	}
	else if(function==5)//指示灯参数 设置界面
	{	
	 	tab1=14; tab2=3; tab3=10; tab4=10; tab5=10; tab6=10; tab7=10; tab8=led_set;
	}	
}

void main()
{
	initialize();//初始化
	while(1)
	{
		key_function();//按键功能
		
		dat_read();//数据读取
		dat_display();//数据显示
	}
}

void timer0_display()interrupt 1
{
	TH0 = (65536-1000)/256;//定时器0装载
	TL0 = (65536-1000)%256;
	display();	//数码管扫描显示

	dat_t++;
	if(dat_t==50) AD_state = 1;
	else if(dat_t==150) time_state = 1;
	else if(dat_t==250) temp_state = 1;
	else if(dat_t==300) dat_t = 0;

	if(time==1)//开始计时持续时间
	{
		if(++time_3s==3000)//计时3000ms
		{
			time_3s = 0;
			time3 = 1;	//计时完成
			light_tem = light; //重新赋值新的状态
		}	
	}
}	

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值