第十四届蓝桥杯单片机组(赛题+程序)

第十四届蓝桥杯单片机组(赛题+程序)

该赛题考于2023.4.8 ,于2023.4.28 复盘。

今年的题目是比较难的了,模块多,而且逻辑也更加复杂,考了NE555、I2C、DS1302、DS18B20,同时客观题也不好做。
笔者客观题只对3个,程序题大概完成80%,勉强进入省一。

第十四届蓝桥杯单片机组(赛题+程序)_第1张图片

一、赛题 

1.客观题

第十四届蓝桥杯单片机组(赛题+程序)_第2张图片

 答案: 1.D    2.B   3.ABC   4.D   5.A    6.AC   7.A   8.B   9.D   10.ABD

 2.程序题

第十四届蓝桥杯单片机组(赛题+程序)_第3张图片

 二、程序

1.main.c

/* ***************************
 
	第十四届蓝桥杯单片机组程序
	                           by wull
	                           2023.4.28
**************************** */

#include "STC15.h"
#include "iic.h"
#include "onewire.h"
#include "ds1302.h"
#include "intrins.h"

#define uchar unsigned char
#define uint unsigned int
	
code unsigned char Seg_Table[] =   
{
0xc0, //0
0xf9, //1
0xa4, //2
0xb0, //3
0x99, //4
0x92, //5
0x82, //6
0xf8, //7
0x80, //8
0x90, //9
0x88, //A
0x83, //b
0xc6, //C
0xa1, //d
0x86, //E
0x8e, //F   15
0xff, //灭  16
0xbf, //-   17               10111111
0x89, //H   18               10001001
0x8c  //P   19               10001100
}; 
//********************温湿度采集数据记录变量************** 

uchar xdata temper_caiji[100]={0};         // 温度存放
uchar temper_max;                          // 温度最大值
long int temper_sum=0;                     // 温度总和
float temper_ave;                          // 温度平均值(浮点数)
uint temper_aver;                          // 温度平均值(整数)
uchar xdata shidu_caiji[100]={0};         // 湿度存放
uchar shidu_max;                          // 湿度最大值
long int shidu_sum=0;                     // 湿度总和
float shidu_ave;                          // 湿度平均值(浮点数)
uint shidu_aver;                          // 湿度平均值(整数)

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

uchar dspcom=0;                             // 数码管位选标志位
uchar dspbuff[8]={16,16,16,16,16,16,16,16}; // 8个数码管
uchar now[7]={0};                           // 时间的 时分秒存放
uchar ad_value;                             // 光敏电阻电压
uint v_value;                               // 光敏电阻电压*10
uchar temper,Shidu,Canshu=30,Chufa=0;       // 温度,湿度,参数,触发值
uchar Jiemian=1,Huixian=1;                  // 界面切换值,回显界面切换值
uint count_t=0,intr=0,intr1=0,intr2=0;      // 计数变量
uint count_f;                               // 频率计数 
uint dat_f;                                 // 频率值
bit F_key = 0,Lightstate;    						    // 按键按下标志
uint keycount= 0;				                    // 按键计数变量

bit flag,flag1,flag2;                       // 标志位


//***********************初始化**************************

void InitAll()      // 初始化 关闭LED 蜂鸣器等
{
	P2=(P2&0x1f)|0xa0;
	P0=0x00;
	P2=(P2&0x1f)|0x80;
	P0=0xff;
	P2=(P2&0x1f);
}

void Timer0_Init(void)		 // 定时器1 计数
{

	TMOD = 0x1F;			//设置定时器模式
	TL0 = 0xff;				//设置定时初始值
	TH0 = 0xff;				//设置定时初始值
	TR0 = 1;				//定时器1开始计时
	
	ET0=1;
	EA=1;
}

void Timer1_Init(void)		//2毫秒@12.000MHz     // 定时器2 定时2ms
{
	AUXR &= 0xBF;			//定时器时钟12T模式
	TMOD &= 0x0F;			//设置定时器模式
	TL1 = 0x30;				//设置定时初始值
	TH1 = 0xF8;				//设置定时初始值
	TF1 = 0;				//清除TF1标志
	TR1 = 1;				//定时器1开始计时
	
	ET1=1;
	EA=1;
}

void DisplaySMG()                //数码管显示 位选+段选
{
	P2=(P2&0x1f)|0xe0;
	P0=0xff;
	
	P2=(P2&0x1f)|0xc0;
	P0=1<999999) dspbuff[1]=dat_f/1000000;
//	else dspbuff[1]=19;
//	if(dat_f>99999) dspbuff[2]=dat_f/100000%10;
//	else dspbuff[2]=19;
//	if(dat_f>9999) dspbuff[3]=dat_f/10000%10;
//	else dspbuff[3]=19;
//	if(dat_f>999) dspbuff[4]=dat_f/1000%10;
//	else dspbuff[4]=19;
//	if(dat_f>99) dspbuff[5]=dat_f/100%10;
//	else dspbuff[5]=19;
//	if(dat_f>9) dspbuff[6]=dat_f/10%10;
//	else dspbuff[6]=19;
//	dspbuff[7]=dat_f%10;

//	dspbuff[5]=v_value/100;
//	dspbuff[6]=v_value/10%10;
//	dspbuff[7]=v_value%10;
}

void Display4()               // 温湿度界面
{
  dspbuff[0]=14;
	dspbuff[1]=16;dspbuff[2]=16;
	dspbuff[3]=temper/10;
	dspbuff[4]=temper%10;
	dspbuff[5]=17;
	if((Shidu>10)&&(Shidu<90))
	{
		dspbuff[6]=Shidu/10;
	  dspbuff[7]=Shidu%10;
	}
	else 
	{
		dspbuff[6]=10;
	  dspbuff[7]=10;
	}
}

void DisplayLED()        // LED指示灯功能
{
	P2=(P2&0x1f)|0x80;
	if(Jiemian==1) P00=0;       // LED1亮
	 else P00=1;
	if(Jiemian==2) P01=0;       // LED2亮
	 else P01=1;
	if(Jiemian==3) P02=0;       // LED3亮
	 else P02=1;
	if(temper>Canshu)
	{
		if(intr1<50) P03=0;       // LED4闪烁
		 else P03=1;
	}
	 else P03=1;
	if((Shidu>10)&&(Shidu<90))
	{
		P04=1;          
	}
	else 
	{
		P04=0;                    // LED5亮
	}
	if(Chufa>=2)    
	{
		if((temper_caiji[Chufa]50)
	{
		Lightstate=1;              //亮状态
	}

	if(Lightstate==1)
	{
		if(v_value<50)
		{
			Lightstate=0; 
      Chufa++;                            //触发值+1
			temper_caiji[Chufa-1]=temper;       //温度值采集
			if((Shidu>10)&&(Shidu<90))
	    {
				shidu_caiji[Chufa-1]=Shidu;       //湿度值采集
			}
			flag2=1;
			Display4();		                      //界面4 温湿度界面
			Delay3000ms();                      // 持续3s
      flag2=0;
		}
	}
	temper_max=temper_caiji[0];             //求温度最大值,平均值
	temper_sum=temper_caiji[0]; 
	for(i=1;i98) Canshu=0;
				else Canshu++;
			}
		}		
		while(!P33);
	}
	if(P32==0)                  //S9
	{
		Delay5ms();
    if(P32==0)
		{
			keycount = 0;		
			F_key = 1;			//标志按键按下状态
			while(P32== 0)		//等待按键松开
			{

			}
			F_key = 0;	
      				
			if(keycount> 1000)	   //按下时间大于2秒,长按
			{
				if((Huixian==3)&&(Jiemian==2))
				{
					Chufa = 0;		    //触发次数清除为00
				}
			}
			else				         //按下时间小于2秒,短按  温度参数-1
			{
				if(Jiemian==3)
				{
					if(Canshu<1) Canshu=99;
					else Canshu--;
				}
			}
		}		
	}
}

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

//******************************MAIN********************************
void main()
{
	InitAll();
	Timer0_Init();
	Timer1_Init();
	ds1302_writepro(0);
	ds1302_Settime(0x13,0x03,0x05);     // DS1302初始时间
	ds1302_writepro(1);
	while(1)
	{
		if(flag)        //定时器每隔0.2s读取数据
		{
			flag=0;
			ReadTime();                 //读时间
			
			Init_PCF8591();
			ad_value=Read_PCF8591();     //读光敏电阻电压
			v_value=ad_value*100/51;
			
			temper=ReadTemper();        //读温度
		}
		if(Jiemian==1)
		{
			Display1();
		}
		else if(Jiemian==2)
		{
			Display2();
		}
		else if(Jiemian==3)
		{
			Display3();
		}
		Keyscan();
		DisplayLED();
		CaijiChufa();
	}
}

//************************中断服务函数***********************
void intr_Timer0() interrupt 1
{
	count_f++;        //频率值计数
}

void intr_Timer1() interrupt 3
{
	DisplaySMG();
	if(F_key == 1)				//在按键按下期间进行计数
	{
		keycount++;				  //按键按下的持续时间
	}
	if(++intr==50)    //数据读取间隔时间
	{
		flag=1;
		intr=0;
	}
	if(++intr1==100)      //闪烁0.1S定时
	{
		intr1=0;
	}
	if(++count_t==500)    //1S定时
	{
		dat_f=count_f;              //频率值
		count_f=0;                     
		count_t=0;
		
		Shidu=2*dat_f/45+(10/9);   //湿度值换算
	}
}
//*************************************************************

2.iic.c

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

sbit scl=P2^0;
sbit sda=P2^1;
#define DELAY_TIME	5

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

void Init_PCF8591()
{
	I2CStart();
	I2CSendByte(0x90);
	I2CWaitAck();
	I2CSendByte(0x01);
	I2CWaitAck();
	I2CStop();
}

unsigned char Read_PCF8591()
{
	unsigned char temp;
	I2CStart();
	I2CSendByte(0x91);
	I2CWaitAck();
	temp=I2CReceiveByte();
	I2CSendAck(1);
	I2CStop();
	return temp;
}

3.ds1302.c

/*	# 	DS1302代码片段说明
	1. 	本文件夹中提供的驱动代码供参赛选手完成程序设计参考。
	2. 	参赛选手可以自行编写相关代码或以该代码为基础,根据所选单片机类型、运行速度和试题
		中对单片机时钟频率的要求,进行代码调试和修改。
*/								
#include "STC15.h"
#include "intrins.h"
sbit SCK=P1^7;
sbit SDA=P2^3;
sbit RST=P1^3;
//
void Write_Ds1302(unsigned  char temp) 
{
	unsigned char i;
	for (i=0;i<8;i++)     	
	{ 
		SCK = 0;
		SDA = temp&0x01;
		temp>>=1; 
		SCK=1;
	}
}   

//
void Write_Ds1302_Byte( unsigned char address,unsigned char dat )     
{
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1; 	_nop_();  
 	Write_Ds1302(address);	
 	Write_Ds1302(dat);		
 	RST=0; 
}

//
unsigned char Read_Ds1302_Byte ( unsigned char address )
{
 	unsigned char i,temp=0x00;
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
 	RST=1;	_nop_();
 	Write_Ds1302(address);
 	for (i=0;i<8;i++) 	
 	{		
		SCK=0;
		temp>>=1;	
 		if(SDA)
 		temp|=0x80;	
 		SCK=1;
	} 
 	RST=0;	_nop_();
 	SCK=0;	_nop_();
	SCK=1;	_nop_();
	SDA=0;	_nop_();
	SDA=1;	_nop_();
	return (temp);			
}

4.onewire.c

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

sbit DQ=P1^4;
//
void Delay_OneWire(unsigned int t)  
{
	unsigned char i;
	while(t--){
		for(i=0;i<12;i++);
	}
}

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

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

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

unsigned char ReadTemper()
{
	unsigned char temp;
	unsigned LSB,MSB;
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0x44);
	while(!DQ);
	init_ds18b20();
	Write_DS18B20(0xcc);
	Write_DS18B20(0xbe);
	LSB=Read_DS18B20();
	MSB=Read_DS18B20();
	
	temp=LSB>>4;
	temp=temp|(MSB<<4);
	return temp;
}

三、演示视频

第十四届蓝桥杯单片机演示视频

你可能感兴趣的:(蓝桥杯单片机,单片机,蓝桥杯,嵌入式硬件)