第十一届蓝桥杯电子类国赛总结回顾
2020年11月14日,蓝桥杯电子类国赛终于结束了,准备了挺久的。决赛没考超声波和串口,有点意外,题目较为简单这也意味着今年的竞争会格外激烈了,祝愿自己能有个好成绩吧哈哈。已经大三了,这应该是我唯一一次参加电子类了。下次还有机会参加蓝桥杯的话应该回去玩玩C语言组,虽然自己C语言菜的不谈哈哈,整理一下资料,写个总结吧,希望对之后参加这个比赛的同学能有一点点帮助。
备赛期间学习的是电子设计工坊的资料(可以上淘宝搜索即可-所以看过他们视频的同学应该会对我整理的概念会比较清楚)。
省赛和国赛真题和模拟题的源码放在之后的博客里吧,不然太长了,大家有需要的去看一下就行。省赛的不全(重做了一次电脑,没了)。
冲鸭!
tips: 1. shift+tab 选中的代码块整体左移
2.有时会出现程序实际上没有烧录进去,此时要重新生成一下hex文件
组合按键时候使用(替代if)
#define SetKeyBoard(x) P4= (x>>3) | (x>>4); P3=x //规律:上下对称结构,上面右移3,4;下面左移3,4
#define GetKeyBoard() ((P4&0x10)<<3) | ((P4&0x04)<<4) | (P3&0x3f)
注意组合按键时候给出任意两个按键的组合,根据电路图判断出对应键值(多多练习)
1.一定要把底层驱动的.h文件复制到c文件所在文件夹才能生效
矩阵按键键值对应码的确定:分别令横向和纵向为低电平,得到两组数据,在相“或”得到最终结果
ds1302写入和读出的数据均为BCD码
EEPROM:是一种掉电数据不丢失的存储芯片
3.第十届蓝桥杯比赛驱动代码:
只有单总线协议onewire需要更改(延时扩大12倍,用for循环)
4.用定时器计算器得到的定时器初始化代码要自己补充ET0=1和EA=1.
- PCF8591写:0x90, 读:0x91
AT24C02写:0xa0, 读:0xa1
6.定时器中时间的判断可用大于,而不用等于
读取温度时候要先关闭定时器ET0=0,读完温度后再打开ET0=1.(iic读电压等也要用此方式,保护时序)
7.当既有蜂鸣器控制,又有继电器控制时,可以设置两个标志位,在循环中整体分四种情况讨论(具体见第五届模拟题灌溉系统代码)
8.尽量不用浮点型(见自动售水机)
9.超声波发送与接收引脚定义:#define TX P10
#define RX P11
10.LED微亮情况的解决:先送P0信号,防止在打开锁存器的瞬间P0处于不确定状态(见省赛彩灯控制器)
11.写AT24C02要有延时10ms(用delay)(可在开头先写一次,排除先前别人写入的干扰,即在while(1)之前写一次,然后再删去该部分程序即可)
12.ds18b20温度读取一开始的85消除方法
void main() //先读取10次
{u8 keyvalue;P2=0x80;P0=0xff;P2=0;P2=0xa0;P0=0;P2=0;Timer0Init();set_sfm(23,59,50);for(chuli_i=0;chuli_i<10;chuli_i++){ET0=0;temp_chuli=(u8)rd_temperature_f();ET0=1;}while(1)
13.对LED的操作可以设各个灯的代表比如led1,led2,led3等等,最后用led1| led2 | led3的形式总和即可
14.ADC: A表示模拟信号,D表示数字信号
注意看DAC的输出函数(记忆):电压跟随效果
15.用PCF8591电压值模拟湿度的时候,读取的数值应该除以255.f(256.f)整除的话得到的一直是0
16.要用到定时器和计数器时候,定时器的配置直接复制STC,计数器的配置自己写,不用配置AURX(详见第十届省赛代码部分)
比如用定时器0当做计数器,则直接写TMOD & =0xf0 //保留高四位(之前对定时器1的配置),将第四位置0便于下一行对计数器的配置
TMOD | = 0x04;
TH0=0;
TL0=0;
ET0=1;
TR0=1;
EA=1;
***注意***:1.IAP15单片机M1M0=00为16位自动重装载,不用在中断中再次进行赋初值。2.NE555频率的读取要从超声波模块取下一个连接子,接到P34和SIGNAL上。3.计数器读取频率50ms比较合适,之后乘上20即可。4.TR0对于定时器0的定时和计数功能都有影响。5.T0设置为计数器时,P3^4每一个下降沿都会进入中断,寄存器值加1。
- IAP15的超声波使用关键:
(1).定时器T0直接复制STC代码即可,T1的使用要么不加AUXR的赋值,要么只能用12T模式(用1T会出错,数值会很大,与实际不符)。
(2)超声波的定时器1中要把中断使能ET1关闭(ET1=0),定时开关TR1关闭(TR1=0)。用标志位手动清零的方式,这样能实现显示999状态。
18.判断密码相同,串口发送相同,可以定义一个函数来判断(return 0 or return 1)
19.同时读取PCF8591的0x03和0x01时,有可能出现数据串位现象,(此时交换下0x01和0x03即可)
20.串口发送的是ASCII码值,所以如果是数字,要加 ’ 0 ',进行转换
21.定义二维数组前面加 xdata (因为数组太大会越界)
22.led灯的操作最好是给每种状态设flag,最后统一对P0赋值
23.最高位的零不显示的方法:
以前使用判断位数,然后分别赋值的方法,过于繁琐。
简便方法如下:
在正常的8位数组赋值之后再加一个for循环:
for(i=0;fre_display[i]==smg_duan[0];i++)
{display[i]=0x00; //数码管如果是显示数字0,就赋值位0x00(不显示)
}
24.自己写头文件的时候要注意最后要加#endif
注意extern的用法,在头文件中声明(不赋值),在对应的c文件中定义
25.蓝桥杯第十一届模拟题总结:
待解决:左移操作的便捷方法
删除操作:
for(j=6;j>6-input_index;j--) //每按下一次删除键,删除一位,从左向右移动一次{modi_code_display[j+1]=modi_code_display[j];}modi_code_display[7-input_index]=0x00;input_index--;
26.注意单总线协议的延时补充代码
void Delay_OneWire(unsigned int t)
{unsigned char i; //特别注意:for循环要放在while循环里面,否则会出错while(t--){for(i=0;i<12;i++);}
}
27.再访串口:(2020.4.2)
ES=1 串行口中断标志位
ET1 是中断允许标志位 在串口得初始化中不能开启ET1 (因为串口已经有中断了,再开启定时器中断会产生干扰)
TR1 是定时器开启标志
void UartInit(void) //1200bps@11.0592MHz
{SCON = 0x50; //8位数据,可变波特率AUXR |= 0x40; //定时器1时钟为Fosc,即1TAUXR &= 0xFE; //串口1选择定时器1为波特率发生器TMOD &= 0x0F; //设定定时器1为16位自动重装方式TL1 = 0x00; //设定定时初值TH1 = 0xF7; //设定定时初值 ET1 = 0; //禁止定时器1中断 不要开启定时器1的中断标志位ET1TR1 = 1; //启动定时器1 ES=1; //串行口中断标志位 从该行开始需要自己写EA=1;SendString("STC15F2K60S2\r\nUart Test !\r\n");
}
28.关于EEPROM。
写EEPROM的时候要注意写入的数据是否大于256,如果是则要做相应的除法处理。
29.长短按,双击中,key_return要手动赋初值为0:(u8 key_return=0;)
30.关于NE555
要用到P34,所以要把定时器0作为计数器,P34为定时器0的计数器外部脉冲口
- 关于三位一体综合键盘
(1) 三位一体矩阵键盘出现按一下跳动很多时候,考虑时候是返回值写成了key_val,要改成key_return。
(2) 双击函数中出现只有第一次双击有效,后面只能执行单击,考虑是否为没有写key_time_1=0在相应位置。
(3)如果出现长按和组合按键实现不了,单击和双击能实现,则检查是否在key_long_short_double_click()函数中的case KEY_STATE_0中没有写else{key_return=key_val_1)},只写了if(key_val_1>0 && key_val_1<50)
(4)组合按键出现按下组合键时候,连续加两次值,表明没有松手检测,去检查有没有在key_state_4里转到松手检测的key_state_3, 有可能误写成转到 key_state_0了。
(5)检查底层有没有修改 复制后的各个temporary的值。
(6) 出现任何按键都没有反应时,可能是switch中的。key_state=key_state_1误写成了key_state_0,(key_long_short_click和key_long_short_double_click()这两个函数的switch都需要检查)。
(7)key_long_short_double_click()中最后是key_return=key_prev_1(不是key_val_1),因为此时处于第一次单击后的等待时间,是无按键状态,超过500ms后此时是无按键状态。
33.NE555频率读取出现数码管数值一直增加,到65536后清零又重新累加的情况分析
if(fre_flag){fre_flag=0;TR0=0; //计数器关闭fre=TH0*256+TL0;//在计数器关闭和重新打开之间要对TH0和TL0清零处理 TH0=TL0=0;TR0=1;fre*=20;...}
34.DAC输出代码
void SetDACOut(unsigned char val) //set DAC
{IIC_Start();IIC_SendByte(0x90); //写操作的地址IIC_WaitAck();IIC_SendByte(0x40); //DACIIC_WaitAck(); IIC_SendByte(val); //传值IIC_WaitAck();IIC_Stop();
}
35.矩阵键盘长按不松手数值一直加(没有松手检测)
case key_state_2:if(key_val==NO_KEY){key_state=key_state_0;key_return=key_prev; //short}else{key_time++;if(key_time>=50){key_state=key_state_3; //此处没有到key_state_3中,则没有松手检测key_return=key_val+100; //long //key_state_3是松手检测}}break;
36.串口之extern
1.extern用在变量声明中常常有这样一个作用,你在*.c文件中声明了一个全局的变量,这个全局的变量如果要被引用,就放 在*.h中并用extern来声明。
2.如果函数的声明中带有关键字extern,仅仅是暗示这个函数可能在别的源文件里定义,没有其它作用。即下述两个函数声明没有区别:
uart.c中定义为 unsigned char rec_table[6]
unsigned char rec_index=0;
uart.h中声明时才要加extern:
extern unsigned char rec_table[6]
extern unsigned char rec_index;
37.关于驱动代码 : 一个_nop_()等于一个机器周期
iic: 延时上的不同写法(核心:要延时10个机器周期以上)
写法一:(第十届资源数据包)
#define DELAY_TIME 5void IIC_Delay(unsigned char i)
{do{_nop_();}while(i--);
}void IIC_Start(void)//主要看SDA和SCL后的延时方法即可得知延时方法
{SDA = 1;SCL = 1;IIC_Delay(DELAY_TIME);SDA = 0;IIC_Delay(DELAY_TIME);SCL = 0;
}
//------------------------------------------------------------写法二:(用somenop作延时)
#define somenop {_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();_nop_();} //10个机器周期以上
void IIC_Start(void)
{SDA = 1;SCL = 1;somenop; SDA = 0;somenop;SCL = 0;
}
38.串口中16进制发送转换成10进制
u8 hextoDec(u8 hex) /*16进制->10进制,用于显示到数码管上(字符也可转换,如FF->255) 1111 1111 = 2 ^ 8 */
{ u8 sum=0; u8 mul=1;u8 count=0;u8 i;u8 r;do{r=hex%16;for(i=0;i<count;i++)mul*=16;mul*=r;sum+=mul;mul=1;count++;}while(hex/=16);return sum; //最后的十进制数
}
39 .单片机ISP下载软件串口助手的hex模式和文本模式的区别 首先hex模式是十六进制模式,当我们用电脑以hex模式给单片机USART口发数据时,发的是十六进制,单片机接收的也是十六进制;如果要转换为10进制数,要用相应的算法进行处理。 当我们用电脑以文本模式给单片机发数据时,只能发字母(0-9,a-z,A-Z等其他符号),单片机收到的也是字母!总结:不论你发的是什么,单片机收到的都是ASCII码。2.注意: 向ds1302直接输入时分秒时不能直接写入,必须先把十进制的数据转化为BCD码,这时候写入才是有效的数据。
BCD码:用4位二进制数来表示十进制数中的0~9这十个数码的编码形式,简称为BCD码。
0000 ~ 1001
void set_sfm(unsigned char shi,unsigned char fen,unsigned char miao)
/*该写法是将10进制转换成BCD码写入的方法,区别于串口发送中的将16进制转换成10进制*/{Write_Ds1302_Byte(0x8e,0); Write_Ds1302_Byte(0x80,miao/10*16+miao%10); /Write_Ds1302_Byte(0x82,fen/10*16+fen%10);Write_Ds1302_Byte(0x84,shi/10*16+shi%10);Write_Ds1302_Byte(0x8e,0x80);}
4.串口发送为ASCII码值,所以如果单片机给电脑发数字的话程序中要加上 ’ 0 ’
'\r’是回车,使光标移到行首,(carriage return)0X0D
'\n’是换行,使光标下移一格,(line feed)0x0A
Windows系统里面,每行结尾是“<回车><换行>”,即“\r\n”;
5.当出现读取NE555频率,连接P34和SIGNAL时,矩阵键盘要用普通形式,不能用移位形式,否则会有干扰,没有松手检测效果
但是矩阵键盘的普通形式无法实现组合按键。组合按键必须使用移位法矩阵键盘写法
#define NO_KEY 0 //因为分两步写时,key_val得到的是0,所以NO_KEY要为0,而不是0xff//-------------------底层------------------------
u8 key_scan()
{u8 key_temp,key_temporary=0;u8 key1,key2;P30=0;P31=0;P32=0;P33=0;P34=1;P35=1;P42=1;P44=1;if(P44==0)key1=0x70;if(P42==0)key1=0xb0;if(P35==0)key1=0xd0;if(P34==0)key1=0xe0;if((P44==1)&&(P42==1)&&(P35==1)&&(P34==1))key1=0xf0;P30=1;P31=1;P32=1;P33=1;P34=0;P35=0;P42=0;P44=0;if(P33==0)key2=0x07;if(P32==0)key2=0x0b;if(P31==0)key2=0x0d;if(P30==0)key2=0x0e;if((P33==1)&&(P32==1)&&(P31==1)&&(P30==1))key2=0x0f;key_temp=key1|key2;switch(key_temp){case 0x77:key_temporary=4;break;case 0x7b:key_temporary=5;break;case 0x7d:key_temporary=6;break;case 0x7e:key_temporary=7;break;case 0xb7:key_temporary=8;break;case 0xbb:key_temporary=9;break;case 0xbd:key_temporary=10;break;case 0xbe:key_temporary=11;break;case 0xd7:key_temporary=12;break;case 0xdb:key_temporary=13;break;case 0xdd:key_temporary=14;break;case 0xde:key_temporary=15;break;case 0xe7:key_temporary=16;break;case 0xeb:key_temporary=17;break;case 0xed:key_temporary=18;break;case 0xee:key_temporary=19;break;}return key_temporary;
}
//----------------判断层------------------
u8 key_long_short_click() //key_val得到的是0,所以NO_KEY要为0,而不是0xff
{static unsigned char key_state=key_state_0,key_prev,key_time=0;u8 key_val=0,key_return=0;key_val=key_scan();switch(key_state){case key_state_0:if(key_val!=NO_KEY){key_state=key_state_1;key_prev=key_val;}break;case key_state_1:if(key_val==NO_KEY){key_state=key_state_0;}else{key_state=key_state_2;key_time=0;}break;case key_state_2:if(key_val==NO_KEY) //short{key_state=key_state_0; key_return=key_prev;}else{key_time++; //0.8s==800ms 10ms扫描一次 -->80/* 要求不松手一直快速增加,所以不进入松手检测key_state_3,key_state一 直是key_state_2,松手后进入switch后的case key_state_2时因为 key_val==NO_KEY, 所以会回到初始状态,系统将重新运行 */if(key_time>=80){key_return=key_val; }break;}return key_return;
}
定时器2的学习和使用总结
2.定时器2用法
尤其注意定时器T2的初始化过程,是直接对8位寄存器进行操作的,然后还有T2在15系列的中断号 12。定时器2①T2控制寄存器-AUXR
//---------------------------------------------------------------------------------------
注意:(1)由于无法用查询法,所以尽量不用到超声波检测中(较复杂)。
(2) 中断允许寄存器 IE2 不可位寻址,所以主程序中想要关中断来保护时许时不能直接对 ET2 操作,要对寄存器IE2整体赋值。
void Timer2Init(void) //1毫秒@12.000MHz //用于模板
{AUXR |= 0x04; //定时器时钟1T模式T2L = 0x20; //设置定时初值T2H = 0xD1; //设置定时初值AUXR |= 0x10; //定时器2开始计时IE2 |= (1<<2); // (自己写) 0100 ->开启中断 关闭的写法:IE2 &= (~(1<<2))EA = 1;
}
3.串口文件写好后编译若出现很多警告,检查是否将uart.c加入到工程中
4.单片机内部晶振工作频率和波特率初始化函数中的要对应,否则串口通信会出错。
普通51单片机不能修改,使用的晶振为11.0592MHz或12MHz, 而IAP15可以在STC-ISP中设置多种晶振频率。
5.用移位法矩阵键盘对串口会有影响,最好用普通赋值法矩阵键盘
uart通信判断数据接收完成方法——超时检测法
注:这个方法是我在备赛期间从CSDN上的大佬那学习来的(特别好用)
之前一直在想串口中断函数里面怎么判断接收的数据是否收完,其中一种方法可以规定好接收回来的数据的数据格式,比方说固定以换行字符作为结束符号,但是这个方法的问题在于有时候不一定规定得了,换句话说假如单片机和某个芯片模块进行通信,而那个模块发送的数据字节我们则是没办法规定它是以什么结束的,如果是单片机和单片机通信的话就可以。而我后来网上查找资料发现还有一种方法就是超时检测法。
超时检测法其实原理也很简单,就是用定时器去定时扫描,比如:定义一个变量,给这个变量赋一个初值,然后每当进入定时器中断里面,则该变量减一;在串口中断方面,每当进入串口中断,则重新给这个变量赋最初的那个初值。也就是说,如果数据发送完了,那么就不会进入串口中断,因此,当该变量减到为0的时候,我们就可以认为数据已经接收完了。
第十一届蓝桥杯电子类国赛总结回顾相关推荐
- 第十一届蓝桥杯 2020年国赛真题及解析 (Java 大学B组)
第十一届蓝桥杯 2020年国赛真题 Java 大学B组 A 美丽的 2 B 扩散 C 阶乘约数 D 本质上升序列 E 玩具蛇 F 蓝肽子序列 G 皮亚诺曲线距离 H 画廊 I 补给 J 质数行者 所 ...
- 2020第十一届蓝桥杯C/C++国赛B组
文章目录 试题 A: 美丽的 2 试题 B: 扩散 试题 C: 阶乘约数 试题 D: 本质上升序列 试题 E: 玩具蛇 试题 F: 皮亚诺曲线距离 试题 G: 游园安排 试题 H: 答疑 试题 I: ...
- 2020年第十一届蓝桥杯javaB组国赛
文章目录 试题 A: 美丽的 2 试题 B: 扩散 试题 C: 阶乘约数 试题 D: 本质上升序列 试题 E: 玩具蛇 试题 F: 蓝肽子序列 试题 G: 皮亚诺曲线距离 试题 H: 画廊 试题 I: ...
- 历届蓝桥杯Scratch编程国赛 初级 中级 青少年编程比赛国赛真题解析【持续更新 已更新至27题】
历届蓝桥杯国赛真题 第十三界.十二届.十一届等历届青少年蓝桥杯Scratch编程比赛国赛真题解析 国赛真题01-河马带球[试看] [蓝桥杯国赛真题01]Scratch河马带球 少儿编程蓝桥杯Scrat ...
- 2020第十一届蓝桥杯7月份省赛真题(JavaB组题解)
2020第十一届蓝桥杯7月份省赛真题(JavaB组题解) 试题 A: 解密 试题 B: 纪念日 试题 C: 合并检测 试题 D: 分配口罩 试题 E: 斐波那契数列最大公约数 试题 F: 分类计数 试 ...
- 第十二届蓝桥杯青少年组国赛C++中级组 第1题 -- 第3题(python3实现)
12届蓝桥杯青少年组国赛C++中级组编程题 12届蓝桥杯青少年组国赛C++中级组编程题_lybc2019的博客-CSDN博客 蓝桥杯算法学习路线 | 全程制作过程公开 蓝桥杯算法学习路线 | 全程制作 ...
- 【2021年蓝桥杯Java-B组国赛题解】
2021年蓝桥杯Java-B组国赛
- 2020年第十一届蓝桥杯第二场省赛B组C++题解
2020年第十一届蓝桥杯第二场省赛B组C++题解 题单 第一题 第二题 第三题 第四题 第五题 第六题 第七题 第八题 题单 第一题 小蓝要为一条街的住户制作门牌号. 这条街一共有 2020 位住户, ...
- 蓝桥杯2013年国赛A组——网络寻路(DFS和中转边巧解)
蓝桥杯2013年国赛A组--网络寻路 1.题目描述 2.输入输出 3.样例输入和输出 4.题目分析 1.首先明确,题目中的目的地有两种,一种是回到原点,一种是到达没有到达的地方 2.在路径中经过的点不 ...
最新文章
- 【风控建模】在python中使用评分卡技术
- Java泛型中的通配符?
- 牛客题霸 NC13 二叉树的最大深度
- 来来来,大家说一下CPU!【关于 CPU 的一些基本知识总结】
- Megacli恢复RAID0磁盘数据
- 允许Sublime编辑器在Ubuntu上输入中文
- 【github系列】github代码仓创建及更新
- Linux修改时区和时间
- fiddler everywhere使用_用Fiddler抓取iOS https流量
- Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 nacos
- 华为发布IdeaHub S2系列,与华为云会议结合更强大
- 小米pro15拆机_小米笔记本拆解
- 王道训练营3月11日
- mine 规范_2016国家最新设计及验收标准名称汇编GB
- 在Azure的云服务器上搭建个人网站
- 类似QQ的可隐藏的便签工具SNOTE
- ue4 从小到大_UE4 Pak 相关知识总结
- C# 上传本地文件到远程共享文件夹,从远程共享文件夹下载文件到本地
- 消除VMware启动虚拟机时的floppy0提示的方法
- 计量经济学笔记——自相关的检验和处理(转载)