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

 

 注:因为我自己的板子上的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<dat_p)
            {    
                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<reg52.h>
#include<iic.h>
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<<pos;
  P2=0XE0;P0=value;
}
void display_U() //数据界面
{
	 displaysmg_byte(0,0xc1);
	 delaysmg(100);
	 displaysmg_byte(5,smg_dot[dat_u/100]);
	 delaysmg(100);
	 displaysmg_byte(6,smg_nodot[(dat_u/10)%10]);
	 delaysmg(100);
	 displaysmg_byte(7,smg_nodot[dat_u%10]);
	 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 display_P() //参数界面
{
	 displaysmg_byte(0,0x8c);	 
	 delaysmg(100);
	 displaysmg_byte(5,smg_dot[dat_p/100]);
	 delaysmg(100);
	 displaysmg_byte(6,smg_nodot[(dat_p/10)%10]);
    delaysmg(100);
	 displaysmg_byte(7,smg_nodot[dat_p%10]);
	 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);
	 P2=0XC0;P0=0XFF;P2=0XE0;P0=0XFF;
}
void display_N() //计数界面
{
	 if(count_n>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)//显示电压小于参考电压
	{
		count++;
		if(count==100)//且持续时间大于5s 
		{
			L1_kai=1;//令点亮L1的标志 L1_kai=1
			count=0;//定时时间要清零!!!
		}
	}
	else 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<dat_p)
			{	
				count_n++;
				t=0;
			}	break;
		}
		if(count_n%2!=0)//如果计数值为奇数,L2亮 
		{
			L2=0;
		}
		if(L1_kai==1)//L1亮
		{
			L1&=0;
		}   
		else if(L1_kai==0)
		{
			L1&=1;
		}
		if(key_not>=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();
  }
}

  • 14
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
蓝桥杯单片机第十一届省赛题目要求参赛选手使用单片机实现一个特定的功能,具体要求可能会随着每一届比赛的不同而有所变化。在回答此问题时,需要明确具体的题目要求和实现功能,并进行详细的说明。 由于没有提供具体的第十一届省赛题目的信息,我无法给出具体的答案。不过,可以给出一个示例性的回答来说明如何回答此类问题。 示例回答: 根据蓝桥杯单片机第十一届省赛题目要求,我们的任务是设计一个智能家居控制系统。该系统需要能够实现以下功能: 1. 控制家中的照明系统:可以通过单片机控制灯的开关,调节灯的亮度和颜色。 2. 控制家中的窗帘系统:可以通过单片机控制窗帘的升降和角度。 3. 监测室内温湿度:单片机需要连接温湿度传感器,实时获取室内的温度和湿度数据,并可以进行显示或记录。 4. 天气预报功能:通过网络模块连接互联网,获取实时的天气数据,并在单片机上进行显示或语音输出。 5. 安全警报系统:单片机需要能够检测门窗是否关闭,若有异常情况,比如门窗未关闭或有人非法进入,则触发警报。 6. 远程控制功能:通过手机APP或网页,可以远程控制智能家居系统。 根据以上的题目要求,我们可以先设计硬件部分,选择合适的传感器和执行器,并将其与单片机进行连接。然后,编写相应的代码,实现上述功能。最后,进行调试和测试,确保系统的正常运行和功能完备。 这仅为一个示例回答,具体的第十一届省赛题目要求可能与此不同。如需了解具体题目要求,请参考官方的赛题公告。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值