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

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

题目来自电子设计工坊
最后一两周的时间在做两套模拟题,将各个模块的使用都练习一遍

在这里插入图片描述

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

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

/**************************************
*第十三届蓝桥杯单片机省赛模拟
*Date:2022-3-29
*Author:小殷
***************************************/

sfr P4 = 0xc0;
sbit H1 = P3^0;
sbit H2 = P3^1;
sbit H3 = P3^2;
sbit H4 = P3^3;

sbit L1 = P3^4;
sbit L2 = P3^5;
sbit L3 = P4^2;
sbit L4 = P4^4;


sbit  LED1 = P0^0;
sbit  LED2 = P0^1;

unsigned char s_press = 0,s_count = 0; //按键按下标志位和计时
unsigned char count = 0,led_flag = 0;	//计时  led标志位
unsigned int count_value = 0,count_value2 = 0;//按键值 和保存值
unsigned char interface = 1;	//界面
//数码管段码
unsigned char code smg_data[] = {
    
    0xC0,0xF9,0xA4,0xB0,0x99,0x92,
																	0x82,0xF8,0x80,0x90,0xbf,0xff};


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

//操作锁存器
void Init_74HC138(unsigned char channel)
{
    
    
 	switch(channel)
	{
    
    
	 	case 4:P2 = (P2 & 0x1f) | 0x80;break; //Y4
		case 5:P2 = (P2 & 0x1f) | 0xa0;break; //Y5
		case 6:P2 = (P2 & 0x1f) | 0xc0;break; //Y6
		case 7:P2 = (P2 & 0x1f) | 0xe0;break; //Y7
		case 0:P2 = (P2 & 0x1f) | 0x00;break; //不选通任何一个
	}
		P2 = (P2 & 0x1f) | 0x00;
}

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

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


//显示数码管数据 累加和减的数据
void SMG_Display_Data1(void)
{
    
    
 //0001 0001  ->0x88
 	SMG_DisplayBit(0,0x88);
	delay(200);
	//	SMG_DisplayBit(0,0xff);
	SMG_DisplayBit(1,0xff);
	delay(200);
	SMG_DisplayBit(2,0xff);
	delay(200);
	SMG_DisplayBit(3,0xff);
	delay(200);
	SMG_DisplayBit(4,0xff);
	delay(200);
	//3位数码管来显示键值
	if(count_value > 99)
	{
    
    
		SMG_DisplayBit(5,smg_data[count_value/100]);
	 	delay(200);
	}
	if(count_value > 9)
	{
    
    
			SMG_DisplayBit(6,smg_data[count_value/10%10]);
			delay(200);
	}
	
	SMG_DisplayBit(7,smg_data[count_value%10]);
	delay(200);
	SMG_All(0xff);
	delay(200);
}


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

//回显数据显示
void SMG_Display_Data2(void)
{
    
    
 //1001 0001 ->0x89
 	SMG_DisplayBit(0,0x89);
	delay(200);
	//	SMG_DisplayBit(0,0xff);
	SMG_DisplayBit(1,0xff);
	delay(200);
	SMG_DisplayBit(2,0xff);
	delay(200);
	SMG_DisplayBit(3,0xff);
	delay(200);
	SMG_DisplayBit(4,0xff);
	delay(200);
	//3位数码管来显示键值
	if(count_value > 99)
	{
    
    
		SMG_DisplayBit(5,smg_data[count_value2/100]);
	 	delay(200);
	}
	if(count_value > 9)
	{
    
    
			SMG_DisplayBit(6,smg_data[count_value2/10%10]);
			delay(200);
	}
	
	SMG_DisplayBit(7,smg_data[count_value2%10]);
	delay(200);
	SMG_All(0xff);
	delay(200);
}


//EEPROM写操作
void Write_AT24C02(unsigned char addr,unsigned char dat)
{
    
    
 	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

//读操作
unsigned char Read_AT24C02(unsigned char addr)
{
    
    
 	unsigned int temp = 0;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();

	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_SendAck(1);
	IIC_Stop();
	return temp;
}


void Key_Scan(void)
{
    
    
	H3 = 0;
	H1 = H2 = H4 = 1;
	L1 =  L2 = L3 = L4 = 1;
	//S9		回显
	if(L3 == 0)
	{
    
    
	 	delay(20);
		if(L3 == 0)
		{
    
    
		 	while(L3 == 0){
    
    
			if(interface == 1)
			{
    
    
			 	interface = 2; //界面切换
				SMG_Display_Data1();	
			}
			else if(interface == 2)
			{
    
    
			 	interface = 1;
				SMG_Display_Data2();
			}
		}
		}
	}
	//S5 减
	else if(L4 == 0)
	{
    
    
	 	delay(20);
		if(L4 == 0)
		{
    
    
			
		 	while(L4 == 0)	 
			{
    
    
				SMG_Display_Data1();
			}
			 //在计数界面下进行键值的减
			if(interface == 1)
			{
    
    
					count_value--;
			}
		
		}
	}

	H4 = 0;
	H1 = H2 = H3 = 1;
	L1 =  L2 = L3 = L4 = 1;
	//S8	存储
	if(L3 == 0)
	{
    
    
	 	delay(20);
		if(L3 == 0)
		{
    
    
			//每次按下时将计时和标志位清零
			s_press = 0;
			s_count = 0;
		 	while(L3 == 0)	
			{
    
    
					SMG_Display_Data1();
			}	
			if(s_press == 1)	 //长按标志
			{
    
    
			 	count_value = 0;			//计数清零
			}
			//短按
			else
			{
    
    
				if(interface == 1)
				{
    
    
				 	//count_value2 = count_value;		//保存当前值
					Write_AT24C02(0x00,count_value);
				}
			}
		
		}
	}
	//S4  加
	else if(L4 == 0)
	{
    
    
	 	delay(20);
		if(L4 == 0)
		{
    
    		
			
			 	while(L4 == 0)
				{
    
    
				 	SMG_Display_Data1();
				}
				//在计数界面下 进行键值的累加
				if(interface == 1)
				{
    
    
					count_value++;
				}
		}
	}

}


//dac数据
void Read_DAC(float dat)
{
    
    
 	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x43);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}




//电压显示
void Voltage_Tackle(void)
{
    
    
 	//为5非0 整数倍	 DAC->4  ELSE DAC ->1
	if((count_value % 5)== 0)
	{
    
    
	 	Read_DAC(204); //数字转模拟	  0-5  ->0-255
		//5/255 = 4/x    4x51 = 204
	}
	else
	{
    
    
	 	Read_DAC(51);
	}
}

void Led_Tackle(void)
{
    
    
	if(interface == 1)
	{
    
    
	 	LED1 = 0;
	}
	else
	{
    
    
	 	LED1 = 1;
	}
	if(count_value > count_value2)
	{
    
    
	 		if(led_flag == 0)
			{
    
    
			 	LED2 = 0;
			}
			else if(led_flag == 1)
			{
    
    
			 	LED2 = 1;
			}
	}
	Init_74HC138(4);
}


void Init_Timer(void)
{
    
    
 	TMOD = 0x01;
	TH0 = (65535-50000)/256;		 //50ms
	TL0 = (65535-50000)%256;
	ET0 = 1;
	TR0 = 1;
	EA  = 1;
}
//主函数
void main(void)
{
    
    
	Init_System();
	Init_Timer();
	while(1)
	{
    
    
		Key_Scan();
	 	switch(interface)
		{
    
    
		 	case 1:SMG_Display_Data1();break;
			case 2:
						count_value2 = Read_AT24C02(0x00);
						SMG_Display_Data2();break;
		}
		Led_Tackle();
		Voltage_Tackle();
		
	}
}


void Server_Timer0() interrupt 1
{
    
    
 	TH0 = (65535-50000)/256;		 //50ms
	TL0 = (65535-50000)%256;
	count++;
	s_count++;
	if(count == 4) //0.2s 开启led标志位
	{
    
    
		count = 0;
	 	if(led_flag == 0)
		{
    
    
		 	led_flag = 1;
		}
		else if(led_flag == 1)
		{
    
    
		 	led_flag = 0;
		}
	}

	if(s_count == 40) //定时2s
	{
    
    
	 	s_press = 1; //长按标志位置1 代表已进入长按模式
	} 

}

猜你喜欢

转载自blog.csdn.net/boybs/article/details/123829667