【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
做技术的同学,大部分都会把精力放在技术本身,却忽视了学的东西有什么实际的用途。就拿gpio来说,一般我们点灯也好、做输入也好,最多也就是当成一个实验demo在使用。可是大家有没有思考过,其实这样一个模块就已经是一个完整的输入、输出的系统了。简单的方面,我们可以做一个2-4译码器、3-8译码器,复杂一点的,我们可以做玩具、做一个设备改造的模块。
很多同学不理解这个设备改造的模块,还是以卷帘门为例。过去卷帘门,一般就是向上按键按下去,卷帘门上升;向下按键按下去,卷帘门下降。如果我们想扩展一下这个功能,比如向上按下去的时候,为了安全需要,不仅卷帘门上升,还要有一个语音和红绿灯显示,这个时候就可以用这样一个模块来完成了。过去可能非标领域一般都是通过plc来完成,现在我们自己学会了mcu开发,就很自然地想通过mcu来完成。
1、按键输入
按键输入是和按键输出对应的。按键输出,一般是led点亮、熄灭,又或者是蜂鸣器呼叫等等而按键输入,更多时候来自于外部的反馈,它表示使用的人员希望开启、使用或者是关闭某个功能。
2、main函数分析
首先,我们还是看下整个demo的原貌,
int main(void)
{
SystemClock_Config();
LED_GPIO_Config();
Key_GPIO_Config();
while(1)
{
if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON )
{
LED1_ON;
}
else
{
LED1_OFF;
}
}
}
和之前相比较,整个流程多了两部分,第一个是添加Key_GPIO_Config,这个主要是告诉mcu,哪些按键希望被当做是key输入使用。第二个是Key_Scan,主要用于检测当前KEY1_PIN是不是已经被按下。如果是被按下了,那么LED1点亮,反之熄灭。
3、配置按键输入
前面我们说过,要配置按键输入,需要看下Key_GPIO_Config是如何实现的。这部分关注的重点,集中在它和之前GPIO输出有什么差别。
void Key_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
KEY1_GPIO_CLK_ENABLE();
GPIO_InitStructure.Pin = KEY1_PIN;
GPIO_InitStructure.Mode = GPIO_MODE_INPUT;
GPIO_InitStructure.Pull = GPIO_NOPULL;
HAL_GPIO_Init(KEY1_GPIO_PORT, &GPIO_InitStructure);
}
这里的KEY1_PIN是a0,不过不是重点。重点在于,当key处于输入状态的时候,它的mode和pull是不一样的。这部分,大家可以对比一下之前led的设置,这样看起来效果更好。
void LED_GPIO_Config(void)
{
GPIO_InitTypeDef GPIO_InitStruct;
LED1_GPIO_CLK_ENABLE();
GPIO_InitStruct.Pin = LED1_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(LED1_GPIO_PORT, &GPIO_InitStruct);
LED_RGBOFF;
}
4、轮询检查key的状态
较早读书的时候,我会认为轮询是非常低效的一种情况。但是到了mcu这里,轮询是非常常见的一种开发方式。特别是功能比较单一的时候,轮询其实很简洁、很鲁棒,几乎不会出错,
uint8_t Key_Scan(GPIO_TypeDef* GPIOx,uint16_t GPIO_Pin)
{
if(HAL_GPIO_ReadPin(GPIOx,GPIO_Pin) == KEY_ON )
{
return KEY_ON;
}
else
{
return KEY_OFF;
}
}
5、测试方法
之前野火提供的测试demo其实不是这样,它的case其实是依据它自身的开发板实现的。上面有现成的实体按键。这边的话,我们既然是用一个stm32f103的核心板进行测试,那么就用一根短接线进行测试好了。
短接线的一头连接在a0上面,另外一头可以连接到电源3.3v,又或者是gnd上面。如果是连接在电源3.3v上面,c13应该亮起;反之则熄灭。通过这样的方式,也可以观察到按键输入的实际效果。另外还有一点要注意的是,我们核心板上面只有一个c13可以点灯,这和野火官方的demo不太一样,所以同样需要改造一下,
#define LED1_PIN GPIO_PIN_13
#define LED1_GPIO_PORT GPIOC
#define LED1_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE()
6、美中不足
这边按键按下去的时候,正常情况下都会delay延时一下,一段事件之后确认按键是不是真的被按下。这样做的好处是防止误触、或者是抖动的发生。当然,我们也可以让测试做的更好玩一点,比如设置成闪烁的形式,
int main(void)
{
SystemClock_Config();
LED_GPIO_Config();
Key_GPIO_Config();
while(1)
{
if( Key_Scan(KEY1_GPIO_PORT,KEY1_PIN) == KEY_ON )
{
HAL_Delay(1000);
LED1_ON;
HAL_Delay(1000);
LED1_OFF;
}
else
{
LED1_OFF;
}
}
}