作者:马一飞 QQ:791729359
在学习过程中有什么问题可以联系
(原本资料是以网盘的方式公开提供给任何蓝桥杯爱好者进行下载的,但是最近临近蓝桥杯考试,遇到了很多伸手党,我无偿给爱好者们解答学习上的问题,回复得比较慢居然还有同学来说我这样那样,所以决定不再随意提供自己写的源码和资料。博主已经开始参加工作了,也不是闲着没事干盯着电脑手机为你们服务。记住,不要成为伸手党,要自己多动手实现。)
同样,与LED的配置相同,我们先创建一个HARDWARE目录,并且创建一个IO.c和IO.h放在HARDWARE目录下。同时还要吧IO.c文件放入到工程里。还要把.h文件的路径告诉编译器。
那么到这一步,我们的准备工作就做好了,可以开始准备编写独立按键的代码。
编写按键初始化函数
void KEY_Init(void) //按键初始化函数
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_Init(GPIOB, &GPIO_InitStructure);
}
在编写的过程中我们还得看一下开发板电路原理图,确定好按键是连接在哪个引脚上。
很显然,我们能够很清楚的看到,他分别连接在了PA0,PA8,PB1,PB2的引脚上。那我们就可以开始对他们进行编程了。
首先必不可少的要先使能PA,PB引脚的时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB,ENABLE);
那么这个函数的原型我们可以再RCC的库函数里找到。同时,我们对这个引脚进行初始化。
GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);
这个函数原型在GPIO的库函数里可以找到。(具体寻找方法请参考LED章节)
并且把这PA0,PA8,PB1,PB2的模式设置为上拉输入,也就是GPIO_Mode_IPU。因为我们这个按键另外一端连接的是地,当我们按键没有按下的时候,我们的引脚会被上拉电阻拉高,获取到高电平,只有当我们按下按键时,引脚的电平才会变为低电平。
同时我们还在IO.h里进行了一个宏定义
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);
这个函数的作用是可以用来获取某个引脚的电平,返回值就是它的电平状态(高电平返回1,低电平返回0)。我们进行一个宏定义可以使我们接下来更方便的获取引脚的电平值(注意:宏定义后一定不要加分号)。
接下来我们就可以开始撰写按键的读取函数了(按键的读取函数编写比较长,我们就截取一部分来讲解,因为下面都是一样的)
可以很明显的看到,我定义了4个16位的静态无符号整型变量,这4个静态变量的作用就是用来计数的。当我们按键一被按下时候,我们的key1_sum 加一,然后就可以执行短按按键的程序,直到我们松开了按键一后,key1_sum才会清零。当然,大家也可以自己编写自己的按键程序,每个人都有自己的代码风格,我的这样编写按键读取函数的好处是可以使用长短按键的功能,那么这个功能的实现后面在讲解。
在编写完按键读取函数后,我们要通过定时器,来扫描我们的按键函数,我们现在main.c里面定义一个按键读取标志位
同时在主循环里面还得编写,当这个按键读取标志位被置1时候,按键就进行一次读取,读取完成后就标志位清零。
这个方式有点类似于我们任务调度一样,只有当这个标志位置1了,才代表我们可以读取这个按键函数,如果没置1的话我们则不读取。
那么我们这个KEY_Flag到底什么时候才置1呢,这时候我们就要开始用我们的滴答定时器来定时了。我们去到stm32f10x_it.c这个文件里,添加这些命令。
之前说过,这个滴答定时中断函数我们可以看做是一个1ms的定时器,我们在定时器里面计数,当计数值等于50(也就是50ms),我们就把计数值清零,同时KEY_Flag 置1,我们就可以在主循环里读取我们按键函数了。也就是说来理想状态下,每50ms就会读取一次KEY_Read()这个函数,那么就会有人问,这也就是在理想情况,那么我们再主循环里面添加了很多其他的函数,那么KEY_Read()的读取间隔就会大于50ms,答案是一定会的,但是在蓝桥杯里我们可以不考虑这个情况,因为蓝桥杯嵌入式的比赛中,其他外设所考的模块里,没有一个模块是需要用到长时间的延时函数的,因此这个干扰在蓝桥杯中可以忽略不计,我们直接按照理想状态来编写就好。
同时也会有人问,为什么要50ms扫描一次KEY_Read()呢?想了解这个问题的话建议还是私聊我吧,经测试扫描间隔只要大于50ms,基本就已经不会受到按键抖动的影响了。大家可以使用这个结论。
拓展部分(长按触发)
长按触发功能其实在蓝桥杯嵌入式的比赛中并不常考,但第九届的嵌入式省赛中却考到了长短按键的功能。
给大家的代码里面,我也写了一个长按触发的代码提供给大家理解,其实这个原理也很简单,也就使用了一个计数的方式,然后到了你指定的计数值再触发。
我用了按键4来演示这个效果,之前也讲到了,我们每50ms就会扫描一次KEY_Read()这个函数,如果按键被按下的话,相应的计数值每50ms加1,直到松开按键,相应的计数值才会清零。
在程序中我们可以看到,当我们一直按下按键4,直到key4_sum加到40的时候,我们才执行长按的程序,也就是 40 * 50 = 2000ms ,我们就对进行LED8取反的操作。为了更好的显示这个长按的效果,当触发了长按之后,我把key4_sum = 30,只要持续按下按键4不松开,每过500ms都会执行一次长按的程序。
那么达到的效果就是,当我们按下按键4超过2s时候,LED8就会以0.5S的间隔进行闪烁,知道按键松开后停止。我们可以把程序烧录到蓝桥杯嵌入式开发板里查看他的效果。
(以上仅属于个人观点)