蓝桥杯单片机第十二届国赛参考程序

前言:

师承小蜜蜂。头文件使用reg52.h。

赛题:

 

 

 

 

 

 

 个人参考程序:(未使用模块化,程序有点乱)

main.c

#include <REGX52.H>
#include "DS1302.h"
#include "intrins.h"
#include "iic.h"

sfr P4=0xc0;

sbit TX=P1^0;
sbit RX=P1^1;
sbit L1=P4^4;
sbit L2=P4^2;
sbit L3=P3^5;
sbit L4=P3^4;

void HC573(unsigned char channel,unsigned char value);
void Delay(int x);
void Nixie(unsigned char column,unsigned char value);
void System_init();

unsigned char code Read_Ds1302[7]={0x81,0x83,0x85,0x87,0x89,0x8b,0x8d};//时钟
unsigned char code Write_Ds1302_address[7]={0x80,0x82,0x84,0x86,0x88,0x8a,0x8c};
unsigned char code Array[18]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x80,0xc6,0xc0,0x86,0x8e,
0xbf,0x7f};
unsigned char code Array_pot[10]={0x40,0x79,0X24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
unsigned char Time[]={0x55,0x59,0x23,0x00,0x00,0x00,0x00};//设置时间
unsigned char Key_Flag=1;//10ms循环扫描按键
unsigned char Mode_S4=0;//s4按键
unsigned char Mode_S5=0;//s5按键
unsigned int Distance;//超声波数据
unsigned char Mode_chao=0;//数据测量模式
unsigned char Mode_stroate=0;//数据记录页面模式
unsigned char Time_collect=2;//采集时间参数
unsigned char Distance_collect=20;//采集距离参数
//参数需要退出页面后生效,故设置中间变量代替
unsigned char Time_collect1=2;
unsigned char Distance_collect1=20;
unsigned char Flag_chao=0;//超声波采集标志位(定时模式)
unsigned char Rb2_Data=0;//光敏电阻读取
unsigned char Flag_chao1=0;//超声波采集标志位(触发模式)
unsigned char chao_Max=0;//最大值
unsigned char chao_Min=200;//最小值
unsigned int  chao_ave=0;//平均值
unsigned char Array_chao[50];//存放数据数组
unsigned int cnt=0;//记录次数
unsigned char Flag_alarm=0;//报警标志位
unsigned char cnt_alarm=0;//警报次数
unsigned char LED_Stat=0xff;//灯光
unsigned char LED=0xff;
//光敏电阻读取
void Read_RB2()
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	Rb2_Data=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
}
//设置DAC
void Set_DAC()
{
	unsigned char tem;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x41);
	I2CWaitAck();
	if(cnt!=0)
	{
		if(Array_chao[cnt-1]<10)
		{
			I2CSendByte(51);
		}
		else if(Array_chao[cnt-1]>80)
		{
			I2CSendByte(255);
		}
		else
		{
			tem=(3*Array_chao[cnt-1])+15;
			I2CSendByte(tem);
		}
	}
	I2CSendAck(1);
	I2CStop();
}
//定时器初始化
void Time_init()
{
	TMOD=0x01;
	TH0=(65535-10000+1)/256;
	TL0=(65535-10000+1)%256;
	ET0=1;
	TR0=1;
	TF0=0;
	EA=1;
}
//按键
unsigned char Key_Scan()
{
	unsigned char Ket_Value;
	unsigned int Key_temp;
	
	L1=0;L2=1;L3=1;L4=1;P3|=0x0F;
	Key_temp=P3&0x0f;
	
	L1=1;L2=0;L3=1;L4=1;P3|=0x0F;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	
	L1=1;L2=1;L3=0;L4=1;P3|=0x0F;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	
	L1=1;L2=1;L3=1;L4=0;P3|=0x0F;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	
	switch(~Key_temp)
	{
		case 0x8000:Ket_Value=4;break;
		case 0x4000:Ket_Value=5;break;
		case 0x2000:Ket_Value=6;break;
		case 0x1000:Ket_Value=7;break;
		
		case 0x0800:Ket_Value=8;break;
		case 0x0400:Ket_Value=9;break;
		case 0x0200:Ket_Value=10;break;
		case 0x0100:Ket_Value=11;break;
		
		case 0x0080:Ket_Value=12;break;
		case 0x0040:Ket_Value=13;break;
		case 0x0020:Ket_Value=14;break;
		case 0x0010:Ket_Value=15;break;
		
		case 0x0008:Ket_Value=16;break;
		case 0x0004:Ket_Value=17;break;
		case 0x0002:Ket_Value=18;break;
		case 0x0001:Ket_Value=19;break;
		default :Ket_Value=0;
	}
	return Ket_Value;
}
//时钟初始化
void Ds1302_init()
{
	unsigned char i;
	Write_Ds1302_Byte(0x8e,0x00);
	for(i=0;i<7;i++)
	{
		Write_Ds1302_Byte(Write_Ds1302_address[i],Time[i]);
	}
	Write_Ds1302_Byte(0x8e,0x80);
}
//超声波测距
void Delay12us()		//@12.000MHz
{
	unsigned char i;

	_nop_();
	_nop_();
	i = 28;
	while (--i);
}
void Send_Wave()
{
	unsigned char i;
	for(i=0;i<8;i++)
	{
		TX=1;
		Delay12us();
		TX=0;
		Delay12us();
	}
}
void Time_Chao()
{
	unsigned int temp;
	TMOD&=0x01;
	TH1=0x00;
	TL1=0x00;
	Send_Wave();
	TR1=1;
	while((RX==1)&&(TF1==0));
	TR1=0;
	if(TF1==0)
	{
		temp=TH1;
		temp=(temp<<8)|TL1;
		Distance=((temp/10)*17)/100+3;
	}
	else 
	{
		TF1=0;
	}
	TH1=0x00;
	TL1=0x00;
	Flag_chao=0;
	Flag_chao1=0;//清除标志位,确保每次只测量一次
}

//读取时钟
void Read_time()
{
	unsigned char i;
	for(i=0;i<7;i++)
	{
		Time[i]=Read_Ds1302_Byte(Read_Ds1302[i]);
	}
}
void Key_Read()
{
	unsigned char Key_Temp,Key_Up;
	static unsigned char Key_Old=0;
	
	if(Key_Flag)return;
	Key_Flag=1;
	
	Key_Temp=Key_Scan();
	Key_Up=~Key_Temp&(Key_Temp^Key_Old);
	Key_Old=Key_Temp;
	
	if(Key_Up==4)
	{
		if(Mode_S4==0){Mode_S4=1;Mode_S5=0;}//S4切换时,都回到模式的第一个页面
		else if(Mode_S4==1)
		{
			Mode_S4=0;Mode_S5=0;
			Time_collect=Time_collect1;//退出页面,参数生效
			Distance_collect=Distance_collect1;
		}
	}
	else if(Key_Up==5)
	{
		if(Mode_S4==0)
		{
			if(Mode_S5==0){Mode_S5=1;}
			else if(Mode_S5==1)
			{
				Mode_S5=2;
				Mode_stroate=0;//每次进入数据记录页面,都是最大值页面
			}
			else if(Mode_S5==2)Mode_S5=0;
		}
		else if(Mode_S4==1)//参数设置页面切换
		{
			if(Mode_S5==0)Mode_S5=1;
			else if(Mode_S5==1)Mode_S5=0;
		}
	}
	else if(Key_Up==8)
	{
		if(Mode_S4==0)
		{
			if(Mode_S5==1)//超声波模式切换
			{
				if(Mode_chao==0)Mode_chao=1;
				else if(Mode_chao==1)Mode_chao=0;
			}
			else if(Mode_S5==2)//数据记录页面切换
			{
				if(Mode_stroate==0)Mode_stroate=1;
				else if(Mode_stroate==1)Mode_stroate=2;
				else if(Mode_stroate==2)Mode_stroate=0;
			}
		}
	}
	else if(Key_Up==9)
	{
		if(Mode_S4==1)
		{
			if(Mode_S5==0)//参数设置
			{
				if(Time_collect1==2)Time_collect1=3;
				else if(Time_collect1==3)Time_collect1=5;
				else if(Time_collect1==5)Time_collect1=9;
				else if(Time_collect1==9)Time_collect1=2;
			}
			else if(Mode_S5==1)
			{
				Distance_collect1+=10;
				if(Distance_collect1>80)Distance_collect1=10;
			}
		}
	}
}
//显示时间页面
void Display_time()
{
	Nixie(1,Array[Time[2]/16]);
	Nixie(2,Array[Time[2]%16]);
	Nixie(3,Array[16]);
	Nixie(4,Array[Time[1]/16]);
	Nixie(5,Array[Time[1]%16]);
	Nixie(6,Array[16]);
	Nixie(7,Array[Time[0]/16]);
	Nixie(8,Array[Time[0]%16]);
}

//距离数据页面
void Display_Distance()
{
	Nixie(1,0xc7);
	if(Mode_chao==0)Nixie(2,Array[12]);
	else if(Mode_chao==1)Nixie(2,Array[15]);
	Nixie(3,0xff);
	Nixie(4,0xff);
	Nixie(5,0xff);
	if(Distance>99)Nixie(6,Array[Distance/100%10]);else Nixie(6,0xff);
	if(Distance>9)Nixie(7,Array[Distance/10%10]);else Nixie(7,0xff);
	Nixie(8,Array[Distance%10]);
}
//数据记录页面
void Display_DataStorate()
{
	Nixie(1,0x89);
	if(Mode_stroate==1)
	{
		Nixie(2,Array[16]);
		if(chao_ave>1000)Nixie(5,Array[chao_ave/1000%10]);
		if(chao_ave>100)Nixie(6,Array[chao_ave/100%10]);
		Nixie(7,Array_pot[chao_ave/10%10]);
		Nixie(8,Array[chao_ave%10]);
	}
	else if(Mode_stroate==0)
	{
		Nixie(2,0xfe);
		Nixie(5,0xff);
		if(chao_Max>99)Nixie(6,Array[chao_Max/100%10]);
		if(chao_Max>9)Nixie(7,Array[chao_Max/10%10]);
		Nixie(8,Array[chao_Max%10]);
	}
	else if(Mode_stroate==2)
	{
		Nixie(2,0xf7);
		Nixie(5,0xff);
		if(chao_Min>99)Nixie(6,Array[chao_Min/100%10]);
		if(chao_Min>9)Nixie(7,Array[chao_Min/10%10]);
		Nixie(8,Array[chao_Min%10]);
	}
	Nixie(3,0xff);
	Nixie(4,0xff);
}
//参数设置页面
void Display_Para()
{
	Nixie(1,0x8c);
	Nixie(3,0xff);
	Nixie(4,0xff);
	Nixie(5,0xff);
	Nixie(6,0xff);
	if(Mode_S5==0)
	{
		Nixie(2,Array[1]);
		Nixie(7,Array[Time_collect1/10%10]);
		Nixie(8,Array[Time_collect1%10]);
	}
	else if(Mode_S5==1)
	{
		Nixie(2,Array[2]);
		Nixie(7,Array[Distance_collect1/10%10]);
		Nixie(8,Array[Distance_collect1%10]);
	}
}
//页面显示选择函数
void Display_All()
{
	if(Mode_S4==0)
	{
		if(Mode_S5==0)
		{
			Display_time();
		}
		else if(Mode_S5==1)
		{
			Display_Distance();
		}
		else if(Mode_S5==2)
		{
			Display_DataStorate();
		}
	}
	else if(Mode_S4==1)
	{
		Display_Para();
	}
}
//最大值,最小值,平均值计算
void calculate_data()
{
	unsigned char i;
	unsigned int sum=0;
	Array_chao[cnt]=Distance;
	if(Mode_chao==1)//如果是触发模式
	{
		if(((Array_chao[cnt]-Distance_collect)<=5)||((Distance_collect-Array_chao[cnt])<=5))
		{//当前测量数据在参数±5cm范围内
			cnt_alarm++;//警报次数+1
		}
		else 
		{
			cnt_alarm=0;//否则警报次数清零
		}
		if(cnt_alarm>=3)//如果警报次数大于3
		{
			Flag_alarm=1;//警报标志位
		}
		else 
		{
			Flag_alarm=0;
		}
	}
	cnt++;
	for(i=0;i<cnt;i++)
	{
		sum+=Array_chao[i];
	}
	chao_ave=sum*10/cnt;//平均值,扩大10倍算小数
	if(Distance>chao_Max)//最大值
	{
		chao_Max=Distance;
	}
	if(Distance<chao_Min)//最小值
	{
		chao_Min=Distance;
	}
}
//超声波模式选择
void Mode_Choose()
{
	if(Mode_S5==1)
	{
		if(Mode_chao==0)//触发模式
		{
			Read_RB2();//读光敏电阻
			if(Rb2_Data>100)//亮
			{
				Flag_chao1=1;//置标志位
			}
			else if((Flag_chao1==1)&&(Rb2_Data<100))//如果标志位为1且变为暗模式
			{//执行一次超声波测量,和数据计算
				Time_Chao();
				calculate_data();
			}
		}
		else if(Mode_chao==1)//定时模式
		{
			if(((Time[0]%Time_collect)==0)&&(Flag_chao==1))//当标识位为1且满足条件
			{//执行一次超声波测量
				Time_Chao();
				calculate_data();
			}
			else if((Time[0]%Time_collect)!=0)
			{//当过了能被时间参数整除的那一秒,再重新置标志位
				Flag_chao=1;
			}
		}
	}
}
//灯光使用
void LED_Run()
{
	if(Mode_S4==0)
	{
		if(Mode_S5==0)//LED1
		{
			LED_Stat=LED&0xfe;
			HC573(4,LED_Stat);
		}
		else if(Mode_S5==1)//LED2
		{
			LED_Stat=LED&0xfd;
			HC573(4,LED_Stat);
		}
		else if(Mode_S5==2)//LED3
		{
			LED_Stat=LED&0xfb;
			HC573(4,LED_Stat);
		}
		if(Mode_chao==0)//LED4
		{
			LED_Stat=LED_Stat&0xf7;
			HC573(4,LED_Stat);
		}
		if((Mode_chao==1)&&(Mode_S5==1))
		{
			if(Flag_alarm==1)//警报灯
			{
				LED_Stat=LED_Stat&0xef;
				HC573(4,LED_Stat);
			}
			else
			{
				LED_Stat=LED_Stat|0x10;
				HC573(4,LED_Stat);
			}
		}
		else
		{
			LED_Stat=LED_Stat|0x10;
			HC573(4,LED_Stat);
		}
	}
	else if(Mode_S4==1)//参数设置页面关闭LED1,2,3
	{
		LED_Stat=LED_Stat|0x07;
		HC573(4,LED_Stat);
	}
	if(Rb2_Data>100)//亮状态L6
	{
		LED_Stat=LED_Stat&0xdf;
		HC573(4,LED_Stat);
	}
	else 
	{
		LED_Stat=LED_Stat|0x20;
		HC573(4,LED_Stat);
	}
}
void main()
{
	System_init();
	while(1)
	{
		Mode_Choose();
		Read_time();
		Key_Read();
		Display_All();
		LED_Run();
		Set_DAC();
	}
}

void Time0() interrupt 1
{
	TH0=(65535-10000+1)/256;
	TL0=(65535-10000+1)%256;
	Key_Flag=0;//10ms刷新一次按键
}

void System_init()
{
	HC573(4,0xff);
	HC573(5,0x00);
	Time_init();
	Ds1302_init();
}

void HC573(unsigned char channel,unsigned char value)
{
	P2=(0x1f&P2)|0x00;
	P0=value;
	switch(channel)
	{
		case 4:P2=(0x1f&P2)|0x80;break;
		case 5:P2=(0x1f&P2)|0xa0;break;
		case 6:P2=(0x1f&P2)|0xc0;break;
		case 7:P2=(0x1f&P2)|0xe0;break;
		case 0:P2=(0x1f&P2)|0x00;break;
	}
	P2=(0x1f&P2)|0x00;
}

void Delay(int x)		//@12.000MHz
{
	unsigned char i, j;
	while(x--)
	{
		i = 12;
		j = 169;
		do
		{
			while (--j);
		} while (--i);
	}
}

void Nixie(unsigned char column,unsigned char value)
{
	HC573(6,0x01<<(column-1));
	HC573(7,value);
	Delay(1);
	HC573(6,0x01<<(column-1));
	HC573(7,0xff);
}

ds1302.c:

#include <REGX52.H>
#include "intrins.h"

sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^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);			
}

ds1302.h

#ifndef __DS1302_H_
#define __DS1302_H_

void Write_Ds1302(unsigned  char temp) ;
void Write_Ds1302_Byte( unsigned char address,unsigned char dat );
unsigned char Read_Ds1302_Byte ( unsigned char address );


#endif

iic.c

#include <REGX52.H>
#include "intrins.h"

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

#define DELAY_TIME	5

//
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);
}

iic.h

#ifndef __IIC_H_
#define __IIC_H_

void I2CStart(void);
void I2CStop(void);
void I2CSendByte(unsigned char byt);
unsigned char I2CReceiveByte(void);
unsigned char I2CWaitAck(void);
void I2CSendAck(unsigned char ackbit);

#endif

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

brepot

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值