【第十三届蓝桥杯单片机省赛题软件部分1】

【第十三届蓝桥杯单片机省赛题软件部分1】

第十四届蓝桥杯又开始啦,XDM都在做准备了麦,明年的蓝桥杯将是自己大学期间最后一个比赛了,希望可以取得一个更好的成绩,努力勿辜负,加油。

一、题目要求

【第十三届蓝桥杯单片机省赛题软件部分1】_第1张图片
【第十三届蓝桥杯单片机省赛题软件部分1】_第2张图片
【第十三届蓝桥杯单片机省赛题软件部分1】_第3张图片
【第十三届蓝桥杯单片机省赛题软件部分1】_第4张图片
【第十三届蓝桥杯单片机省赛题软件部分1】_第5张图片【第十三届蓝桥杯单片机省赛题软件部分1】_第6张图片

【第十三届蓝桥杯单片机省赛题软件部分1】_第7张图片
【第十三届蓝桥杯单片机省赛题软件部分1】_第8张图片

二、软件部分
#include "reg52.h"
#include "iic.h"

/******************************************************************
*第十三届蓝桥杯省赛软件部分实现									  *
*Author:小殷童鞋 												  *
*Date:2022-12-13                                                  *      
*******************************************************************/
sbit S4 = P3^3;
sbit S5 = P3^2;
sbit S6 = P3^1;
sbit S7 = P3^0;

unsigned int f_count = 0,count = 0,period = 0;   //频率  显示频率  周期变量
unsigned char Rd_Data = 0,Rd_Volt = 0, channel = 1; //通道模拟数据 电压 和通道变量
unsigned char interface = 1;     //界面
unsigned int old_volt = 0,old_f = 0; //缓存电压和频率
unsigned char long_press_flag = 0,t_count = 0,press_count = 0; //长按标志 计时  长按次数变量
unsigned char led_flag = 1,led_status = 0xff,old_led_status = 0xff;//led启动标志 led状态 led旧状态变量
//共阳
unsigned char code SMG_Duan[] = {0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
								 0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E,0xbf}; //数码管段码

unsigned char code smg_dot[] ={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10}; //带小数点
//简单延时
void delay(unsigned int t)
{
	while(t--);
}
//744HC138初始化
void Init_74HC138(unsigned char dat)
{
	switch(dat)
	{
		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;
	}
	P2 = (P2 & 0x1f) | 0x00;
}

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

//操作所有数码管
void Controal_All_SMG(unsigned char dat)
{
	P0 = 0xff;
	Init_74HC138(6);
	P0 = dat;
	Init_74HC138(7);
}

//数码管数据显示频率
void SMG_Display_Frequent(void)
{
	SMG_DisplayByBit(0,SMG_Duan[15]);
	delay(200);
	if(count > 999999)
	{
		SMG_DisplayByBit(1,SMG_Duan[count/1000000]);
		delay(200);
	}
	if(count > 99999)
	{
		SMG_DisplayByBit(2,SMG_Duan[count/100000%10]);
		delay(200);
	}
	if(count > 9999)
	{
		SMG_DisplayByBit(3,SMG_Duan[count/10000%10]);
		delay(200);
	}
	if(count > 999)
	{
		SMG_DisplayByBit(4,SMG_Duan[count/1000%10]);
		delay(200);
	}
	if(count > 99)
	{
		SMG_DisplayByBit(5,SMG_Duan[count/100%10]);
		delay(200);
	}
	
	if(count > 9)
	{
		SMG_DisplayByBit(6,SMG_Duan[count/10%10]);
		delay(200);
	}	
	SMG_DisplayByBit(7,SMG_Duan[count%10]);
	delay(200);
	Controal_All_SMG(0xff);
	delay(200);
	
}


//周期显示
void SMG_Display_Period(void)
{
	SMG_DisplayByBit(0,~0x37);
	delay(200);
	if(count > 999999)
	{
		SMG_DisplayByBit(1,SMG_Duan[period/1000000]);
		delay(200);
	}
	if(count > 99999)
	{
		SMG_DisplayByBit(2,SMG_Duan[period/100000%10]);
		delay(200);
	}
	if(count > 9999)
	{
		SMG_DisplayByBit(3,SMG_Duan[period/10000%10]);
		delay(200);
	}
	if(count > 999)
	{
		SMG_DisplayByBit(4,SMG_Duan[period/1000%10]);
		delay(200);
	}
	if(count > 99)
	{
		SMG_DisplayByBit(5,SMG_Duan[period/100%10]);
		delay(200);
	}
	
	if(count > 9)
	{
		SMG_DisplayByBit(6,SMG_Duan[period/10%10]);
		delay(200);
	}	
	SMG_DisplayByBit(7,SMG_Duan[period%10]);
	delay(200);
	Controal_All_SMG(0xff);
	delay(200);
	
}


//PCF8591电压采集
void PCF8591_Volt_Rd1(unsigned char channel)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	if(channel == 1)
	{
		IIC_SendByte(0x01);    //光敏
	}
	else if(channel == 3)
	{
		IIC_SendByte(0x03);    //电压
	}
	IIC_WaitAck();
	IIC_Stop();
	
	IIC_Start();
	IIC_SendByte(0x91);
	IIC_WaitAck();
	Rd_Data = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	Rd_Volt = Rd_Data * (5.0/255)  * 100;    //扩大100倍方便显示	
}



//数码管电压显示数据
void SMG_Display_Volt(void)
{
	SMG_DisplayByBit(0,~0x3e);
	delay(200);
	SMG_DisplayByBit(1,0xbf);
	delay(200);
	SMG_DisplayByBit(2,SMG_Duan[channel]);       //通道编号
	delay(200);
	SMG_DisplayByBit(3,0xff);
	delay(200);
	SMG_DisplayByBit(4,0xff);
	delay(200);

	SMG_DisplayByBit(5,smg_dot[Rd_Volt/100]);    //电压
	delay(200);
	SMG_DisplayByBit(6,SMG_Duan[Rd_Volt/10%10]);
	delay(200);
	SMG_DisplayByBit(7,SMG_Duan[Rd_Volt%10]);
	delay(200);
	Controal_All_SMG(0xff);
	delay(200);	
}

//按键控制
void Key_Scans(void)
{
	if(S4 == 0)
	{
		delay(20);
		if(S4 == 0)
		{
			while(S4 == 0)
			{
				//在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
				if(interface == 1)
				{
					SMG_Display_Frequent();
				}
				else if(interface == 2)
				{
					SMG_Display_Period();
				}
				else if(interface == 3)
				{
					SMG_Display_Volt();                                                         
				}
			}
			if(interface == 1)
			{
				interface = 2;
			}
			else if(interface == 2)
			{
				interface = 3;
			}
			else if(interface == 3)
			{
				interface = 1;
			}
		}
	}
	
	if(interface == 3)
	{
		
		//S5通道切换
		if(S5 == 0)
		{
			delay(20);
			if(S5 == 0)
			{				
				while(S5 == 0)
				{
					PCF8591_Volt_Rd1(channel);
					SMG_Display_Volt();
				}
				if(channel == 1)
					  {
						channel = 3;
					}
					else if(channel == 3)
					{
						channel = 1;
					}
				
			}
		}
	}
	
	//S6缓存channel 电压
	if(S6 == 0)
	{
		delay(20);
		if(S6 == 0)
		{
			t_count = 0;
			long_press_flag = 0;

			while(S6 == 0)
			{
				//在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
				if(interface == 1)
				{
					SMG_Display_Frequent();
				}
				else if(interface == 2)
				{
					SMG_Display_Period();
				}
				else if(interface == 3)
				{
					SMG_Display_Volt();                                                         
				}
				
				if(long_press_flag == 1) //长按
				{
					if(press_count == 0)
					{
						press_count = 1;
						led_flag = 0;  //禁用LED 全部熄灭
						old_led_status = led_status; //缓存Led状态
						P0 = 0xff;
						Init_74HC138(4);
					}
					else if(press_count == 1)
					{
						//恢复LED功能
						press_count = 0;
						led_status = old_led_status; //将缓存的LED状态重新赋值给led_status
						led_flag = 1;                //启用LED功能
					}
					
				}
				else{
					if(channel == 3)
					{
						old_volt = Rd_Volt;
					}
				}
				
			}
			
		}
	}
	
	
	//S7缓存频率
	if(S7 == 0)
	{
		delay(20);
		if(S7 == 0)
		{
			while(S7 == 0)
			{
				//在按键一直按下时 避免数码管熄灭  根据相应的界面显示相应的数据
				if(interface == 1)
				{
					SMG_Display_Frequent();
				}
				else if(interface == 2)
				{
					SMG_Display_Period();
				}
				else if(interface == 3)
				{
					SMG_Display_Volt();                                                         
				}
			}
			old_f = count;     //将实时采集的频率count的值缓存到old_f变量中
		}
	}
}

//定时器初始化
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;
}

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


//主函数
void main(void)
{
	Init_System();          //系统初始化
	Init_Timer();           //定时器初始化
	while(1)
	{
		PCF8591_Volt_Rd1(channel);
		Key_Scans();
		switch(interface)
		{
			case 1:SMG_Display_Frequent();break;
			case 2:SMG_Display_Period();break;
			case 3:SMG_Display_Volt();break;
		}
		if(led_flag == 1)
		{
			if(old_volt < Rd_Volt) //L1 open
			{
				led_status =  0xfe;     //0111 1111
			}
			if(old_f < count)
			{
				led_status &= 0xfd;       //1011 1111
			}
			if(interface == 1)
			{
				led_status &= 0xfb;    //1101  1111
			}
			if(interface == 2)
			{
				led_status &= 0xf7;  //1110 1111
			}
			if(interface == 3)
			{
				led_status &= 0xef; //1111  0111
			}
			P0 = led_status;
			Init_74HC138(4);
		}
	}
}


void Timer0_Server() interrupt 1
{
	f_count++;
}

void Timer1_Server() interrupt 3
{
	static unsigned char t = 0;
	TH1  = (65535 - 50000)/256;  //高八位50ms
	TL1  = (65535 - 50000)%256;	
	t++;
	t_count++;
	if(t == 20)  //1s
	{
		count = f_count;
		period = (1.0/count) * 1000000;
		f_count = 0;
		t = 0;
	}
	if(t_count >= 20) //超过或等于1s
	{
		long_press_flag = 1;
	}
}
有时间就多多练习,You Can Make It

在这里插入图片描述

你可能感兴趣的:(蓝桥杯学习,蓝桥杯,单片机)