完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
GPIO(General-purpose input/output)即通用输入输出,根据名字就能够了解到在实际应用中可以有很多种用途,最常见的便是用来控制LED灯的亮灭,或用来侦测输入信号的高低变化。英创工控主板都给用户提供了丰富的GPIO资源,ESMARC系列的板卡拥有32位GPIO,为了方便用户能够更方便的进行开发,英创公司进一步在软件上也增加了一些实用的功能。在GPIO用作控制LED灯的时候,用户可以直接使用Linux的LED子系统来对指定的GPIO口进行设置和操作,比如LED的亮灭或者设置触发方式等。如果是将GPIO设置为输入状态侦测输入信号的高低变化,一旦电平发生变化,内核就会通知应用程序,这时使用select函数就可以接收到内核发出的消息,不用再通过while或者for函数不断的轮询,实际的功能已经在ESMARC系列的ESM6800主板上通过测试和验证了。下面就针对两个功能来介绍一下具体的使用方法。 用户使用GPIO控制LED灯,可以直接调用英创公司提供的API函数,将GPIO置为输出然后置高或者置低。不过Linux系统将控制LED灯的这部分功能整合起来,设计成了一个标准的LED子系统,对LED子系统的操作在shell环境中就能完成。英创公司也将这部分功能的支持加入到了板卡中,如果熟悉使用LED子系统来控制的用户,就可以选用这种方式。通过加载一个内核模块led-emtronix.ko来启用LED子系统,加载的时候通过参数gpios来设置需要使用LED子系统操作的GPIO,gpios参数为一个32位的整数,代表32位GPIO,1表示enable而0表示disable。所以当我们选用GPIO0~GPIO3时,加载内核模块的命令如下:insmode led-emtronix.ko gpios=0x0f,加载完成后,用户可以在/sys/class/leds/目录下看到新生成了四个对应的文件夹LED1、LED2、LED3和LED4,注意,为了方便用户区分,LED子文件夹的标号和GPIO的标号是一一对应的,比如GPIO10生成的子文件夹为LED10。 加载内核模块 我们选择LED0这个目录进入,可以看到里面有许多文件,我们要使用到的文件为brightness和trigger这两个。 文件列表 brightness这个文件用来控制LED的开关,对应板卡的GPIO电平高低,当brightness文件的值为0时,GPIO输出低电平,当brightness文件的值为1时GPIO则输出高电平,需要注意的是,加载内核模块后,默认情况为输出低电平即brightness文件的值为0。在shell中需要查看brightness的值可以使用命令cat brightness: 查看brightness文件 如果是需要设置brightness文件的值,则可以使用echo命令: 设置brightness文件的值 另一个文件trigger的作用是设置触发方式,默认为none即没有触发方式。使用cat命令读取trigger文件可以得到支持的所有触发方式,如下图看到有磁盘,定时器,心跳,背光等多种触发方式: 查看触发方式 有方括号的表示为现在的有效触发方式,如果要选用heartbeat作为触发方式,还是使用echo命令来进行设置: 设置trigger 设置之后可以通过示波器看到对应的GPIO像心跳一样,每秒会进行一次拉高拉底。按照上面所介绍的方法,就能够使用LED子系统来对板卡的GPIO进行控制。 接下来介绍一下输入事件通知的功能,英创板卡的GPIO上电是默认都为输入状态(有3.3V上拉),在默认状态下是不会响应输入电平变化进行事件通知的。要启用这一功能,需要调用英创公司提供的,设置GPIO输入状态的API来实现。也就是在程序中需要调用一次API,设置GPIO为输入,才会使能这一位GPIO的输入事件通知功能,代码如下:
int GPIO_OutDisable(int fd, unsigned int dwDisBits) { int rc; struct double_pars dpars;
dpars.par1 = ESM6800_GPIO_OUTPUT_DISABLE; dpars.par2 = dwDisBits;
rc = write(fd, &dpars, sizeof(struct double_pars)); return rc; }
rc = GPIO_OutDisable(fd, i1); //set GPIO as input if(rc < 0) { printf("GPIO_OutEnable::failed %dn", rc); return rc; }
当设置完成后,GPIO作为输入状态,同时内核会在输入的电平变化时通知应用层,使用select函数来监听GPIO的句柄的读事件就能够获取到通知,用户可以通过多线程的方式来实现,代码如下:
while( 1 ) { //设置读事件 FD_ZERO(&fdRead); FD_SET(fd,&fdRead);
//设置超时时间 atime.tv_sec = 0; aTime.tv_usec = 20000;
ret = select(fd+1,&fdRead,NULL,NULL,&aTime); //printf( "select ret = %dn", ret);
if (ret < 0 ) { printf("error!n"); break; }
if (ret > 0) { //判断是否读事件 if (FD_ISSET(fd,&fdRead)) { //读事件触发,进行相应的动作 dwPinState = 0xffffffff; rc = GPIO_PinState(fd, &dwPinState); if(rc < 0) { printf("GPIO_PinState::failed %dn", rc); return rc; } printf("PinState = 0x%08xn", dwPinState); } } } 当输入电平发生变化,select侦测到读事件,就可以进行相应的操作,示例代码只是简单的读取了当前GPIO的输入电平状态,用户可以根据实际的应用来修改。当有多路GPIO用于侦测输入电平变化的时候,在接收到读事件后,如果需要判断是哪一位GPIO侦测到电平变化,就要立刻读取当前GPIO的状态来以此进行判断。对于不需要这一功能的用户也不会有什么影响,当调用函数将GPIO设置为输入后,不使用select函数去监听GPIO的句柄即可,其他功能都和原来一致。 英创公司希望通过增加一些类似的实用功能,让用户的开发能够更加方便,如果在使用过程中遇到任何问题,可以和英创公司的工程师联系寻求技术支持。 |
|
相关推荐 |
|
只有小组成员才能发言,加入小组>>
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-22 12:23 , Processed in 0.581821 second(s), Total 42, Slave 31 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号