蓝桥杯单片机国赛13届

注意:超声波:用定时器1的12T模式 16位不可重装模式 

main.c 

#include <STC15F2K60S2.H>
#include <intrins.h>
#include "iic.h"

code unsigned char Seg_Table[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char smg[8];
//三个半小时

//参数
unsigned char fram_freq=90; //9.0KHZ  1.0-12.0
unsigned char fram_west=40; //10%-60%
unsigned char fram_dist=6; //0.6m  0.1-1.2

typedef struct
{
	unsigned char b1:1;
	unsigned char b2:1;
	unsigned char b3:1;
	unsigned char b4:1;
	unsigned char b5:1;
	unsigned char b6:1;
	unsigned char b7:1;
	unsigned char b8:1;
}Bits;

typedef union
{
	unsigned char Hex;
	Bits B;
}HextoB;

HextoB led_ctrl;


void vDevice_Process(unsigned char p2dat,unsigned char p0dat)
{
	P0 = p0dat;
	P2 = (P2&0x1f)|p2dat;
	P2 = P2&0x1f;
}
//----------定时器
void Timer2Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x50;		//设置定时初值
	T2H = 0xFB;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	
	IE2 |= 0x04;
	EA=1;
}
void Timer0Init(void)		//1毫秒@12.000MHz
{

	TMOD |= 0x05;		//设置定时器模式
	TL0 = 0;		//设置定时初值
	TH0 = 0;		//设置定时初值
	TR0 = 1;		//定时器0开始计时
}
void Timer1Init(void)		//1微秒@12.000MHz
{
	AUXR &= 0xBF;		//定时器时钟12T模式
	TMOD &= 0x0F;		//设置定时器模式
	TMOD |= 0x10;		//设置定时器模式
	TL1 = 0xFF;		//设置定时初值
	TH1 = 0xFF;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
}



//-----------测频率
unsigned int cnt_freq;
unsigned int freq;
unsigned int freq_khz;
void vGet_freq()
{
	if(cnt_freq>=1000)
	{
		cnt_freq=0;
		freq = (TH0<<8)|TL0;
		TH0=0;TL0=0;
		freq_khz = freq/1000.0f*10; //注意对较大的数如何保留小数,如果先乘10会超出65535范围出现错误。应该先除以浮点数再乘10就是保留了小数点一位
	}
}

//-----脉冲输出
unsigned char pwm_num=8;//占空比
unsigned char pwm;
void vPWM_out()
{
	if(freq_khz>fram_freq) 
	{
		if(pwm<8)
		{
			vDevice_Process(0xa0,0x20);
		}
		else if(pwm<10)
		{
			vDevice_Process(0xa0,0x00);
		}
		else
		{
			pwm=0;
		}
	}
	
	if(freq_khz<fram_freq) 
	{
		if(pwm<2)
		{
			vDevice_Process(0xa0,0x20);
		}
		else if(pwm<10)
		{
			vDevice_Process(0xa0,0x00);
		}
		else
		{
			pwm=0;
		}
	}
}


//----------测湿度 RB2
unsigned char cnt_rb2;
unsigned char west;  //湿度
unsigned char rb2;
void vGet_west()
{
	if(cnt_rb2>=100)
	{
		cnt_rb2=0;
		EA=0;
		rb2 = Read_rb2();//电压转为0-100范围 100对应5V,即可用电压值表示湿度
		EA=1;
		west = rb2;
		if(west>=100) west=99; //因为用两位数码管显示,所以最大时是99
		
		
	}
}

//---------DAC输出 与湿度有关
void vDAC_Process()
{
	if(west<=fram_west) Out_DAC(58); //1V 1V转折点是湿度参数
	else if(west<80) Out_DAC(58+230/(80.0f-fram_west)*(west-fram_west)); 
	else if(west>80) Out_DAC(255);
}




//----------超声波测距//12T的16位不可重装模式才准
void vSend_wave()
{
	unsigned char i,j;
	for(i=0;i<8;i++)
	{
		P10=1;
		for(j=0;j<25;j++)
		_nop_();
		P10=0;
		for(j=0;j<25;j++)
		_nop_();
	}
}

unsigned int vRecive_wave()
{
	unsigned int dat;
	TH1=0;TL1=0;
	vSend_wave();
	TR1=1;
	while((P11==1)&&(TF1==0));
	TR1=0;
	if(TF1==1)
	{
		TF1=0;
		dat = 999;
	}
	else
	{
		dat = ((TH1<<8)|TL1)*0.0175;
	}
	return dat;
}

unsigned char cnt_dist;
unsigned int dist;
unsigned char state_RELAY=0; //0断开 1闭合
unsigned char cnt_RELAY=0; //闭合次数统计
void vGet_dist()
{
	if(cnt_dist>=100)
	{
		cnt_dist=0;
		dist = vRecive_wave();
	}
}


//----------数码管
unsigned char mode1=0; //mode1 频率 湿度 测距 参数 mode2
unsigned char mode_freq=0,mode_dist=0,mode_set=0;
void vSmg_Process()
{
	if(mode1==0)//频率界面
	{
		unsigned int dat;
		if(mode_freq==0)dat=freq;
		else dat=freq_khz;
		smg[0]=0x8e;
		smg[1]=0xff;
		smg[2]=Seg_Table[dat/100000];
		smg[3]=Seg_Table[dat/10000%10];
		smg[4]=Seg_Table[dat/1000%10];
		smg[5]=Seg_Table[dat/100%10];
		if(mode_freq==0)smg[6]=Seg_Table[dat/10%10];
		else smg[6]=Seg_Table[dat/10%10]&0x7f;
		smg[7]=Seg_Table[dat%10];
	}
	if(mode1==1)//湿度界面
	{
		smg[0]=0x89;
		smg[1]=0xff;
		smg[2]=0xff;
		smg[3]=0xff;
		smg[4]=0xff;
		smg[5]=0xff;
		smg[6]=Seg_Table[west/10];
		smg[7]=Seg_Table[west%10];
	}
	if(mode1==2)//测距界面
	{
		if(mode_dist==0)
		{
			smg[0]=0x88;
			smg[1]=0xff;
			smg[2]=0xff;
			smg[3]=0xff;
			smg[4]=0xff;
			if(dist>=100)smg[5]=Seg_Table[dist/100];
			else smg[5]=0xff;
			if(dist>=10)smg[6]=Seg_Table[dist/10%10];
			else smg[6]=0xff;
			smg[7]=Seg_Table[dist%10];
		}
		else if(mode_dist==1)
		{
			smg[0]=0x88;
			smg[1]=0xff;
			smg[2]=0xff;
			smg[3]=0xff;
			smg[4]=0xff;
			smg[5]=Seg_Table[dist/100]&0x7f;
			smg[6]=Seg_Table[dist/10%10];
			smg[7]=Seg_Table[dist%10];
		}
	}
	if(mode1==3)//参数界面
	{
		if(mode_set==0)//频率参数
		{
			smg[0]=0x8c;
			smg[1]=Seg_Table[1];
			smg[2]=0xff;
			smg[3]=0xff;
			smg[4]=0xff;
			if(fram_freq>=100)smg[5]=Seg_Table[fram_freq/100];
			else smg[5]=0xff;
			smg[6]=Seg_Table[fram_freq/10%10]&0x7f;
			smg[7]=Seg_Table[fram_freq%10];
		}
		if(mode_set==1)//湿度参数
		{
			smg[0]=0x8c;
			smg[1]=Seg_Table[2];
			smg[2]=0xff;
			smg[3]=0xff;
			smg[4]=0xff;
			smg[5]=0xff;
			smg[6]=Seg_Table[fram_west/10];
			smg[7]=Seg_Table[fram_west%10];
		}
		if(mode_set==2)//距离参数
		{
			smg[0]=0x8c;
			smg[1]=Seg_Table[3];
			smg[2]=0xff;
			smg[3]=0xff;
			smg[4]=0xff;
			smg[5]=0xff;
			smg[6]=Seg_Table[fram_dist/10]&0x7f;
			smg[7]=Seg_Table[fram_dist%10];
		}
	}
}

void vSmg_Show()
{
	static unsigned char i;
	vDevice_Process(0xc0,0);
	vDevice_Process(0xe0,smg[i]);
	vDevice_Process(0xc0,0x01<<i);
	i = (i+1)%8;
}

//------------独立按键
unsigned char Trg,Cont;
void Three_line()
{
	unsigned char ReadData=P3^0xff;
	Trg = ReadData&(ReadData^Cont);
	Cont = ReadData;
}

unsigned char cnt_key;
unsigned int cnt_1s;
void vKeys_Process()
{
	if(cnt_key>=10)
	{
		cnt_key=0;
		Three_line();
		
		if(Trg == 0x08) //S4
		{
			mode1 = (mode1+1)%4;
			if(mode1==0)led_ctrl.Hex=0xff;
			if(mode1==3) 
			{
				mode_set=0;
				led_ctrl.Hex=0xff;
			}
		}
		if(Trg == 0x04) //S5
		{
			if(mode1==3)
			{
				mode_set = (mode_set+1)%3;
			}
		}
		if(Trg == 0x02) //S6
		{
			if(mode1==3)//参数界面下
			{
				switch(mode_set)
				{
					case 0:
						fram_freq += 5;
						if(fram_freq>120)fram_freq=10;
					break;
					case 1:
						fram_west += 10;
						if(fram_west>60)fram_west=10;
					break;
					case 2:
						fram_dist += 1;
						if(fram_dist>12)fram_dist=1;
					break;
				}
			}
			else if(mode1==2)//测距界面下
			{
				mode_dist = (mode_dist+1)%2;
			}
		}
		
		if(Cont==0x01)//长按S7计时
		{
			cnt_1s++; //10ms加1 100就是1s
		}
		if(Cont == 0x00 &&Trg == 0x00)
		{
			
			if(cnt_1s>=100)//长按S7 清零继电器开关次数
			{
				cnt_1s=0;
			}
			else if(cnt_1s!=0)//短按S7
			{
				cnt_1s=0;
				if(mode1==3)//参数界面下
				{
					switch(mode_set)
					{
						case 0:
							fram_freq -= 5;
							if(fram_freq<10)fram_freq=120;
						break;
						case 1:
							fram_west -= 10;
							if(fram_west<10)fram_west=60;
						break;
						case 2:
							fram_dist -= 1;
							if(fram_dist<1)fram_dist=12;
						break;
					}
				}
				else if(mode1==0)//测距界面下
				{
					mode_freq = (mode_freq+1)%2;
				}
			}
		}
		
	}
}

//----------LED 控制
unsigned int cnt_100msled;

void vLED_Process()
{
	switch(mode1)
	{
		case 0:
			led_ctrl.B.b1=0;//频率界面
			led_ctrl.B.b2=1;
			led_ctrl.B.b2=1;
		break;
		case 1:
			led_ctrl.B.b1=1;
			led_ctrl.B.b2=0;//湿度界面
			led_ctrl.B.b3=1;
		break;
		case 2:
			led_ctrl.B.b1=1;
			led_ctrl.B.b2=1;
			led_ctrl.B.b3=0;//距离界面
		break;
	}
	vDevice_Process(0x80,led_ctrl.Hex);
}

//----------系统初始化
void vSystem_init()
{
	led_ctrl.Hex=0xff;
	vDevice_Process(0x80,0xff);
	vDevice_Process(0xa0,0x00);
}

void main()
{
	vSystem_init();
	Timer2Init();
	Timer0Init();
	Timer1Init();
	while(1)
	{
		vSmg_Process();
		vGet_freq();
		if(mode1==1)vGet_west();
		vGet_dist();
		vKeys_Process();
		vDAC_Process();
	}
}

unsigned char cnt_10; //100us十次就是1ms
void Timer2_service() interrupt 12
{
	cnt_10++;
	pwm++;
	vPWM_out();
	cnt_100msled++;
	if(cnt_10>=10)
	{
		cnt_10=0;
		cnt_freq++;cnt_rb2++;cnt_dist++;cnt_key++;
		vSmg_Show();
	}
	vLED_Process();
	if(cnt_100msled>=1000)
	{
		cnt_100msled=0;
		if(mode1==3)
		{
			if(mode_set==0)//频率参数
			{
				led_ctrl.B.b1 = ~led_ctrl.B.b1;
				led_ctrl.B.b2=1;
				led_ctrl.B.b3=1;
			}
			if(mode_set==1)//频率参数
			{
				led_ctrl.B.b1=1;
				led_ctrl.B.b2 = ~led_ctrl.B.b2;
				led_ctrl.B.b3=1;
			}
			if(mode_set==2)//频率参数
			{
				led_ctrl.B.b1=1;
				led_ctrl.B.b2=1;
				led_ctrl.B.b3 = ~led_ctrl.B.b3;
			}
		}
	}
	if(state_RELAY==0)//继电器操作
	{		
		if(dist>fram_dist*10)
		{
			state_RELAY=1;
			vWrite_24c02(0x00,state_RELAY);
			cnt_RELAY++;
			vDevice_Process(0xa0,0x10); //闭合继电器
		}
	}
	else if(state_RELAY==1)
	{
		if(dist<fram_dist*10)
		{
			state_RELAY=0;
			vDevice_Process(0xa0,0x00);//断开继电器
		}
	}
}







iic.c 

/*	#   I2C代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/
#include <reg52.h>
#include <intrins.h>

#define DELAY_TIME	5

sbit sda=P2^1;
sbit scl=P2^0;
void Delay5ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 59;
	j = 90;
	do
	{
		while (--j);
	} while (--i);
}

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

//测量RB2电压
unsigned char Read_rb2()
{
	unsigned int dat;
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x43);
	I2CWaitAck();
	
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	dat = I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	
	return dat*100/255; //0-100 注意这里先乘100所以要用int类型的dat
}

//输出电压dac
void Out_DAC(unsigned char dat)
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x40);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
	
}

//24c02写
void vWrite_24c02(unsigned char addr,unsigned char dat)
{
	I2CStart();
	I2CSendByte(0xa0);
	I2CWaitAck();
	I2CSendByte(addr);
	I2CWaitAck();
	I2CSendByte(dat);
	I2CWaitAck();
	I2CStop();
	Delay5ms();
}





iic.h 

#ifndef __IIC_H__
#define __IIC_H__

unsigned char Read_rb2(); //0~100
void Out_DAC(unsigned char dat);
void vWrite_24c02(unsigned char addr,unsigned char dat);

#endif

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值