蓝桥杯单片机第13届省赛题

本文记录了作者参加第十三届蓝桥杯单片机竞赛的实战经验,分享了在编程过程中遇到的LED与数码管乱串、晶振频率调节等问题及解决方案。通过调试,实现了LED闪烁、温度显示和继电器控制等功能。代码包括主文件、矩阵按键和数码管显示,展示了如何处理硬件交互和实时数据更新。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

笔者是参加第十三届蓝桥杯单片机15组的第二批成员,此次赛题是在4.9日拿到赛题时候第一时间练习并调试得到最终的模板。有不妥之处还望斧正,相互进步相互学习哈。

目录

前言

赛题感受

 代码驱动


赛题感受

       这是刚刚过去的第十三届第一场嵌入式的省赛,模拟比赛的时候,拿到赛题,就发现相较于上一年难了一些。在编程的初期还是有很多的bug,但也都一一化解,最终得到了完美的答案。

        在刚拿到赛题之时,首先脑中首先想到要用的是什么模块,先将所需要的模块整理出来,确定可以很好的使用,之后再开始研究赛题。

        问题1.LED与数码管乱串问题

        问题2.调节下载晶振的频率影响数码管显示温度

        问题3.LED闪烁与继电器等其他的模块有机结合

据我的感受,只要大家能够耐心一步一步思考,能够排查出自己出现bug的原因,一定能够实现完美运行的。

 

 

 代码驱动如下:

 

主文件下:

#include "Key16.h"
#include "smg.h"
#include "ds1302.h"	
#include "onewire.h"


void allinit(void)
{
	P2=P2&0x1f|0x80;
	P0=0xff;
	P2=P2&0x1f|0xa0;
	P0=0x00;
}

bit bit_5,bit_6;
u16 DS18B20_temp;

void control(void);
void Led_Port(void);
void Mode_Change(void);

void main()
{
	allinit();
	DS1302_init();
	Timer1Init();
	DS18B20_temp=(char)DS18B20Read();
	delay_ms(800);
	while(1)
		{
			Key_Prc();
			control();
			Led_Port();
			DS1302_read();
			Mode_Change();
			Display1(zero,one);
			Display2(two,three);
			Display3(four,five);
			Display4(six,seven);
		}
}

void control(void){
	DS18B20_temp=(char)DS18B20Read();
	if(bit_1==0){
		P2=0x80,P0=0xff,P0&=0xfd,P2=0x80;
			if(DS18B20_temp>=Temp_Para){
				P2=0xa0,P0=0x00,P0|=0x10,P2=0xa0;bit_3=1;
			}
			else if(DS18B20_temp<Temp_Para){
				P2=0xa0,P0=0x00,P0&=0xef,P2=0xa0;bit_3=0;
			}
	}
	else {
		P2=0x80,P0=0xff,P0|=0x02,P2=0x80;bit_3=0;
				if(DS1302_time[0]==0&&DS1302_time[1]==0){
						P2=0xa0,P0=0x00,P0|=0x10,P2=0xa0;bit_3=1;bit_5=1;
						}
					if(bit_5==1){
						bit_3=1;
							if(DS1302_time[0]==5){
								P2=0xa0,P0=0x00,P0&=0xef,P2=0xa0;bit_3=0;bit_5=0;
								}
						}
	}
}


void Led_Port(void){
	if(DS1302_time[0]==0&&DS1302_time[1]==0){
		P2=0x80,P0=0xff,P0&=0xfe,P2=0x80;bit_6=1;//灯五秒
	}
	else if(bit_6==1){
		if(DS1302_time[0]==5){
			P2=0x80,P0=0xff,P0|=0x01,P2=0x80;bit_6=0;
		}
	}
	if(bit_4==1){
		P2=0x80,P0=0xff,P0&=0xfb,P2=0x80;
	}
	if(bit_4==0||bit_3==0){
		P2=0x80,P0=0xff,P0|=0x04,P2=0x80;
	}
}



void Mode_Change(void){
	if(Mode_flag==0){
		DS18B20_temp=(int)(DS18B20Read()*1000);
		zero=15,one=1,two=11,three=11,four=11,
		five=DS18B20_temp/10000,
		six=DS18B20_temp/1000%10+16;
			if(six>=26)six=16;
		seven=DS18B20_temp/100%10;
	}
	else if(Mode_flag==1&&bit_2==0){
		zero=15,one=2,two=11,three=DS1302_time[2]/10,
		four=DS1302_time[2]%10,five=10,
		six=DS1302_time[1]/10,
		seven=DS1302_time[1]%10;
	}
	else if(Mode_flag==2){
		zero=15,one=3,two=11,three=11,four=11,five=11,
		six=Temp_Para/10,seven=Temp_Para%10;
	}
	if(bit_2==1){
		zero=15,one=2,two=11,three=DS1302_time[1]/10,
		four=DS1302_time[1]%10,
		five=10,
		six=DS1302_time[0]/10,
		seven=DS1302_time[0]%10;
	}
}

完整版矩阵按键:

#include "Key16.h"
#include "smg.h"
#include "ds1302.h"	

u8 Key_value,Key_flag,Key,Key_Down,Key_Up,Key_old;
u16 Key_temp;

u8 Mode_flag;
bit bit_1,bit_2,bit_3,bit_4;
u8 Temp_Para=23,bit_time;

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


u8 Key_Read(void)
{
	P44=0,P42=1,P35=1,P34=1,P3|=0x0f;
	Key_temp=P3;
	P44=1,P42=0,P35=1,P34=1,P3|=0x0f;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	P44=1,P42=1,P35=0,P34=1,P3|=0x0f;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	P44=1,P42=1,P35=1,P34=0,P3|=0x0f;
	Key_temp=(Key_temp<<4)|(P3&0x0f);
	
	switch(~Key_temp){
		case 0x8000: Key_value=4;break;
		case 0x4000: Key_value=5;break;
		case 0x2000: Key_value=6;break;
		case 0x1000: Key_value=7;break;
			
		case 0x0800: Key_value=8;break;
		case 0x0400: Key_value=9;break;
		case 0x0200: Key_value=10;break;
		case 0x0100: Key_value=11;break;
			
		case 0x0080: Key_value=12;break;
		case 0x0040: Key_value=13;break;
		case 0x0020: Key_value=14;break;
		case 0x0010: Key_value=15;break;
			
		case 0x0008: Key_value=16;break;
		case 0x0004: Key_value=17;break;
		case 0x0002: Key_value=18;break;
		case 0x0001: Key_value=19;break;
		
		default :Key_value=0;
	}
	return (Key_value);
}


void Key_Prc(void){
	
	if(Key_flag) return;
		Key_flag=1;
	
	Key=Key_Read();
	Key_Down=Key&(Key^Key_old);
	Key_Up=~Key&(Key^Key_old);
	Key_old=Key;
	
	if(Key_Down){
		switch(Key){
			case 12:if(++Mode_flag==3)Mode_flag=0;break;
			case 13:bit_1=~bit_1;break;
			case 16:if(Mode_flag==2){
									if(++Temp_Para>99)Temp_Para=99;
									}break;
			case 17:if(Mode_flag==2){
									if(--Temp_Para<10)Temp_Para=10;
									}
							else if(Mode_flag==1)bit_2=1;break;
		}
	}
	
	
	if(Key_Up){
		switch(Key_Up){
			case 17:if(Mode_flag==1){
						bit_2=0;
						zero=15,one=2,two=11,three=DS1302_time[2]/10,
						four=DS1302_time[2]%10,
						five=10,
						six=DS1302_time[1]/10,
						seven=DS1302_time[1]%10;
			}
		}
	}
}


void Timer1() interrupt 3{
	if(++Key_flag==10) Key_flag=0;
	if(bit_3==1){
		bit_time++;
		if(bit_time==100)bit_4=1;
		else if(bit_time==200){bit_4=0;bit_time=0;}
	}
}

数码管代码如下:

#include "smg.h"

unsigned char code smgduan[]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,
0xf8,0x80,0x90,0xbf,0xff,0xc6,0x8c,0x88,0xc1,0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10,0xbf};//0-9
unsigned char smgwei[]={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80};
u8 zero,one,two,three,four,five,six,seven;


void Display1(zero,one)
{
	P2=0xc0,P0=smgwei[0];
	P2=0xff,P0=smgduan[zero];
	delay_ms(1);
	
	P2=0xc0,P0=smgwei[1];
	P2=0xff,P0=smgduan[one];
	delay_ms(1);
	
	P2=0xc0,P0=0xff;
	P2=0xff,P0=0xff;
}


void Display2(two,three)
{
	P2=0xc0,P0=smgwei[2];
	P2=0xff,P0=smgduan[two];
	delay_ms(1);
	
	P2=0xc0,P0=smgwei[3];
	P2=0xff,P0=smgduan[three];
	delay_ms(1);
	
	P2=0xc0,P0=0xff;
	P2=0xff,P0=0xff;
}

void Display3(four,five)
{
	P2=0xc0,P0=smgwei[4];
	P2=0xff,P0=smgduan[four];
	delay_ms(1);
	
	P2=0xc0,P0=smgwei[5];
	P2=0xff,P0=smgduan[five];
	delay_ms(1);
	
	P2=0xc0,P0=0xff;
	P2=0xff,P0=0xff;
}

void Display4(six,seven)
{
	P2=0xc0,P0=smgwei[6];
	P2=0xff,P0=smgduan[six];
	delay_ms(1);
	
	P2=0xc0,P0=smgwei[7];
	P2=0xff,P0=smgduan[seven];
	delay_ms(1);
	
	P2=0xc0,P0=0xff;
	P2=0xff,P0=0xff;
}

<think>好的,我现在需要处理用户关于第十五蓝桥杯单片机相关目的查询。首先,用户明确提到想要查找第十五目,但提供的引用内容中有三个不同的来源,其中引用[1]和[2]明确提到了第十五,而引用[3]是第十一的。因此,我需要先确认哪些引用内容与用户的问直接相关。 首先,引用[1]详细描述了第十五的程序,涉及NE555定时器和DA输出的内容,这应该是最相关的。用户的问正是关于这一目,所以这部分信息需要重点提取。引用[2]虽然也提到了第十五,但主要是模拟III的配置要求,可能不是用户需要的具体目内容。引用[3]属于第十一,与用户的问无关,可以忽略。 接下来,我需要确保回答的结构符合用户的要求:结构清晰,分步骤解决问,并且引用正确的来源。用户提供的示例中,回答部分包括了目概述、关键知识点、实现难点以及参考代码示例,这可以作为模板。同时,需要生成相关问,放在最后。 需要注意的是,用户提供的引用[1]中有提到具体的模块如NE555和DA输出,以及调参操作和DA倍率调整,这些细节应包含在回答中。同时,用户示例中的代码部分是关于快速排序的,但在此处可能需要调整,因为用户的问是关于单片机编程,可能需要展示相关的代码结构,比如NE555的配置或DA输出的处理。但根据引用内容,用户提供的引用[1]附有可运行代码,但实际回答中并没有给出代码,所以可能需要避免猜测具体代码,只描述实现逻辑。 此外,用户要求回答使用中文,并正确使用LaTeX格式。例如,涉及数学表达式或变量时使用$...$,如频率参数可能需要用变量表示,如$f$或者电压$V$。独立公式如果有的话需要用$$...$$,但根据现有信息,可能暂时不需要。 最后,生成的相关问需要围绕第十五蓝桥杯单片机目的内容,例如涉及的知识点、难点、优化方法等。需要确保问与用户提供的引用内容相关,比如关于NE555的使用、DA输出的调整、EEPROM存储等。 总结步骤: 1. 提取引用[1]中关于第十五单片机目的描述,概述目内容和涉及模块。 2. 分点说明关键知识点,如NE555定时器、DA输出、调参操作等。 3. 描述实现难点,如调参中的正负数处理、DA倍率调整逻辑。 4. 生成相关问,围绕目涉及的模块和知识点提问。 5. 确保引用正确,引用标识放在相关描述的末尾。</think>根据提供的参考资料,第十五蓝桥杯单片机程序的核心内容如下: ### 目概述 1. **主要模块**:围绕NE555定时器的频率检测与DA输出控制展开,需实现以下功能: - 通过NE555测量输入信号的频率,并完成调参(包含正负数值调节) - 根据超限参数动态调整DA输出的倍率[^1] 2. **硬件配置**:需严格按照官方要求配置竞板,包括NE555模块、DA转换模块和LED/LCD显示模块[^2]。 ### 关键知识点 1. **NE555频率检测** - 需通过定时器捕获或外部中断测量NE555输出的方波频率,涉及公式: $$f = \frac{1}{T}$$ 其中$T$为信号周期,需通过定时器计数计算。 2. **DA输出控制** - 根据频率超限状态调整DA输出电压的倍率,例如: - 若频率超过阈值,DA输出倍率增加$k$(如$k=1.2$) - 若频率低于阈值,倍率减少$k$ 3. **参数存储** - 类似往设计(如第十一),需将关键参数(如电压放大值$V_p \times 10$)保存至EEPROM内部地址[^3]。 ### 实现难点 1. **调参逻辑**:需处理正负数调节的边界条件,例如频率偏差计算可能涉及符号判断。 2. **实时性要求**:频率测量与DA输出需保持同步,避免显示或输出滞后。 ### 参考代码框架(伪代码) ```c void main() { init_NE555(); // 初始化NE555定时器捕获 init_DA(); // 配置DA输出 while(1) { f = measure_frequency(); // 测量频率 if (f > threshold) adjust_DA_gain(+k); // 正方向调整倍率 else adjust_DA_gain(-k); // 负方向调整倍率 update_EEPROM(); // 存储参数 } } ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值