第十二届蓝桥杯单片机组国赛代码

other.h

#ifndef __OTHER_H_
#define __OTHER_H_

#include <stc15f2k60s2.h>
#include "intrins.h"

sbit TX = P1^0;
sbit RX = P1^1;

void close_perl(void);
unsigned char seg_tran(int num);
void seg_disp(int adr,int num);
void seg_disp_f(int adr,int num);
int key_scan(void);
void 	Delay2ms(void);
void Delay12us(void);
void output_b(void);
void Timer0Init(void);
unsigned char distance_get(void);

#endif

other.c

#include <other.h>

void close_perl(void)//关闭外设
{
	P0 = 0xff;
	P2 = P2&0x1f|0x80;
	P2 = P2&0x1f;
	
	P0 = 0x00;
	P2 = P2&0x1f|0xa0;
	P2 = P2&0x1f;
}

unsigned char seg_tran(int num)//数码管转置
{
	unsigned char date;
	
	switch(num)
	{
		case 0:	date = 0xC0;break;
		case 1:	date = 0xF9;break;
		case 2:	date = 0xA4;break;
		case 3:	date = 0xB0;break;
		case 4:	date = 0x99;break;
		case 5:	date = 0x92;break;
		case 6:	date = 0x82;break;
		case 7:	date = 0xF8;break;
		case 8:	date = 0x80;break;
		case 9:	date = 0x90;break;
		case 10:	date = 0xbf;break;//-
		case 11:	date = 0xc7;break;//L
		case 12:	date = 0x8e;break;//f
		case 13:	date = 0xc6;break;//c
		case 14:	date = 0x89;break;//H
		case 15:	date = 0xfe;break;//上
		case 16:	date = 0xf7;break;//下
		case 17	:	date = 	0x8c	;	break;//p
	}
	
	return date;
}

void seg_disp(int adr,int num)//数码管显示
{
	unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
	P0 = seg_adr[adr];
	
	P2 = P2&0x1f|0xc0;
	P2 = P2&0x1f;
	P0 = seg_tran(num);
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
}

void seg_disp_f(int adr,int num)//数码管显示(含小数点)
{
	unsigned char seg_adr[8] = {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
	P0 = seg_adr[adr];
	
	P2 = P2&0x1f|0xc0;
	P2 = P2&0x1f;
	P0 = seg_tran(num)&0x7f;
	
	P2 = P2&0x1f|0xe0;
	P2 = P2&0x1f;
}	

int key_scan(void)//矩阵按键扫描
{
	int key_mark,key;
	P3 = 0x0f;
	
	P44 = 0;P42 = 1;P35 = 1;P34 = 1;
	key = P3;
	P44 = 1;P42 = 0;	key = (key<<4)|(P3&0x0f);
	P42 = 1;P35 = 0;	key = (key<<4)|(P3&0x0f);
	P35 = 1;P34 = 0;	key = (key<<4)|(P3&0x0f);
	
	switch(~key)
	{
		case 0x8000: key_mark = 4;break;
		case 0x4000: key_mark = 5;break;
		case 0x0800: key_mark = 8;break;
		case 0x0400: key_mark = 9;break;
		default: key_mark = 0;break;
	}
	return key_mark;
}

void Delay2ms()		//@12.000MHz
{
	unsigned char i, j;

	i = 24;
	j = 85;
	do
	{
		while (--j);
	} while (--i);
}


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

unsigned char distance_get(void)
{
	unsigned char distance, num = 10;
	TX = 0;
	TL0 = 0xF4;	
	TH0 = 0xFF;
	TR0 = 1;
	while(num --)
	{
		while(!TF0);
		TX ^= 1;
		TF0 = 0;
	}
	TR0 = 0;
	TL0 = 0;
	TH0 = 0;
	TR0 = 1;
	while(RX && !TF0);
	TR0 = 0;
	if(TF0)
	{
		TF0 = 0;
		distance = 255;
	}
	else
		distance = ((TH0 << 8) + TL0) * 0.017;
	return distance;
}

iic.c

void dac_pcf(unsigned char dac)
{
	IIC_Start();
	
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x43);
	IIC_WaitAck();
	IIC_SendByte(dac);
	IIC_WaitAck();
	
	IIC_Stop();
}

unsigned char adc_pcf(void)
{
	unsigned char adc;
	
	IIC_Start();
	
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x41);
	IIC_WaitAck();
	
	IIC_Start();
	
	IIC_SendByte(0x91);
	IIC_WaitAck();
	adc = IIC_RecByte();
	IIC_WaitAck();
	
	IIC_Stop();
	return adc;
}

mian.c

#include <other.h>
#include <iic.h>
#include <ds1302.h>

#define led1 0x01
#define led2 0x02
#define led3 0x04
#define led4 0x08
#define led5 0x10
#define led6 0x20

unsigned char key_old;
unsigned char dac;
unsigned char adc;
unsigned int distance;
unsigned int distance_ever;
bit disp_mode;//界面切换
char perl_mode;//外设切换
bit chuma_mode;//触发模式
char jilu_mode;//数据记录模式
char c_mode;//参数模式
bit light_mode;	//光照强度,0为暗,1为常光
bit light_mode_old;//旧光照强度
bit light_mode_new;//新光照强度
char time_c_mode;//时间参数模式
char time_c_sz[5] = {2,3,5,7,9};//时间参数
char time_c;
unsigned char distance_c = 10;//距离参数

unsigned char ds1302_write[3] = {0x80,0x82,0x84};
unsigned char ds1302_read[3] = {0x81,0x83,0x85};
unsigned char ds1302_first[3] = {0x00,0x20,0x20};

unsigned char dis_max = 0;
unsigned char dis_min = 0;
unsigned int dis_all_10;//所有距离之和*10
unsigned int dis_arr_10;//所有距离之和平均值*10
unsigned int	dis_number = 0;//采集次数

unsigned int over_times = 0;//超出范围次数
bit led5_ok = 0;

void ds1302_init(void)
{
	int t;
	Write_Ds1302_Byte(0x8e,0);//关闭写保护
	for(t = 0; t < 3; t++)
	{
		Write_Ds1302_Byte(ds1302_write[t],ds1302_first[t]);//写入时间		
	}
	Write_Ds1302_Byte(0x8e,1);//开启写保护
}

void key_pro(void)
{
	unsigned char key_vol,key_down;
	
	key_vol = key_scan();
	key_down = key_vol&(key_vol^key_old);
	key_old = key_vol;
	
	switch(key_down)
	{
		case 4://界面切换按键
			disp_mode = ~disp_mode;
			//	0为数据显示
			//	1为参数设置
		break;
		
		case 5:
			if(disp_mode == 1)//参数设置界面选择
			{
				perl_mode = 0;
				c_mode ++;
				if(c_mode == 2)	c_mode = 0;//采集时间 距离参数
			}
			else if(disp_mode == 0)//数据显示界面选择
			{
				c_mode = 0;
				perl_mode	++;
				if(perl_mode == 3)	perl_mode = 0;//时间 距离 数据记录
			}
		break;
		
		case 8:
			if((disp_mode == 0)&&(perl_mode == 1))	chuma_mode = ~chuma_mode;//其他触发 定时
			else if((disp_mode == 0)&&(perl_mode == 2))	
			{
				jilu_mode ++;
				if(jilu_mode == 3)	jilu_mode = 0;//大 均 小
			}
		break;
		
		case 9:
			if((disp_mode == 1)&&(c_mode == 0))
			{
				time_c_mode ++;
				if(time_c_mode == 5)	time_c_mode = 0;
				time_c = time_c_sz[time_c_mode];
			}
			
			else if((disp_mode == 1)&&(c_mode == 1))
			{
				distance_c = distance_c + 10;
				if(distance_c == 90)	distance_c = 10;
			}
			
		break;
	}
}
void other_pro(void)
{
	
	adc = adc_pcf();//电压读出
	dac_pcf(dac);//电压写入	
	distance_ever = distance_get();//一直测
	//判断光照强度
	if(adc > 40)	light_mode = 1;
	else	light_mode = 0;
	light_mode_new = light_mode;
	
	//dac输出函数
	if(distance <= 10)	dac = 51;
	else if((distance > 10)&&(distance <= 80))	dac = 3*distance+23;
	else dac = 255;
	
	//距离采集
	if(chuma_mode == 0)//触发采集
	{
		if((light_mode_new == 0)&&(light_mode_old == 1))//由亮变暗
		{
			distance = distance_ever;//距离采集一次
			dis_number = dis_number+1;//采集次数加一次
			if(distance > dis_max)	dis_max = distance;//大于最大值,则替换
			if(distance < dis_min)	dis_min = distance;//小于最小值,则替换
			dis_all_10 = dis_all_10 + distance*10;
			dis_arr_10 = dis_all_10/dis_number;
			
			if((distance < distance_c+5)&&(distance > distance_c-5))	over_times ++;//参数约定范围
			else over_times = 0;
		}
	}
	else if(chuma_mode == 1)//定时采集
	{
		if(	((Read_Ds1302_Byte(ds1302_read[0])/16*10 + Read_Ds1302_Byte(ds1302_read[0])%16)	%   time_c) == 0	)
		{
			distance = distance_ever;//距离采集一次
			dis_number = dis_number+1;//采集次数加一次
			if(distance > dis_max)	dis_max = distance;//大于最大值,则替换
			if(distance < dis_min)	dis_min = distance;//小于最小值,则替换
			dis_all_10 = dis_all_10 + distance*10;
			dis_arr_10 = dis_all_10/dis_number;
			if((distance < distance_c+5)&&(distance > distance_c-5))	over_times ++;//参数约定范围
			else over_times = 0;
		} 
	}
	if(over_times >= 3)	led5_ok = 1;//允许led5亮
	else led5_ok = 0;
	
	light_mode_old = light_mode; 
}

void seg_pro(void)
{
	//时间数据显示界面
	if(disp_mode == 0)//数据界面
	{
		if(perl_mode == 0)//时间参数
		{
			seg_disp(0,Read_Ds1302_Byte(ds1302_read[2])/16);Delay2ms();
			seg_disp(1,Read_Ds1302_Byte(ds1302_read[2])%16);Delay2ms();
			seg_disp(2,10);Delay2ms();
			seg_disp(3,Read_Ds1302_Byte(ds1302_read[1])/16);Delay2ms();
			seg_disp(4,Read_Ds1302_Byte(ds1302_read[1])%16);Delay2ms();
			seg_disp(5,10);Delay2ms();
			seg_disp(6,Read_Ds1302_Byte(ds1302_read[0])/16);Delay2ms();
			seg_disp(7,Read_Ds1302_Byte(ds1302_read[0])%16);Delay2ms();
		}
		else if(perl_mode == 1)//距离参数
		{
			seg_disp(0,11);Delay2ms();
			
			if(chuma_mode == 0)	{seg_disp(1,13);Delay2ms();}
			else if(chuma_mode == 1)	{seg_disp(1,12);Delay2ms();}
			
			if(distance > 100)	seg_disp(5,distance/100);Delay2ms();
			if(distance > 10)	seg_disp(6,distance%100/10);Delay2ms();
			seg_disp(7,distance%10);Delay2ms();
		}
		else if(perl_mode == 2)//距离记录
		{
			seg_disp(0,14);Delay2ms();//H
			switch(jilu_mode)
			{
				case 0:	
					seg_disp(1,15);Delay2ms();
					if(dis_max > 100)	seg_disp(5,dis_max/100);Delay2ms();
					if(dis_max > 10)	seg_disp(6,dis_max%100/10);Delay2ms();
					seg_disp(7,dis_max%10);Delay2ms();
				break;
				
				case 1:	
					seg_disp(1,10);Delay2ms();
					if(dis_arr_10 > 1000)	seg_disp(4,dis_arr_10/1000);Delay2ms();
					if(dis_arr_10 > 100)	seg_disp(5,dis_arr_10%1000/100);Delay2ms();
					seg_disp_f(6,dis_arr_10%100/10);Delay2ms();
					seg_disp(7,dis_arr_10%10);Delay2ms();
				break;
				
				case 2:
					seg_disp(1,16);Delay2ms();
					if(dis_min > 100)	seg_disp(5,dis_min/100);Delay2ms();
					if(dis_min > 10)	seg_disp(6,dis_min%100/10);Delay2ms();
					seg_disp(7,dis_min%10);Delay2ms();
				break;
			}
		}
	}
	
	else if(disp_mode == 1)//参数
	{
		if(c_mode == 0)
		{
			seg_disp(0,17);Delay2ms();
			seg_disp(1,1);Delay2ms();
			seg_disp(6,time_c_sz[time_c_mode]/10);Delay2ms();
			seg_disp(7,time_c_sz[time_c_mode]%10);Delay2ms();
		}
		
		else if(c_mode == 1)
		{
			seg_disp(0,17);Delay2ms();
			seg_disp(1,2);Delay2ms();
			seg_disp(6,distance_c/10);Delay2ms();
			seg_disp(7,distance_c%10);Delay2ms();
		}
	}
}

void led_pro(void)
{
	P0 = 0xff;
	
	//Led1
	if((disp_mode == 0)&&(perl_mode == 0))	P0 = P0&(~led1);
	else	P0 = P0|(led1);
	
	//led2
	if((disp_mode == 0)&&(perl_mode == 1))	P0 = P0&(~led2);
	else	P0 = P0|(led2);
	
	//led3
	if((disp_mode == 0)&&(perl_mode == 2))	P0 = P0&(~led3);
	else	P0 = P0|(led3);
	
	//led4
	if(chuma_mode == 0)	P0 = P0&(~led4);
	else	P0 = P0|(led4);
	
	//led5
	if(led5_ok == 1)	P0 = P0&(~led5);
	else	P0 = P0|(led5);
	
	//Led6
	if(light_mode == 1)	P0 = P0&(~led6);
	else	P0 = P0|(led6);
	
	
	P2 = P2&0x1f|0x80;
	P2 = P2&0x1f;
}

void main(void)
{
	close_perl();
	Timer0Init();
	ds1302_init();
	dis_min = distance_get();//最小值先取一个值
	while(1)
	{
		key_pro();
		other_pro();
		seg_pro();
		led_pro();
	}
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值