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.

  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。
  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. 关于三位一体综合键盘
    (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的时候,我们就可以认为数据已经接收完了。

第十一届蓝桥杯电子类国赛总结回顾相关推荐

  1. 第十一届蓝桥杯 2020年国赛真题及解析 (Java 大学B组)

    第十一届蓝桥杯 2020年国赛真题 Java 大学B组 A 美丽的 2 B 扩散 C 阶乘约数 D 本质上升序列 E 玩具蛇 F 蓝肽子序列 ​G 皮亚诺曲线距离 H 画廊 I 补给 J 质数行者 所 ...

  2. 2020第十一届蓝桥杯C/C++国赛B组

    文章目录 试题 A: 美丽的 2 试题 B: 扩散 试题 C: 阶乘约数 试题 D: 本质上升序列 试题 E: 玩具蛇 试题 F: 皮亚诺曲线距离 试题 G: 游园安排 试题 H: 答疑 试题 I: ...

  3. 2020年第十一届蓝桥杯javaB组国赛

    文章目录 试题 A: 美丽的 2 试题 B: 扩散 试题 C: 阶乘约数 试题 D: 本质上升序列 试题 E: 玩具蛇 试题 F: 蓝肽子序列 试题 G: 皮亚诺曲线距离 试题 H: 画廊 试题 I: ...

  4. 历届蓝桥杯Scratch编程国赛 初级 中级 青少年编程比赛国赛真题解析【持续更新 已更新至27题】

    历届蓝桥杯国赛真题 第十三界.十二届.十一届等历届青少年蓝桥杯Scratch编程比赛国赛真题解析 国赛真题01-河马带球[试看] [蓝桥杯国赛真题01]Scratch河马带球 少儿编程蓝桥杯Scrat ...

  5. 2020第十一届蓝桥杯7月份省赛真题(JavaB组题解)

    2020第十一届蓝桥杯7月份省赛真题(JavaB组题解) 试题 A: 解密 试题 B: 纪念日 试题 C: 合并检测 试题 D: 分配口罩 试题 E: 斐波那契数列最大公约数 试题 F: 分类计数 试 ...

  6. 第十二届蓝桥杯青少年组国赛C++中级组 第1题 -- 第3题(python3实现)

    12届蓝桥杯青少年组国赛C++中级组编程题 12届蓝桥杯青少年组国赛C++中级组编程题_lybc2019的博客-CSDN博客 蓝桥杯算法学习路线 | 全程制作过程公开 蓝桥杯算法学习路线 | 全程制作 ...

  7. 【2021年蓝桥杯Java-B组国赛题解】

    2021年蓝桥杯Java-B组国赛

  8. 2020年第十一届蓝桥杯第二场省赛B组C++题解

    2020年第十一届蓝桥杯第二场省赛B组C++题解 题单 第一题 第二题 第三题 第四题 第五题 第六题 第七题 第八题 题单 第一题 小蓝要为一条街的住户制作门牌号. 这条街一共有 2020 位住户, ...

  9. 蓝桥杯2013年国赛A组——网络寻路(DFS和中转边巧解)

    蓝桥杯2013年国赛A组--网络寻路 1.题目描述 2.输入输出 3.样例输入和输出 4.题目分析 1.首先明确,题目中的目的地有两种,一种是回到原点,一种是到达没有到达的地方 2.在路径中经过的点不 ...

最新文章

  1. 【风控建模】在python中使用评分卡技术
  2. Java泛型中的通配符?
  3. 牛客题霸 NC13 二叉树的最大深度
  4. 来来来,大家说一下CPU!【关于 CPU 的一些基本知识总结】
  5. Megacli恢复RAID0磁盘数据
  6. 允许Sublime编辑器在Ubuntu上输入中文
  7. 【github系列】github代码仓创建及更新
  8. Linux修改时区和时间
  9. fiddler everywhere使用_用Fiddler抓取iOS https流量
  10. Centos7 Kubernetes(k8s) 开发服务器(单服务器)部署 nacos
  11. 华为发布IdeaHub S2系列,与华为云会议结合更强大
  12. 小米pro15拆机_小米笔记本拆解
  13. 王道训练营3月11日
  14. mine 规范_2016国家最新设计及验收标准名称汇编GB
  15. 在Azure的云服务器上搭建个人网站
  16. 类似QQ的可隐藏的便签工具SNOTE
  17. ue4 从小到大_UE4 Pak 相关知识总结
  18. C# 上传本地文件到远程共享文件夹,从远程共享文件夹下载文件到本地
  19. 消除VMware启动虚拟机时的floppy0提示的方法
  20. 计量经济学笔记——自相关的检验和处理(转载)

热门文章

  1. XML进阶增删改查及gdv的小知识
  2. 图扑推出可视化智慧仓储管理系统,能否解决购物狂欢节爆仓危机?
  3. 菜鸟安装Nodejs环境
  4. 株洲做网站多少钱,株洲企业网站建设多少钱
  5. 如何分发大文件、文件夹传输解决方案
  6. 客户端/服务器程序_了解客户端/服务器协议和Web应用程序
  7. 医疗系统的流程与相应技术
  8. 新版火狐浏览器自定义about:newtab页面背景图
  9. Category详解
  10. Mac上修复Gitee错误Oauth: Access token is expired