蓝桥杯单片机第十一届省赛(第一场)

蓝桥杯单片机第十一届省赛(第一场),第1张

 

 注:因为我自己的板子上的s16和s17按键有问题,故换成了s8和s9, *** 作原理是一样的,大家可以自行更改。


这套赛题,我觉得难点有:

①电压计数的条件,是在曲线下降的时候才+1,上升的时候并不加1

解决方法:实时电压从大于参考电压的状态到第一个小于参考电压的状态时说明经历了一个下降沿,此时计数值加1;同时设置标志,找到一个下降状态后使用switch()函数返回退出,否则的话计数值会一直增加。


        unsigned char t;
        switch(t)
        {
            case 0:
            if(dat_u>dat_p)
            {    
                t=1;
            } break;
            case 1:
            if(dat_u             {    
                count_n++;
                t=0;
            }    break;
        }

②L1和L3灯的点亮

对于点亮L1,我设置了一个控制它的变量 L1_kai,用来控制L1的点亮和熄灭

关于无效按键的计数,在下面的代码中,我只考虑了题目中所涉及的2*2按键,大家可以对整个矩阵按键进行无效按键计数(会稍微麻烦)。


解决方法:设置无效按键计数变量key_not,如果按键有效(s12按下、在参数界面按下s8和s9、在计数界面按下s13),则计数值清零key_not=0;如果按键无效(不在参数界面按下s8和s9、不在计数界面按下s13),则计数值加1key_not++;

③E2PROM

在退出参数界面时保存放大了10倍的电压参数到E2PROM,我选择将写 *** 作write_24c02(0x00,dat_p/10);    放在参数加或者减的部分中。


#include
#include
sfr P4=0XC0;

sbit R3=P3^2;
sbit R4=P3^3;
sbit C2=P4^2;
sbit C3=P3^5;

sbit L1=P0^0;
sbit L2=P0^1;
sbit L3=P0^2;
unsigned char code smg_nodot[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char code smg_dot[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char count_n=0;//电压计数
unsigned char count=0;//定时5s计数
unsigned char dat_value=0;//采取电位器数据
float dat_uu=0;//转换电压数据
unsigned int dat_u=0;//显示电压数据
unsigned int dat_p=0;//显示参数数据
unsigned char flag_s12=0;//按键切换界面标志
unsigned char L1_kai=0;	//	开启或关闭L1状态的标志
unsigned char key_not=0;//无效按键计数
void key();
void read_Rb2();
void displaysmg();
void write_24c02(unsigned char add,unsigned char dat);
void delaysmg(unsigned int t)
{
	while(t--);
}
void displaysmg_byte(unsigned char pos,unsigned char value)
{
  P2=0XE0;P0=0XFF;
  P2=0XC0;P0=0X01<99)
	 {
	 	displaysmg_byte(5,smg_nodot[count_n/100]);
	   delaysmg(100);
	 }
	 if(count_n>9)
	 {
	 	displaysmg_byte(6,smg_nodot[(count_n/10)%10]);
	   delaysmg(100);
	 }
	 displaysmg_byte(7,smg_nodot[count_n%10]);
	 delaysmg(100);	
	 displaysmg_byte(0,0xc8);	 
	 delaysmg(100);
	 displaysmg_byte(1,0xff);
	 delaysmg(100);
	 displaysmg_byte(2,0xff);
	 delaysmg(100);
	 displaysmg_byte(3,0xff);
	 delaysmg(100);
	 displaysmg_byte(4,0xff);
	 delaysmg(100);
}
void init_T0()//定时器初始化
{
  TH0=(65535-50000)/256;//定时50ms
  TL0=(65535-50000)%256;//定时50ms
  TMOD=0X01;//定时器0,工作方式1,0000 0001
  EA=1;
  ET0=1;
  TR0=1;
}
void service_t0() interrupt 1	//中断定时服务函数
{
 
  TH0=(65535-50000)/256;//定时50ms
  TL0=(65535-50000)%256;//定时50ms
  if(dat_u=dat_p)//显示电大于或等于参考电压
	{
		L1_kai=0;//令点亮L1的标志 L1_kai=0,关闭L1(此状态下一定要关闭)
		count=0;//定时时间要清零!!!
	}	
}
void read_Rb2()//电位器Rb2电压模数转换
{
	IIC_Start();
	IIC_SendByte(0x90);//写地址
	IIC_WaitAck();
	IIC_SendByte(0x03);//电位器Rb2通道号3
	IIC_WaitAck();
	IIC_Stop();

	IIC_Start();
	IIC_SendByte(0x91);//读地址
	IIC_WaitAck();
	dat_value=IIC_RecByte();//读数据
	IIC_SendAck(1);
	IIC_Stop();

	dat_uu=dat_value*(5.0/255);//电位器的采样数据转换为相应的电压
	dat_u=dat_uu*100;//放大100倍,变为整数进行显示数据处理
}
void displaysmg()//界面显示函数
{
  switch(flag_s12)
  {
  	 case 0:
		 display_U();break;
	 case 1:
	 	 display_P();break;
  	 case 2:
		 display_N();break;
  }	
}
void key()
{
	R4=0;//s12
	R3=C2=C3=1;
	if(C3==0)
	{
	  delaysmg(100); //消抖处理
	  if(C3==0)
	  {
		  key_not=0;//有效按键 *** 作,无效按键计数清零
		  while(C3==0)
		  {		
		  	  displaysmg();
		  }
		  flag_s12++;
		  if(flag_s12==3)//使界面在三个状态下循环
		  {
		  	  flag_s12=0;
	     }
		}
	}
	R3=0;//s13
	R4=C2=C3=1;
	if(C3==0)
	{
	  delaysmg(100);
	  if(C3==0&&flag_s12==2)//s13在计数界面按下,有效按键
	  {
	  	  key_not=0;//无效按键计数清零
		  while(C3==0)
		  {
		  	  displaysmg();
		  }
		  count_n=0;
	  }
	  else if(C3==0&&flag_s12!=2)//s13//s13不在计数界面按下,无效按键
		{
			delaysmg(100);
			if(C3==0&&flag_s12!=2)
			{		
			  while(C3==0&&flag_s12!=2)
			  {		
			  	  	displaysmg();
			  }
			  key_not++;//无效按键计数+1
			}
		}
	}
	R4=0;//s8
	R3=C2=C3=1;
	if(C2==0)
	{
	  delaysmg(100);
	  if(C2==0&&flag_s12==1)//s8在参数界面按下,有效按键
	  {
	  	  key_not=0;//无效按键次数清零
		  while(C2==0&&flag_s12==1)
		  {
		  	  displaysmg();
		  }
		  	 dat_p+=50;
			 if(dat_p>=500) dat_p=0;//注意边界值为500
			 write_24c02(0x00,dat_p/10);
	  }
	  else if(C2==0&&flag_s12!=1)//s8不在参数界面按下,无效按键
		{
			delaysmg(100);
			if(C2==0&&flag_s12!=1)
			{		
			  while(C2==0&&flag_s12!=1)
			  {		
			  	  	displaysmg();
			  }
			  key_not++;//无效按键次数+1
			}
		}
	}
	R3=0;//s9
	R4=C2=C3=1;
	if(C2==0)
	{
	  delaysmg(100);
	  if(C2==0&&flag_s12==1) //s9在参数界面按下,有效按键
	  {
	  	  key_not=0;//无效按键次数清零
		  while(C2==0&&flag_s12==1)
		  {
		  	  displaysmg();
		  }
		  	 dat_p-=50;
			 if(dat_p<=0) dat_p=500;//注意边界值为0
			 write_24c02(0x00,dat_p/10);	
	  }
	  else if(C2==0&&flag_s12!=1)//s9在不参数界面按下,无效按键
		{
			delaysmg(100);
			if(C2==0&&flag_s12!=1)
			{		
			  while(C2==0&&flag_s12!=1)
			  {		
			  	  	displaysmg();
			  }
			  key_not++; //无效按键次数加1
			}
		}
	}
}
void led_n()//led
{
		unsigned char t;
		P2=0X80;
	   read_Rb2();
		switch(t)
		{
			case 0:
			if(dat_u>dat_p)
			{	
				t=1;
			} break;
			case 1:
			if(dat_u=3) L3&=0;//如果无效按键计数值大于或等于3,L3亮 ,反之灭
		else L3&=1;
}
void write_24c02(unsigned char add,unsigned char dat)
{
	 IIC_Start();
	 IIC_SendByte(0xa0);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();
	 IIC_SendByte(dat);
	 IIC_WaitAck();
	 IIC_Stop();
}
unsigned char read_24c02(unsigned char add)
{
	 unsigned char dat1;
	 IIC_Start();
	 IIC_SendByte(0xa0);
	 IIC_WaitAck();
	 IIC_SendByte(add);
	 IIC_WaitAck();

	 IIC_Start();
	 IIC_SendByte(0xa1);
	 IIC_WaitAck();
	 dat1=IIC_RecByte();
	 IIC_SendAck(1);
	 IIC_Stop();
	 return dat1;
}
void main()
{
  P2=0XA0;P0=0X00;P2=0X80;P0=0XFF; 
  init_T0();
  dat_p=read_24c02(0x00)*10;
  while(1)
  {
  	 read_Rb2();
	 key();
	 displaysmg();
	 led_n();
  }
}

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/langs/564775.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-06
下一篇 2022-04-06

发表评论

登录后才能评论

评论列表(0条)

保存