独立按键实际上是一个非自锁的轻触开关,有左右两个触点,当按下时左右两个触点闭合,当松开时左右两个触点断开。
想要使用外部的按键控制单片机有两种比较常见的方法:IO扫描和外部中断。对于IO扫描的方式而言,需要单片机以比较高的频率去不间断地判断IO口的输入电平,随后根据IO电平来执行后续的逻辑。外部中断的方式会在章节十二中进行详细介绍,本章着重介绍IO扫描的控制方式。(单片机通过检测按键按下前后的高低电平变化,来判断按键是否按下。通过程序的控制,就可以实现不同的功能与设置。机械式按键在按下或者释放时,由于机械弹性作用的影响,通常伴随有一定时间的触点机械抖动,然后其触点才稳定下来。抖动时间长短与开关的机械特性有关,一般为5-10ms。在触点抖动期间检测按键的按下与否,可能会导致判断错误,为了克服机械抖动所产生的影响,必须采取消抖措施,可分为硬件消抖和软件消抖。)
对于一个IO而言,在将其配置为输入模式之后,该引脚上的电平受外部电路影响,基本可以分为三种状态:高电平、低电平、浮空。高低电平很好理解,这里说明浮空的意义,浮空就是不对该IO进行任何电气属性的连接,此时该IO上的电平是未知的(虽然从直观感受上来看此时IO电压应该是0,但是空气中会有噪声,电路板上也会有噪声,某些电磁干扰也会充当噪声,所以浮空输入的IO电压实际上是未知的)。典型的浮空输入型IO电路如图3-1所示:
图3-1 浮空输入IO电路
当开关闭合,IO电压等于VCC电压,当开关断开,IO电压未知,此时IO电压可能会受到不明来源的干扰,如果使用该电路作为IO扫描的电路方案,抗干扰能力会不好,容易造成误触发,故此应用场景下不考虑使用该电路。和浮空输入相比,比较好的办法是使用上拉电阻或下拉电阻将IO的电压固定下来,带上拉电阻或下拉电阻电路如图3-2所示:
图3-2 上拉电阻(左) 和 下拉电阻(右)
电路上拉电阻可以将IO电压固定在VCC电压,当开关闭合时,IO接地使其电压变为GND电压;下拉电阻可以将IO电压固定在GND电压,当开关闭合时,IO电压其实就是电阻R2的电压,此时R2的电压就是VCC。使用上拉/下拉电阻可以很好地提高IO扫描的抗干扰性能,一般情况这两个电路不会有很大区别,挑一个你喜欢的用就好。按键通过金属导体的相互接触来控制电信号,由于机械特性,这种接触实际上并不可靠,手指按下按键不代表按键真的闭合且保持稳定,这种情况就是按键抖动,抖动过程中按键控制的信号处于亚稳态,亚稳态的信号不可靠,不能将其作为IO扫描的最终结果,为了获取正确的按键状态,我们需要对按键进行消抖处理,按键消抖大概可以分为两种方式:
图3-3 硬件消抖电路
在条件允许的情况下,硬件消抖的效果会更好,如果PCB没有多余的空间留给这个消抖电容,使用软件消抖同样是一个不错的方案。
CW32F003核心板上一共有两个按键,一个复位和一个用户按键,复位作为单片机的特殊功能,不可以作为按键使用,故只有用户按键可以作为按键使用。CW32F003核心板关于独立按键的原理图如图3-4所示。
图3-4 CW32F003按键电路
通过上面的原理图可以了解到,按键的一端接到了地,另一端接到单片机的PB2引脚上。通过检测PB2引脚的电平状态,判断按键是否按下。当按键松开的时候,PB2检测到的电平为高电平,当按键按下的时候,PB2检测到的电平为低电平。外部电路不含上下拉电阻,对IO而言是浮空输入,因此需要使用单片机内部的上下拉电阻;电路不含消抖电容,故编程上需要对按键进行软件消抖。**3.4.按键控制LED灯亮灭
一般我们使用GPIO的输入功能,都需要有以下几个步骤。
从开发板原理图了解到按键接的是单片机的PB2。我们要使能按键就需要配置GPIOB端口。下面我们就以按键连接的PB2进行介绍。3.4.1.1.开启GPIO的端口初始化由于时钟的配置在之前的章节已有说明,故不再赘述,我们直接对端口进行初始化。初始化的代码与上文GPIO输出的配置略有不同,完整代码如下:
void Gpio_Init(void)
{
__RCC_GPIOC_CLK_ENABLE();//打开GPIOC的时钟,PC0控制LED亮灭
GPIO_InitTypeDef GPIO_InitStruct;
GPIO_InitStruct.Pins = GPIO_PIN_0;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.IT = GPIO_IT_NONE;
GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
GPIO_Init(CW_GPIOC, &GPIO_InitStruct);
__RCC_GPIOB_CLK_ENABLE();//打开GPIOB的时钟,PB2控制按键输入
GPIO_InitStruct.Pins = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP; //没有输入时PB2默认为高电平
GPIO_InitStruct.IT = GPIO_IT_NONE;
GPIO_Init(CW_GPIOB, &GPIO_InitStruct);
}
本次实验采用软件消抖,消抖函数的编写思路为:设置按键检测标志位(Flag_Key),当单片机检测到按键按下,即PB2为低电平时,将标志位置1;在后续的条件判断中如果标志位为1,则检测按键是否松开,若已松开则完成本次判断,认为按键已经按下过一次。这种方式可以不用延时判断,节约软件资源。完整的按键检测程序如下:
uint8_t Flag_Key; //按键标志位
extern uint8_t Flag_LED; //LED显示标志位
void Key_Scan(void)
{
if(GPIO_ReadPin(CW_GPIOB,GPIO_PIN_2) == GPIO_Pin_RESET) //检测PB2是否为低电平
{
Flag_Key = 1;
}
if(Flag_Key) //接着判断标志位
{
if(GPIO_ReadPin(CW_GPIOB,GPIO_PIN_2) == GPIO_Pin_SET) //如果按键已经松开
{
Flag_Key = 0; //清零标志位,等待下一次按键检测
if(Flag_LED == 0) Flag_LED = 1; //按键按下该变LED显示标志位的值,由显示标志位控制LED
else Flag_LED = 0;
}
}
}
在按键按下更改LED显示标志位后,需要根据显示标志位的值来控制LED灯的亮灭。
uint8_t Flag_LED;
void LED_Init(void)
{
GPIO_WritePin(CW_GPIOC,GPIO_PIN_0,GPIO_Pin_SET); //初始化让LED灯处于熄灭状态
}
void LED_Lighting(void)
{
if(Flag_LED == 1)
{
GPIO_WritePin(CW_GPIOC,GPIO_PIN_0,GPIO_Pin_RESET); //亮
}
else
{
GPIO_WritePin(CW_GPIOC,GPIO_PIN_0,GPIO_Pin_SET); //灭
}
}
最终主函数里只需要运行相应的初始化函数和上面的函数:
int main()
{
RCC_Configuration();
Gpio_Init();
LED_Init();
while(1)
{
审核编辑 黄宇
全部0条评论
快来发表一下你的评论吧 !