第十届蓝桥杯决赛

目录

题目

考点

代码

主函数

iic

1、iic.c

2、iic.h

onewire

1、onewire.c

2、onewire.h

总结


题目

链接:https://pan.baidu.com/s/1YNoXIue8yaNIr1EJAL6N-g 
提取码:tucz 


考点

1、LED,矩阵按键,数码管

2、DAC,EEPROM

3、超声波测距

4、串口

5、测温

代码

主函数

#include <stc15f2k60s2.h>
#include "intrins.h"
#include "onewire.h"
#include "iic.h"
#include <stdio.h>
# include <string.h>
#define uchar unsigned char
#define uint unsigned int
#define semopon {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();}
sbit Buzzer = P0^6;
sbit Relay = P0^4;

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

/*************  本地常量声明    **************/
uchar code t_display[]={                       //标准字库
//   0    1    2    3    4    5    6    7    8    9    A    B    C    D    E    F
    0x3F,0x06,0x5B,0x4F,0x66,0x6D,0x7D,0x07,0x7F,0x6F,0x77,0x7C,0x39,0x5E,0x79,0x71,
//black  -     H    J    K    L    N    o   P    U     t    G    Q    r   M    y
    0x00,0x40,0x76,0x1E,0x70,0x38,0x37,0x5C,0x73,0x3E,0x78,0x3d,0x67,0x50,0x37,0x6e,
    0xBF,0x86,0xDB,0xCF,0xE6,0xED,0xFD,0x87,0xFF,0xEF,0x46};    //0. 1. 2. 3. 4. 5. 6. 7. 8. 9. -1

uchar code T_COM[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};      //位码
uchar table[]={16,16,16,16,16,16,16,16};

//按键
uchar ReadData,Trg,Cont,Keypress;
//长按与短按同时使用时
uchar key_up,key_12,key_13;
bit key_flag;
//指示灯
uchar LED;

//超声波
uint t,ucDist,Dist;//时间,距离
int dist_temp=35;//距离参数
bit dist_flag;
//功能
bit mode_falg=1;//0为数据界面,1为参数设置界面
uchar set_mode=0,set_mode_num=0;//set_mode为数据界面切换,set_mode_num为参数界面切换
float temp;//温度
int temp_num=30;//温度参数
uint num=0;//变更次数
bit temp_flag;
bit DAC_flag;//dac输出状态  0:启动 1:停止
uint cun[4]={30,35,30,35};//变量转换,保存有效值的

//串口
bit busy;
uchar rx_buf[30];
uchar rx_cnt=0;
bit rx_flag;
uchar rx_ideltime=0;//计时的

void vRxIdle_press();
//关闭外设
void allinit()
{
	P2=0xa0;Buzzer = 0;Relay = 0; P2=0x00;
	P2=0x80;P0=0xff;P2=0x00;
}


//指示灯
void Set_LED()
{
	P2=0x80;P0=~LED;P2=0x00;
}

void Timer5Init(void)		//1毫秒@12.000MHz
{
	AUXR |= 0x04;		//定时器时钟1T模式
	T2L = 0x20;		//设置定时初值
	T2H = 0xD1;		//设置定时初值
	AUXR |= 0x10;		//定时器2开始计时
	IE2  |= 0x04;    //允许中断           //定时器2必须写
}

void Timer() interrupt 12
{
	static uint smg_count,key_count,i,temp_count,dist_count;
	static int p=0,q=0;
	if(++smg_count>=2)
	{
		smg_count=0;
		P2=0xe0;P0=0xff;P2=0x00;
		P2=0xc0;P0=T_COM[i];P2=0x00;
		P2=0xe0;P0=~t_display[table[i]];P2=0x00;
		i++;
		if(i>=8)i=0;
	}
	if(++key_count>=10)//按键消抖
	{
		key_count=0;
		key_flag=1;
	}
	if(++temp_count>=200)//温度读取
	{
		temp_count=0;
		temp_flag=1;
	}
	if(++dist_count>=200)//距离读取
	{
		dist_count=0;
		dist_flag=1;
	}
	if(key_12&&!key_up)//s12长按
	{
		if(++p>=1000)
		{
			num=0;
			key_12=0;
			p=0;
		}
	}else{
		p=0;
	}
	if(key_13&&!key_up)//s13长按
	{
		if(++q>=1000)
		{
			DAC_flag=~DAC_flag;//dac停止
			key_13=0;
			q=0;
		}
	}else{
	q=0;
	}
	vRxIdle_press();//串口清除函数
}

//矩阵按键
void ReadKey()
{
	P3=0xf0;
	P44=P42=1;
	P37=P44;
	P36=P42;
	Keypress=P3;
	
	P3=0x0f;
	P44=P42=0;
	ReadData=(P3|Keypress)^0xff;
	Trg=ReadData&(ReadData^Cont);
	Cont=ReadData;
}

void disp_key()
{
	if(key_flag)
	{
		key_flag=0;
		Set_LED();
		ReadKey();
		if(Cont==0)key_up=1;
		if(Trg==0x28)//s12
		{
			key_up=0;
			key_12=1;
		}
		if(Trg==0x24)//s13
		{
			key_up=0;
			key_13=1;
		}
		if(key_12&&key_up)//s12短按
		{
			EA=0;
			Write_eeprom(0x18,num);
			EA=1;
			if(mode_falg==0){
				set_mode++;
				if(set_mode>=3)set_mode=0;
			}
			if(mode_falg==1)
			{
				set_mode_num++;
				if(set_mode_num>=2)set_mode_num=0;
			}
			key_12=0;
		}
		if(key_13&&key_up)//s13短按
		{
			mode_falg=~mode_falg;
			if(mode_falg==0)set_mode=0;
			if(mode_falg==1)set_mode_num=0;
			key_13=0;
		}
		if(Trg==0x18)//s16
		{
			if(mode_falg&&set_mode_num==0)
			{
				temp_num-=2;
				if(temp_num<0)temp_num=0;
			}
			if(mode_falg&&set_mode_num==1)
			{
				dist_temp-=5;
				if(dist_temp<0)dist_temp=0;
			}
		}
		if(Trg==0x14)//s17
		{
			if(mode_falg&&set_mode_num==0)
			{
				temp_num+=2;
				if(temp_num>98)temp_num=98;
			}
			if(mode_falg&&set_mode_num==1)
			{
				dist_temp+=5;
				if(dist_temp>95)dist_temp=95;
			}
		}
	}
}



//超声波
void Send_wavc()
{
	uchar i=8;
	do{
		TX=1;
		semopon;semopon;semopon;semopon;semopon;semopon;
		semopon;semopon;
		TX=0;
		semopon;semopon;semopon;semopon;semopon;semopon;
		semopon;semopon;
	}while(i--);
}

uint Read_DIST()
{
	if(dist_flag)
	{
		dist_flag=0;
		Send_wavc();
		TR0=1;
		while((RX==1)&&(TF0==0));
		TR0=0;
		if(TF0==1)
		{
			TF0=0;
			ucDist=49;//范围是10-50
		}else{
			t=TH0;
			t<<=8;
			t|=TL0;
			ucDist=(int)(t*0.017);
		}
		TH0=0;
		TL0=0;
	}
	return ucDist;
}

void disp_DAC()
{
	if(DAC_flag==0)//启动
	{
		if(Dist<=dist_temp)
		{
			Write_dac(102);//2v
		}else{
			Write_dac(204);//4v
		}
	}else{//停止
		Write_dac(20);//0.4v
	}
}

void disp_LED()
{
	if((temp/100)>=temp_num)
	{
		LED|=1;//L1亮
	}else{
		LED&=~1;//L1灭
	}
	if(Dist>=dist_temp)
	{
		LED|=2;//L2亮
	}else{
		LED&=~2;//L2灭
	}
	if(DAC_flag==0)
	{
		LED|=4;//L3亮
	}else{
		LED&=~4;//L3灭
	}
	LED&=~0xf8;
}
串口
void UartInit(void)		//4800bps@12.000MHz
{
	SCON = 0x50;		//8位数据,可变波特率
	AUXR |= 0x40;		//定时器1时钟为Fosc,即1T
	AUXR &= 0xFE;		//串口1选择定时器1为波特率发生器
	TMOD &= 0x0F;		//设定定时器1为16位自动重装方式
	TL1 = 0x8F;		//设定定时初值
	TH1 = 0xFD;		//设定定时初值
	ET1 = 0;		//禁止定时器1中断
	TR1 = 1;		//启动定时器1
	ES=1;
	EA=1;
}
//串口服务函数
void isr_uart() interrupt 4
{
	if(RI)
	{
		RI=0;
		rx_ideltime=0;
		rx_buf[rx_cnt++]=SBUF;
		if(rx_buf[rx_cnt-1] == '\n')
		{
			rx_cnt=0;
			rx_flag=1;
		}
	}
	if(TI)
	{
		TI=0;
		busy=0;
	}
}

//串口接收空闲时间计时
void vRxIdle_press()
{
	rx_ideltime++;
	if(rx_ideltime>=50)
	{
		rx_ideltime=0;
		rx_cnt=0;
		memset(rx_buf,'\0',sizeof(rx_buf));
	}

}
//串口发送数据
void SendData(uchar dat)
{
	while(busy);
	busy=1;
	SBUF=dat;
}

//发送字符串
void SendString(char *s)
{
	while(*s)
	{
		SendData(*s++);
	}
}
//串口发送和接收
void vUartRX_press()
{
	if(rx_flag)
	{
		rx_flag=0;
		if(rx_buf[0]=='S' && rx_buf[1]=='T' && rx_buf[2]=='\r')
		{
			SendData('$');SendData(Dist/10+'0');SendData(Dist%10+'0');SendData(',');
			SendData((int)temp/1000+'0');SendData((int)temp/100%10+'0');SendData('.');
			SendData((int)temp/10%10+'0');SendData((int)temp%10+'0');
			SendString("\r\n");
		}
		else if(rx_buf[0]=='P' && rx_buf[1]=='A' && rx_buf[2]=='R' && rx_buf[3]=='A' && rx_buf[4]=='\r')
		{
			SendData('#');SendData(temp_num/10+'0');SendData(temp_num%10+'0');SendData(',');
			SendData(dist_temp/10+'0');SendData(dist_temp%10+'0');
			SendString("\r\n");
		}
		else
		{
			SendString("ERROR\r\n");
		}
	}
}


//主函数
void main()
{
	allinit();
	UartInit();
	Timer5Init();
	num=Read_eeprom(0x18);
	while((int)(Read_Temp()*0.0625)==85);
	while(1)
	{
		if(temp_flag)
		{
			temp_flag=0;
			//EA=0;
			temp=Read_Temp()*0.0625*100;
			//EA=1;
		}
		Dist=Read_DIST();
		if(mode_falg==0)
		{
			cun[2]=temp_num;
			cun[3]=dist_temp;
			if(cun[0]!=cun[2]||cun[1]!=cun[3])
			{
				num++;
				if(num>=65536)num=65536;
				cun[0]=cun[2];
				cun[1]=cun[3];
			}
		}
		if(mode_falg==0)//数据界面
		{
			switch(set_mode)
			{
				case 0://温度
					table[0]=12;table[1]=16;
					table[2]=16;table[3]=16;
					table[4]=(int)temp/1000;table[5]=(int)temp/100%10+32;
					table[6]=(int)temp/10%10;table[7]=(int)temp%10;	
				break;
				case 1://距离
					table[0]=21;table[1]=16;
					table[2]=16;table[3]=16;
					table[4]=16;table[5]=16;
					table[6]=Dist/10;table[7]=Dist%10;	
				break;
				case 2://变更次数
					table[0]=28;table[1]=16;
					table[2]=16;
					table[3]=(num>=10000)?num/10000:16;
					table[4]=(num>=1000)?num/1000%10:16;
					table[5]=(num>=100)?num/100%10:16;
					table[6]=(num>=10)?num/10%10:16;
					table[7]=num%10;
				break;
			}
		}
		else{//参数设置界面
			switch(set_mode_num)
			{
				case 0://温度
					table[0]=24;table[1]=16;
					table[2]=16;table[3]=1;
					table[4]=16;table[5]=16;
					table[6]=temp_num/10;table[7]=temp_num%10;	
				break;
				case 1://距离
					table[0]=24;table[1]=16;
					table[2]=16;table[3]=2;
					table[4]=16;table[5]=16;
					table[6]=dist_temp/10;table[7]=dist_temp%10;	
				break;
			}
		}
		vUartRX_press();//串口
		disp_LED();//灯
		disp_DAC();//dac
		disp_key();//按键
	}
}

iic

1、iic.c

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

#include "reg52.h"
#include "intrins.h"

#define DELAY_TIME 5

#define SlaveAddrW 0xA0
#define SlaveAddrR 0xA1

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

void IIC_Delay(unsigned char i)
{
    do{_nop_();}
    while(i--);        
}
//总线启动条件
void IIC_Start(void)
{
    SDA = 1;
    SCL = 1;
    IIC_Delay(DELAY_TIME);
    SDA = 0;
    IIC_Delay(DELAY_TIME);
    SCL = 0;	
}

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

//等待应答
bit IIC_WaitAck(void)
{
    bit ackbit;
	
    SCL  = 1;
    IIC_Delay(DELAY_TIME);
    ackbit = SDA;
    SCL = 0;
    IIC_Delay(DELAY_TIME);
    return ackbit;
}

//通过I2C总线发送数据
void IIC_SendByte(unsigned char byt)
{
    unsigned char i;

    for(i=0; i<8; i++)
    {
        SCL  = 0;
        IIC_Delay(DELAY_TIME);
        if(byt & 0x80) SDA  = 1;
        else SDA  = 0;
        IIC_Delay(DELAY_TIME);
        SCL = 1;
        byt <<= 1;
        IIC_Delay(DELAY_TIME);
    }
    SCL  = 0;  
}

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

//eeprom
void Write_eeprom(unsigned char add,unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

unsigned char Read_eeprom(unsigned char add)
{
	unsigned char temp;
	IIC_Start();
	IIC_SendByte(0xa0);
	IIC_WaitAck();
	IIC_SendByte(add);
	IIC_WaitAck();
	
	IIC_Start();
	IIC_SendByte(0xa1);
	IIC_WaitAck();
	temp=IIC_RecByte();
	IIC_WaitAck();
	IIC_Stop();
	
	return temp;
}

//DAC
void Write_dac(unsigned char dat)
{
	IIC_Start();
	IIC_SendByte(0x90);
	IIC_WaitAck();
	IIC_SendByte(0x40);
	IIC_WaitAck();
	IIC_SendByte(dat);
	IIC_WaitAck();
	IIC_Stop();
}

2、iic.h

#ifndef _IIC_H
#define _IIC_H

void IIC_Start(void); 
void IIC_Stop(void);  
bit IIC_WaitAck(void);  
void IIC_SendByte(unsigned char byt); 
unsigned char IIC_RecByte(void); 

//eeprom
void Write_eeprom(unsigned char add,unsigned char dat);
unsigned char Read_eeprom(unsigned char add);
//DAC
void Write_dac(unsigned char dat);
#endif

onewire

1、onewire.c

/*
  程序说明: 单总线驱动程序
  软件环境: Keil uVision 4.10 
  硬件环境: CT107单片机综合实训平台(外部晶振12MHz) STC89C52RC单片机
  日    期: 2011-8-9
*/
#include "reg52.h"

sbit DQ = P1^4;  //单总线接口

//单总线延时函数
void Delay_OneWire(unsigned int t)  //STC89C52RC
{
	t=t*10;
	while(t--);
}

//通过单总线向DS18B20写一个字节
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);
}

//从DS18B20读取一个字节
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;
}

//DS18B20设备初始化
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;
}

//读取温度
int Read_Temp()
{
	unsigned char low,high;
	int temp;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	low=Read_DS18B20();
	high=Read_DS18B20();
	
	temp=(high<<8|low);
	return temp;
}

2、onewire.h

#ifndef __ONEWIRE_H
#define __ONEWIRE_H

unsigned char rd_temperature(void);  //
//读取温度
int Read_Temp();
#endif

总结

        串口恶心得一批,不过以后遇到应该能解决了!!!

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
第十届蓝桥杯人物相关性题目是一道经典的编程问题,要求我们在给定的人物关系图中,判断两个人物之间是否存在一条关系链,即判断两个人物是否直接或间接地相关。 在这道题目中,我们可以使用图的搜索算法来解决问题。一种常见的算法是深度优先搜索(DFS),另一种是广度优先搜索(BFS)。 大概的思路是:首先,我们需要构建人物关系图,可以通过邻接矩阵、邻接表等数据结构来存储图的信息。然后,我们选择一个起始节点,从该节点开始进行搜索。如果在搜索的过程中找到了目标节点,即两个人物之间存在直接关系,那么我们可以结束搜索并返回结果。如果没有找到目标节点,则需要继续深入搜索,或者在广度搜索中扩展搜索队列。如果最终搜索完整个图都没有找到目标节点,那么可以判定两个人物之间不存在关系链。 具体实现时,可以使用递归或者栈来实现DFS,使用队列来实现BFS。在DFS中,我们可以利用函数的递归调用来实现深度搜索;在BFS中,我们可以通过队列不断地将待搜索节点加入队列,实现广度搜索。 总的来说,第十届蓝桥杯人物相关性题目考察了对图的数据结构和搜索算法的掌握程度。需要我们理解并实现图的构建和搜索过程,进而判断两个人物之间的相关性。这道题目不仅考察了编程基础知识,也锻炼了问题分析和解决能力,是一道非常有挑战性的编程题目。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值