【第十三届蓝桥杯单片机省赛模拟冲刺01】

第十三届蓝桥杯单片机省赛模拟冲刺

赛前一两周一定要多练习,把之前写过的程序在好好看看,把每个模块的代码都多敲几遍,把常考的每个模块部分都吃透,如果理解不了的趁时间还比较充足该背的背牢。同时在准备编程题的同时 也要多看看客观题,比较所占分值还是挺多的。
总之加油加油 尽自己最大努力就好。

修改版

前面没有实现长按功能,修改版本已解决,但是是长按时间到达之后松手后才反应,想要的效果是长按还未松开按键就可以反应 希望大佬可以指正。
总的来说全部功能还是实现了

在这里插入图片描述

一、题目

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

该模拟题的整体 难度并不是很大,不同界面之间的切换是必考的,所以如何去实现不同界面之间的合理切换是很重要的。还是那句把常用的模块熟悉掌握,剩下的就多练习,练习不同功能之间处理的逻辑思路,这一点是非常重要的。
这套模拟题难一点的就是按键的长按处理,因为自己之前没有写过长按的按键,下面的demo中就只差长按的处理了。还望各位大佬指教。

二、代码解析

#include "reg52.h"
#include "iic.h"


/*****************************************************
*第十三届省赛模拟
*Date:2022-3-27
*Author:小殷
*****************************************************/


//独立按键定义
sbit S7 = P3^0;
sbit S6 = P3^1;
sbit S5 = P3^2;
sbit S4 = P3^3;

//LED定义
sbit LED1 = P0^0;
sbit LED2 = P0^1;
sbit LED3 = P0^2;
sbit LED4 = P0^3;
sbit LED5 = P0^4;

unsigned int Frequent = 0 ,f_data = 0,count = 0,count_flag = 0;   //频率相关变量
unsigned int Period = 0;    //周期
unsigned int Voltage_Rd1 = 0,Voltage_Rb2 = 0,Voltage = 0; //电压
unsigned int old_voltage  = 0,old_frequent = 0;
unsigned char led_flag = 0; //0 代表开启  1 代表关闭
unsigned char channel = 1,interface = 1 ; //通道编号  和显示界面
unsigned char time_flag = 0; //1s标志
unsigned char s7_press = 0,s_count = 0,s7_mode = 0; //按键长按下标志  ,计时变量  模式切换
unsigned char code smg_data[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90,0xbf,0xff};
unsigned char code smg_data_dot[] = {0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char led[] = {0xfe,0xfd,0xfb,0xf7,0xef,0xff,0xff,0xff}; //led


void SMG_Display_V(void);
void SMG_Display_F(void);
void SMG_Display_T(void);

/**********************简单延时**********************/
void delay(unsigned char t)
{
 	while(t--);
}


void delay_smg(unsigned char t)
{
 	while(t--)
	{
	 	if(interface == 1)
		{
			 SMG_Display_F();
		}
		else if(interface == 2)
		{
				SMG_Display_T();
		}
		else if(interface == 3)
		{
			 SMG_Display_V();
		}

	}
}


/**********************锁存器操作********************/
void Init_74HC138(unsigned char n)
{
 	switch(n)
	{
	 	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;
		case 0:P2 = (P2 & 0x1f) | 0x00;break;
	}
}

/*********************数码管安位操作*******************/
void SMG_DisplayBit(unsigned char pos,unsigned char dat)
{
 	Init_74HC138(6);
	P0 = (0x01 << pos);
	Init_74HC138(7);
	P0 = dat;
	Init_74HC138(0);
}

/*************************关闭所有数码管***************/
void SMG_Close(void)
{
	Init_74HC138(6);
	P0 = 0xff;
	Init_74HC138(7);
	P0 = 0xff;
	Init_74HC138(0);
}	

/**********************系统初始化**********************/
void Init_System(void)
{
 	Init_74HC138(4);
	P0 = 0xff;
	Init_74HC138(5);
	P0 = 0x00;
	Init_74HC138(0);
}

/***********************数码管功能显示******************/
void SMG_Display_F(void)
{
 	SMG_DisplayBit(0,0x8e);  // F ->0111 0001 0x8e
	delay(200);
	if(Frequent > 999999)
	{
		SMG_DisplayBit(1,smg_data[Frequent/1000000]);
	  delay(200);
	}
 if(Frequent > 99999)
	{
		SMG_DisplayBit(2,smg_data[Frequent/100000%10]);
	 delay(200);
	}
	 if(Frequent > 9999)
	{
		SMG_DisplayBit(3,smg_data[Frequent/10000%10]);
		delay(200);
	}
 if(Frequent > 999)
	{
		SMG_DisplayBit(4,smg_data[Frequent/1000%10]);
	  delay(200);
	}
 if(Frequent > 99)
	{
		 SMG_DisplayBit(5,smg_data[Frequent /100%10]);
		 delay(200);
	}
 if(Frequent > 9)
	{
		SMG_DisplayBit(6,smg_data[Frequent /10%10]);
		delay(200);
	}

	SMG_DisplayBit(7,smg_data[Frequent %10]);
	delay(200);
	SMG_Close();

}

/*****************************周期显示***********************/
void SMG_Display_T(void)
{
	Period = 1.0/Frequent *1000000;
	SMG_DisplayBit(0,0xc8);  // >0001 0011  0xc8
	delay(200);
	if(Period > 999999)
	{
		SMG_DisplayBit(1,smg_data[Period/1000000]);
	  delay(200);
	}
 if(Period > 99999)
	{
		SMG_DisplayBit(2,smg_data[Period/100000%10]);
	 delay(200);
	}
	 if(Period > 9999)
	{
		SMG_DisplayBit(3,smg_data[Period/10000%10]);
		delay(200);
	}
 if(Period > 999)
	{
		SMG_DisplayBit(4,smg_data[Period/1000%10]);
	  delay(200);
	}
 if(Period > 99)
	{
		 SMG_DisplayBit(5,smg_data[Period /100%10]);
		 delay(200);
	}
 if(Period > 9)
	{
		SMG_DisplayBit(6,smg_data[Period /10%10]);
		delay(200);
	}

	SMG_DisplayBit(7,smg_data[Period %10]);
	delay(200);
	SMG_Close();
	
}

/*******************************电压显示**********************/
void SMG_Display_V(void)
{
	SMG_DisplayBit(0,0xc1);  // >1000 0011  0xc8
	delay(200);
	SMG_DisplayBit(1,0xbf); // -  
	delay(200);
	SMG_DisplayBit(2,smg_data[channel]);  
	delay(200);
	SMG_DisplayBit(3,0xff);  
	delay(200);
	SMG_DisplayBit(4,0xff);  
	delay(200);
	SMG_DisplayBit(5,smg_data_dot[Voltage/100]);  
	delay(200);
	SMG_DisplayBit(6,smg_data[Voltage/10%10]);  
	delay(200);
	SMG_DisplayBit(7,smg_data[Voltage%10]);  
	delay(200);
	SMG_Close();
	delay(200);
}
/******************************定时器初始化******************/
void Init_Timer(void)
{
 	TMOD = 0x16; //定时器0计数 定时器1 计时
	TH0 = 0xff;
	TL0 = 0xff;
	TH1 = (65535-50000)/256; //50ms
	TL1 = (65535-50000)%256;
	ET0 = 1;
	ET1 = 1;
	TR0 = 1;
	TR1 = 1;
	EA  = 1;
}




unsigned char  Read_RD1(void)
{
	 unsigned char temp  = 0;
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(0x01);   //光敏通道
	 IIC_WaitAck();
	 IIC_Stop(); 
	 
	 IIC_Start();
	 IIC_SendByte(0x91);
	 IIC_WaitAck();
	 temp = IIC_RecByte();
	 IIC_SendAck(1);
	 IIC_Stop(); 
	 return temp;
}



unsigned char  Read_RD2(void)
{
	 unsigned char temp  = 0;
	 IIC_Start();
	 IIC_SendByte(0x90);
	 IIC_WaitAck();
	 IIC_SendByte(0x03);   //电位器通道
	 IIC_WaitAck();
	 IIC_Stop(); 
	 
	 IIC_Start();
	 IIC_SendByte(0x91);
	 IIC_WaitAck();
	 temp = IIC_RecByte();
	 IIC_SendAck(1);
	 IIC_Stop(); 
	 return temp;
}

/***************************按键处理*************************/
void KeyScans(void)
{
 	if(S4 == 0)
	{
	 	delay_smg(20);
		if(S4 == 0)
		{
		 	while(S4 == 0); //等待按键松开
			if(interface == 1)
			{
			 	interface = 2;
				SMG_Display_F();
			}
			else if(interface == 2)
			{
			 	interface = 3;
				SMG_Display_T();
			}
			else if(interface == 3)
			{
			 	interface = 1;
				SMG_Display_V();
			}
		}
	}

	if(S5 == 0)
	{
	 	delay_smg(20);
		if(S5 == 0)
		{
		 	while(S5 == 0); //等待按键松开
			if(channel == 1)
			{
			 	channel = 3;
			}
			else if(channel == 3)
			{
				channel = 1;
			}
		}
	}

	if(S6 == 0)
	{
	 	delay_smg(20);
		if(S6 == 0)
		{
		 	while(S6 == 0); //等待按键松开
			old_voltage = Voltage ;		 //保存旧值
		}
	}

	if(S7 == 0)
	{
	 	delay_smg(20);
		if(S7 == 0)
		{
			s7_press = 0;   //按键按下标志
			s_count = 0;
			while(S7 == 0); //等待按键松开
			if(s7_press == 1)	   //长按
			{
				if(s7_mode == 0)	//模式切换变量 第一次长按关闭Led功能  再次长按打开led功能
				{
				 	s7_mode = 1;
					led_flag = 1;	 //关闭led功能
				}
				else if(s7_mode == 1)
				{
				 	s7_mode = 0;
					led_flag = 0;		//打开led功能
				}	
			}
			else	  //短按
			{
	    	old_frequent = Frequent;	 //保存旧值
			}
		}
		

	}

}

/************************Led操作函数*************************/
void Led_Running(void)
{
 	if(led_flag == 0)
	{	
		Init_74HC138(4); //选通Y4 进行LED 控制
		//通道3的实时电压数据大于缓存电压数据,指示灯L1点亮,否则熄灭
		if(Voltage > old_voltage )
		{
		 	//P0 = led[0];
			LED1 = 0;
		}
		else
		{
		 	LED1 = 1;
		}
		//实时频率值大于缓存频率数据,指示灯L2点亮,否则熄灭
		 if(Frequent > old_frequent )
		{
			//P0 = led[1];
			LED2 = 0;	
		}
		else
		{
		 	LED2 = 1;
		}
		 //处于频率界面,指示灯L3点亮,否则熄灭
		if(interface == 1)
		{
		 	//P0 = led[2];
			LED3 = 0;
		}
		else
		{
		 	LED3 = 1;
		}
		//处于周期界面,指示灯L4点亮,否则熄灭。
		if(interface == 2)
		{
		 	//P0 = led[3];
			LED4 = 0;
		}
		else
		{
		 	LED4 = 1;
		}
		//处于电压界面,指示灯L5点亮,否则熄灭
		 if(interface == 3)
		{
		 	//P0 = led[4];
			LED5 = 0;
		}
		else
		{
		 	LED5 = 1;
		}
	}
	else if(led_flag == 1)
	{
		P0 = 0xff;
	 	Init_74HC138(4);	
	}
	//Init_74HC138(0);
}
/****************************主函数**************************/
void main(void)
{
 	Init_System();
	Init_Timer();
	while(1)
	{
		KeyScans();
		switch(interface)
		{
		 	case 1:SMG_Display_F();break;
			case 2:SMG_Display_T();break;
			case 3:SMG_Display_V();break;
		}
	 	if(interface == 3)
		{
			switch(channel)
			{
			  case 1: Voltage_Rd1 = Read_RD1();
	 	   				  Voltage = ( Voltage_Rd1/255.0 *5*100);//将其扩大100倍方便显示
								break;
				case 3:	Voltage_Rb2 = Read_RD2();
	 	   				  Voltage = ( Voltage_Rb2/255.0 *5*100);//将其扩大100倍方便显示
				        break;
			}
		}

		Led_Running();

	}

}

void Server_Timer0() interrupt 1
{
	 f_data++; 
}


void Server_Timer1() interrupt 3
{
	TH1 = (65535-50000)/256; //50ms
	TL1 = (65535-50000)%256;
	count++;
	s_count++;
	if(count == 20) //1s
	{
	 	Frequent = f_data;
		f_data = 0;
		count = 0;
	}

	//长按计时
	if(s_count == 20)
	{
	 	s7_press = 1;	 //到达1s  s7press 置1
	}

}

加油

  • 9
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小殷学长

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

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

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

打赏作者

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

抵扣说明:

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

余额充值