s3c2440学习之路-005 轮训模式读取key(按键)
2021-09-09 来源:eefocus
硬件平台:jz2440
软件平台:Ubuntu16.04 arm-linux-gcc-3.4.5
源码位置: https://github.com/lian494362816/C/tree/master/2440/006_key
1.原理分析
按键是常用的电子元器件,去读按键的方法主要有2种
1)轮训方式,就是需要不断的去读取按键的数值
2)中断方式,通过外部中断来实现,只有当按键 按下/松开 时才会触发,不需要不断的去读取按键的值
中断的方式配置比较复杂,本篇博客就先讲通过轮训的方式读取按键的值。
硬件原理很简单,从电源正极到地中间串联1个电阻和1个按键开关,然后2440的某个pin脚在连接上去,通过去读pin脚的电平来获取按键的数值。
当按键未按下时,读取到的就是高电平,2440获取到的就是1
当按键按下时,读取到的就是地电平,2440获取到的就是0
jz2440的原理图可能看上去有不同,因为分成了2个部分,1个是电阻上拉部分,1个是按键接地部分,不过最后组合起来就是上面那张图片的效果。这里有4按键,不过这次只用其中的3个。
EINT0–GPF0
EINT2–GPF2
EINT11–GPG3
jz2440按键原理图
2.主要流程
2440的GPIO pin脚有不同的功能,不过一般GPIO pin脚有3种模式,输入模式、输出模式、特殊功能模式。
输出模式和输出模式好理解,特殊功能模式则是这个pin脚的特殊功能,每个pin脚都不一样。
如当做外部中断、当做LCD控制引脚等等。如要需要读取按键的数值,当然就需要配置成输入模式了。 这里只配置3个按键,因为开发板上刚好有3个led灯,可以通过led的亮灭来显示按键的状态
1)将GPF0,GPF2, GPG3 设置成输入模式, 通过GPFCON和GPGCON来控制
2)读取GPF0, GPF2,GPG3的数值。GPF0,GPF2的数值通过读取GPFDAT的第0,第2位来确定。GPG3 的数值通过去读GPGDAT的第3位来确定
3)通过死循环,不断的读取GPFDAT和GPGDAT的数值来判断按键状态
4)若按键按下,则led亮,若按键未按下,则led灭
3. 源码
key.c
/*
Input =b00
EINT0 GPF0 [1:0]
EINT2 GPF2 [5:4]
EINT11 GPG3 [7:6]
*/
int key_init(void)
{
GPFCON &= ~(0x3 << 0);
GPFCON &= ~(0x3 << 4);
GPGCON &= ~(0x3 << 6);
return 0;
}
按键的初始化代码很简单,将3个GPIO配置成输出模式即可
key.c
int main(void)
{
int i = 0;
int key_gpf_value = 0;
int key_gpg_value = 0;
led_init();
key_init();
while(1)
{
key_gpf_value = GPFDAT;
key_gpg_value = GPGDAT;
/* 1 key release */
if (key_gpf_value & (1 << 0))
{
led_off(6);
}
else /* 0 key press */
{
led_on(6);
}
if (key_gpf_value & (1 << 2))
{
led_off(5);
}
else
{
led_on(5);
}
if(key_gpg_value & (1 <<3))
{
led_off(4);
}
else
{
led_on(4);
}
}
return 0;
}
主函数先初始化按键和led, 然后通过while(1)不断的去读取GPFDAT,GPGDAT来获取按键的状态。 led_on, led_off 传入4,5,6 分别对应3个不同的led, 这里不做展开介绍。
这个程序只是简单的介绍如何通过轮训的方式来读取按键的值,程序主要存在2个问题:
1)实际使用中,可不能使用while(1)不停的读取按键的数值,这样做很浪费CPU。(不过以前写单片机程序就是这样做的)
2)按键存在消斗的问题,实际的电平波形是会出现来回抖动的,如下图的虚线就是判断电平高地的标准线。因为电平抖动,一次按键 按下/松开 的过程中会出现多次 按下/松开 的结果。因为程序是靠led来显示结果,如果是 按下/松开 通过串口打印结果的话,一次 按下/松开 串口可能会喷出多次不同的结果。 处理的方式就是延迟一会之后再次去读取,如果数值还是一样的话,那就是正确的结果了,否则就是抖动。