问答
直播中

刘 刚

10年用户 42经验值
擅长:6933
私信 关注

【MYS-6ULX-IOT试用体验】Go语言与GPIO: 2 按键处理

本帖最后由 sandman78 于 2017-6-26 09:32 编辑

        开发板上S2为用户按键,按下按键会引起中断,中断服务程序会产生事件,该事件通过EVDEV返回到用户程序。我们在获取输入设备的事件时往往通过/dev/input/eventx来获取,通过open read操作完成。
通过命令捕获按键状态

使用下面的命令获取按键对应的事件名
  1. $ cat /proc/bus/input/devices
  2. ...省略无关显示
  3. I: Bus=0019 Vendor=0001 Product=0001 Version=0100
  4. N: Name="gpio-keys"
  5. P: Phys=gpio-keys/input0
  6. S: Sysfs=/devices/platform/gpio-keys/input/input2
  7. U: Uniq=
  8. H: Handlers=kbd event2
  9. B: PROP=0
  10. B: EV=3
  11. B: KEY=4

从最后一段可知Name="gpio-keys"对应的是Handlers=kbd event2

访问event2的设备结点捕获按键状态
  1. $ cat /dev/input/event2 | hexdump -C
  2. 00000000  78 77 09 59 68 2e 03 00  01 00 02 00 00 00 00 00  |xw.Yh...........|
  3. 00000010  78 77 09 59 68 2e 03 00  00 00 00 00 00 00 00 00  |xw.Yh...........|
  4. 00000020  78 77 09 59 ef b9 0b 00  01 00 02 00 01 00 00 00  |xw.Y............|
  5. 00000030  78 77 09 59 ef b9 0b 00  00 00 00 00 00 00 00 00  |xw.Y............|

命令执行后处于等待状态,按下按键后将上报事件
中间两块为收到的数据,共有16列
  • 第1列到第8列为事件发生的时间
  • 第9第10列为 1 表示为按键事件
  • 第13-16列为0表示按键按下, 为1表示按键释放


通过程序捕获按键状态
用Go来获取按键状态时,先打开/dev/input/event2文件,在阻塞读取数据,并通过Go的通信机制通知应用程序

代码分解
程序开启两个goroutine,一个用于读取按键事件,另一个模拟应用,用于事件处理
  1.     const keyEventFile = "/dev/input/event2"
  2.     k, err := os.Open(keyEventFile)
定义文件名为常量,并打开文件

  1. data := make([]byte, 16)
  2. _, err := k.Read(data)
阻塞读取上报的数据

  1. var et uint16
  2. buf := bytes.NewReader(data[8:10])
  3. err = binary.Read(buf, binary.LittleEndian, &et)
提取事件类型,bytes用于处理数组切片,binary包用于字节序列和数据之间的转化,binary.LittleEndian表示采用小端方式处理

  1.     if et == evKey {
  2.         buf = bytes.NewReader(data[12:])
  3.         err = binary.Read(buf, binary.LittleEndian, &value)
  4.     }
如果事件类型为按键事件,继续读取4个字节数据,该数据表示是按下或释放按键

  1.     ch := make(chan uint32)
  2.     ch <- value
将收到的数据传递给应用程序,这里利用了Go提供的Channel通信机制, Channel是goroutine之间进行通信的一种方式

程序验证
交叉编译并在开发板上运行
  • 按下按键后,控制台输出"Key Pressed"
  • 释放按键后,控制台输出"Key released"。
完整代码
  1. package main

  2. import (
  3.     "bytes"
  4.     "encoding/binary"
  5.     "fmt"
  6.     "os"
  7. )

  8. const keyEventFile = "/dev/input/event2"
  9. const evKey = 1

  10. func main() {
  11.     k, err := os.Open(keyEventFile)
  12.     check(err)
  13.     defer k.Close()
  14.     ch := make(chan uint32)
  15.     go func() {
  16.         data := make([]byte, 16)
  17.         for {
  18.             _, err := k.Read(data)
  19.             check(err)
  20.             var et uint16
  21.             buf := bytes.NewReader(data[8:10])
  22.             err = binary.Read(buf, binary.LittleEndian, &et)
  23.             check(err)
  24.             var value uint32
  25.             if et == evKey {
  26.                 buf = bytes.NewReader(data[12:])
  27.                 err = binary.Read(buf, binary.LittleEndian, &value)
  28.                 check(err)
  29.                 ch <- value
  30.             }
  31.         }
  32.     }()

  33.     go func() {
  34.         for {
  35.             value := <-ch
  36.             if value == 0 {
  37.                 fmt.Println("Key pressed")
  38.             } else if value == 1 {
  39.                 fmt.Println("Key released")
  40.             }
  41.         }
  42.     }()

  43.     fmt.Println("Press enter key to exit")
  44.     var b [1]byte
  45.     os.Stdin.Read(b[:])
  46. }

  47. func check(err error) {
  48.     if err != nil {
  49.         panic(err)
  50.     }
  51. }







回帖(1)

jinglixixi

2018-4-19 08:35:00
学习了!                        
举报

更多回帖

发帖
×
20
完善资料,
赚取积分