十三届蓝桥杯单片机组省赛真题程序解析

第一次参加蓝桥杯,线上比赛,记录一下

比赛刚开始了十分钟才做上客观题,做上了之后才发现看一次题警告一次,当时就蚌埠住了,随便做了做就交了,手册也没怎么查(查一下直接给了3次黄牌,就没敢查了)其实老师10点的时候说这个没影响了,但是当时腾讯会议监考老师说话噪声很大,也没听清

最后开考40分钟才做完客观题(其实大部分都不会,都是蒙的,真想不到当时咋做半小时的),收到30个黄牌警告,刚才对答案好像就对了三四个选择,哎~

不过还好这次程序题占比大一点,写的也比较顺利,中间基本没有卡,花了近三小时写完的

客观题答案解析https://mp.weixin.qq.com/s/IAe9PAHb5-BMee2uIpdAeg

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LqR6b6ZTWF4MDAwMDE0,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LqR6b6ZTWF4MDAwMDE0,size_20,color_FFFFFF,t_70,g_se,x_16

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5LqR6b6ZTWF4MDAwMDE0,size_20,color_FFFFFF,t_70,g_se,x_16

 

//代码是十三届蓝桥杯单片机组省赛比赛的时候写的,当时验证的要求都实现了,也许还有一些没发现的BUG,欢迎指出哦,比赛给的ONEWIRE函数要改一下时序和声名,DS1302直接不变
#include <STC15F2K60S2.H>
#include <DS1302.H>
#include <ONEWIRE.H>

bit flag=0,X1,Y1,X2,Y2,X3,Y3,X4,Y4,RELAY,RELAY1,MODE1=0,L1,L3;
unsigned char KEY,flag_k,MODE,VALUE=23,LED_COUNT;
unsigned int Temper,COUNT;
unsigned char code Nixie[23]={0xC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF
,0X40,0X79,0X24,0X30,0X19,0X12,0X02,0X78,0X00,0XBF,0XC1};
//数码管段码值,按顺序分别是0~9,分隔符,全灭,带小数点0~9,字母U
unsigned char Nixie_Buffer[8]={11,11,11,11,11,11,11,11};
//数码管显示值缓存数组,第0~8位对应数码管0~8位
unsigned char DS1302_Buffer[7]={0X30,0X25,0X23,0X09,0X04,0X06,0X22};
//DS1302时间值存储数组
void Delay500ms()		//@12.000MHz
{
	unsigned char i, j, k;

	_nop_();
	_nop_();
	i = 23;
	j = 205;
	k = 120;
	do
	{
		do
		{
			while (--k);
		} while (--j);
	} while (--i);
}
void HL138(unsigned char channel){
	switch(channel){
		case 4:P2=(P2&0X1F)|0X80;break;
		case 5:P2=(P2&0X1F)|0XA0;break;
		case 6:P2=(P2&0X1F)|0XC0;break;
		case 7:P2=(P2&0X1F)|0XE0;break;
	}
	P2=P2&0X1F;
}//锁存器选择函数
void Nixie_change(unsigned char d1,d2,d3,d4,d5,d6,d7,d8){
	Nixie_Buffer[0]=d1;
	Nixie_Buffer[1]=d2;
	Nixie_Buffer[2]=d3;
	Nixie_Buffer[3]=d4;
	Nixie_Buffer[4]=d5;
	Nixie_Buffer[5]=d6;
	Nixie_Buffer[6]=d7;
	Nixie_Buffer[7]=d8;
}
//数码管缓存数组值改写函数
void Nixie_scan(){
	unsigned char number;
	P0=0XFF;HL138(7);
	P0=0X01<<number;HL138(6);
	P0=Nixie[Nixie_Buffer[number]];HL138(7);
	if(++number==8)number=0;
//定时扫描数码管,读出数码管缓存数组对应的段码值
	P0=0XFF;
//清空P0寄存器中的值
	if(MODE1==0){
		if(RELAY==1){
			P0=P0&0X10;
		}
		else{
			P0=P0&0X00;
		}
		RELAY1=0;
	}
	else{
		if(RELAY1==1){
			P0=P0&0X10;
		}
		else{
			P0=P0&0X00;
		}	
	}
//定时扫描继电器,和同样使用锁存器的数码管放在同一个函数中,防止数码管鬼影
	if(P0==0X10){
		L3=1;
	}
	else{
		L3=0;
	}
//判断继电器是否吸合,决定L3灯状态
	HL138(5);
	P0=0XFF;
	if(MODE1==0){
		P0=P0&0XFE;
	}
	if(L1==1){
		P0=P0&0XFD;
	}
	else{
		P0=P0|0X02;
	}
	if(L3==1){
		LED_COUNT++;
		LED_COUNT%=50;
		if(LED_COUNT==25){
			P0=P0&0XFB;
		}
		if(LED_COUNT==0){
			P0=P0|0X40;
		}
	}
	else{
		LED_COUNT=0;
	}
	HL138(4);
//LED状态判断函数,定时扫描
}
void Key_scan(){
	if(flag_k==9){
		P34=1;P35=0;
		P32=P33=1;
		if(P32==0){X1=1,Y1=0;}
//如果第一次扫描为P32按下
		if(P33==0){X2=1,Y2=0;}
		if(P32==1){Y1=1;}
//如果20ms后再次进入p32松手
		if(P33==1){Y2=1;}
		if(X1==1&&Y1==1){KEY=13;X1=0;Y1=0;}
//判断是否是按键按下的松手动作
		if(X2==1&&Y2==1){KEY=12;X2=0;Y2=0;}
//扫描S13,S12两个键
		P34=0;P35=1;
		P32=P33=1;
		if(P32==0){X3=1,Y3=0;}
		if(P33==0){X4=1,Y4=0;}
		if(P32==1){Y3=1;}
		if(P33==1){Y4=1;}
		if(X3==1&&Y3==1){KEY=17;X3=0;Y3=0;}
		if(X4==1&&Y4==1){KEY=16;X4=0;Y4=0;}
	}		
}
//按键扫描函数,20ms进入一次,通过20ms时间间隔代替消抖
void DS18B20_READ(){
	unsigned char MSB,LSB;
	
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0X44);
	init_ds18b20();
	Write_DS18B20(0XCC);
	Write_DS18B20(0XBE);
	LSB=Read_DS18B20();
	MSB=Read_DS18B20();
	Temper=MSB;
	Temper=(Temper<<8)|LSB;
	Temper=(Temper/16.0)*10;
//除16.0是为了将数据右移四位并且转换为float类型数据运算(可保留小数位),乘以10是为了放大10倍保证转换成int变量后小数后一位不丢失,同理,乘以100可放大100倍相当于保留两位小数数据
}
//DS18B20的读取函数
void DS1302_W(){
	unsigned char i,addr=0x80;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++){
		Write_Ds1302_Byte(addr,DS1302_Buffer[i]);
		addr+=2;
	}
	Write_Ds1302_Byte(0x8e,0x80);
}
//DS1302写函数
void DS1302_R(){
	unsigned char i,addr=0x81;
	for(i=0;i<7;i++){
		DS1302_Buffer[i]=Read_Ds1302_Byte(addr);
		addr+=2;
	}
}
//DS1302读函数
void Timer0Init(void)		
{
	AUXR |= 0x80;		
	TMOD &= 0xF0;		
	TL0 = 0X40;		
	TH0 = 0XA2;		
	TF0 = 0;		
	TR0 = 1;
	EA=1;
	ET0=1;
}
//定时器配置,2ms溢出一次
void main(){
	DS18B20_READ();
	DS1302_W();
	Delay500ms();
	Timer0Init();
	P0=0XFF;HL138(4);
	P0=0X00;HL138(5);
	P0=0XFF;HL138(6);
	P0=0XFF;HL138(7);
//初始化
	while(1){
		if(KEY==12){
			MODE++;
			MODE%=3;
			KEY=0;
		}
//按下S12,切换显示界面
		if(flag==1){
			if(flag_k==9){
				DS18B20_READ();
				DS1302_R();
			}
//每20ms读取一次温度和时间
			if((DS1302_Buffer[0]==0)&&(DS1302_Buffer[1]==0)){
				L1=1;
			}
//整点时,L1灯标志位置1,上方的LED扫描函数中点亮L1的条件达成
			if((DS1302_Buffer[0]/16==0)&&(DS1302_Buffer[0]%16==5)&&(DS1302_Buffer[1]==0))            
            {
				L1=0;
			}
//00分05秒时,熄灭L1		
			if(MODE==0){
				Nixie_change(22,1,11,11,11,Temper/100,Temper%100/10+12,Temper%10);
			}
//显示温度值的界面
			if(MODE==1){
				if(X3==1&&Y3==0){					 
Nixie_change(22,2,11,DS1302_Buffer[1]/16,DS1302_Buffer[1]&0X0F,21,DS1302_Buffer[0]/16,DS1302_Buffer[0]&0X0F);
					while(X3==1&&Y3==0);
				}
//界面2时,S17正在按下时,显示分秒
				else {
				if(KEY==17){
					KEY=0;
					if(VALUE==10){
						VALUE=100;
					}
					VALUE--;
				}				Nixie_change(22,2,11,DS1302_Buffer[2]/16,DS1302_Buffer[2]&0X0F,21,DS1302_Buffer[1]/16,DS1302_Buffer[1]&0X0F);
//松开S17后,温度参数减一,显示时分界面
				}
			}		
			if(MODE==2){
				if(KEY==16){
					KEY=0;
					if(VALUE==99){
						VALUE=9;
					}
					VALUE++;
					
				}
				if(KEY==17){
					KEY=0;
					if(VALUE==10){
						VALUE=100;
					}
					VALUE--;
				}
				Nixie_change(22,3,11,11,11,11,VALUE/10,VALUE%10);
//温度参数设置界面					}
		if(KEY==13){
			KEY=0;
			MODE1=!MODE1;
		}
//S13按键切换温度控制模式和时间控制模式
		if(MODE1==0){
			if(Temper/10>=VALUE){
				RELAY=1;
			}
			else if(Temper/10<VALUE){
				RELAY=0;
			}
		}
//温度控制模式
		if(MODE1==1){
			if((DS1302_Buffer[0]==0)&&(DS1302_Buffer[1]==0)){
				RELAY1=1;
			}
			if((DS1302_Buffer[0]/16==0)&&(DS1302_Buffer[0]%16==5)&&(DS1302_Buffer[1]==0))        
            {
				RELAY1=0;
			}
		}
//时间控制模式
			flag=0;
		}
	}
}
void Timer0Init_service() interrupt 1{
	Nixie_scan();
	flag=1;
	flag_k++;
	flag_k%=10;
	Key_scan();
}
//定时扫描函数,数码管2ms一次,按键20ms一次

 

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值