蓝桥杯单片机省赛总结

十四届模拟题二

1.知识点

在这里插入图片描述
1.串口存放数组一定要足够大,不然会出现存储不下导致发送不了的问题
2.如果发送串口超过数组存储,会出现程序崩溃的情况,因此必须在发送时加以限制
在这里插入图片描述
修改方案
在这里插入图片描述
在发送中断函数中加以限制,避免胡乱发送的情况

3.按下按键s19会出现数码管直接乱码的情况 解决方法
在这里插入图片描述
在扫描之前将定时器关闭,在扫描之后将P3复位,复位后再将ET1打开。

4.内存的问题 用xdata

5.继电器与蜂鸣器不能同时使用的问题如何解决
把局部变量变成全局变量
在这里插入图片描述
在这里插入图片描述
放在外面

第十四届

1.知识点

在这里插入图片描述

1.串口输出数据(重点)
2.超声波
3.LED闪烁
4.互斥点亮

第十三届蓝桥杯问题汇总

1. 知识点

1.界面切换
2.温度,时钟模块
3.继电器
4.不同模式下同一按键对应不同功能
5.长按从A界面跳转到B界面,松开后恢复A界面
6.计时五秒,到达5s后led自动熄灭
7.有个bug就是温度控制与时间控制可能存在互相干扰的情况
8.led以一定时间闪烁

1.ds1302模块书写代码还不熟练
ds1302需要自己书写两个函数一个为(Set_Rtc)一个为(Read_Rtc)其中书写逻辑就是按照芯片手册查询地址,Set-Rtc流程是关闭写保护——把时分秒数据写入——开启写保护

void Set_Rtc(unsigned char *ucRtc)
{
	unsigned char temp;
	
	Write_Ds1302_Byte(0x8e, 0);
	
	temp = (((ucRtc[0]/10)<<4)|(ucRtc[0]%10));
	Write_Ds1302_Byte(0x84, temp);	
	
	temp = (((ucRtc[1]/10)<<4)|(ucRtc[1]%10));
	Write_Ds1302_Byte(0x82, temp);	

	temp = (((ucRtc[2]/10)<<4)|(ucRtc[2]%10));
	Write_Ds1302_Byte(0x80, temp);	
	
	Write_Ds1302_Byte(0x8e, 0x80);	

}


void Read_Rtc(unsigned char *ucRtc)
{
	unsigned char temp;
	
	temp = Read_Ds1302_Byte(0x85);
	ucRtc[0] = (((temp>>4)*10)+(temp&0x0f));
	
	temp = Read_Ds1302_Byte(0x83);
	ucRtc[1] = (((temp>>4)*10)+(temp&0x0f));	
	
	temp = Read_Ds1302_Byte(0x81);
	ucRtc[2] = (((temp>>4)*10)+(temp&0x0f));	

}

主函数中有两处位置是必须增加的一个是数码管前面需要写

	Read_Rtc(ucRtc);

一个是主函数中一定要写

	Set_Rtc(ucRtc);//上电设置时间 因为有*号因此只用地址就可以

2.DS18B20模块书写不熟练
1.书写代码流程 初始化——跳过ROM——开始温度转化——初始化——跳过ROM——读取暂存寄存器中数据——将暂存寄存器数据赋予MSB跟LSB——返回数据

2.其中最重要的一点就是返回数据时一定是除以16.0,如果除以16会出现小数点后数据丢失的情况。

3.主函数中定义温度变量一定要用float型

4.在数码管前面有一行代码是需要我们必须添加的

Temperature = Read_Temperature();

主函数问题
1.主函数中要先写延时再写读取温度。

	Read_Remperature();//读取温度
	Delay750ms();//等待温度转换

2.主函数中是设置时间,数码管函数中是读取时间。

第十三届(第二场)

在这里插入图片描述

1.知识点

1.AD/DA采集电压

AD_Voltage = AD_Read(0x43) / 51.0;//将AD采集的电压送入电压存储变量

2.超声波模块
3.数码管高位熄灭
4.重点参数设置与参数显示
在这里插入图片描述
5.DA输出与测量(重点)
出现问题 20-80cm之间用DA是不能输出的

第十二届(第一场)

在这里插入图片描述

1.知识点

1.温度读取到小数点后两位
2.DAC输出线性电压
3.LED互斥点亮

	unsigned char i;//For循环专用变量
	for(i=0;i<3;i++) //互斥点亮
		Led_Display[i+1] = (i == Seg_Disp_Mode);

第十二届(第二场)

在这里插入图片描述

1.知识点

1.高位如果没有数据熄灭

while(Seg_Display[i] == 0)
			{
				Seg_Display[i] = 10;
				if(i++ == 6)  //一定要加这个限制条件 不然会卡死
					break;
			}

2.ne555模块学习 频率显示
看另一篇文章
3.iic头文件中 .h文件上面需要补充__

#ifndef _IIC_H__
#define _IIC_H__

4.周期显示 就是频率变换而成
因为是以微秒为单位因此1s=1000000us

Cycle = 1000000/Freq;

5.在键盘设置时一定要按照要求进行设置,不然会出现长按没有用的情况

第十一届(第一场)

1.知识点

1.电压值超过电压参数设置值就加一
在这里插入图片描述

if(Voltage_Set < Voltage)
		Voltage_Flag = 1;
else if(Voltage_Flag == 1)
	{
		Voltage_Flag = 0;
		Voltage_Num++;
	}

2.无效按键(必须排除case 0)不然会出现问题

case 0://排除0
		break;

3.按键按一次加0.5(浮点数)(重点)
4.led在满足条件五秒后点亮
在这里插入图片描述

**
5.EEPROM进行保存

第十一届(第二场)

在这里插入图片描述

1.知识点

1.上下限温度设置
2.参数合理性判断
3.DA输出电压
4.LED互斥点亮

ucLed[0] = (Temperature > Temperature_Params_Ctrol[0]);
	ucLed[1] = (Temperature <= Temperature_Params_Ctrol[0] && Temperature >= Temperature_Params_Ctrol[1]);
	ucLed[2] = (Temperature < Temperature_Params_Ctrol[1]);

第十届

**
所用模块
在这里插入图片描述

1.知识点

问题
1.AD上电 传回值一直为255
解决方案
iic.c中底层驱动写错了 pcf8591底层驱动有 6+6+1行 可以用来检查

2.DA输出电压随着电位器RB2输出电压变化而变化(重点DA与AD)

DA_Write(AD_Read(0x43));

3.NE555频率调节
4.数码管统一开启与关闭

if(Seg_Enable_Flag == 1) //数码管使能
		Seg_Disp(Seg_Pos,Seg_Buf[Seg_Pos],Seg_Point[Seg_Pos]);
	else
		Seg_Disp(Seg_Pos,10,0); //熄灭所有数码管

5.LED统一开启与关闭

if(Led_Enable_Flag == 1) //Led使能
		Led_Disp(Seg_Pos,ucLed[Seg_Pos]);
	else
		Led_Disp(Seg_Pos,0); //熄灭所有Led

6.互斥点亮

Led_Display[2] = (AD_Voltage >= 3.5 || (AD_Voltage >= 1.5 && AD_Voltage < 2.5));//互斥点亮
	Led_Display[3] = ((Freq >= 1000 && Freq < 5000) || Freq >= 10000);//互斥点亮

第九届

所用模块
在这里插入图片描述

1.知识点

1.数码管闪烁
2.高位熄灭(重点)与之前不一样 因为与数码管闪烁配合会出现BUG,因此所放在位置的顺序需要进行修改
3.PWM调节

第八届(思路比较难)需要重点看

所用模块
在这里插入图片描述

1.知识点

1.应用ds1302后,减按键到0后如何判断是24还是60

if(Alarm_Set[Clock_Set_Index] == (Clock_Set_Index==0?24:60))

2.如何实现如下功能
在这里插入图片描述
(1)一定要将显示数组与设置数组分开设置两个数组

unsigned char uRtc[3] = {23,59,00};//时钟存放数组
unsigned char uRtc_Set[3];//时钟数据设置数组

(2)设置数组指针

unsigned char uRtc_Index;//时间参数数据指针 0-小时 1-分钟 2-秒

(3)

case 7://时钟设置
			if(Seg_Disp_Mode == 0 || Seg_Disp_Mode == 2)//只有在时钟界面下按键才生效
			{
				if(Seg_Disp_Mode == 0)//是否在时钟显示界面
				{
					uRtc_Set[0] = uRtc[0];
					uRtc_Set[1] = uRtc[1];
					uRtc_Set[2] = uRtc[2];
					Seg_Disp_Mode = 2;//去时钟设置界面
				}
				else
				{				
					if(uRtc_Index++ == 2)
					{
						Set_Rtc(uRtc_Set);//重新设置时钟数据
						uRtc_Index = 0;
						Seg_Disp_Mode = 0;//返回时钟显示界面
					}
				}
			}
		break;

3.L1以0.2秒为间隔闪烁,持续五秒。
4.界面切换(按键按下在A界面 按键松开在B界面) 难度升级版(需要额外设置一个变量) 有一个界面也需放在函数外面
5.闹钟提示状态下按下任意按键关闭闪烁
6.十六进制如何加减
7.闹钟设置
(1)需要准备两个数组一个闹钟设置 一个闹钟显示数组
(2)

if(Alarm_Flag == 1)//闹钟使能状态
	{
		if(Key_Down)//任意按键按下
		{
			Alarm_Flag = 0;
			Timer_5000Ms = 0;
		}	
	}

8.当在23.59.59设置时本来应该跳到00.00.00结果却跳到了00.01.00了
(原因减速问题)
9.在写时间判断时,后面一定要加()不然会出现显示错误的情况
在这里插入图片描述
10.任何按键下,led停止闪烁(注意一定要计时器复位,不让下次计时就不能满足5s了)
在这里插入图片描述

第七届

所用模块
在这里插入图片描述

1.知识点

1.PWM 固定频率 运用到两个定时器
在这里插入图片描述

void Timer1Server() interrupt 3
{
	if(++Seg_Pos == 8) Seg_Pos = 0;//数码管显示专用
	Led_Disp(Seg_Pos,Led_Display[Seg_Pos]);//LED进行0-7扫描并显示
	if(Sys_Running_Flag == 0)
	{
		if(++Led_PWM == 10)//让记录第几次的变量,在0-9之间变化
		{
			P34 = 1;//每10次拉高一次
			Led_PWM = 0;
			Led_Display[3] = Led_Display[4] = 1;
		}
		switch(Mode_PWM)//
		{
			case 0:
				Led_Level = 2;
			break;
			case 1:
				Led_Level = 3;
			break;
			case 2:
				Led_Level = 7;
			break;
		}
	
		if(Led_PWM == Led_Level)//到模式规定的状态位置,拉低一次。
		{
			Led_Display[3] = Led_Display[4] = 0;
			P34 = 0;
		}
	}
	else
	Led_Display[0] = Led_Display[1] = Led_Display[2] = Led_Display[3] = Led_Display[4] = Led_Display[5] = Led_Display[6] = Led_Display[7] = 0;
}

第六届

硬件模块
在这里插入图片描述

1.知识点

1.如何按照时间间隔将温度采集的十位数据存放到数组中去,并且在按键使能下显示出来。
在这里插入图片描述

if(One_Temperature_Collection == 1 && Time_Collection_Flag == 1)//一次收集完成并且采集时间还未完成
	{
		Temperatrure_Collection[Temperatrure_Collection_Index] = (unsigned char)Read_Temperature();//将温度依次放进温度采集数组中
		One_Temperature_Collection = 0;//一次温度采集标志位复位
			if(Temperatrure_Collection_Index++ == 9)采集完成
			{
				Temperatrure_Collection_Index = 0;
				Time_Collection_Flag = 0;//标志位复位
				Seg_Disp_Mode = 2;
				Led_Display[0] = 1;
			}
	}

注中断中只写定时就可以 其他都在中断外面写 如果有需要控制的去定义标志位进行控制即可

if(Time_Collection_Flag == 1 && One_Temperature_Collection == 0)//开始采集
	{
		if(++Temperature_Timer == (Time_Collection[Time_Collection_Index]*100))
		{
			Temperature_Timer = 0;
			One_Temperature_Collection = 1;//一次收集完成
		}
	}

第五届

硬件框图
在这里插入图片描述

1.知识点

1.用按键输入数据
定义一个数组一个指针,数组中每一位存放按键输入的数据,再用指针去选择。
2.如何将输入个位数据转换成两位数据(如将输入的数值3,0变成最高温度30)

T_Max_Temp = Temperature_Set[0]*10+Temperature_Set[1];
T_Min_Temp = Temperature_Set[2]*10+Temperature_Set[3];

3.如果需要验证数据合理性怎么办
先定义两个数组,一个为暂存数组,一个为真正存储数组

unsigned char T_Max=30,T_Min=20;//最终最高温度 最低温度
unsigned char T_Max_Temp,T_Min_Temp;//最高温度 最低温度(暂存)

如果满足条件就将暂存数组的值给真正数组,如果不满足条件就什么都不干,那么真正的数组就依然不会改变。
4.继电器底层函数

void Relay_Disp(unsigned char enable)	//pos是位置,enable是是否点亮LED 1为点亮 0为熄灭
{
	static unsigned char temp = 0x00;			//只有第一次时temp为0x00
	static unsigned char temp_old = 0xff;
	if(enable)														//如果enable=1就进入,启动蜂鸣器
		temp |= 0x10;
	else									//如果enable=0就进入,关闭蜂鸣器
		temp &= ~0x10;
	if(temp != temp_old)									//temp值与temp_old不相等,说明temp值改变了就进入一次
	{
		P0=temp;														
		P2=(P2 & 0X1f) | 0xa0;						//Y5输出0,蜂鸣器和继电器控制 
		P2 &= 0x1f;
		temp_old = temp;										//temp_old都是被动改变,只有temp改变他才会改变
	}
}

第四章

硬件模块
在这里插入图片描述

1.知识点

1.AD值与湿度的关系换算。

	Humidity = Ad_Read(0x03) / 2.56;//实时读取湿度数据

2.EEPROM底层函数容易不熟,需要多加练习!

第三届

硬件框图
在这里插入图片描述
难点
1.出水量与总价具有关联关系 如何实现这种关联关系
在这里插入图片描述

if(Water_10ml_Flag == 1)
	{
		Output_Water += 0.01;//每10ms加0.01
		Water_Money_All += 0.005;//每10ms加0.005
		Water_10ml_Flag = 0;
		if(Output_Water == 99.99)//当超过99.99时,自动停水,并跳转到界面一
		{
			Water_Flag = 0;
			Seg_Disp_Mode = 1;
		}
	}
  • 4
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猫先桑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值