第十四届蓝桥杯单片机组省赛

整体来说这届省赛是历史最难,考试的时候没有把所有功能全部实现,但是还是拿了省一

 

考完试把代码回顾了一遍,现在完整代码,全部功能已实现,
测频率 T0计数 T1定时
矩阵按键采用2×4,中断扫描法写的,强烈推荐终端扫描的方法,一点都不抖,而且可以决定是按下按键执行我们需要的功能还是松手按键执行功能,还可以实现长短按功能

//完美代码
//测频率 T0计数 T1定时
//学会用中间变量和测量最大值和平均值

#include "stc15f2k60s2.h"
#include "intrins.h"
#include "ds1302.h"
#include "iic.h"
#include "onewire.h"
                                                                               /*11-  12C  13H  14F  15P   16E  17A*/
unsigned char code tab[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0xff,0xbf,0xc6,0x89,0x8e,0x8c,0x86, 0x88};
unsigned char dscom=0;
unsigned char dsbuff[8]={0};
extern unsigned char clk[3];
unsigned char keysta[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keyback[2][4]={{1,1,1,1},{1,1,1,1}};
unsigned char keybuff[2][4]={{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff}};
unsigned char code keycode[2][4]={{5,9,13,17},{4,8,12,16}};
unsigned char number=0;
unsigned char ds_count=0;
unsigned char ad_count=0;
unsigned int wendu_count=0;
unsigned char fre_count=0;
unsigned int ym_count=0;
unsigned int frequence;
unsigned char ym_mode=1;// 页面标志位 1时间界面 2回显界面 3参数界面
unsigned char hx_mode=1;// 回显标志位 1温度回显 2湿度回显 3时间回显
unsigned char ad_value;   //光照
unsigned char ad_value_last;//上个光照
unsigned int tempurture;  //温度
unsigned int tempurture_caiji;//采集的温度
unsigned int tempurture_last;
unsigned int tempurture_max;
unsigned int tempurture_ave=250;
unsigned int shidu=0;       //湿度
unsigned int shidu_caiji;   //采集的湿度
unsigned int shidu_last;
unsigned int shidu_max=100;
unsigned int shidu_ave=200;
unsigned char ym; //进入手势页面 把当前页面值存给ym
unsigned int key_count=0;
unsigned int tempurture_sum=0;
unsigned char i=0;
unsigned int shidu_sum=0;
unsigned char led_number=0xff;
char canshu=27;
bit ds_read_flag=0;       //
bit ad_flag=0;            //
bit wendu_flag=0;         //
bit wuxiao_flag=0;
bit key_bit=0;
bit longthing=0;
bit l1_flag=0;
bit l2_flag=0;
bit l3_flag=0;
bit l4_flag=0;
bit l5_flag=0;
bit l6_flag=0;

sbit h0=P3^0;
sbit h1=P3^1;
sbit h2=P3^2;
sbit h3=P3^3;
sbit l0=P4^4;
sbit l1=P4^2;
sbit l2=P3^5;
sbit l3=P3^4;

void keysong(unsigned char keydat);
void keyaction(unsigned char dat);
void yemian();
void led_handle();
void LED_function();

void select573(unsigned char channel)
{
	P2&=0x1f;
	P0=0xff;
	switch(channel)
	{
		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;
	}
}
void allinit()
{
	select573(4);P0=0xff;
	select573(5);P0=0x00;
	select573(6);P0=0xff;
	select573(7);P0=0xff;
}
void display()
{
	select573(7);P0=0xff;
	select573(6);
	P0=1<<dscom;
	select573(7);
	P0=tab[dsbuff[dscom]];
	if(++dscom==8)
		dscom=0;
}
void timerinit()
{
	TH1=(65535-1000)/256;
	TL1=(65535-1000)%256;
	TMOD=0x05;
	TF1=0;
	TR1=1;
	ET1=1;
	EA=1;
	
	TH0=0;
	TL0=0;
	TF0=0;
	ET0=0;
	TR0=1;
}
//===================按键函数=====================================================================================================================
//============按键扫描=====================
void keyscan()
{
	unsigned char i;
	static unsigned char j=0;
	keybuff[j][0]=keybuff[j][0]<<1|l0;
	keybuff[j][1]=keybuff[j][1]<<1|l1;
	keybuff[j][2]=keybuff[j][2]<<1|l2;
	keybuff[j][3]=keybuff[j][3]<<1|l3;
	for(i=0;i<2;i++)
	{
		if((keybuff[i][j]&0x0f)==0)
		{
			keysta[i][j]=0;
		}
		else if((keybuff[i][j]&0x0f)==0x0f)
		{
			keysta[i][j]=1;
		}
	}
	j++;
	if(j>=2)
	{
		j=0;
	}
	switch(j)
	{
		case 0:h2=0;h3=1;break;
		case 1:h3=0;h2=1;break;
	}
}
//============按键处理==========================
void keyhandle()
{
	unsigned char i,j;
	for(i=0;i<2;i++)
	{
		for(j=0;j<4;j++)
		{
			if(keyback[i][j]!=keysta[i][j])
			{
				if(keysta[i][j]==0)
				{
					keyaction(keycode[i][j]);
				}
				else if(keysta[i][j]==1)
				{
					keysong(keycode[i][j]);
				}
				keyback[i][j]=keysta[i][j];
			}
		}
	}
}
//============按键按下====================
void keyaction(unsigned char dat)
{
	if(dat==4) //界面按键
	{
		if(ym_mode==1)//从时间页面切换到回显界面 处于回显界面
		{
			ym_mode=2; //2回显界面
			hx_mode=1; //1温度回显
		} 
		else if(ym_mode==2)   ym_mode=3; //3参数界面
		else if(ym_mode==3)   ym_mode=1; //1时间界面
	}
	if(dat==5) //回显按键
	{
		if(ym_mode==2)//如果在2回显界面 
		{
			if(hx_mode==1)      hx_mode=2;//2湿度回显
			else if(hx_mode==2) hx_mode=3;//3时间回显
			else if(hx_mode==3) hx_mode=1;//1温度回显
		}
	}
	if(dat==8) //在参数界面下 加参数
	{
		if(ym_mode==3) //如果在参数界面下
		{
			canshu+=1;
			if(canshu>=99) 
				canshu=99;
		}
	}
	if(dat==9) //在参数界面下 减参数
	{
		if(ym_mode==3) //如果在参数界面下
		{
			canshu-=1;
			if(canshu<=0) 
				canshu=0;
		}
		key_bit=1;
	}
}
//============按键松开=============
void keysong(unsigned char keydat)
{
	if(ym_mode==3&&keydat==9) //=清除所有记录,触发次数重置为0
	{
		if(longthing==1) //=执行的操作
		{
			longthing=0;
			number=0;
			tempurture_max=200;
			shidu_max=100;
		}
		key_bit=0;
		key_count=0;
	}
}
//=====================main函数===============================================================================================
void main(void)
{
	allinit();
	timerinit();
	ds1302init();
	while(1)
	{
		keyhandle();
		
		if(ds_read_flag==1) //读取时间
		{
			ds_read_flag=0;
			ds1302read();
		}
		ad_value_last=ad_value;
		if(ad_flag==1) //读取光照
		{
			ad_flag=0;
			ad_value=pcf_ad(1);
		}
		if(wendu_flag==1) //读取温度
		{
			wendu_flag=0;
			tempurture=read_temperature();
		}
		
//=====光照触发采集======================================================================
		//防止巧合,刚从第四个页面出来main函数刚好执行到这里再次进入,ym_mode的值还没来得及改变,
		//又被赋值,一直会是4,就不会跳出所以这里加一个条件 (ym_mode!=4)
		if(((ad_value_last-ad_value)>50)&&(ym_mode!=4)) 
		{
			ym=ym_mode;
			ym_mode=4;
			
			//=====频率转换为湿度=数据无效这组数据放弃
			if(frequence<=200)  
			{
				wuxiao_flag=1;  //无效标志位置一
				shidu=100;      //保留一位小数 *10
			}
			else if(frequence>=2000)
			{
				wuxiao_flag=1;
				shidu=900;      //保留一位小数 *10
			}
	    else
			{
				wuxiao_flag=0;
			}
				
			if(wuxiao_flag==0) //  数据有效的时候才进行数据采集
			{
				number++;
				i++;
				//=====温度最大值平均值===================================    tempurture_last  shidu_last
				tempurture_last=tempurture_caiji;
				if(tempurture>tempurture_max)
				{
					tempurture_max=tempurture;
				}
				else
				{
					tempurture_max=tempurture_max;
				}
				tempurture_caiji=tempurture;
				tempurture_sum+=tempurture;
				tempurture_ave=tempurture_sum/i;
				//=====频率转换为湿度===============
				if(frequence<2000&&frequence>200) 
				{
					shidu=(0.044445*frequence+1.11111)*10;//保留一位小数 *10	
				}
				//=====求出最大湿度=========================
				shidu_last=shidu_caiji;
				if(shidu>shidu_max)
				{
					shidu_max=shidu;			
				}
				else
					shidu_max=shidu_max;
				shidu_caiji=shidu;
				//=====平均湿度==========================
				shidu_sum+=shidu;
				shidu_ave=shidu_sum/i;
			}		
		}
		LED_function();
//========
	}
}

//=====================中断函数===============================================================================================
unsigned char l4_count=0;
void timer1()interrupt 3
{
	led_handle();
	display();
	yemian();
	keyscan();
	//======读取时间=========
	ds_count++;
	if(ds_count>=50) 
	{
		ds_read_flag=1;
		ds_count=0;
	}
	//======读取光照ad=======
	ad_count++;
	if(ad_count>=200) 
	{
		ad_count=0;
		ad_flag=1;
	}
	//======读取温度=========
	wendu_count++;
	if(wendu_count>=500) 
	{
		wendu_count=0;
		wendu_flag=1;
	}
	//======读取频率=========
	fre_count++;
	if(fre_count==200) 
	{
		TR0=0;
		fre_count=0;
		frequence=(TH0*256+TL0)*5;
		TH0=0;
		TL0=0;
		TR0=1;
	}
	//====3秒切换页面========
	if(ym_mode==4)
	{
		ym_count++;
		if(ym_count>=3000)
		{
			ym_count=0;
			ym_mode=ym;
		}
	}
	//======按键长按=========
	if(key_bit==1)
	{
		key_count++;
		if(key_count>=2000)
		{
			key_count=0;
			longthing=1;
		}
	}
//=====LED功能部分======================================
	//=====L1===========
	if(l1_flag==1)
	{
		led_number&=0xfe;
	}
	else
	{
		led_number|=0x01;
	}
	//=====L2===========
	if(l2_flag==1)
	{
		led_number&=0xfd;
	}
	else
	{
		led_number|=0x02;
	}
	//=====L3===========
	if(l3_flag==1)
	{
		led_number&=0xfb;
	}
	else
	{
		led_number|=0x04;
	}
	//=====L4===========
	if(l4_flag==1)
	{
		l4_count++;
		if(l4_count<=100)
		{
			led_number&=0xf7;
		}
		else if((l4_count>100)&&(l4_count<=200))
		{
			led_number|=0x08;
		}
		else if(l4_count>200)
		{
			l4_count=0;
		}
	}
	else
	{
		led_number|=0x08;
	}
	//=====L5===========
	if(l5_flag==1)
	{
		led_number&=0xef;
	}
	else
	{
		led_number|=0x10;
	}
	//=====L6===========
	if(l6_flag==1)
	{
		led_number&=0xdf;
	}
	else
	{
		led_number|=0x20;
	}
}

//=====LED功能部分================================================================================
void LED_function()
{
//========界面指示灯=================
	//=====L1=========
	if(ym_mode==1) //时间界面
		l1_flag=1;
	else
		l1_flag=0;
	//=====L2=========
	if(ym_mode==2) //回显界面
		l2_flag=1;
	else
		l2_flag=0;
	//=====L3=========
	if(ym_mode==4) //湿度界面
		l3_flag=1;
	else
		l3_flag=0;
//========报警指示灯=================
	//=====L4=========
	if(tempurture_caiji>(canshu*10)) //采集温度大于温度参数
	{
		l4_flag=1;   //L4以0.1s间隔闪烁
	}
	else
		l4_flag=0;
	//=====L5=========
	if(wuxiao_flag==1) //采集到无效数据L5亮,直到有效数据出现L5灭
	{
		l5_flag=1;
	}
	else
		l5_flag=0;
	//=====L6=========
	if((tempurture_caiji>tempurture_last)&&(shidu_caiji>shidu_last)&&(number>=2)) //采集温度和湿度均比上次高L6亮,否则灭
	{
		l6_flag=1;
	}
	else
		l6_flag=0;
}
//==============LED中断函数=============
void led_handle()
{
	P0=0xff;
	select573(4);
	P0=led_number;
}

//=====================页面函数===============================================================================================
void yemian()
{
	if(ym_mode==1) //1时间界面
	{
		dsbuff[0]=clk[2]/16;
		dsbuff[1]=clk[2]%16;
		dsbuff[2]=11;
		dsbuff[3]=clk[1]/16;
		dsbuff[4]=clk[1]%16;
		dsbuff[5]=11;
		dsbuff[6]=clk[0]/16;
		dsbuff[7]=clk[0]%16;
	}
	else if(ym_mode==2) //2回显界面
	{
		if(number==0)
		{
			if(hx_mode==1) //1温度回显
			{
				dsbuff[0]=12;
				dsbuff[1]=10;
				dsbuff[2]=10;
				dsbuff[3]=10;
				dsbuff[4]=10;
				dsbuff[5]=10;
				dsbuff[6]=10;
				dsbuff[7]=10;
			}
			else if(hx_mode==2) //2湿度回显
			{
				dsbuff[0]=13;
				dsbuff[1]=10;
				dsbuff[2]=10;
				dsbuff[3]=10;
				dsbuff[4]=10;
				dsbuff[5]=10;
				dsbuff[6]=10;
				dsbuff[7]=10;
			}
			else if(hx_mode==3) //3时间回显
			{
				dsbuff[0]=14;
				dsbuff[1]=10;
				dsbuff[2]=10;
				dsbuff[3]=10;
				dsbuff[4]=10;
				dsbuff[5]=10;
				dsbuff[6]=10;
				dsbuff[7]=10;
			}
		}
		else
		{
			if(hx_mode==1) //1温度回显
			{
				dsbuff[0]=12;
				dsbuff[1]=10;
				dsbuff[2]=tempurture_max/100;
				dsbuff[3]=tempurture_max/10%10;
				dsbuff[4]=11;
				dsbuff[5]=tempurture_ave/100;
				dsbuff[6]=tempurture_ave/10%10;
				dsbuff[7]=tempurture_ave%10;
			}
			else if(hx_mode==2) //2湿度回显
			{
				dsbuff[0]=13;
				dsbuff[1]=10;
				dsbuff[2]=shidu_max/100;
				dsbuff[3]=shidu_max/10%10;
				dsbuff[4]=11;
				dsbuff[5]=shidu_ave/100;
				dsbuff[6]=shidu_ave/10%10;
				dsbuff[7]=shidu_ave%10;
			}
			else if(hx_mode==3) //3时间回显
			{
				dsbuff[0]=14;
				dsbuff[1]=number/10;
				dsbuff[2]=number%10;
				dsbuff[3]=clk[2]/16;
				dsbuff[4]=clk[2]%16;
				dsbuff[5]=11;
				dsbuff[6]=clk[1]/16;
				dsbuff[7]=clk[1]%16;
			}
		}
	}
	else if(ym_mode==3) //3参数界面
	{
		dsbuff[0]=15;
		dsbuff[1]=frequence/10000;
		dsbuff[2]=frequence%10000/1000;
		dsbuff[3]=frequence%1000/100;
		dsbuff[4]=frequence%100/10;
		dsbuff[5]=frequence%10;
		dsbuff[6]=canshu/10;
		dsbuff[7]=canshu%10;
	}
//=============4采集触发界面===========================
	if(ym_mode==4) 
	{
		if(wuxiao_flag==1)
		{
			dsbuff[0]=16;
			dsbuff[1]=10;
			dsbuff[2]=10;
			dsbuff[3]=tempurture/100;
			dsbuff[4]=tempurture/10%10;
			dsbuff[5]=11;
			dsbuff[6]=17;
			dsbuff[7]=17;
		}
		else
		{
			dsbuff[0]=16;
			dsbuff[1]=10;
			dsbuff[2]=10;
			dsbuff[3]=tempurture/100;
			dsbuff[4]=tempurture/10%10;
			dsbuff[5]=11;
			dsbuff[6]=shidu/100;
			dsbuff[7]=shidu/10%10;
		}
	}
}

IIC.c 函数

#include "iic.h"
#include "intrins.h"

#define DELAY_TIME	5


sbit scl=P2^0;
sbit sda=P2^1;


//
static void I2C_Delay(unsigned char n)
{
    do
    {
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();
        _nop_();_nop_();_nop_();_nop_();_nop_();		
    }
    while(n--);      	
}

//
void I2CStart(void)
{
    sda = 1;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 0;
	I2C_Delay(DELAY_TIME);
    scl = 0;    
}

//
void I2CStop(void)
{
    sda = 0;
    scl = 1;
	I2C_Delay(DELAY_TIME);
    sda = 1;
	I2C_Delay(DELAY_TIME);
}

//
void I2CSendByte(unsigned char byt)
{
    unsigned char i;
	
    for(i=0; i<8; i++){
        scl = 0;
		I2C_Delay(DELAY_TIME);
        if(byt & 0x80){
            sda = 1;
        }
        else{
            sda = 0;
        }
		I2C_Delay(DELAY_TIME);
        scl = 1;
        byt <<= 1;
		I2C_Delay(DELAY_TIME);
    }
	
    scl = 0;  
}

//
unsigned char I2CReceiveByte(void)
{
	unsigned char da;
	unsigned char i;
	for(i=0;i<8;i++){   
		scl = 1;
		I2C_Delay(DELAY_TIME);
		da <<= 1;
		if(sda) 
			da |= 0x01;
		scl = 0;
		I2C_Delay(DELAY_TIME);
	}
	return da;    
}

//
unsigned char I2CWaitAck(void)
{
	unsigned char ackbit;
	
    scl = 1;
	I2C_Delay(DELAY_TIME);
    ackbit = sda; 
    scl = 0;
	I2C_Delay(DELAY_TIME);
	
	return ackbit;
}

//
void I2CSendAck(unsigned char ackbit)
{
    scl = 0;
    sda = ackbit; 
	I2C_Delay(DELAY_TIME);
    scl = 1;
	I2C_Delay(DELAY_TIME);
    scl = 0; 
	sda = 1;
	I2C_Delay(DELAY_TIME);
}

unsigned char pcf_ad(unsigned char channel)
{
	unsigned char temp;
	EA=0;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(channel);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	EA=1;
	return temp;
}

onewire.c函数
 

#include "onewire.h"
#include "intrins.h"
sbit DQ=P1^4;

//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

//
void Write_DS18B20(unsigned char dat)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		DQ = 0;
		DQ = dat&0x01;
		Delay_OneWire(5);
		DQ = 1;
		dat >>= 1;
	}
	Delay_OneWire(5);
}

//
unsigned char Read_DS18B20(void)
{
	unsigned char i;
	unsigned char dat;
  
	for(i=0;i<8;i++)
	{
		DQ = 0;
		dat >>= 1;
		DQ = 1;
		if(DQ)
		{
			dat |= 0x80;
		}	    
		Delay_OneWire(5);
	}
	return dat;
}

//
bit init_ds18b20(void)
{
  	bit initflag = 0;
  	
  	DQ = 1;
  	Delay_OneWire(12);
  	DQ = 0;
  	Delay_OneWire(80);
  	DQ = 1;
  	Delay_OneWire(10); 
    initflag = DQ;     
  	Delay_OneWire(5);
  
  	return initflag;
}

float read_temperature()
{
	unsigned int temp;
	unsigned char low,high;
	EA=0;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	
	low=Read_DS18B20();
	high=Read_DS18B20();
	EA=1;
	temp=high;
	temp=temp<<8;
	temp=temp|low;
	temp*=0.625;
	return temp;
	
}

ds1302.c函数

#include "ds1302.h"
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;

unsigned char clk[3];
//
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

void ds1302init()
{
	Write_Ds1302_Byte(0x8e,0x00);
	Write_Ds1302_Byte(0x80,0x05);
	Write_Ds1302_Byte(0x82,0x03);
	Write_Ds1302_Byte(0x84,0x13);
	Write_Ds1302_Byte(0x8e,0x80);
}
void ds1302read()
{
	clk[0]=Read_Ds1302_Byte(0x81);
	clk[1]=Read_Ds1302_Byte(0x83);
	clk[2]=Read_Ds1302_Byte(0x85);
}

  • 6
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值