s5pv210——按键

以下内容源于朱有鹏嵌入式课程的学习,以及博客http://www.cnblogs.com/biaohc/p/6353954.html的学习整理,如有侵权,请告知删除。


一、按键

1、按键的物理特性

  • 按钮没有被按下时,内部是断开的。
  • 按钮被按下时,内部保持接通(闭合)状态;如果放手,则由于弹簧作用,按钮又被弹开,内部断开。
  • 一般按键有4个引脚,分成2对:一对是常开触点(像上面描述的不按则断开,按下则闭合);一对是常闭触点(平时不按时是闭合的,按下后是断开的)。

2、按键的电学原理(结合原理图分析)

s5pv210——按键_第1张图片s5pv210——按键_第2张图片

(1)硬件接法: SW5:GPH0_2,SW6:GPH0_3SW78910:GPH2_0123;

(2)按键的电路连接分析

  • 按钮没有按下,则按钮内部断开,GPIO引脚处电压为高电平;
  • 按钮被按下时,则按钮内部导通,外部VDD经过电阻和按钮连接到地,形成回路,此时GPIO引脚处电压就变成了低电平。

(3)总结

  • 按键的按下与弹开,分别对应GPIO的两种电平状态(按下则GPIO为低电平,弹开则GPIO为高电平)。
  • SoC内部通过检测这个GPIO的电平高低来判断按键是否被按下,这个判断结果即可作为SoC的输入信号。

3、按键属于输入类设备

按键一般用来做输入设备(向SoC发送信息的设备,叫输入设备),由人向SoC发送按键信号(按键信号有2种:按下信号和弹开信号)。

  • 有些设备是单纯的输入设备,譬如按键、触摸屏等;
  • 有些设备是单纯的输出设备,譬如LCD;
  • 有些设备是既能输入又能输出的,叫输入输出设备(IO),譬如串口。

4、按键的2种处理方式

SoC处理按键有2种思路:轮询方式和中断方式。

  • 轮询方式:SoC每隔一段时间去读取(按键所对应的)GPIO的电平高低,以此获得按键信息;缺点在于CPU要一直注意按键事件,会影响CPU做其他事情。
  • 中断方式:SoC事先设定好GPIO触发的中断所对应的中断处理程序ISR,当按键按下或弹开时会触发GPIO对应的外部中断,导致ISR执行,从而自动处理按键信息。

二、轮询方式处理按键

1、X210开发板的按键接法

  • 由原理图可以看出:按下时是低电平,弹起时是高电平

2、按键对应的GPIO模式设置

  • 按键接到GPIO上,按键按下还是弹起,决定外部电路的接通与否,从而决定这个GPIO引脚的电压是高还是低;
  • 这个电压可以作为这个GPIO引脚的输入信号,此时GPIO配置为输入模式,即可从SoC内部读取该引脚的电平为1还是0(1对应高电平,0对应低电平)。
  • GPH0CON(0xE0200C00),GPH0DAT(0xE0200C04),GPH2CON(0xE0200C40),GPH2DAT(0xE0200C44)。
  • 在CON寄存器中将GPIO设置为input模式,然后读取DAT寄存器:读取到的相应位的值为1表示外部是高电平,读取到的位的值为0表明外部是低电平。
  • GPH0CON的每4bit(GPH0CON[?])控制GPH0的一个引脚(引脚?)的模式。

s5pv210——按键_第3张图片s5pv210——按键_第4张图片

s5pv210——按键_第5张图片s5pv210——按键_第6张图片s5pv210——按键_第7张图片

3、轮询方式处理按键的程序流程

  • 第一步,先初始化GPIO模式为input;
  • 第二步,循环读取GPIO的电平值,然后判断有无按键按下;

4、轮询方式检测有无按键

/*
 *        s5pv210裸机实验
 *        
 *        key
 *
 */
 

#define _REG_GPH0CON            (*(volatile unsigned int *)0xE0200C00)
#define _REG_GPH0DAT            (*(volatile unsigned int *)0xE0200C04)
#define _REG_GPH2CON            (*(volatile unsigned int *)0xE0200C40)
#define _REG_GPH2DAT            (*(volatile unsigned int *)0xE0200C44)

void led_blink(void);
void led_off(void);

void key_init(void)
{
    //EINT2配置为输入模式
    _REG_GPH0CON &= ~(0xFF<<8);    
    //GPH2_0~GPH2_3置为输入
    _REG_GPH2CON &= ~(0xFFFF<<0);
    
}

void key_polling(void)
{
    key_init();
    while (1) {
//由于通过_REG_GPH0CON设置GPH0_2这个引脚为输入模式,
//_REG_GPH0DAT这个寄存器对应的位就是对应引脚的值
        if (!(_REG_GPH0DAT & (0x1<<2))) {
        led_blink();
    }
        if (!(_REG_GPH0DAT & (0x1<<3))) {
        led_blink();
    }
    if (!(_REG_GPH2DAT & (0x1<<0))) {
        led_blink();
    }
    if (!(_REG_GPH2DAT & (0x1<<1))) {
        led_blink();
    }
    if (!(_REG_GPH2DAT & (0x1<<2))) {
        led_blink();
    }
    if (!(_REG_GPH2DAT & (0x1<<3))) {
        led_blink();
    }
    
    }
    
}


三、外部中断

1、什么是外部中断?数据手册在哪里?

1SoC支持的中断类型中有一类叫外部中断。

  • 内部中断,指中断源来自于SoC内部(一般是内部外设),譬如串口、定时器等部件产生的中断;
  • 外部中断是SoC外部的设备,通过外部中断对应的GPIO引脚产生的中断。

2)按键在SoC中就使用外部中断来实现。

  • 将按键电路接在外部中断的GPIO上,然后将GPIO配置为外部中断模式。
  • 此时通过按按键改变按键电路的电压高低,这个电压高低会触发GPIO对应的外部中断,通过引脚传进去给CPU处理。

2、电平触发和边沿触发

  • 外部中断的触发模式主要有2种:电平触发和边沿触发。
  • 电平触发:电平触发分为高电平触发和低电平触发。电平触发的特点是,只要电平满足条件就会不停触发中断。
  • 边沿触发分为上升沿触发、下降沿触发和双边沿触发三种。边沿触发不关心电平常规状态,只关心电平变化的瞬间(边沿触发不关心电平本身是高还是低,只关心变化是从高到低还是从低到高的这个过程)。如果关注的是按键按下和弹起这两个事件本身,那么应该用边沿触发来处理按键;如果关心的是按键按下/弹起的那一段时间,那么应该用电平触发。

3、关键寄存器:CONPENDMASK

1外部中断设置需要涉及到4个寄存器

  • 接线引脚要设置为中断模式;(通过对应的GPIO控制寄存器,比如GPH0是通过GPH0CON寄存器控制的)
  • 设置中断触发的方式;
  • 中断掩码设置为使能中断;
  • 中断挂起要设置为0,发生中断以后,中断处理函数要把中断挂起为重新写为0

2GPH0CON寄存器

s5pv210——按键_第8张图片

  • 接入中断的引脚要设置为EXT_INT中断模式;

3)EXT_INT_0_CON寄存器

s5pv210——按键_第9张图片s5pv210——按键_第10张图片

  • 配置外部中断的触发方式。触发方式就是说外部电平怎么变化就能触发中断,也就是说这个外部中断产生的条件是什么。

4EXT_INT_0_PEND寄存器(中断挂起寄存器)

s5pv210——按键_第11张图片

  • 每一位对应一个外部中断,没有中断时值为0
  • 发生中断后,硬件自动将此寄存器中该中断对应的位置1,我们去处理完这个中断后应该手工将该位置0
  • PEND寄存器的位相当于一个标志,如果发生了中断暂时忙来不及去处理时,这个位一直是1(这就是挂起),直到处理了此中断才会手工清除(写代码清除)这个挂起位,表示此中断被处理了。

5EXT_INT_0_MASK寄存器

s5pv210——按键_第12张图片

  • 各个外部中断的使能/禁止开关。
  • EXT_INT_0_MASK:中断掩码要设置为0。

4、中断方式处理按键 

#define EXT_INT_0_CON    0xE0200E00
#define EXT_INT_2_CON    0xE0200E08
#define EXT_INT_0_PEND    0xE0200F40
#define EXT_INT_2_PEND    0xE0200F48
#define EXT_INT_0_MASK    0xE0200F00
#define EXT_INT_2_MASK    0xE0200F08

#define _REG_EXT_INT_0_CON    (*(volatile unsigned int *)EXT_INT_0_CON)
#define _REG_EXT_INT_2_CON    (*(volatile unsigned int *)EXT_INT_2_CON)
#define _REG_EXT_INT_0_PEND    (*(volatile unsigned int *)EXT_INT_0_PEND)
#define _REG_EXT_INT_2_PEND    (*(volatile unsigned int *)EXT_INT_2_PEND)
#define _REG_EXT_INT_0_MASK    (*(volatile unsigned int *)EXT_INT_0_MASK)
#define _REG_EXT_INT_2_MASK    (*(volatile unsigned int *)EXT_INT_2_MASK)


//中断方式初始化按键
void key_inter_init(void)
{
    
    //ENIT2、ENIT3引脚设置为中断模式
    _REG_GPH0CON |= (0xFF<<8);
    //ENIT16、ENIT17、ENIT18、ENIT19引脚设置为中断模式
    _REG_GPH2CON |= (0xFFFF<<0);
    
    //设置ENIT2、ENIT3为下降沿触发
    _REG_EXT_INT_0_CON &= ~(0xFF<<8);
    _REG_EXT_INT_0_CON |= ((0x2<<8) | (0x2<<12));
    //设置ENIT16、ENIT17、ENIT18、ENIT19为下降沿触发
    _REG_EXT_INT_2_CON &= ~(0xFFFF<<0);
    _REG_EXT_INT_0_CON |= ((0x2<<0) | (0x2<<4) | (0x2<<8) | (0x2<<12));
    
    //使ENIT2、ENIT3能外部中断;
    _REG_EXT_INT_0_MASK &= ~(0x3<<2);
    //使ENIT16、ENIT17、ENIT18、ENIT19能外部中断;
    _REG_EXT_INT_2_MASK &= ~(0xF<<0);

/*    
    //清ENIT2、ENIT3中断挂起
    _REG_EXT_INT_0_PEND |= (0x3<<2);
    //清ENIT16、ENIT17、ENIT18、ENIT19中断挂起
    _REG_EXT_INT_2_PEND |= (0xF<<0);

*/
    clean_int_pend();
}

 总结:

(1)由于按键的连接方式,知按键是连接到GPH0和GPH1的。

以GPH0为例,接了按键eint1、enit2。可以通过GPH0CON寄存器控制GPH0每个引脚的模式(输出、输入、中断)。如果是中断,可知eint1和eint2的中断号分别为2,3,可以统一看做是中断组号0下的中断,因此是在ext_int_0_前缀的寄存器下继续进行触发条件的设置(EXT_INT_0_CON寄存器),以及是否启用中断的设置(EXT_INT_0_MASK寄存器)。由于是中断2,3,因此设置的是2,3中断对应的位([]中为2,3的)。

 

 

附:串口输出和按键消抖

1、基于串口标准输出的按键调试

  • 以之前的串口stdio的工程为基础来移植添加轮询方式按键处理。
  • 注意USB下载方式可能有错误(有可能不下载,也有可能下载了执行不对),解决方案是用SD卡启动来替代。

2、按键消抖

1)按键这种物理器件本身会有抖动信号

  • 抖动信号指的是在电平由高到低(也就是按键按下时)或者电平由低到高(也就是按键弹起时)过程中,电平的变化不是立刻变化,而是经过了一段时间的不稳定期才完成变化,在这个不稳定期间电平可能会时高时低反复变化,这个不稳定期就叫抖动。
  • 抖动期内获取按键信息是不可靠的,要想办法消抖。

2)什么叫消抖?

  • 消抖就是用硬件或者软件方法来尽量减小抖动期对按键获取的影响。
  • 第一是硬件消抖,消抖思路就是尽量减小抖动时间,方法是通过硬件添加电容等元件来减小抖动;
  • 第二是软件消抖,消抖思路是发现一次按键按下/弹起事件后,不立即处理按键,而是延时一段时间(一般1020ms,这就是消抖时间)后再次获取按键键值,如果此次获取和上次一样是按下/弹起,那就认为真的按下/弹起了。
  • 一般比较精密需要的时候,需要硬件消抖和软件消抖一起配合。









你可能感兴趣的:(ARM裸机)