查看: 1009|回复: 0

米尔科技Rico Board试用笔记三——应用程序开发之LED和GPIO

[复制链接]
  • TA的每日心情
    开心
    2016-10-12 17:42
  • 签到天数: 1 天

    连续签到: 1 天

    [LV.1]初来乍到

    发表于 2016-11-3 08:54:22 | 显示全部楼层 |阅读模式
    分享到:
    0 前言
       上一期,我们讲的是搭建开发环境及程序演示。讲真,上次真的花了我不少功夫,主要是对虚拟机的使用比较陌生,关于文件共享、网络配置方面比较繁琐,一直在学着怎么使用。好在基本上搞定了,其实还有个问题:win10系统下,Virtual Box(版本4.1.18)中的虚拟机网络桥接宿主机一直没有搞定,这就意味着虚拟机无法与宿主机、开发板同处一个局域网中,传输文件会比较麻烦,如果大家有好的解决方案,请告诉我。现在这一期,开始在上面编程了。我的想法是,利用已经写好的硬件驱动,写几个应用程序。比如基本的按键key、LED灯、串口通信方面的。好了,现在就开始正式的征程吧。
       写应用程序,在我看来,应该是调用Linux系统提供的应用程序接口(API),通过内核,来控制硬件。那么就需要找到这些API,那这些API到底在哪儿呢?比如说LED灯的操作,如何完成初始化,然后指定某个引脚为输出,再指定输出高或低电平,这些应该都是API中给定的。后来事实证明,我想的有点简单,因为Linux文件系统很复杂,而我又是新手,好多文件我都是第一次接触的。
       在手册中,并没有指出这些接口所在的文件,可能对于老手来说,这些都不是事儿。然后对我们这种刚入门的菜鸟来说,就是很大的困难。这里先推荐一下大家上米尔官网上的论坛:https://www.myir-tech.com/bbs/forum.php,AM437X系列芯片比较新,资料比较少,大家可以参照AM335X系列的。里面有一篇是介绍Linux设备驱动源码文件列表的。

       大家如果有兴趣可以打开去看看哦。其实Linux系统已经把很多接口通用化了。从后面的内容就可以明显感觉到,操作GPIO就像操作文件一样,有open, read, write, close等。这里放一张图,说的是用户程序、操作系统、驱动和硬件之间的关系。

    1 LED灯玩法
    上面说了这么多,是不是有点晕乎乎的。好的,下面开始结合LED灯讲讲硬件接口编程。开发板上有4个LED灯,写着D23~D25,打开开发板原理图,找到D23~D25;

    再找到对应的芯片引脚,

    对应的是GPIO1_24~GPIO1_27,这里说一下GPIO的编号方式。举个例子,GPIO1_24意味着是1*32+24=56,对应的GPIO56。
    怎么来控制它们呢?一种方式是通过虚拟文件系统sysfs:
    cd /sys/class/leds/status_led1/
    然后你会发现有一些基本操作:
    比如说把非零值传给brightness文件(在Linux中,设备皆文件,LED灯也是这样啊。),
    echo 1 > brightness
    就可以点亮小灯;
    把零值传给brightness文件,
    echo 0 > brightness
    就可以关闭小灯;
    把heartbeat传给trigger,
    echo heartbeat > trigger
    就可以让小灯闪烁(即心跳灯)。
    比如说系统运行时D23小灯一直在闪烁,就是以下这句话的效果:
    echo heartbeat > /sys/class/leds/status_led0/trigger
    是不是很神奇。
    2 在C程序中操作LED
       上面的一种方法,讲的是在应用层通过shell方式控制LED,下面介绍的这种,是通过C语言来实现的。下面贴上我写的代码。思路:在C程序中操作LED,首先要设置trigger属性为nono,将指示灯设置为用户控制。然后操作brightness属性0和1每隔1s交替变换,设置LED点亮或熄灭。
    #include <stdio.h>#include <sys/types.h>#include <sys/stat.h>#include <fcntl.h>#include <string.h>#define TRIGGER         "trigger"#define LED_PATH                "/sys/class/leds/"#define LED_STATUS                "brightness"#define TRIGGER_NONE        "none"int main(int argc, char **argv){        char path[40], data[2];        int fd, ret, flag = 0;                if (argv[1] == NULL)        {                printf("Usage: ./led status_led3");                return 0;        }                strcpy(path, LED_PATH);        strcat(path, argv[1]);        strcat(path, "/" TRIGGER);                fd = open(path, O_RDWR);        if (fd < 0)        {                perror("open");                return -1;        }                ret = write(fd, TRIGGER_NONE, strlen(TRIGGER_NONE));                if (ret < 0)        {                perror("write");                return -1;        }                close(fd);                stpcpy(path, LED_PATH);        strcat(path, argv[1]);        strcat(path,"/" LED_STATUS);                fd = open(path, O_WRONLY);        if (fd < 0)        {                perror("open");                return -1;        }                for (;;)        {                data[0] = flag?'0':'1';                ret = write(fd, data, 1);                if (ret < 0)                {                        perror("write");                        return -1;                }                                flag =!flag;                sleep(1);        }        return 0;}   写完代码后,修改下Makefile文件里的变量,然后编译,没有错误后,将执行文件拷贝到目标板中,增加权限后,输入以下指令执行:
    $./led status_led3
    3 GPIO玩法
       介绍完LED灯的两种玩法,下面讲一下GPIO的。
    科普一下,Linux下用文件IO的方式操作GPIO(/sys/class/gpio),通过sysfs方式控制GPIO,先访问/sys/class/gpio目录,向export文件写入GPIO编号,使得该GPIO的操作接口从内核空间暴露到用户空间,GPIO的操作接口包括direction和value等,direction控制GPIO方向,而value可控制GPIO输出或获得GPIO输入。文件IO方式操作GPIO,使用到了4个函数open、close、read、write。
    ARM Linux开发板GPIO输入输出接口操作,对于大部分的 ARM Linux 开发板来说,其实都已经把所有的GPIO驱动做好了,我们要做的就是去使用它。
    (1)、GPIO目录
    在ARM Linux中,GPIO驱动的目录是:/sys/class/gpio/,所以,要首先进入这个目录,命令:
    $ cd /sys/class/gpio/
    (2)、目录解析
    使用ls命令查看目录详情:
    $ ls
    export       gpiochip128  gpiochip32   gpiochip96
    gpiochip0    gpiochip160  gpiochip64   unexport
    如上列出了6个gpio目录、export、unexport文件。gpio目录对应基地址,比如芯片的IO定义为GPIO0_0~GPIO0_31、GPIO1_0~GPIO1_31等等,那么GPIO0对应的base就是gpiochip0,GPIO1对应的base就是gpiochip32,以此类推。大家有兴趣可以可以进入其中一个目录看看,
    $cd gpiochip32
    $ls
    base       label      ngpio      power      subsystem  uevent
    具体内容就不一一介绍了,如果有需要,我可以再写个介绍。
    (3)、控制实例
    比如要实现控制 GPIO5_9(5*32+9=169) 口,在/sys/class/gpio目录下先生成一个gpio169 目录:
    $ echo 169 > export
    $ cd gpio169
    $ ls
    active_low  direction   edge        power       subsystem   uevent
    (4)、控制
    $ cat direction        #查看方向
    in
    $ echo out > direction   #设置为输出
    $ cat value           #获取值
    0
    $ echo 1 > value       #设置为1
    这时候,你可以用万用表去测一下J11上12号引脚(GPIO5_9)的电平;

    关于GPIO的使用,还有另外两种方式,可以参考这篇文章,写得比较详细:https://www.myir-tech.com/bbs/thread-7220-1-1.html
    4 小结
       这一期的内容,需要有一定的嵌入式Linux开发基础。因为之前没有做过嵌入式Linux开发项目,都是基于Cortex-M系列的应用开发,所以我还是下了不少功夫,Cortex-A系列的复杂度比Cortex-M系列高出几个数量级,何况米尔公司又没有提供非常详细的入门引导教程。建议大家可以找几本嵌入式Linux方面的书来看看。嵌入式Linux开发还有一个重要内容需要去学习,就是Qt嵌入式开发。所以,我准备将更多的时间精力放在Qt开发上。下一期就是关于这个主题的,我希望能将更多有价值的内容分享给大家。
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-4-26 14:14 , Processed in 0.124541 second(s), 17 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.