TL62x-EVM的OpenPLC实践(二)硬件初始化

缓慢推进中,但是找到了一些参考资料:

1. 一个PSM example: https://d28lcup14p4e72.cloudfront.net/203128/6168244/PSM-Instructions.pdf

2. 官方对PSM的简介:https://openplc.discussion.community/post/megaioind-industrial-building-automation-for-raspberrypi-9832564?trail=30

看起来是要先借助原有嵌入式开发板的有关库,读取有关的参数并存储为变量,然后再通过psm.set_var(), psm.get_var()建立嵌入式开发板和逻辑变量的联系。具体示例如下:

在webserver中,在以下界面中编程:

 1 TL62x有关GPIO的使用原理

具体参考官方文档:【3-用户手册】文件夹中的2-2Linux应用开发手册.pdf,有关源码在【TL62x-EVM_V1.4\4-软件资料\Demo\python-demos】文件夹中。

1. led_flash案例

参考该文档的2.1节,进行有关开发API的探索

(1)首先查看有关的设备节点,具体如下:

 (2)利用SD card,将官方提供的led_flash.py拷贝至评估版的文件系统

登录评估版的系统,可以发现有关的文件已经拷贝过来了:

 (3)查看程序信息,如下:

 (4)执行程序,可以看到评估底板上的LED在进行闪烁:

 按下“Ctrl+C”终止程序。

(5)进行源码分析

①导入的库
import signal, time
# signal库用于处理信号,信号是在操作系统中用于通知进程发生了某些事件的一种机制。通过signal库,可以捕获和处理各种信号,比如终止信号、中断信号等,以便进行相应的处理
# time库提供了处理时间和日期的函数,包括获取当前时间、休眠一定时间、格式化时间等功能。通过time库,可以方便地进行时间相关的操作
import os, sys, getopt
# os库提供了与操作系统交互的函数,包括文件和目录操作、进程管理、环境变量等功能。通过os库,可以实现对操作系统的各种操作,比如创建文件、执行系统命令、获取当前工作目录等
# sys库提供了与Python解释器交互的函数和变量,包括命令行参数、标准输入输出、异常处理等功能。通过sys库,可以获取和修改Python解释器的运行时信息,以及与解释器进行交互

② main函数

我们在这里摘取部分代码:

led = Led("/sys/class/leds/") # Led的路径

""" enumerate all led """
ret = led.enumerate_led()
""" can not find led """
if not ret:
   print ("can not find led!")
   exit(3)
 
 """ control flash all led """
print ("\n flash led ...")
led.flash_led()
③ 去LED类中寻找上面三个函数的源码
1 类的初始化
class Led(object):
    ……
    def __init__(self, led_path):
        self.led_path = led_path    # Led path
        self.leds     = []          # Save the led found

2 找led

class Led(object):

  ……

def enumerate_led(self):
        led_name = "user-led"

        """ find led """
        for filename in os.listdir(self.led_path):
            if led_name in filename:
                self.leds.append(os.path.join(self.led_path, filename))

        if len(self.leds) == 0:
            return False

        """
        led sort, e.g.
        /sys/class/leds/user-led0
        /sys/class/leds/user-led1
        /sys/class/leds/user-led2
        """
        ……
 

从评估版也可以看出LED的地址确实如下:

 3 控制led闪烁

class Led(object):

  ……

def flash_led(self):
        led_num = len(self.leds)

        while not Led.quit_flag:
            """ Turn on leds """
            for i in range(led_num):
                """ Set the led brightness value to 1 to turn on the led """
                ret = os.system("echo 1 > %s/brightness" % (self.leds[i]))

                if ret != 0:
                    print ("Error: Failed to turn on %s") % self.leds[i]

            """ Keep the leds on for 500 ms """
            time.sleep(0.5)

            for i in range(led_num):
                """ Set the led brightness value to 0 to turn off the LED """
                os.system("echo 0 > %s/brightness" % (self.leds[i]))

            """ Keep the leds off for 500 ms """
            time.sleep(0.5)

2. key_test案例

参考该文档的2.2节,进行有关开发API的探索

(1)查看有关程序的信息,发现出现错误:

 于是安装有关的库文件,再查看程序信息发现成功:

 (2)执行程序,终端结果如下:

按下“Ctrl + Z”终止程序。

 (3)进行源码分析

① 导入的库

import signal, time
import os, sys, getopt, select
import evdev

② main函数

key_dev = ""   # key deivce path

    """ parse parameter """
    try:
        options, remainder = getopt.getopt(sys.argv[1:], 'vhd:', ['version', 'help', 'device='])
        for opt, arg in options:
            if ……
            elif opt in('-d', '--device'):
                key_dev = arg # 说明按键的地址是:/dev/input/event1

    except getopt.GetoptError as err:
        print ('ERROR: %s' % err)
        exit(1)

    ……
 

    key_device = KeyDevice()

    """ open key device,借助按键地址控制按键 """
    res = key_device.open_device(key_dev)
    if not res:
        print ("open %s failed!" % key_dev)
        exit(3)

    """ Listen for the button to be pressed """
    key_device.listen_key_pressed()

③ 去KeyDevice类中找上面两个函数的源码

1 打开有关设备

class KeyDevice(object):
……
def open_device(self, key_dev):
        try:
            """ open key device, if success, return True"""
            self.key_dev = evdev.InputDevice(key_dev)
            return True
        except Exception as e:
            print (e)
            return False

2 监控有关事件

def listen_key_pressed(self):
        try:
            print ("Please press the key to test.\n")

            """
            Listen for the button to be pressed
            event.value: 1: pressed; 0: released
            """
            for event in self.key_dev.read_loop():
                if event.type == evdev.ecodes.EV_KEY:
                    if event.code == evdev.ecodes.KEY_PROG1 and event.value == 1:
                        print ("User key0 pressed!\n")

                    elif event.code == evdev.ecodes.KEY_PROG2 and event.value == 1:
                        print ("User key1 pressed!\n")

        except Exception as e:
            if not KeyDevice.quit_flag:
                print (e)

 2 尝试修改代码——第一次失败

将有关代码修改如下:

#import all your libraries here
import psm
import signal, time
import os, sys, getopt, select
import evdev

#global variables


def hardware_init():
#Insert your hardware initialization code in here
psm.start()

def update_inputs():
#place here your code to update inputs

psm.set_var("IX0.0", evdev.InputDevice("/dev/input/event1"))


def update_outputs():
#place here your code to work on outputs
a = psm.get_var("QX0.0")
if a == True:
os.system("echo 1>/sys/class/leds/user-led0/brightness")


if __name__ == "__main__":
hardware_init()
while (not psm.should_quit()):
update_inputs()
update_outputs()
time.sleep(0.1) #You can adjust the psm cycle time here
psm.stop()

但是发现依旧存在问题:

 失败了。注意到在有关按钮输入的demo代码中,不同的按钮是通过evdev.ecodes.KEY_PROG1/evdev.ecodes.KEY_PROG2这样的事件类型(?)来区分的,而不是类似于OpenPLC提供的官方示例中的API。所以我们有必要进一步查看python中evdev库的有关内容。

通过这个帖子:https://cloud.tencent.com/developer/ask/sof/1284947/answer/1776633,知道了evdev不能在windows环境下运行,只能在Linux下运行,因为evdev是基于Linux内核事件的。我也尝试在win主机上安装evdev库,发现的确失败了,所以尝试在ubuntu虚拟机上安装evdev。

3 第二次尝试——查看evdev源码

目标:在evdev源码中发现有关GPIO的接口,从而成功编写openplc的psm.py

evdev的官方文档:https://python-evdev.readthedocs.io/en/latest/usage.html

参照官方文档,可以使用Python的evdev库来获取系统中的输入设备列表,并输出每个设备的路径、名称和物理地址信息

但gpio-keys/input0这样的路径信息,通常表示这是一个内核中的输入设备,而不是一个直接可控制的设备。

如果要控制输入设备,需要使用evdev库中的InputDevice对象来读取和处理设备发送的输入事件。如果要控制特定的输入设备,需要了解该设备发送的事件类型和如何处理这些事件。

1.  在虚拟机上安装evdev库

(1)首先安装pip:

sudo apt install python3-pip

(2)然后安装evdev库:

pip install evdev

发现在ubuntu上果然成功安装!

 2. 查看evdev库源文件

(1)找到evdev库的存储路径:

在命令行输入:

pip show evdev

结果如下:

 可以发现它的路径中有隐藏文件夹

(2)启用显示隐藏文件

在用户目录中,按下“ctrl+H”键,可以发现隐藏文件夹显示。

 按照前面找到的evdev路径,可以找到evdev的有关库文件

3. 阅读相关源码

经过一番查找,发现和按键有关的源代码如下

(1)设备初始化

TL62x提供的demo中有关源码为: self.key_dev = evdev.InputDevice(key_dev) # 其中key_dev为/dev/input/event1

在evdev中有关源码为:

【device.py】文件中

class InputDevice(EventIO): # 类
  
  def __init__(self, dev):
          """
          Arguments
          ---------
          dev : str|bytes|PathLike # demo中取值为/dev/input/event1
            Path to input device
          """

          #: Path to input device.
          self.path = dev if not hasattr(dev, "__fspath__") else dev.__fspath__()

          # Certain operations are possible only when the device is opened in
          # read-write mode.
          try:
              fd = os.open(dev, os.O_RDWR | os.O_NONBLOCK) # 尝试以读写模式(os.O_RDWR)和非阻塞模式(os.O_NONBLOCK)打开设备。如果成功打开文件,则将文件描述符赋值给'fd'变量
          except OSError:
              fd = os.open(dev, os.O_RDONLY | os.O_NONBLOCK) # 如果在上面尝试中出现OSError异常,说明设备不支持读写模式,可能只支持只读模式

          #: A non-blocking file descriptor to the device file.
          self.fd = fd

          # Returns (bustype, vendor, product, version, name, phys, capabilities).
          info_res = _input.ioctl_devinfo(self.fd) # _input是一个用C语言编写的Python扩展库

          #: A :class:`DeviceInfo <evdev.device.DeviceInfo>` instance.
          self.info = DeviceInfo(*info_res[:4]) # *用于解包一个序列,将序列中的元素作为函数的单独参数传递。*info_res[:4]表示取info_res元组的前四个元素,

          #: The name of the event device.
          self.name = info_res[4]

          #: The physical topology of the device.
          self.phys = info_res[5]

          #: The unique identifier of the device.
          self.uniq = info_res[6]

          #: The evdev protocol version.
          self.version = _input.ioctl_EVIOCGVERSION(self.fd)

          #: The raw dictionary of device capabilities - see `:func:capabilities()`.
          self._rawcapabilities = _input.ioctl_capabilities(self.fd)

          #: The number of force feedback effects the device can keep in its memory.
          self.ff_effects_count = _input.ioctl_EVIOCGEFFECTS(self.fd)
(2)监控设备输入
TL62x提供的demo中有关源码为:
 for event in self.key_dev.read_loop():
                if event.type == evdev.ecodes.EV_KEY:
                    if event.code == evdev.ecodes.KEY_PROG1 and event.value == 1:
                        print ("User key0 pressed!\n")

                    elif event.code == evdev.ecodes.KEY_PROG2 and event.value == 1:
                        print ("User key1 pressed!\n")
在evdev中有关源码为:
【eventio.py】文件中,
class EventIO:
  def read_loop(self):
          """
          Enter an endless :func:`select.select()` loop that yields input events.
          """

          while True: # 无限循环
              r, w, x = select.select([self.fd], [], []) # 使用select.select函数来等待文件描述符self.fd上的可读事件。r: 就绪读取的文件描述符列表,w: 就绪写入的文件描述符列表,x: 发生异常的文件描述符列表
              for event in self.read(): # 通过调用self.read()方法来获取输入事件
                  yield event
 
  def read(self):
          """
          Read multiple input events from device. Return a generator object that
          yields :class:`InputEvent <evdev.events.InputEvent>` instances. Raises
          `BlockingIOError` if there are no available events at the moment.
          """

          # events -> [(sec, usec, type, code, val), ...]
          events = _input.device_read_many(self.fd) # _input是一个用C语言编写的Python扩展库

          for event in events:
              yield InputEvent(*event)
(3)openplc中set_var的有关源码
在openplc的psm中,需要利用psm.set_var将本地变量和plc中定义的输入逻辑变量关联,有关源码如下:
【openplc-webserver-psm】文件夹的psm.py文件中有
def set_var(variable_name, value): # variable_name是psm中逻辑变量的名字,value是利用开发板有关的库读取的数据
    var = extract_variable(variable_name)
    io_type = var[0]
    address = var[1]

    if (io_type == var_type.DIG_INP):
        return d_inputs.setValues(address, value) # 可以发现是直接将有关的值赋给了有关的地址

    elif (io_type == var_type.DIG_OUT):
        return d_outputs.setValues(address, value)

    elif (io_type == var_type.ANA_INP):
        return a_inputs.setValues(address, value)

    elif (io_type == var_type.ANA_OUT):
        return a_outputs.setValues(address, value)

    else:
        return 0
4. 再次修改代码,psm中有关的代码改为

import psm
import signal, time
import os, sys, getopt, select
import evdev

#global variables


class KeyDevice(object):
quit_flag = False

def open_device(self, key_dev):
try:
  """ open key device, if success, return True"""
  self.key_dev = evdev.InputDevice(key_dev)
  return True
except Exception as e:
  print (e)
  return False

def listen_key_pressed(self):
  try:
    while (not psm.should_quit()):
      for event in self.key_dev.read_loop():
        if event.type == evdev.ecodes.EV_KEY:
          if event.code == evdev.ecodes.KEY_PROG1 and event.value == 1:
            print("User key0 pressed!\n")
            psm.set_var("IX0.0", True)
            psm.set_var("IX0.1",False)
            # 更新输出
            a = psm.get_var("QX0.0")
            if a == True:
              os.system("echo 1>/sys/class/leds/user-led0/brightness")
            else:
              os.system("echo 0 > /sys/class/leds/user-led0/brightness")
            time.sleep(0.1) #You can adjust the psm cycle time here
          elif event.code == evdev.ecodes.KEY_PROG2 and event.value == 1:
            print("User key1 pressed!\n")
            psm.set_var("IX0.1", True)
            psm.set_var("IX0.0", False)
            # 更新输出
            a = psm.get_var("QX0.0")
            if a == True:
              os.system("echo 1>/sys/class/leds/user-led0/brightness")
            else:
              os.system("echo 0 > /sys/class/leds/user-led0/brightness")
            time.sleep(0.1) #You can adjust the psm cycle time here
  except Exception as e:
    if not KeyDevice.quit_flag:
    print (e)

@classmethod
def stop(cls):
cls.quit_flag = True

 

def hardware_init():
#Insert your hardware initialization code in here
psm.start()

 

if __name__ == "__main__":
  hardware_init()
  key_dev="/dev/input/event1"
  key_device = KeyDevice()

  res = key_device.open_device(key_dev)
  if not res:
  print ("open %s failed!" % key_dev)
  exit(3)

  key_device.listen_key_pressed()

  psm.stop()

 
结果为:

psm倒是没报错了,但为什么只有在点击 User key1 的时候会出现I/O error?

而且实验现象没有实现

 4 第三次尝试——借助evdev实现了有点问题的实验现象

现将实验代码粘贴到此处:

 

import psm
import signal, time
import os, sys, getopt, select
import evdev

#global variables


class KeyDevice(object):
  quit_flag = False

  def open_device(self, key_dev):
  try:
    """ open key device, if success, return True"""
    self.key_dev = evdev.InputDevice(key_dev)
    return True
  except Exception as e:
    print (e)
    return False

  def listen_key_pressed(self):
    try:
      while (not psm.should_quit()):
        for event in self.key_dev.read_loop():
          if event.type == evdev.ecodes.EV_KEY:
            print("detect something happen!")
            if event.code == evdev.ecodes.KEY_PROG1 and event.value == 1:
              print("User key0 pressed!\n")
              psm.set_var("IX0.0", True)
              psm.set_var("IX0.1", False)
              print("update input!")
              # 更新输出
              a = psm.get_var("QX0.0")
              print("update output!")
              print(a)
              if a == True:
                ret = os.system("echo 1 > /sys/class/leds/user-led0/brightness")
                if ret !=0:
                  print("Error: Failed to turn on led")
              else:
                ret = os.system("echo 0 > /sys/class/leds/user-led0/brightness")
                if ret!=0:
                  print("Error: Failed to turn off led")
              time.sleep(0.1) #You can adjust the psm cycle time here
          elif event.code == evdev.ecodes.KEY_PROG2 and event.value == 1:
            print("User key1 pressed!\n")
              psm.set_var("IX0.1", True)
            psm.set_var("IX0.0", False)
            print("update input!")
                 # 更新输出
            a = psm.get_var("QX0.0")
            print("update output!")
            print(a)
            if a == True:
              ret = os.system("echo 1 > /sys/class/leds/user-led0/brightness")
              if ret !=0:
                print("Error: Failed to turn on led")
            else:
              ret = os.system("echo 0 > /sys/class/leds/user-led0/brightness")
            if ret!=0:
              print("Error: Failed to turn off led")
            time.sleep(0.1) #You can adjust the psm cycle time here
  except Exception as e:
    if not KeyDevice.quit_flag:
      print (e)

@classmethod
def stop(cls):
  cls.quit_flag = True

 

def hardware_init():
#Insert your hardware initialization code in here
  psm.start()

 

if __name__ == "__main__":
  hardware_init()

  key_dev="/dev/input/event1"
  key_device = KeyDevice()

  res = key_device.open_device(key_dev)
  print("open sucessfully")
  if not res:
    print ("open %s failed!" % key_dev)
    exit(3)

  key_device.listen_key_pressed()

  psm.stop()

奇怪的是,感觉代码没有改变什么,但是就可以正常运行了,Log如下:

 目前的实验现象是:

当LED熄灭时,按两次user1按键,LED会亮起,然后无论按多少次user1按键,LED都不会灭;

再按两次user2按键,LED会熄灭,然后无论按多少次user2按键,LED都不会亮。

5 第四次尝试,成功实现

以下代码可以成功实现预期实验现象:

当LED熄灭时,按一次user1按键,LED会亮起,然后无论按多少次user1按键,LED都不会灭;

再按一次user2按键,LED会熄灭,然后无论按多少次user2按键,LED都不会亮。

改进的重点:针对按键被释放的事件(event.value == 0)编写了逻辑

 

#import all your libraries here
import psm
import signal, time
import os, sys, getopt, select
import evdev
import gpiod

#global variables


class KeyDevice(object):
  quit_flag = False

  def open_device(self, key_dev):
    try:
      """ open key device, if success, return True"""
      self.key_dev = evdev.InputDevice(key_dev)
      return True
    except Exception as e:
      print (e)
      return False

  def listen_key_pressed(self):
    try:
      while (not psm.should_quit()):
        psm.set_var("IX0.0", False) #常开开关
        #time.sleep(0.1) #You can adjust the psm cycle time here
        psm.set_var("IX0.1", False) #常闭开关
        #time.sleep(0.1) #You can adjust the psm cycle time here
        for event in self.key_dev.read_loop():
          if event.type == evdev.ecodes.EV_KEY:
            if event.code == evdev.ecodes.KEY_PROG1:
              if event.value == 1: # 表示按键被按下
                print("User key0 pressed!")
                psm.set_var("IX0.0", True)
                print("update input!")
                #time.sleep(0.1) #You can adjust the psm cycle time here
                # 更新输出
                update_outputs()
                #time.sleep(0.1) #You can adjust the psm cycle time here
              elif event.value == 0: # 表示按键被释放
                psm.set_var("IX0.0", False)
                #time.sleep(0.1) #You can adjust the psm cycle time here
                update_outputs()
                #time.sleep(0.1) #You can adjust the psm cycle time here
            elif event.code == evdev.ecodes.KEY_PROG2:
              if event.value == 1: # 表示按键被按下
                print("User key1 pressed!")
                psm.set_var("IX0.1", True)
                print("update input!")
                #time.sleep(0.1) #You can adjust the psm cycle time here
                # 更新输出
                update_outputs()
                #time.sleep(0.1) #You can adjust the psm cycle time here
              elif event.value == 0: # 表示按键被释放
                psm.set_var("IX0.1", False)
                #time.sleep(0.1) #You can adjust the psm cycle time here
                update_outputs()
                #time.sleep(0.1) #You can adjust the psm cycle time here

    except Exception as e:
      if not KeyDevice.quit_flag:
        print (e)

@classmethod
def stop(cls):
  cls.quit_flag = True

 

def hardware_init():
#Insert your hardware initialization code in here
  psm.start()

def update_outputs():
  a = psm.get_var("QX0.0")
  print("update output!")
  if a == True:
    ret = os.system("echo 1 > /sys/class/leds/user-led0/brightness")
    if ret !=0:
      print("Error: Failed to turn on led")
  else:
    ret = os.system("echo 0 > /sys/class/leds/user-led0/brightness")
    if ret!=0:
      print("Error: Failed to turn off led")


if __name__ == "__main__":
  hardware_init()

  key_dev="/dev/input/event1"
  key_device = KeyDevice()

  res = key_device.open_device(key_dev)
  print("open sucessfully")
  if not res:
    print ("open %s failed!" % key_dev)
    exit(3)

  key_device.listen_key_pressed()

  psm.stop()

6 失败的尝试

6.1 libgpiod库

参考资料:https://doc.embedfire.com/linux/rk356x/Python/zh/latest/circuit/digital_io.html

https://blog.csdn.net/Fenglin6165/article/details/103967292

首先查询GPIO信息,如下:

 可以发现,开发板的按钮和gpio-401,gpio-505是互相连接的,当按下按钮适,有关GPIO引脚的状态会改变。

下面尝试通过libgpiod库进行引脚的检测

1. 安装libgpiod库,如下:

sudo apt-get install gpiod

检查是否安装成功:

 出现问题,发现python无法找到gpiod

问题应该是gpiod安装到了python找不到的地方,于是利用pip重新安装:

 发现python可以成功导入gpiod了

 2. 查看按钮对应的chip和line,如下:

gpioinfo

 可以看到,user-key0对应chip2, line2; user-key1对应chip1 line19.

3. 尝试利用gpiod库操作开发板的GPIO

按照网上的源码,觉得有关的代码应该这样写:

if __name__ == "__main__":
hardware_init()

# line offset
BUTTON_key0_offset = 2
BUTTON_key1_offset = 19
# chip
chip2 = gpiod.Chip("2",gpiod.Chip.OPEN_BY_NUMBER)
chip1 = gpiod.Chip("1",gpiod.Chip.OPEN_BY_NUMBER)
# initialize button
key0 = chip2.get_line(BUTTON_key0_offset)
key1 = chip1.get_line(BUTTON_key1_offset)
key0.request(consumer="BUTTON", type=gpiod.LINE_REQ_DIR_IN)
key1.request(consumer="BUTTON", type=gpiod.LINE_REQ_DIR_IN)

while (not psm.should_quit()):
  print("key0")
  print( key0.get_value())
  print("key1")
  print(key1.get_value())

  key0.release()
  key1.release()
psm.stop()

但报错,发现这个库的用法和网上的用法有些区别,准备看源码

首先查看安装的gpiod的版本:

 去github上,下载1.5.4的源码,经过调整,现在我想这样写的:

# line offset
BUTTON_key0_offset = 2
# chip
chip2 = gpiod.chip("2",gpiod.chip.OPEN_BY_NUMBER)
# initialize button
key0 = chip2.get_line(BUTTON_key0_offset)

config = gpiod.line_request()

config.consumer="BUTTON"
config.request_type=gpiod.line_request.DIRECTION_INPUT
key0.request(config)

但发现报错:

>>> key0.request(config)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python3.8/dist-packages/gpiod/libgpiodcxx/__init__.py", line 553, in request
rv = libgpiod.gpiod_line_request(_m_line, conf, default_val)
File "/usr/local/lib/python3.8/dist-packages/gpiod/libgpiod/__init__.py", line 479, in gpiod_line_request
return gpiod_line_request_bulk(bulk, config, [default_val])
File "/usr/local/lib/python3.8/dist-packages/gpiod/libgpiod/__init__.py", line 522, in gpiod_line_request_bulk
return _line_request_values(bulk, config, default_vals)
File "/usr/local/lib/python3.8/dist-packages/gpiod/libgpiod/__init__.py", line 387, in _line_request_values
status = ioctl(fd, GPIO_GET_LINEHANDLE_IOCTL, req)
OSError: [Errno 16] Device or resource busy

尝试了许多次,发现这个问题无法解决,可能是因为有关GPIO已经被评估底板上的按钮绑死了,所以无法继续观测了。

6.2 使用input子系统

参考网址:https://doc.embedfire.com/linux/imx6/linux_base/zh/latest/linux_app/input_subsystem/input_subsystem.html

input子系统是Linux对输入设备提供的统一驱动框架。如按键、键盘、触摸屏和鼠标等输入设备的驱动方式是类似的,当出现按键、触摸等操作时,硬件产生中断,然后CPU直接读取引脚电平,或通过SPI、I2C等通讯方式从设备的寄存器读取具体的按键值或触摸坐标,然后把这些信息提交给内核。使用input子系统 驱动的输入设备可以通过统一的数据结构提交给内核,该数据结构包括输入的时间、类型、代号以及具体的键值或坐标,而内则通过/dev/input目录下的文件接口传递给用户空间。

在Linux内核源码的“Documentation/input”目录包含了input子系统相关的说明。

1. 首先安装evtest工具

sudo evtest

2. 然后进行运行evtest工具,进行测试

 几个奇怪的事情:只能检测到event 1,而且无论按下user key 0还是user key 1,value都是从0——>1。

3. 根据原博客后续的文字,发现这实际上和evdev库很类似,所以也不行。

同时,在安装evtest后,将和Openplc runtime有关的一些库卸载了,所以这种方法失败。

6.3 直接将GPIO export到用户空间

还有一种方法:https://blog.csdn.net/weixin_37787043/article/details/123553972

https://blog.csdn.net/Fenglin6165/article/details/103967292

这种方法可以将一个 GPIO 端口导出(export)到用户空间,以便用户可以访问和控制该 GPIO 端口。

posted @ 2024-02-29 14:55  碳酸钾K2CO3  阅读(48)  评论(0编辑  收藏  举报