嵌入式技术william hill官网
直播中

刘 刚

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

【MYD-Y6ULX试用体验】控制GPIO

本帖最后由 sandman78 于 2018-4-12 11:41 编辑

Linux支持应用程序通过sysfs在用户空间进行GPIO的控制或读取状态,这里采用Rust语言的sysfs_gpio crate实现IO控制。

Rust中, crate是一个独立的可编译单元。具体说来,就是一个或一批文件。它编译后,会对应着生成一个可执行文件或一个库。sysfs_gpio提供了方便的访问GPIO的方法。

为了简化描述,这里采用sysfs_gpio仓库里面的例子说明

首先下载代码到本地
  1. $ git clone github.com/rust-embedded/rust-sysfs-gpio
  2. $ cd rust-sysfs-gpio
编译完成后,可在target/armv7-unknown-linux-gnueabihf/debug/examples 目录下看到生成的可执行文件blinky,将该文件复制到开发板中,加入可执行权限。

交叉编译IO输出的例子程序
  1. $ cargo build --example blinky --target armv7-unknown-linux-gnueabihf

输入./blinky,可看到提示Usage: ./blinky tion_ms> ,该程序需要三个参数,分别是操作的GPIO,运行时间和闪烁时间。

MYB-Y6ULX 提供了扩展口,这里选用扩展接口J14的8脚测试,经查找芯片手册可知该脚为gpio1.IO26,对应Linux中的GPIO26,在该脚接入发光二极管威廉希尔官方网站 ,运行程序

  1. # ./blinky 26 10000 100
可看到对应管脚电平高低变化5次。

核心代码如下

  1. fn blink_my_led(led: u64, duration_ms: u64, period_ms: u64) -> sysfs_gpio::Result<()> {
  2.     let my_led = Pin::new(led);
  3.     my_led.with_exported(|| {
  4.         my_led.set_direction(Direction::Low)?;
  5.         let iterations = duration_ms / period_ms / 2;
  6.         for _ in 0..iterations {
  7.             my_led.set_value(0)?;
  8.             sleep(Duration::from_millis(period_ms));
  9.             my_led.set_value(1)?;
  10.             sleep(Duration::from_millis(period_ms));
  11.         }
  12.         my_led.set_value(0)?;
  13.         Ok(())
  14.     })
  15. }

下面解释一下执行过程,

  1. let my_led = Pin::new(led);

构建一个Pin
  1. my_led.with_exported(|| {
  2.     ....

导出GPIO, 想当于执行 echo N > /sys/class/gpio/export, 这里使用了闭包的语法

  1. my_led.set_direction(Direction::Low)?
设置端口为输出,并输出低电平

引用: my_led.set_value(1)?
设置端口输出高电平

完整代码如下
  1. extern crate sysfs_gpio;

  2. use sysfs_gpio::{Direction, Pin};
  3. use std::time::Duration;
  4. use std::thread::sleep;
  5. use std::env;

  6. struct Arguments {
  7.     pin: u64,
  8.     duration_ms: u64,
  9.     period_ms: u64,
  10. }

  11. // Export a GPIO for use.  This will not fail if already exported
  12. fn blink_my_led(led: u64, duration_ms: u64, period_ms: u64) -> sysfs_gpio::Result<()> {
  13.     let my_led = Pin::new(led);
  14.     my_led.with_exported(|| {
  15.         my_led.set_direction(Direction::Low)?;
  16.         let iterations = duration_ms / period_ms / 2;
  17.         for _ in 0..iterations {
  18.             my_led.set_value(0)?;
  19.             sleep(Duration::from_millis(period_ms));
  20.             my_led.set_value(1)?;
  21.             sleep(Duration::from_millis(period_ms));
  22.         }
  23.         my_led.set_value(0)?;
  24.         Ok(())
  25.     })
  26. }

  27. fn print_usage() {
  28.     println!("Usage: ./blinky ");
  29. }

  30. fn get_args() -> Option {
  31.     let args: Vec = env::args().collect();
  32.     if args.len() != 4 {
  33.         return None;
  34.     }
  35.     let pin = match args[1].parse::() {
  36.         Ok(pin) => pin,
  37.         Err(_) => return None,
  38.     };
  39.     let duration_ms = match args[2].parse::() {
  40.         Ok(ms) => ms,
  41.         Err(_) => return None,
  42.     };
  43.     let period_ms = match args[3].parse::() {
  44.         Ok(ms) => ms,
  45.         Err(_) => return None,
  46.     };
  47.     Some(Arguments {
  48.              pin: pin,
  49.              duration_ms: duration_ms,
  50.              period_ms: period_ms,
  51.          })
  52. }

  53. fn main() {
  54.     match get_args() {
  55.         None => print_usage(),
  56.         Some(args) => {
  57.             match blink_my_led(args.pin, args.duration_ms, args.period_ms) {
  58.                 Ok(()) => println!("Success!"),
  59.                 Err(err) => println!("We have a blinking problem: {}", err),
  60.             }
  61.         }
  62.     }
  63. }



更多回帖

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