前言

明天就是国赛了,时间挺快的,得赶紧复习一下了。
摸鱼摸到现在,差不多已经放弃了。

国赛的模块其实只是比省赛多了几个常见的外设和模块儿,这里就不细述了,具体可以看省赛模块总结


目录

  • 前言
  • 1、串口
    • 1.1、串口初始化
    • 1.2、串口发送不定字长数据
    • 1.3、数字转化字符串
  • 2、矩阵键盘
  • 3、按键长按
  • 4、超声波测距
    • 注意事项
    • 代码
  • 5、数码管消位动态显示
  • 6、温度传感器小数的处理
  • 后记

1、串口

1.1、串口初始化

串口的配置可以通过STC-ISP来对波特率进行配置

STC15拥有多个定时器,因此波特率发生器也可以是定时器2发生,这可以很好避免一些模块儿的冲突。

当配置完波特率记得打开串口中断

不同的串口中断,对应不同的寄存器,但是默认的串口1中断往往是可谓寻址的ES


由图我们可以蓝桥杯单片机的串口中断有2种。由于串口1就可以用到定时器2发生波特率,所以我们应该不需要串口2.。。

void UartInit(void)      //4800bps@12.000MHz
{SCON = 0x50;      //8位数据,可变波特率AUXR |= 0x01;      //串口1选择定时器2为波特率发生器AUXR |= 0x04;        //定时器2时钟为Fosc,即1TT2L = 0x8F;       //设定定时初值T2H = 0xFD;        //设定定时初值AUXR |= 0x10;      //启动定时器2ES = 1;            //打开串口1中断
}

1.2、串口发送不定字长数据

这里不得不说,32寄存器多是真的爽,一个总线空闲中断IDLE标志位解决一切不定字长数据带来的烦恼。但是51的中断标志位只有RI(开始接收数据标志位)和TI(数据发送完毕标志位)。但是话说得好,上有政策下有对策 ,我们可以用超时检测法来接收不定字长的数据!

原理:每当串口完成接收一字节的数据,我们就让其中一个定时器开始一个计时,并且清零计时的数据。在定时器中断中,若计时大于20ms就判定为超时,不再接受数据。

代码:

需要定义的全局变量
uint8 pdata RxBuf[20];//用于接收数据
uint8 pdata usart_count = 0;//接收数据长度
bit usart_time_flag = 0;//定时器计数标志位串口中断部分
void usart1it() interrupt 4
{uint8 tmp = 0;usart_time_flag = 0;TI = 0;if(RI){RI = 0;tmp = SBUF;RxBuf[usart_count] = tmp;usart_count++;}usart_time_flag = 1;
}定时器中断部分
void interrupt0() interrupt 1
{static uint8  usart_Timer = 0;TL0 = 0x18;        //设置定时初值TH0 = 0xFC;        //设置定时初值if(usart_time_flag)usart_Timer++;elseusart_Timer = 0;if(usart_Timer >= 30){usart_Timer = 0;RxBuf[usart_count] = '\0';usart_count = 0;Usart_Rx_Mod(RxBuf);usart_time_flag = 0;}
}

1.3、数字转化字符串

数字转化字符串可以直接使用c语言自带的sprintf函数
该函数在stdio.h的头文件中
一定记得加!!
使用代码

uint16 Temp_Dat; //注意,这里数据一定要定义为十六位长度的数据!!
uint8 Temp_Dat_Str[3];
sprintf(Temp_Dat_Str,"%d",Temp_Dat);

2、矩阵键盘

矩阵键盘我们可以参考金沙滩的方法,动态扫描消抖!!
代码

uint8 code Key[4][4] = {{ 4, 5, 6, 7},{ 8, 9,10,11},{12,13,14,15},{16,17,18,19},
};uint8 pdata KeySta[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},
};
void Key_State()//此函数在主循环中使用
{static uint8 backup[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},};uint8 i = 0,j = 0;for(i=0;i<4;i++){for(j=0;j<4;j++){if(backup[i][j]!=KeySta[i][j]){if(backup[i][j] == 0){Key_Action(Key[i][j]);}Key_Close = 0;backup[i][j] = KeySta[i][j];}}}}void Key_Scan()//此函数在中断中使用
{static uint8 KeyBuf[4][4] = {{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},{0xff,0xff,0xff,0xff},};static uint8 index = 0;uint8 i;KeyBuf[index][0] = (KeyBuf[index][0]<<1)|S1_I;KeyBuf[index][1] = (KeyBuf[index][1]<<1)|S2_I;KeyBuf[index][2] = (KeyBuf[index][2]<<1)|S3_I;KeyBuf[index][3] = (KeyBuf[index][3]<<1)|S4_I;for(i=0;i<4;i++){switch(KeyBuf[index][i]){case 0x0f:KeySta[index][i] = 1;break;case 0x00:KeySta[index][i] = 0;break;default:break;}}switch(index){case 3:S1_O = 0;S4_O = 1;break;case 0:S2_O = 0;S1_O = 1;break;case 1:S3_O = 0;S2_O = 1;break;case 2:S4_O = 0;S3_O = 1;break;default:break;}index++;index &= 0x03;
}

3、按键长按

按键长按的原理和串口超时检测的原理差不多,也是利用标志位,开启一个定时器计数,但是定时器计数需要增加约束。而且这个约束要在开关弹起时关闭!

代码实现

主循环的按键扫描中
void Key_State()
{static uint8 backup[4][4] = {{1,1,1,1},{1,1,1,1},{1,1,1,1},{1,1,1,1},};uint8 i = 0,j = 0;for(i=0;i<4;i++){for(j=0;j<4;j++){if(backup[i][j]!=KeySta[i][j]){if(backup[i][j] == 1)//当按键按下{if(Key[i][j] == 12)//如果是按键12{Long_Key_State_12 = 1;//置位定时器长按按键计数标志位}if(Key[i][j] == 13){Long_Key_State_13 = 1;}}if(backup[i][j] == 0)//当按键弹启{Long_Key_State_13 = 0;//关闭标志位Long_Key_State_12 = 0;if(Key_Close)//此处判断长按动作是否执行过,执行过的话就不执行普通的按键动作Key_Close = 0;//标志位清零elseKey_Action(Key[i][j]);}Key_Close = 0;backup[i][j] = KeySta[i][j];}}}
}定时器中断部分
void interrupt0() interrupt 1
{//============定义长按按键的时间============static uint16 Long_Key_13_Timer = 0;static uint16 Long_Key_12_Timer = 0;//============定义1ms中断============TL0 = 0x18;      //设置定时初值TH0 = 0xFC;        //设置定时初值//============根据按键长按状态判断是否计时============if(Long_Key_State_13)Long_Key_13_Timer++;elseLong_Key_13_Timer = 0;if(Long_Key_State_12)Long_Key_12_Timer++;elseLong_Key_12_Timer = 0;//============当按下时间超过1s,开启功能标志位和取消普通按键动作标志位============if(Long_Key_13_Timer >= 1000){Long_Key_13_Timer = 0;Long_Key_13_Act = 1;Key_Close = 1;}if(Long_Key_12_Timer >= 1000){Long_Key_12_Timer = 0;Long_Key_12_Act = 1;Key_Close = 1;}Key_Scan();
}主函数的功能部分
void main()
{根据需要初始化while(1){if(Long_Key_13_Act){Long_Key_13_Act = 0;//清除动作标志位根据需要填写对应功能}if(Long_Key_12_Act){Long_Key_12_Act = 0;//清除动作标志位根据需要填写对应功能}Key_State();}
}

4、超声波测距

注意事项

国赛加了一个很重要的元器件,那就是超声波测距!!

首先,超声波是根据时间计算距离的,所以很重要的一点,记得关闭中断!!!

其次,蓝桥杯板子上的超声波跟我们平时买的模块不太一样,这上面并没有集成一些自动发送声波的芯片,所以想要我们手动发送8个间隔12微秒的声波。

再让后,超声波的Trig引脚在P10,Echo引脚在P11上。

最后,就是关于STC15的的12T与1T模式.
12T模式代表定时器器计数一次的时间为1微秒,也就是外部晶振震动12次的时间
1T模式代表定时器计数一次的时间为1/12微秒,也就是外部晶振振一次的时间

最后的最后,计算距离的定时器不要开启中断!!!

代码

sbit Trig = P1^0;
sbit Echo = P1^1;void Delay12us()      //@12.000MHz
{unsigned char i;_nop_();_nop_();i = 33;while (--i);
}void Trig_Out()//发送八个超声波
{uint8 i = 0;for(i=0;i<8;i++){Trig = 1;Delay12us();     //@12.000MHzTrig = 0;Delay12us();     //@12.000MHz}
}bit Distence_Cal()//计算距离
{bit error = 1;TH1 = 0;   //保证每次进入定时器1的值为0TL1 = 0;ET0 = 0;Trig_Out();TR1 = 1;      //定时器1开始计时while(Echo == 1&&TF1==0);//当ECHO引脚接收到数据或者定时器超时TR1 = 0;       //关闭定时器1ET0 = 1;       if(TF1 == 0)  //若是ECHO接收到数据{error = 1;Distence = (TH1<<8)+TL1;//获取定时器数值Distence = (Distence)*0.017;//计算距离}else  //若是超时状态{error = 0;TF1 = 0;//定时器超时状态置位}return error;
}

5、数码管消位动态显示

此处要实现的功能为,数码管前几位为零时不显示。也就是可以显示不定长的数字。
可以用math头文件的pow函数来把数字的第一位给取出来,判断是否为零,当发现一个不为零的数字的时候,我们将其正常显示即可。

实现代码

 SMG_SHOW[7] = 0xbf;//=========消零=========for(i=6;i>=0;i--){x = pow(10,i);if((Dat/x)%10 == 0)SMG_SHOW[i] = 0xff;else if((Dat/x)%10 != 0){SMG_SHOW[i] = SMG_NUM[(Dat/x)%10];break;}}//=========消零=========//========正常显示========for(;i>=0;i--){x = pow(10,i);SMG_SHOW[i] = SMG_NUM[(Dat/x)%10];}//========正常显示========

6、温度传感器小数的处理

蓝桥杯的板子需要配合数码管使用。

因此创建两个变量,分别来存储小数和整数!

uint16 Temp_Dat;//存放整数
uint16 Temp_Dec;//存放小数
void Temp_Read()
{uint8 LSB,MSB;uint16 Temp = 0;init_ds18b20();             //初始化ds18b20Write_DS18B20(0xCC);  //写入0xCC跳过ROM操作指令Write_DS18B20(0x44); //启动温度转换Delay_OneWire(100);   //延迟700ms左右,等待温度转换init_ds18b20();              //初始化ds18b20Write_DS18B20(0xCC);  //写入0xCC跳过ROM操作指令Write_DS18B20(0xBE); //启动温度转换LSB = Read_DS18B20(); //读取第八位MSB = Read_DS18B20(); //读取高八位/**************后四位为小数,前四位为符号,中间四位为整数**************/Temp = MSB;Temp = (Temp<<8)|LSB;Temp_Dat = Temp>>4;Temp_Dec = (LSB&0x0f)*6.25;
}

后记

明天就要决赛了。。。。可我感觉不到任何紧张,甚至没有复习欲望。。。。
可以预想到,这次差不多凉了

蓝桥杯单片机国赛模块儿总结相关推荐

  1. 【蓝桥杯】第十三届蓝桥杯单片机国赛 代码程序

    第十三届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这 ...

  2. 【蓝桥杯】第九届蓝桥杯单片机国赛 代码程序

    第九届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这里 ...

  3. 蓝桥杯嵌入式国赛模块训练之数码管

    文章目录 前言 一.电路原理图 1.共阴极数码管 2.SN74LS595N 3. 扩展板跳线帽连接 二.驱动代码 1.seg.h 2.seg.c 总结 前言 数码管是蓝桥杯嵌入式国赛需准备的第一个模块 ...

  4. 【蓝桥杯单片机国赛 第九届】

    蓝桥杯国赛模块讲解 蓝桥杯国赛第九届 题目 做题思路 首先smg测试 独立按键的长短按键 测电压(PCF) 存储数据(AT24C02) DS18B20 NE555 逻辑部分 先写S4控制的1)的三个界 ...

  5. 蓝桥杯单片机国赛客观题_蓝桥杯单片机比赛历年试题获取

    蓝桥杯单片机比赛历年试题获取!!! 准备蓝桥杯蓝桥杯比赛除了对板子各个模块的熟悉外,还有一件事,那就是把它们综合起来运用.当你单独使用板子上的某一个模块时,可能不会有什么问题,甚至对已经反复练习过后的 ...

  6. 第十届蓝桥杯单片机国赛代码实现

    代码如下: #include <STC15F2K60S2.H> #include "iic.h" #include "onewire.h" #inc ...

  7. 蓝桥杯单片机国赛客观题_第十一届蓝桥杯青少年组Scratch竞赛规则与样题

    注意:文末邮福利哦!!! 竞赛时长:Scratch编程组竞赛的选拔赛.省赛及国赛,竞赛时长均为90分钟. 竞赛形式:一人一机,(比赛中 WIFI 网络关闭)选手自带笔记本电脑,电脑上提前预装Scrat ...

  8. 蓝桥杯单片机国赛客观题_【单片机自学入门必+收藏】蓝桥杯Arduino单片机 | 02 趣玩TM1637四位数码管模块...

    TM1637模块:四位红色LED数码管显示器,8级灰度可调,且带有时钟点":",电源接口可接:5v或3.3v,可以通过编写程序实现数字时钟显示.倒计时.按钮交互记分牌等功能. TM ...

  9. 蓝桥杯嵌入式——第十二届蓝桥杯嵌入式国赛

    蓝桥杯嵌入式--第十二届蓝桥杯嵌入式国赛 之前准备省赛的时候用的是旧版的STM32F103,从准备国赛开始就用新版STM32G431平台了,主要是想经过新版的准备学习一下HAL库以及CubeMX的使用 ...

最新文章

  1. mysql启动后在哪里编程_启动mysql后怎么连接数据库
  2. 会话中的存储技术和一些细节
  3. gevent queue应用1
  4. setting an array element with a sequence
  5. python装饰器函数-Python函数装饰器常见使用方法实例详解
  6. div固定在浏览器顶部_手写几种常见的css布局,1垂直两栏左边固定右边自适应,垂直3栏左右固定中间自适应...
  7. java保存文件到linux指定目录_怎么使用java编程实现linux下全部文件目录的遍历
  8. Python_内置模块1
  9. POI读取单元格信息及单元格公式
  10. IUnknow IDispatch IInspectable QueryInterface
  11. 论文解读《使用支持向量机和PSSM谱预测蛋白质中的RNA结合位点》
  12. precision,recall,sensitivity, specificity ,mAP等几种评价指标
  13. 【Java获取国家法定节假日三种工具类其三】
  14. flex 的图片浏览
  15. python求平均数保留两位小数_python求平均数、方差、中位数的例子
  16. 企业如何通过CRM系统做好客户管理?
  17. RIGOL示波器编程使用
  18. 如何在生产环境使用devtools?
  19. 【错误记录】手机应用无法联网 ( 添加 READ_PRIVILEGED_PHONE_STATE 权限导致手机应用网络不可用 )
  20. 《领导力》读后感笔记

热门文章

  1. 【Docker系列】Docker Compose 环境变量
  2. 184-求x的平方根(两种实现方法)
  3. 虚幻4打开游戏开场动画设置相关问题
  4. Qdiscs配置TSN网络
  5. HandsFree OpenRE编译及烧录
  6. 【图像识别】基于模板匹配算法实现手写英文字母识别matlab代码
  7. IOT 赋能旅行场景的实践与展望
  8. 学习总结(2020.4.4)
  9. Shader山下(十七)语义Semantic
  10. 10KW科士达UPS电源PCB原理图10KWUPS方案 10KW科士达,UPS电源 包括PCB, 原理图,源代码。