第四届蓝桥杯单片机国赛试题及程序

本人参加了第十届蓝桥杯单片机国赛,现在把做过的练习发给大家参考一下。

设计一超声波测距报警实时时钟电路

电路具体功能要求:

  1. 电路通电后进入初始化状态:灯 L1 亮,数码管全亮,蜂鸣器接通,1s 后全部

关闭,显示时间设定 11-50-59。

  1. 按下 S7 按键切换显示实时时钟 XX-XX-XX、显示超声波测量距离 XXX。

  2. 显示实时时钟状态下,按 S6 按键进行时间调整,第一次按下 S6 进入时调整,

“时”闪烁;第二次按下 S6 进入分调整,“分”闪烁。再一次按下退出调整。

S4、S5 为调节数值 S5+,S4-(时间距离)的加减按键。

  1. 显示超声波测距状态下,按 S6 按键进行报警距离调整,S6 按第一次进入调

整状态,第二次按下退出,将调节后的数值保存到 24C02 中。S4、S5 为调节数

值 S5+,S4-(时间距离)的加按键。显示超声波报警距离–XXX。

  1. 超声波测距报警初值设定为 30cm,超声波检测超过设定值 X 不报警,小于 X

立即报警,小于 1.2 倍的 X, L1 灯闪烁。

  1. 设计一个欠压电路,12V 供电,电压小于 10V 切断电路电源。

#include<stc15f2k60s2.h>
#include<intrins.h>
#include<ds1302.h>
#include<iic.h>

#define somenop {nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();nop();}
#define u8 unsigned char
u8 code smg_duan[]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x00,0x40};
u8 code smg_wei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};

sbit buzzer=P0^6;
sbit relay= P0^4;

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

#define KEY P3
#define NO_KEY 0xff
#define KEY_STATE0 0
#define KEY_STATE1 1
#define KEY_STATE2 2

u8 xian_shi[8];
u8 mo_si=1,shi_zhong;

void send_wave()
{

	TX=1;
	somenop;somenop;somenop;somenop;somenop;
	somenop;somenop;somenop;somenop;somenop;
	TX=0;

}

void Delay2ms() //@11.0592MHz
{

  unsigned char i, j;
_nop_();
_nop_();
i = 22;
j = 128;
do
{
	while (--j);
} while (--i);

}

u8 key_scan()
{
static unsigned char key_state=KEY_STATE0;
u8 key_value=0,key_temp;
u8 key1,key2;
P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;
if(P440) key1=0x70;
if(P42
0) key1=0xb0;
if(P350) key1=0xd0;
if(P34
0) key1=0xe0;
if((P341)&&(P351)&&(P421)&&(P441)) key1=0xf0;
P30=1;P31=1;P32=1;P33=1;P34=0;P35=0;P42=0;P44=0;
if(P300) key2=0x0e;
if(P31
0) key2=0x0d;
if(P320) key2=0x0b;
if(P33
0) key2=0x07;
if((P301)&&(P311)&&(P321)&&(P331)) key2=0x0f;
key_temp=key1|key2;
switch(key_state)
{

	case KEY_STATE0:
	if(key_temp!=NO_KEY)
	{
		key_state=KEY_STATE1;
	}
	break;
	case KEY_STATE1:
	if(key_temp==NO_KEY)
	{
		key_state=KEY_STATE0;
	}
	else
	{
		switch(key_temp)
		{
			case 0x77:key_value=4 ;break;
			case 0x7b:key_value=5 ;break;
			case 0x7d:key_value=6 ;break;
			case 0x7e:key_value=7 ;break;
			case 0xb7:key_value=8 ;break;
			case 0xbb:key_value=9 ;break;
			case 0xbd:key_value=10;break;
			case 0xbe:key_value=11;break;
			case 0xd7:key_value=12;break;
			case 0xdb:key_value=13;break;
			case 0xdd:key_value=14;break;
			case 0xde:key_value=15;break;
			case 0xe7:key_value=16;break;
			case 0xeb:key_value=17;break;
			case 0xed:key_value=18;break;
			case 0xee:key_value=19;break; 
		}
		key_state=KEY_STATE2;
	}
	break;
	case KEY_STATE2:
	if(key_temp==NO_KEY)
	{
		key_state=KEY_STATE0;
	}
	break;
}
return key_value;

}

void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;

_nop_();
_nop_();
i = 43;
j = 6;
k = 203;
do
{
	do
	{
		while (--k);
	} while (--j);
} while (--i);

}

void Timer0Init(void) //1毫秒@11.0592MHz
{

AUXR |= 0x80;		//定时器时钟1T模式
TMOD &= 0xF0;		//设置定时器模式
TL0 = 0xCD;		//设置定时初值
TH0 = 0xD4;		//设置定时初值
TF0 = 0;		//清除TF0标志
TR0 = 1;		//定时器0开始计时
ET0 = 1;
EA = 1;

}

void Time1Init()//1ms
{

AUXR&=0xbf;
TMOD&=0xbf;
TL1=0x00;
TH1=0x00;
TF1=0;
TR1=0;

}

bit key_flag,sonic_flag=0,shan_shuo=0;
void main()
{

unsigned int t,distance;
u8 shi,fen,miao,shi_1,fen_1,miao_1,shi_zhong=0;  
u8 csb_set=30,csb_mo_si=0;     //超声波正常工作 0    超声波设置距离  1
u8 key_val = NO_KEY;
csb_set=Read_24C02(0x01);

P2 = 0X80;    //初始化要求
P0 = 0X00; 
P2=0XA0;
buzzer =1;
Delay1000ms();
P2 = 0X80;
P0=0XFF;
P2=0XA0;
buzzer =0;
P2 = 0X00;


Timer0Init();
Time1Init();
set_sfm(11,50,59);
while(1)
{	
if(key_flag == 1)
{
	 key_flag = 0;
   key_val = key_scan();
	

	
	 switch(key_val)
	 {
		 case 4: 
			 if(mo_si==1)   //时钟调整模式
			 {
				if(shi_zhong==3)
				{
					if(shi_1==0)
					shi_1=24;
					shi_1--;
				}
				if(shi_zhong==2)
				{
					
					if(fen_1==0)
					fen=60;
					fen_1--;
				}
				if(shi_zhong==1)
				{
						
							if(miao_1==0)
							miao_1=60;
							miao_1--;
						}
			}
			 
			 if(mo_si==0)   //超声波调整模式
			{
			   csb_set--;
				Write_24C02(0x01,csb_set); 			
			}
		 break;
		 case 5:  
			 if(mo_si==1)   //时钟调整模式
	   {
			if(shi_zhong==3)
				{
					shi_1++;
					if(shi_1>23)
					shi_1=0;
				}
				if(shi_zhong==2)
				{
					fen_1++;
					if(fen_1>59)
					fen_1=0;
				}
				if(shi_zhong==1)
				{
					miao_1++;
					if(miao_1>59 )
					miao_1=0;
				}
			}
		 
	    if(mo_si==0)   //超声波调整模式
			{
			   csb_set++;
				Write_24C02(0x01,csb_set); 
								
			}
		 break;
		 case 6:   
			if(mo_si==1)   //位切换
		 {
		   shi_zhong++;
			 if(shi_zhong>=4)
				 shi_zhong=0;
		 }
		 if(mo_si==0)   //超声波模式切换
		 {
		    csb_mo_si++;
			 if(csb_mo_si>=2)
			 {
			    csb_mo_si=0;
			 }
			 
		 }
		 
		 break;
		 case 7:     //时钟  超声波  切换
	    mo_si++;
			if(mo_si>=2)
				mo_si=0;
		
		
		 break;
		
	 }
	 
	 
 }
  if(shi_zhong!=0&&mo_si==1)   //时钟显示
	{
		if(shi_zhong==1&&shan_shuo==1)
		{
			xian_shi[0]=10;
			xian_shi[1]=10;	
		}
		else
		{
			xian_shi[0]=shi_1/10;
			xian_shi[1]=shi_1%10;
		}			
		xian_shi[2]=11;
		if(shi_zhong==2&&shan_shuo==1)
		{
		   xian_shi[3]=10;
		   xian_shi[4]=10;	
		}
		else
		{
			xian_shi[3]=fen_1/10;
			xian_shi[4]=fen_1%10;	
		}
		xian_shi[5]=11;
		if(shi_zhong==3&&shan_shuo==1)
		{
			xian_shi[6]=10;
			xian_shi[7]=10;	
		}
		else
		{
			xian_shi[6]=miao_1/10;
			xian_shi[7]=miao_1%10;		
		}
		 
		if(shi_zhong==3)
		set_sfm(shi_1,fen_1,miao_1);		//写入自己的时分秒
	}
 if(mo_si==1&&shi_zhong==0)
 {
		ET0=0;
		shi=Ds1302_Single_Byte_Read(ds1302_hr_addr);   //现实时分秒
		fen=Ds1302_Single_Byte_Read(ds1302_min_addr);
		miao=Ds1302_Single_Byte_Read(ds1302_sec_addr);
		ET0=1;		
  shi_1=shi/16*10+shi%16;    //存储现在的时分秒用来调节
		fen_1=fen/16*10+fen%16;
		miao_1=miao/16*10+miao%16;	
		xian_shi[0]=shi/16;
		xian_shi[1]=shi%16;
		xian_shi[2]=11;
		xian_shi[3]=fen/16;
		xian_shi[4]=fen%16;
		xian_shi[5]=11;
		xian_shi[6]=miao/16;
		xian_shi[7]=miao%16;
	 
 }
 if(mo_si==0&&csb_mo_si==0)  //超声波测距
 {  
		sonic_flag=0;
		send_wave();
		TR1=1;
		while((RX==1)&&(TF1==0));
		TR1=0;
		if(TF1==1)
		{
			TF1=0;
			distance=999;
		}
		else
		{
			t=TH1;
			t<<=8;
			t|=TL1;
			distance=(unsigned int)(t*0.017);	
		}
		TH1=0;
		TL1=0;
	
    xian_shi[0]=10;
		xian_shi[1]=10;
		xian_shi[2]=10;
		xian_shi[3]=10;
		xian_shi[4]=10;
	  xian_shi[5]=distance/100;
		xian_shi[6]=distance%100/10;
		xian_shi[7]=distance%10;
		Delay2ms()	;
		Delay2ms()	;
		Delay2ms()	;
		Delay2ms()	;
		if(distance<csb_set*1.2)    //距离小于警告值
		{
			if(shan_shuo==1)
		  P2=0X80;P0=0X7F;P2=0X00;	  //led
		
			if(shan_shuo==0)
		  P2=0X80;P0=0XfF;P2=0X00;	
		}
		if(distance>csb_set*1.2)    //距离大于警告值
		{		
		  P2=0X80;P0=0XfF;P2=0X00;			   
		}
		
		if(distance<=csb_set)     //距离小于警告值
		{		
		  P2=0XA0;buzzer=1;relay=0;P2=0X00;//蜂鸣器 继电器
		}
		if(distance>csb_set)  //距离大于警告值
		{		
		  P2=0XA0;buzzer=0;relay=0;P2=0X00;		 //蜂鸣器 继电器
		}
		
		
 }

  if(mo_si==0&&csb_mo_si==1)
	{
	  
	  xian_shi[0]=10;
		xian_shi[1]=10;
		xian_shi[2]=10;
		xian_shi[3]=10;
		xian_shi[4]=10;
	  xian_shi[5]=csb_set/100;
		xian_shi[6]=csb_set%100/10;
		xian_shi[7]=csb_set%10;
	
	
	}

}
}

void Timer0() interrupt 1 using 1
{
static unsigned int key_count = 0,sing_count = 0,i = 0,shan_count=0;
key_count++;
sing_count++;

if(key_count == 10)    //键盘扫描
{
	key_count = 0;
	key_flag = 1;
}

 
if(sing_count == 3)   //数码管显示
{
	sing_count = 0;
	P2 = 0xc0; P0 = 0X00; P2=0X00;
	
  P2 = 0xE0; P0 =~smg_duan[xian_shi[i]]; P2=0X00;
	
	P2 = 0xc0; P0 = smg_wei[i]; P2=0X00;

	i++;
	if(i == 8)
		i = 0;
}

	shan_count++;    //数码管闪烁
	if(shan_count>1000)
	{
		  shan_count=0;
	  	shan_shuo=~shan_shuo;
	}

}

这是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;
}

//应答位控制
void IIC_Ack(unsigned char ackbit)
{
if(ackbit)
{
SDA = 0;
}
else
{
SDA = 1;
}
somenop;
SCL = 1;
somenop;
SCL = 0;
SDA = 1;
somenop;
}

//等待应答
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;

}

unsigned char Read_24C02(unsigned char addr) //24c02的读
{
unsigned char tmp;

IIC_Start();					
IIC_SendByte(0xa0); 		
IIC_WaitAck();					
IIC_SendByte(addr); 		
IIC_WaitAck(); 					

IIC_Start();						
IIC_SendByte(0xa1); 		
IIC_WaitAck();				
tmp = IIC_RecByte();		
IIC_Ack(0); 						
IIC_Stop();							
return tmp;

}

void Write_24C02(unsigned char addr, unsigned char dat) //24c02的写
{
IIC_Start();
IIC_SendByte(0xa0);
IIC_WaitAck();
IIC_SendByte(addr);
IIC_WaitAck();
IIC_SendByte(dat);
IIC_WaitAck();
IIC_Stop();
}

unsigned char read_adc(unsigned char add) //电位器或者光敏电阻
{
unsigned char temp;
IIC_Start();
IIC_SendByte(0x90);
IIC_WaitAck();
IIC_SendByte(add);
IIC_WaitAck();
IIC_Start();
IIC_SendByte(0x91);
IIC_WaitAck();
temp=IIC_RecByte();
IIC_WaitAck();
IIC_Stop();
return temp;
}

这是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();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);
unsigned char Read_24C02(unsigned char addr);
void Write_24C02(unsigned char addr, unsigned char dat);
unsigned char read_adc(unsigned char add);
void write_adc(unsigned char add);

bit IIC_WaitAck(void);
unsigned char IIC_RecByte(void);

#endif

这是ds1302的c文件
#include “ds1302.h”
//
/单字节写入一字节数据/
void Write_Ds1302_Byte(unsigned char dat)
{
unsigned char i;
SCK = 0;
for (i=0;i<8;i++)
{
if (dat & 0x01) // 等价于if((addr & 0x01) ==1)
{
SDA_SET; //#define SDA_SET SDA=1 /电平置高/
}
else
{
SDA_CLR; //#define SDA_CLR SDA=0 /电平置低/
}
SCK_SET;
SCK_CLR;
dat = dat >> 1;
}
}
/
/
/单字节读出一字节数据/
unsigned char Read_Ds1302_Byte(void)
{
unsigned char i, dat=0;
for (i=0;i<8;i++)
{
dat = dat >> 1;
if (SDA_R) //等价于if(SDA_R==1) #define SDA_R SDA /电平读取/
{
dat |= 0x80;
}
else
{
dat &= 0x7F;
}
SCK_SET;
SCK_CLR;
}
return dat;
}

/********************************************************************/
/向DS1302 单字节写入一字节数据/
void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat)
{

RST_CLR;			/*RST脚置低,实现DS1302的初始化*/
SCK_CLR;			/*SCK脚置低,实现DS1302的初始化*/

RST_SET;			/*启动DS1302总线,RST=1电平置高 */
addr = addr & 0xFE;	 
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是写操作,写之前将最低位置零*/	
Write_Ds1302_Byte(dat);	 /*写入数据:dat*/
RST_CLR;				 /*停止DS1302总线*/

}

/********************************************************************/
/从DS1302单字节读出一字节数据/
unsigned char Ds1302_Single_Byte_Read(unsigned char addr)
{
unsigned char temp;
RST_CLR; /RST脚置低,实现DS1302的初始化/
SCK_CLR; /SCK脚置低,实现DS1302的初始化/

RST_SET;	/*启动DS1302总线,RST=1电平置高 */	
addr = addr | 0x01;	 
Write_Ds1302_Byte(addr); /*写入目标地址:addr,保证是读操作,写之前将最低位置高*/
temp=Read_Ds1302_Byte(); /*从DS1302中读出一个字节的数据*/		
RST_CLR;		   /*停止DS1302总线*/
SDA_CLR; 		//xiu gai   fei chang zhong yao

return temp;

}

void set_sfm(char shi,char fen,char miao)
{
Ds1302_Single_Byte_Write(0x8e,0); //关闭写保护
Ds1302_Single_Byte_Write(0x80,(miao/10)*16+miao%10); //以BCD码写入秒数据
Ds1302_Single_Byte_Write(0x82,(fen/10)*16+fen%10); //以BCD码写入分数据
Ds1302_Single_Byte_Write(0x84,(shi/10)*16+shi%10); //以BCD码写入时数据
Ds1302_Single_Byte_Write(0x8e,0x80); //打开写保护
}

这是ds1302的h文件
#ifndef DS1302_H
#define DS1302_H

#include<stc15f2k60s2.h>
#include<intrins.h>
//
sbit SCK=P1^7;
sbit SD=P2^3;
sbit RST=P1^3;
/
/
/复位脚/
#define RST_CLR RST=0 /电平置低/
#define RST_SET RST=1 /电平置高/
/双向数据/
#define SDA_CLR SD=0 /电平置低/
#define SDA_SET SD=1 /电平置高/
#define SDA_R SD /电平读取/
/时钟信号/
#define SCK_CLR SCK=0 /时钟信号/
#define SCK_SET SCK=1 /电平置高/
/********************************************************************/
#define ds1302_sec_addr 0x80 //秒数据地址
#define ds1302_min_addr 0x82 //分数据地址
#define ds1302_hr_addr 0x84 //时数据地址
#define ds1302_date_addr 0x86 //日数据地址
#define ds1302_month_addr 0x88 //月数据地址
#define ds1302_day_addr 0x8A //星期数据地址
#define ds1302_year_addr 0x8C //年数据地址

#define ds1302_control_addr 0x8Ee //写保护命令字单元地址
#define ds1302_charger_addr 0x90 //涓电流充电命令字地址
#define ds1302_clkburst_addr 0xBE //日历、时钟突发模式命令字地址
/********************************************************************/

/********************************************************************/

单字节写入一字节数据*/
extern void Write_Ds1302_Byte(unsigned char dat);
/********************************************************************/
/单字节读出一字节数据/
extern unsigned char Read_Ds1302_Byte(void);

//
/
/
/向DS1302单字节写入一字节数据/
extern void Ds1302_Single_Byte_Write(unsigned char addr, unsigned char dat);
/********************************************************************/
/从DS1302单字节读出一字节数据/
extern unsigned char Ds1302_Single_Byte_Read(unsigned char addr);
extern void set_sfm(char shi,char fen,char miao);

#endif
//
//       END FILE
/
/

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 历蓝桥杯单片机国赛题目的pdf文件包含了多年来比赛的题目,对于参赛者来说非常有价值。这些题目主要涉及单片机的应用,包括各种实际问题的解决方案设计和实现。 蓝桥杯单片机国赛的题目非常好,具有一定的难度和挑战性。在这些题目中,可以看出组织者对参赛者的考察点,如编程基础、算法设计、电路原理和PCB设计等方面的能力要求。 这些题目的难度和要求因年份而异。一些题目可能要求参赛者按照给定的要求,设计和实现具体的功能,比如控制器的编程和接口的设计。还有一些题目则更注重算法的设计和优化,要求参赛者解决一些实际问题,如传感器数据采集和处理、自动控制系统设计等。 参赛者可以通过阅读历蓝桥杯单片机国赛题目的pdf,了解以往比赛的题目类型和要求。同时,可以从中学习其他选手的优秀作品,借鉴他们的思路和方法,不断提高自己的编程水平和解决问题的能力。 总的来说,历蓝桥杯单片机国赛题目pdf是参赛者备战比赛的重要资料,通过认真研读和思考这些题目,可以帮助参赛者更好地了解比赛的要求和考察点,为自己的比赛表现做好准备。同时,也可以通过学习其他选手的优秀作品,借鉴他们的经验和方法,提升自己的编程和设计能力。 ### 回答2: 历蓝桥杯单片机国赛题目pdf经过多年的发展和举办,已经形成了一套完整的题库。这些pdf文件收录了每年蓝桥杯单片机国赛的题目,包括初赛和决赛的所有题目。通过这些pdf文件,参赛选手可以了解到历年比赛中的难度和类型,为他们的备战提供了很好的参考。 每年的比赛题目都由蓝桥杯组委会精心设计,力求在知识点的全面性和难度上有所考量。题目内容通常包括单片机基础知识、电路设计、编程能力等方面的要求。比赛题目除了要求选手具备一定的硬件和软件实验能力外,还要求选手具备良好的分析和解决问题的能力。 通过历蓝桥杯单片机国赛题目pdf的学习,可以帮助选手更好地了解比赛要求,熟悉比赛形式和题型,提高应对复杂问题的能力。同时,这些题目也对教育者具有一定的参考价值,可以作为培训学生的教材和示例。 总之,历蓝桥杯单片机国赛题目pdf对于参赛选手和教育者来说都是非常有价值的资源。通过对这些题目的学习和分析,可以更好地为比赛做好准备,并提高自身的技能水平。希望未来蓝桥杯单片机国赛题目pdf会进一步完善,为单片机爱好者提供更好更全面的支持。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值