第八届蓝桥杯决赛

main.c

#include "main.h"


unsigned char tab[13]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0XBF,0XFF,0X8E};
unsigned char dsbuff[8]={11,11,11,11,11,11,11,11};
unsigned char com;

bit key5 = 0,key7 = 0,key6 = 0;//0-测距显示 1-回显

int key7_num;
unsigned char distince;
int ui_Sonic_flag;
int history[10];//距离历史数据
int num;//次数
int mangqu;//盲区
int result;//计算结果
int dis;//超声波测距结果用于和盲区比较
int dac_num;//dac输出


bit over = 0,start = 0;
bit option = 0;//操作
bit Sonic_flag;

int led_count;
bit led1_flag;//led1闪烁标志
int led_time;//led闪烁次数
bit led1,led7,led8;//led1 led7 led8标志位
int led1_count;

void main(void)
{
	
	EA = 1;
	all_init();
	Timer0Init();
	Timer1Init();
//	eeprom_init();
	
	eeprom_read();
	mangqu = iic_read(0X00);
	Delay3ms();
	while(1)
	{
		Key_Individual();
		Sonic_Proc();
		dac_out();
		
			
		

		 if((key5 == 1))//数据回显
		{
			eeprom_read();
			smg_display((key7_num+1)/10%10,(key7_num+1)/1%10,11,11,11,history[key7_num]/100%10,history[key7_num]/10%10,history[key7_num]/1%10);
		}else if((key6 == 1))//参数设置
		{
			smg_display(12,11,11,11,11,mangqu/100%10,mangqu/10%10,mangqu/1%10);
		}else if((key5 == 0)&&(key6 == 0))
		{
			distince_display();
		}
		if(over == 1)
			{
				while(led_time < 10)
			{
				if(led1_flag == 1)
				{
					led_one(0XFE);
				}else if(led1_flag == 0)
				{
					led_one(0XFF);
				}
				
			}
			if(led_time >= 10)
			{
				led_time = 0;
				over = 0;
			}
		}
	}
}


void distince_display(void)//测距显示界面
{
	
	if(option == 0)//显示上一次测量数据
	{eeprom_read();
		if(num-2 < 0)
		{
			result = history[num-2+10];
		}else if(num-2 >= 0) 
		{
			result = history[num-2];
		}
		
	}else if(option == 1)显示上一次测量与本次测量数据
	{eeprom_read();
		if(num-2 < 0)
		{
			result = history[num-1+10]+history[num-2+10];
		}else if(num-2 >= 0)
		{
			result = history[num-1]+history[num-2];
		}
	}
	smg_display(option,11,result/100%10,result/10%10,result/1%10,history[num-1]/100%10,history[num-1]/10%10,history[num-1]/1%10);	

}

//全部初始化
void all_init(void)
{
	P2 &=0X1F;
	
	P0=0XFF;
	P2 = ((P2&0X1F)|0X80);
	P2 &=0X1F;
	
	P0=0X00;
	P2 = ((P2&0X1F)|0XA0);
	P2 &=0X1F;
	
	P0=0XFF;
	P2 = ((P2&0X1F)|0XE0);
	P2 &=0X1F;
}

//数码管显示
void display(void)
{
	P0 = 0XFF;
	P2 = ((P2&0X1F)|0XE0);
	P2 &= 0X1F;
	
	P0 = 0X01<<com;
	P2 = ((P2&0X1F)|0XC0);
	P2 &= 0X1F;
	
	P0 = tab[dsbuff[com]];
	P2 = ((P2&0X1F)|0XE0);
	P2 &= 0X1F;
	if(++com >= 8)
		com = 0;
}

//数码管显示函数
void smg_display(int s1,int s2,int s3,int s4,int s5,int s6,int s7,int s8)
{
	dsbuff[0] = s1;dsbuff[1] = s2;
	dsbuff[2] = s3;dsbuff[3] = s4;
	dsbuff[4] = s5;dsbuff[5] = s6;
	dsbuff[6] = s7;dsbuff[7] = s8;
}

//独立按键扫描
void Key_Individual(void)
{
	P3 |= 0x0F;
	if(P3_LOW4  != 0x0F)
	{
		Delay3ms();
		if(P3_LOW4  != 0x0F)
		{
			 switch(P3_LOW4)
			{
				case 0x0E://S7
					if(key5 == 1)//回显
					{
						if(++key7_num >= 10)
						{
							key7_num = 0;
						}
					}else if(key5 == 0)
					{
						key7_num = 0;
					}
					
					if(key6 == 1)
					{
						mangqu+=10;
						if(mangqu > 90)
						{
							mangqu = 0;
						}
					}
					
					if((key5 == 0) && (key6 == 0))
					{
						
						option = ~option;
					}
				while(P3_LOW4  == 0x0E);
				break;
	
				case 0x0D://S6//参数设置
					if(key5 == 0)
					{
						key6 = ~key6;//1-参数设置
						if(key6 == 0)
						{
							iic_write(0X00,mangqu);
						}
					}

				while(P3_LOW4  == 0x0D);
				break;
				
				case 0x0B://S5//数据回显
					if(key6 == 0)
					{
						over = 0;
						key5 = ~key5;
					}
					
				while(P3_LOW4  == 0x0B);
				break;
				
				case 0x07://S4
					if((key5 == 0) && (key6 == 0))
					{
						start = 1;//启动测量
					}
				while(P3_LOW4  == 0x07);
				break;
			}
		}
	}
}

void dac_out(void)
{
	if(mangqu >= dis)//输出0v
	{
		pcf8951_dac(0);
	}else if(mangqu < dis)
	{
		dac_num = (dis - mangqu)*0.02;
		if(dac_num > 5)//输出5v
		{
			pcf8951_dac(255);
		}else {
			pcf8951_dac(dac_num*51/5);
		}
	}
}


void led_option(void)//1、7、8
{
	if(key6 == 1)//参数设置7亮
	{
		led_one(0XBF);
	}if(key5 == 1)//数据回显8亮
	{
		led_one(0X7F);
	}else if((key5 == 0)&&(key6 == 0))//全灭
	{
		led_one(0XFF);
	}
}


//定时器
void Timer0Init(void)		//12微秒@12.000MHz
{
	AUXR &= 0x7F;		//定时器时钟12T模式
	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xF4;		//设置定时初值
	TH0 = 0xFF;		//设置定时初值
	TF0 = 0;		//清除TF0标志
	TR0 = 0;		//定时器0停止计时
}



void Timer1Init(void)		//2毫秒@11.0592MHz
{
	AUXR |= 0x40;		//定时器时钟1T模式
	TMOD &= 0x0F;		//设置定时器模式
	TL1 = 0x9A;		//设置定时初值
	TH1 = 0xA9;		//设置定时初值
	TF1 = 0;		//清除TF1标志
	TR1 = 1;		//定时器1开始计时
	ET1 = 1;
}

void timer1_isr() interrupt 3
{
	display();
	if(++ui_Sonic_flag == 50)
	{		
		ui_Sonic_flag = 0;   //超声波刷新频率 300ms一次
		Sonic_flag = 1;
	}
	if(++led_count >= 10)
	{
		led_count = 0;
		led_option();	
	}
	
	if(over == 1)
	{
		if(++led1_count >= 100)
		{
			led1_count = 0;
			led1_flag = ~led1_flag;
			led_time++;	
		}
	}		
}




//超声波


//超声波数据处理函数
unsigned char Sonic(void)
{
  unsigned char Dist , s_num=10;
	TX = 0;
	Timer0Init();
	TR0 = 1;		
	
	while(s_num--)
	{
	  while(!TF0);  
		TX ^= 1;    
		TF0 = 0;      			
	}

  TR0 = 0;  
	TL0 = 0;  
	TH0 = 0;
  TR0 = 1;		

  while(RX && !TF0);  
	TR0 = 0;  
	
	if(TF0)   
	{		
	  TF0 = 0;
	  Dist  = 0;
	}
	else
	{
	  Dist = ((TH0<<8)+TL0)*0.017;
	}
	return Dist;
}


void Sonic_Proc(void)
{
	if(start == 1)
	{
		start = 0;
		
		distince = Sonic();  //测距
		iic_write(0x01+num,distince);Delay3ms();
		
		history[num] = iic_read(0x01+num);Delay3ms();
		dis = history[num];
		over = 1;
		if(++num >= 10)
		{
			num = 0;
		}
	}
}

void eeprom_read(void)
{
	int i;
	for(i=0;i<10;i++)
	{
		history[i] = iic_read(0x01+i);Delay3ms();Delay3ms();
	}
}

//LED操作
void led_one(unsigned char dat)//单个LED操作
{
	P0 = dat;
	P2 = ((P2&0X1F)|0X80);
	P2 &= 0X1F;
}

main.h

#ifndef _MAIN_H
#define _MAIN_H
#include "STC15F2K60S2.h"
#include "iic.h"


sbit TX = P1^0;   	//接收 
sbit RX = P1^1;   	//发射
#define P3_LOW4 (P3&0x0F)


void all_init(void);					//全部初始化
void display(void);						//数码管显示
void smg_display(int s1,int s2,int s3,int s4,int s5,int s6,int s7,int s8);
void Key_Individual(void);		//独立按键扫描
void Timer0Init(void);				//2毫秒@11.0592MHz
void Timer1Init(void);				//2微秒@11.0592MHz
void Sonic_Proc(void);
void distince_display(void);	//测距显示界面
void dac_out(void);
void led_option(void);//1、7、8
void eeprom_read(void);
void led_one(unsigned char dat);//单个LED操作

#endif

iic.c

/*
  程序说明: IIC总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(12MHz)
  日    期: 2011-8-9
*/

#include "iic.h"

//总线启动条件
void IIC_Start(void)
{
	SDA = 1;
	SCL = 1;
	somenop;
	SDA = 0;
	somenop;
	SCL = 0;	
}

//总线停止条件
void IIC_Stop(void)
{
	SDA = 0;
	SCL = 1;
	somenop;
	SDA = 1;
}



//等待应答
bit IIC_WaitAck(void)
{
	SDA = 1;
	somenop;
	SCL = 1;
	somenop;
	if(SDA)    
	{   
		SCL = 0;
		IIC_Stop();
		return 0;
	}
	else  
	{ 
		SCL = 0;
		return 1;
	}
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
	unsigned char i;
	for(i=0;i<8;i++)
	{   
		if(byt&0x80) 
		{	
			SDA = 1;
		}
		else 
		{
			SDA = 0;
		}
		somenop;
		SCL = 1;
		byt <<= 1;
		somenop;
		SCL = 0;
	}
}

//从I2C总线上接收数据
unsigned char IIC_RecByte(void)
{
	unsigned char da;
	unsigned char i;
	
	for(i=0;i<8;i++)
	{   
		SCL = 1;
		somenop;
		da <<= 1;
		if(SDA) 
		da |= 0x01;
		SCL = 0;
		somenop;
	}
	return da;
}


void iic_write(unsigned char addr,unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}


unsigned char iic_read(unsigned char addr)
{
	unsigned char temp;
	
	IIC_Start();
	IIC_SendByte(0XA0);
	IIC_WaitAck();
	IIC_SendByte(addr);
	IIC_WaitAck();
	IIC_Stop();
	
	
	IIC_Start();
	IIC_SendByte(0XA1);
	IIC_WaitAck();
	temp = IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();
	return temp;
}


void pcf8951_dac(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0X90);
	IIC_WaitAck();
	
	IIC_SendByte(0X40);
	IIC_WaitAck();
	
	IIC_SendByte(dat);
	IIC_WaitAck();
	
	IIC_Stop();
}

//3ms延时
void Delay3ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 36;
	j = 1;
	do
	{
		while (--j);
	} while (--i);
}

void eeprom_init(void)
{
	int i;
	for( i = 0; i < 11;i++)
	{
		iic_write(0x00+i,0);Delay3ms();
	}
}

iic.h

#ifndef _IIC_H
#define _IIC_H

#include "STC15F2K60S2.h"
#include "intrins.h"

#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

//总线引脚定义
sbit SDA = P2^1;  /* 数据线 */
sbit SCL = P2^0;  /* 时钟线 */


//函数声明
void IIC_Start(void); 
void IIC_Stop(void);  
//void IIC_Ack(unsigned char ackbit); 
void IIC_SendByte(unsigned char byt); 
bit IIC_WaitAck(void);  
unsigned char IIC_RecByte(void); 
void iic_write(unsigned char addr,unsigned char dat);//eeprom写操作
unsigned char iic_read(unsigned char addr);//eeprom读操作
void pcf8951_dac(unsigned char dat);//pcf8951_dac输出
void eeprom_init(void);
void Delay3ms()	;							//3ms延时

#endif

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值