第十三届 蓝桥杯 单片机设计与开发项目 省赛

  • Post author:
  • Post category:其他



目录


题目分析


代码分析


代码链接


题目分析

就在前不久第十三届蓝桥杯比赛结束,我就把单片机的题目拿过来看了看,下面是我对题目的分析和本次题目的代码。项目工程在文章的末尾,欢迎大家参考和指正。

在看到这道题的时候,看到了题目说按键动作不影响数码管显示和数据采集过程。说明数码管和采集过程需要在中断完成。本道题由于有单总线的存在,造成了数码管扫描时间加长,会造成最后一位数码管格外亮或者视觉暂留效果消失。为解决这一问题,我的方法是修改了DS18B20底层驱动代码,在读取温度的同时也进行了数码管的扫描操作。还得注意的是,由于定时器中断的打开,如果DS1302和DS18B20不放到中断函数里面的话,会造成读取的数据错误,这个原因是,在读取数据的过程中产生了中断,破坏了读取数据的时序。废话不多说了,看源代码吧。

代码分析

主函数

void main(void)
{
	//ds1302初始化
	DS1302_Init(Init_Time);
	Timer0Init();
	
	
	while(1)
	{
		//key
		if(Key_Flag==1)
		{
			KeyValue = KeyScan();
			switch(KeyValue)
			{
				case 12:
					SegShow_Flag++;
					if(SegShow_Flag>2)
					{
						SegShow_Flag=0;
					}
					break;
				case 13:
					Mode_Flag = !Mode_Flag;					//显示界面
					break;
				case 16:
					temp = ParameterChang(SegShow_Flag,temp,0);
					break;
				case 17:
					temp = ParameterChang(SegShow_Flag,temp,1);
					break;
			}
			
			//时间显示模式标记
			SegTime_Flag = TimeShow(SegShow_Flag,KeyValue);
			Key_Flag=0;
		}
	}
}

中断函数

//定时器中断服务函数
void Time0Handler(void)  interrupt 1  //默认中断优先级 1
{
	static u16 tt=0;
	
	//数码管扫描
  SegScan(tab,SegNum);
	
	tt++;
	if((tt%1000) == 0)//100ms
	{
		Key_Flag=1;
		Timer_Flag=1;
		
		
		SegDispaly(SegShow_Flag,SegTime_Flag,temperature,shijian,temp,SegNum);
		//led
		LedFuction(Mode_Flag,RelaySwitch_Flag,shijian);
		//继电器
		RelaySwitch_Flag = RelayFuction(Mode_Flag,temperature,temp,shijian);
	}
	
	if(tt >= 7000)	//700ms
	{
		tt=0;
		//时间
		DS1302_Get(shijian);
		
		//温度
		//12位精度,延时不足。第一次数值错误,不读
		if(Temperature_Flag == 0)
		{
			Temperature_Flag=1;
			TemperGet();
		}
		else
		{
			temperature = TemperGet();
		}
		
	}
}

数码管显示

//显示函数
void SegScan(unsigned char tab[],unsigned char ptr[])
{   
	static unsigned char dspcom;
	 
	P0 = 0xff;
	P2 = ((P2&0x1f)|0xE0);
	P2 &= 0x1f;

	P0 = 1<<dspcom;	
	P2 = ((P2&0x1f)|0xC0); 
	P2 &= 0x1f;
	
	P0 = tab[ptr[dspcom]];	
  P2 = ((P2&0x1f)|0xE0); 
	P2 &= 0x1f;
	
  if(++dspcom >= 8)
	{
     dspcom = 0;
  }    
}

界面切换

//数码管显示信息
void SegDispaly(u8 SegShow_Flag,u8 SegTime_Flag,long temperature,u8* time,u8 temp,u8* ptr)
{
	//温度界面
	if(SegShow_Flag == 0)
	{
		ptr[0]=21;
		ptr[1]=1;
		ptr[2]=22;
		ptr[3]=22;
		ptr[4]=22;
		ptr[5]=temperature/100000;
		ptr[6]=temperature%100000/10000+10;
		ptr[7]=temperature%10000/1000;
	}
	//时间界面
	else if(SegShow_Flag == 1)
	{
		ptr[0]=21;
		ptr[1]=2;
		ptr[2]=22;
		if(SegTime_Flag == 0)
		{
			ptr[3]=time[2]/10;
			ptr[4]=time[2]%10;
			ptr[5]=20;
			ptr[6]=time[1]/10;
			ptr[7]=time[1]%10;
		}
		else
		{
			ptr[3]=time[1]/10;
			ptr[4]=time[1]%10;
			ptr[5]=20;
			ptr[6]=time[0]/10;
			ptr[7]=time[0]%10;
		}
	}
	//参数界面
	else if(SegShow_Flag == 2)
	{
		ptr[0]=21;
		ptr[1]=3;
		ptr[2]=22;
		ptr[3]=22;
		ptr[4]=22;
		ptr[5]=22;
		ptr[6]=temp/10;
		ptr[7]=temp%10;
	}
}

剩下的就是继电器和led的显示,这里就不都一一展出啦,需要的伙伴可以在下面链接自行下载。

代码链接

链接:https://pan.baidu.com/s/1DAbZ5t6LMn_uOdZORoh8HA

提取码:mwl6

–来自百度网盘超级会员V5的分享



版权声明:本文为kingmwl原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。