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

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

题目

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

源码

#include <STC15F2K60S2.H>
#include <intrins.h>
#include "iic.h"
#include "ds1302.h"
#include "onewire.h"
#define KEYPORT P3
#define u8 unsigned char 
#define u16 unsigned int

u8 code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

u8 code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码

u8 key_table[] = {0x88,0x84,0x48,0x44};

u8 screen_table[] = {16,16,16,16,16,16,16,16};

sbit buzzer = P0^6;
sbit relay = P0^4;

u8 readdata,keypress;
u8 Cont,Trg;
u8 shi,fen,miao;
u8 shi_BCD,fen_BCD,miao_BCD;
u8 mode_flag;//模式切换标志位
u8 adc_val;//电压值0-255
u8 LED;

//默认参数
char time_set = 17char temperature_set = 25;
char led_set = 4;

//变化参数中间值
char time_temp = 17;
char temperature_temp = 25;
char led_temp = 4;

float temperature;//温度值
float volt;//电压值0-5V

bit key_flag;
bit read_flag;
bit set_flag;//数据和参数界面切换标志位
bit light_flag;//亮暗等级
bit change_flag;//切换界面标志位

void Init()//初始化
{
	P2=0x80;P0=0xff;P2=0x00;
	P2=0xe0;P0=0xff;P2=0x00;
	P2=0xa0;buzzer = 0; relay = 0;P2=0x00;
}

void key_read()//矩阵键盘
{
	KEYPORT = 0xf0;
	P44 = 1;
	P42 = 1;
	P36 = P42;
	P37 = P44;
	keypress = KEYPORT;
	KEYPORT = 0x0f;
	P44 = 0;
	P42 = 0;
	readdata = (KEYPORT | keypress) ^ 0xff;
	Trg = readdata & (readdata ^ Cont);
	Cont = readdata ;
}

//T0初始化
void Timer0Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x80;		//定时器时钟1T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0x20;		//设置定时初值
	TH0 = 0xD1;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
}

/* Timer0 interrupt routine */
void tm0_isr() interrupt 1
{
    static int smg_count = 0, key_count = 0,read_count = 0,light_count = 0,i = 0;
	smg_count++;key_count++;read_count++;
	
	if(smg_count == 1)
	{
		smg_count = 0;
		P2=0xe0;P0=~t_display[screen_table[i]];P2=0x00;
		P2=0xc0;P0=T_COM[i];P2=0x00;
		i++;
		if(i==8)i=0;
	}
	
	if(key_count == 10)
	{
		key_count = 0;
		key_flag =1;
	}
	
	if(read_count == 200)
	{
		read_count =0 ;
		read_flag = 1;
	}
	
	if(light_flag)
	{
		if(++light_count == 3000)
		{
			light_count  =0;
			LED |= 4;
		}
	}
	else
	{
		if(++light_count == 3000)
		{
			light_count = 0;
			LED &= ~4;
		}
	}
}

void main()
{
	Init();
	Timer0Init();
	set_sfm(16,59,50);//RTC时钟上电默认时间
	while(1)
	{
		EA = 0;//读取时钟数据
		shi_BCD =  Read_Ds1302_Byte ( 0x85 );
		fen_BCD =  Read_Ds1302_Byte ( 0x83 );
		miao_BCD =  Read_Ds1302_Byte ( 0x81 );
		EA = 1;
		
		shi = (((shi_BCD >> 4) & 0x07) * 10 ) + (shi_BCD & 0x0f);
		fen = (((fen_BCD >> 4) & 0x07) * 10 ) + (fen_BCD & 0x0f);
		miao = (((miao_BCD >> 4) & 0x07) * 10 ) + (miao_BCD & 0x0f);
		
		if(read_flag)
		{
			read_flag = 0;
			temperature = rd_temperature();
			EA = 0;
			adc_val = read_adc(0x01);
			EA = 1;
			if(adc_val < 255 / 2)//暗
			{
				light_flag = 1;
			}
			else//亮
				light_flag = 0;
			
			volt = adc_val / 255.0 * 5;
		}
		
		if(key_flag)
		{
			key_flag = 0;
			key_read();
			if(Trg == key_table[0])//s4
			{
				if(set_flag == 1)//当前处于参数界面
				{
					change_flag = 1;
				}
				set_flag = ~set_flag;//数据和参数界面切换
				if(change_flag == 1 && set_flag == 0)//参数界面->数据界面:变化后的参数生效
				{
					time_set = time_temp;
					temperature_set = temperature_temp;
					led_set = led_temp;
				}
				mode_flag = 0;
			}
			
			if(Trg == key_table[1])//s5
			{
				mode_flag++;
				if(mode_flag == 3)
					mode_flag = 0;
			}
			
			if(Trg == key_table[2])//s8:-
			{
				if(set_flag == 1)
				{
					if(mode_flag == 0)
					{
						time_temp--;
						if(time_temp < 0)
						{
							time_temp = 23;
						}
					}
					else if(mode_flag == 1)
					{
						temperature_temp--;
						if(temperature_temp < 0)
						{
							temperature_temp = 99;
						}
					}
					else if(mode_flag == 2)
					{
						led_temp--;
						if(led_temp < 4)
						{
							led_temp = 8;
						}
					}			
				}
			}
			if(Trg == key_table[3])//s9:+
			{
				if(mode_flag == 0)
					{
						time_temp++;
						if(time_temp > 23)
						{
							time_temp = 0;
						}
					}
					else if(mode_flag == 1)
					{
						temperature_temp++;
						if(temperature_temp > 99)
						{
							temperature_temp = 0;
						}
					}
					else if(mode_flag == 2)
					{
						led_temp++;
						if(led_temp > 8)
						{
							led_temp = 4;
						}
					}			
			}
		}
			
		if(set_flag == 0)//数据界面
		{
			if(mode_flag == 0)//时钟显示
			{
				screen_table[0] = shi / 10;
				screen_table[1] = shi % 10;
				screen_table[2] = 17;
				screen_table[3] = fen / 10;
				screen_table[4] = fen % 10;
				screen_table[5] = 17;
				screen_table[6] = miao / 10;
				screen_table[7] = miao % 10;
			}
			else if(mode_flag == 1)//温度显示
			{
				screen_table[0] = 12;
				screen_table[1] = 16;
				screen_table[2] = 16;
				screen_table[3] = 16;
				screen_table[4] = 16;
				screen_table[5] = ((u8)temperature) / 10;
				screen_table[6] = (((u8)temperature) % 10) + 32;
				screen_table[7] = ((u8)(temperature * 10)) % 10;
			}
			else if(mode_flag == 2)//LED显示
			{
				screen_table[0] = 14;
				screen_table[1] = 16;
				screen_table[2] = (u8)volt + 32;
				screen_table[3] = ((u8)(volt * 10)) % 10 ;
				screen_table[4] = ((u16)(volt * 100)) % 10;
				screen_table[5] = 16;
				screen_table[6] = 16;
				screen_table[7] = light_flag;
			}
		}
		else//参数界面
		{
			if(mode_flag == 0)//时钟参数
			{
				screen_table[0] = 24;
				screen_table[1] = 1;
				screen_table[2] = 16;
				screen_table[3] = 16;
				screen_table[4] = 16;
				screen_table[5] = 16;
				screen_table[6] = time_temp / 10;
				screen_table[7] = time_temp % 10;
			}
			else if(mode_flag == 1)//温度参数
			{
				screen_table[0] = 24;
				screen_table[1] = 2;
				screen_table[2] = 16;
				screen_table[3] = 16;
				screen_table[4] = 16;
				screen_table[5] = 16;
				screen_table[6] = temperature_temp / 10;
				screen_table[7] = temperature_temp % 10;
			}
			else if(mode_flag == 2)//LED参数
			{
				screen_table[0] = 24;
				screen_table[1] = 3;
				screen_table[2] = 16;
				screen_table[3] = 16;
				screen_table[4] = 16;
				screen_table[5] = 16;
				screen_table[6] = 16;
				screen_table[7] = led_temp;
			}			
		}
		
/*************************LED显示**************************/
		if(shi >= 8)
		{
			if(shi >= time_set && shi <= 23)
			{
				LED |= 1;
			}
			else
			{
				LED &= ~1;
			}
		}
		else
		{
			if(shi >= time_set && shi < 8)
			{
				LED |= 1;
			}
			else
			{
				LED &= ~1;
			}
		}
		
		if(temperature  < temperature_set)
		{
			LED |= 2;
		}
		else
		{
			LED &= ~2;
		}
		
		if(light_flag == 1)
		{
			if(led_set == 4)
			{
				LED |= 8;
				LED &= ~0x10;
				LED &= ~0x20;
				LED &= ~0x40;
				LED &= ~0x80;
			}
			else if(led_set == 5)
			{
				LED &= ~8;
				LED |= 0x10;
				LED &= ~0x20;
				LED &= ~0x40;
				LED &= ~0x80;
			}
			else if(led_set == 6)
			{
				LED &= ~8;
				LED &= ~0x10;
				LED |= 0x20;
				LED &= ~0x40;
				LED &= ~0x80;
			}
			else if(led_set == 7)
			{
				LED &= ~8;
				LED &= ~0x10;
				LED &= ~0x20;
				LED |= 0x40;
				LED &= ~0x80;
			}
			else if(led_set == 8)
			{
				LED &= ~8;
				LED &= ~0x10;
				LED &= ~0x20;
				LED &= ~0x40;
				LED |= 0x80;
			}
		}
		else
		{
			LED &= ~8;
			LED &= ~0x10;
			LED &= ~0x20;
			LED &= ~0x40;
			LED &= ~0x80;
		}
		P2=0x80;P0 = ~LED ; P2=0x00;//点亮LED
	}
}

赛题总结

1.界面切换

在这里插入图片描述
解法代码

	if(Trg == key_table[0])//s4
	{
		set_flag = ~set_flag;//数据和参数界面切换
		mode_flag = 0;//切换后默认为时间界面
	}

2.参数生效

在这里插入图片描述
解法代码

if(Trg == key_table[0])//s4
{
	if(set_flag == 1)//当前处于参数界面
	{
		change_flag = 1;
	}
	set_flag = ~set_flag;//数据和参数界面切换
	if(change_flag == 1 && set_flag == 0)//参数界面->数据界面:变化后的参数生效
	{
		time_set = time_temp;
		temperature_set = temperature_temp;
		led_set = led_temp;
	}
	mode_flag = 0;
}


关键在于记录从参数界面到数据界面切换的标志位,按下s4时当前处于参数界面,按下后切换为数据界面

3.LED显示

在这里插入图片描述
代码接法

	if(shi >= 8)
	{
		if(shi >= time_set && shi <= 23)
		{
			LED |= 1;
		}
		else
		{
			LED &= ~1;
		}
	}
	else
	{
		if(shi >= time_set && shi < 8)
		{
			LED |= 1;
		}
		else
		{
			LED &= ~1;
		}
	}

分为两种情况:
(1)当前时间大于8:00,即就是处于8:00-23:59之间,需要判断(shi >= time_set && shi <= 23);

(2)当前时间小于8:00,即就是处于0:00-8:00之间,则判断(shi >= time_set && shi < 8);

特殊情况
当shi_set和shi相等时,简单理解可以这样说:从今天的8:00到下一天的8:00,全天L1都是点亮的。

  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浪漫世界值得孤身qwq

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值