蓝桥杯单片机国赛模块儿总结
前言
明天就是国赛了,时间挺快的,得赶紧复习一下了。
摸鱼摸到现在,差不多已经放弃了。
国赛的模块其实只是比省赛多了几个常见的外设和模块儿,这里就不细述了,具体可以看省赛模块总结
目录
- 前言
- 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;
}
后记
明天就要决赛了。。。。可我感觉不到任何紧张,甚至没有复习欲望。。。。
可以预想到,这次差不多凉了
蓝桥杯单片机国赛模块儿总结相关推荐
- 【蓝桥杯】第十三届蓝桥杯单片机国赛 代码程序
第十三届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这 ...
- 【蓝桥杯】第九届蓝桥杯单片机国赛 代码程序
第九届蓝桥杯单片机国赛 程序 题目 hex文件 代码 工程文件 B站视频 更多资料 题目 历届的省赛和国赛的题目我已经在前面的文章(点击查看)里给大家分享了(网盘资源),需要的话,直接去下载,我在这里 ...
- 蓝桥杯嵌入式国赛模块训练之数码管
文章目录 前言 一.电路原理图 1.共阴极数码管 2.SN74LS595N 3. 扩展板跳线帽连接 二.驱动代码 1.seg.h 2.seg.c 总结 前言 数码管是蓝桥杯嵌入式国赛需准备的第一个模块 ...
- 【蓝桥杯单片机国赛 第九届】
蓝桥杯国赛模块讲解 蓝桥杯国赛第九届 题目 做题思路 首先smg测试 独立按键的长短按键 测电压(PCF) 存储数据(AT24C02) DS18B20 NE555 逻辑部分 先写S4控制的1)的三个界 ...
- 蓝桥杯单片机国赛客观题_蓝桥杯单片机比赛历年试题获取
蓝桥杯单片机比赛历年试题获取!!! 准备蓝桥杯蓝桥杯比赛除了对板子各个模块的熟悉外,还有一件事,那就是把它们综合起来运用.当你单独使用板子上的某一个模块时,可能不会有什么问题,甚至对已经反复练习过后的 ...
- 第十届蓝桥杯单片机国赛代码实现
代码如下: #include <STC15F2K60S2.H> #include "iic.h" #include "onewire.h" #inc ...
- 蓝桥杯单片机国赛客观题_第十一届蓝桥杯青少年组Scratch竞赛规则与样题
注意:文末邮福利哦!!! 竞赛时长:Scratch编程组竞赛的选拔赛.省赛及国赛,竞赛时长均为90分钟. 竞赛形式:一人一机,(比赛中 WIFI 网络关闭)选手自带笔记本电脑,电脑上提前预装Scrat ...
- 蓝桥杯单片机国赛客观题_【单片机自学入门必+收藏】蓝桥杯Arduino单片机 | 02 趣玩TM1637四位数码管模块...
TM1637模块:四位红色LED数码管显示器,8级灰度可调,且带有时钟点":",电源接口可接:5v或3.3v,可以通过编写程序实现数字时钟显示.倒计时.按钮交互记分牌等功能. TM ...
- 蓝桥杯嵌入式——第十二届蓝桥杯嵌入式国赛
蓝桥杯嵌入式--第十二届蓝桥杯嵌入式国赛 之前准备省赛的时候用的是旧版的STM32F103,从准备国赛开始就用新版STM32G431平台了,主要是想经过新版的准备学习一下HAL库以及CubeMX的使用 ...
最新文章
- mysql启动后在哪里编程_启动mysql后怎么连接数据库
- 会话中的存储技术和一些细节
- gevent queue应用1
- setting an array element with a sequence
- python装饰器函数-Python函数装饰器常见使用方法实例详解
- div固定在浏览器顶部_手写几种常见的css布局,1垂直两栏左边固定右边自适应,垂直3栏左右固定中间自适应...
- java保存文件到linux指定目录_怎么使用java编程实现linux下全部文件目录的遍历
- Python_内置模块1
- POI读取单元格信息及单元格公式
- IUnknow IDispatch IInspectable QueryInterface
- 论文解读《使用支持向量机和PSSM谱预测蛋白质中的RNA结合位点》
- precision,recall,sensitivity, specificity ,mAP等几种评价指标
- 【Java获取国家法定节假日三种工具类其三】
- flex 的图片浏览
- python求平均数保留两位小数_python求平均数、方差、中位数的例子
- 企业如何通过CRM系统做好客户管理?
- RIGOL示波器编程使用
- 如何在生产环境使用devtools?
- 【错误记录】手机应用无法联网 ( 添加 READ_PRIVILEGED_PHONE_STATE 权限导致手机应用网络不可用 )
- 《领导力》读后感笔记